Inserir nova coluna na tabela no sqlite?

354

Eu tenho uma tabela com colunas name, qty, rate. Agora eu preciso adicionar uma nova coluna COLNewentre as colunas namee qty. Como adiciono uma nova coluna entre duas colunas?

Testador
fonte

Respostas:

677

Você tem duas opções. Primeiro, você pode simplesmente adicionar uma nova coluna com o seguinte:

ALTER TABLE {tableName} ADD COLUMN COLNew {type};

Segundo, e mais complicado, mas na verdade colocaria a coluna onde você deseja, seria renomear a tabela:

ALTER TABLE {tableName} RENAME TO TempOldTable;

Em seguida, crie a nova tabela com a coluna ausente:

CREATE TABLE {tableName} (name TEXT, COLNew {type} DEFAULT {defaultValue}, qty INTEGER, rate REAL);

E preencha com os dados antigos:

INSERT INTO {tableName} (name, qty, rate) SELECT name, qty, rate FROM TempOldTable;

Em seguida, exclua a tabela antiga:

DROP TABLE TempOldTable;

Eu preferiria muito a segunda opção, pois ela permitirá que você renomeie completamente tudo, se necessário.

Raceimaztion
fonte
27
Eu usaria a primeira opção e usaria a opção padrão da opção de envio ALTER TABLE {tableName} ADD COLUMN COLNew {type} DEFAULT {defaultValue}; Mais importante: (pensando no motivo pelo qual você desejaria ordenar as colunas ...) use em todas as ações de registro (como inserir ou adicionar) sempre os nomes das colunas, dessa forma, você nunca cometerá erros em algum lugar do código após alterar a tabela.
Michel.iamit
5
Pela maneira: valor padrão não pode ser adicionado em ALTER TABLE para alguns FieldTypes: sqlite.org/lang_altertable.html
michel.iamit
9
não se esqueça de re-criar índices
Jan Turon
5
você terá de recriar gatilhos também
Christopher K.
7
Não se esqueça de possíveis violações de restrição causadas por chaves estrangeiras: "... mas pode invocar ações de chave estrangeira ou violações de restrição". (consulte sqlite.org/foreignkeys.html#fk_schemacommands ); como uma solução alternativa, você pode desativar as chaves estrangeiras enquanto isso: PRAGMA foreign_keys = ON;(consulte sqlite.org/foreignkeys.html#fk_enable )
Trinimon
112

Você não adiciona colunas entre outras colunas no SQL, apenas as adiciona. Onde eles são colocados depende totalmente do DBMS. O lugar certo para garantir que as colunas saiam na ordem correta é quando você as selectusa.

Em outras palavras, se você os quiser na ordem {name,colnew,qty,rate}, use:

select name, colnew, qty, rate from ...

Com o SQLite, você precisa usar alter table, um exemplo:

alter table mytable add column colnew char(50)
paxdiablo
fonte
2
SELECT * FROM mytable?
EML
Qual é o valor padrão definido se não o especificarmos nas linhas existentes da nova coluna?
22414 Jacob
12
Existem muito poucos casos de uso em que você deveria estar realizando select *. Às vezes, é útil para programas que desejam descobrir tabelas, mas, para a grande maioria dos usos, você deve especificar explicitamente o que deseja e, portanto, a ordem em que deseja.
precisa
4
É insano como essa não é a "resposta aceita". A pergunta original em si demonstra uma completa falta de entendimento de como um RDBMS funciona.
Vada Poché
12

Você pode adicionar uma nova coluna com a consulta

ALTER TABLE TableName ADD COLUMN COLNew CHAR(25)

Mas será adicionado no final, não entre as colunas existentes.

Mudassir
fonte
11

O SQLite limitou o suporte a ALTER TABLE que você pode usar para adicionar uma coluna ao final de uma tabela ou alterar o nome de uma tabela.

Se você deseja fazer alterações mais complexas na estrutura de uma tabela, precisará recriar a tabela. Você pode salvar os dados existentes em uma tabela temporária, soltar a tabela antiga, criar a nova tabela e copiar os dados novamente da tabela temporária.

Por exemplo, suponha que você tenha uma tabela chamada "t1" com os nomes das colunas "a" e "c" e que deseje inserir a coluna "b" nessa tabela. As etapas a seguir ilustram como isso pode ser feito:

BEGIN TRANSACTION;
CREATE TEMPORARY TABLE t1_backup(a,c);
INSERT INTO t1_backup SELECT a,c FROM t1;
DROP TABLE t1;
CREATE TABLE t1(a,b, c);
INSERT INTO t1 SELECT a,c FROM t1_backup;
DROP TABLE t1_backup;
COMMIT;

Agora você está pronto para inserir seus novos dados da seguinte forma:

UPDATE t1 SET b='blah' WHERE a='key'
CJH
fonte
Nos meus testes, a linha INSERT INTO t1 SELECT a,c FROM t1_backup;causa o erro: "a tabela t1 tem 3 colunas, mas foram fornecidos 2 valores: INSERT IN t1 SELECT a, c FROM t1_backup;". A linha correta deve serINSERT INTO t1 (a,c) SELECT a,c FROM t1_backup;
JnLlnd 14/08/18
5
ALTER TABLE {tableName} ADD COLUMN COLNew {type};
UPDATE {tableName} SET COLNew = {base on {type} pass value here};

Esta atualização é necessária para manipular o valor nulo, inserindo um valor padrão conforme necessário. Como no seu caso, você precisa chamar a SELECTconsulta e obterá a ordem das colunas, como o paxdiablo já disse:

SELECT name, colnew, qty, rate FROM{tablename}

e na minha opinião, o nome da sua coluna para obter o valor do cursor:

private static final String ColNew="ColNew";
String val=cursor.getString(cursor.getColumnIndex(ColNew));

portanto, se o índice mudar, seu aplicativo não enfrentará problemas.

Essa é a maneira segura no sentido de que, caso contrário, se você estiver usando CREATE temptableou RENAME tableou CREATE, haveria uma grande chance de perda de dados se não fosse tratado com cuidado, por exemplo, no caso em que suas transações ocorrem enquanto a bateria está acabando.

Naval Kishor Jha
fonte
4

Eu estava enfrentando o mesmo problema e o segundo método proposto na resposta aceita, conforme observado nos comentários, pode ser problemático ao lidar com chaves estrangeiras.

Minha solução alternativa é exportar o banco de dados para um arquivo sql, certificando-se de que as instruções INSERT incluam nomes de colunas. Eu faço isso usando o DB Browser for SQLite, que tem um recurso útil para isso. Depois disso, basta editar a instrução create table e inserir a nova coluna onde desejar e recriar o banco de dados.

Em sistemas do tipo * nix é apenas algo parecido com o

cat db.sql | sqlite3 database.db

Não sei se isso é viável com bancos de dados muito grandes, mas funcionou no meu caso.

Hirabayashi Taro
fonte