Inserire una nuova colonna nella tabella in sqlite?


354

Ho una tabella con le colonne name, qty, rate. Ora devo aggiungere una nuova colonna COLNewtra le colonne namee qty. Come faccio ad aggiungere una nuova colonna tra due colonne?

Risposte:


677

Hai due opzioni. Innanzitutto, potresti semplicemente aggiungere una nuova colonna con il seguente:

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

In secondo luogo, e più complicato, ma in realtà metterebbe la colonna nel punto desiderato, sarebbe rinominare la tabella:

ALTER TABLE {tableName} RENAME TO TempOldTable;

Quindi creare la nuova tabella con la colonna mancante:

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

E popolarlo con i vecchi dati:

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

Quindi eliminare la vecchia tabella:

DROP TABLE TempOldTable;

Preferirei di gran lunga la seconda opzione, poiché ti consentirà di rinominare completamente tutto se necessario.


27
Vorrei scegliere la prima opzione e utilizzare l'opzione predefinita al di fuori dell'opzione secend ALTER TABLE {tableName} AGGIUNGI COLONNA COLNEO {type} DEFAULT {defaultValue}; Ancora più importante: (pensando al motivo per cui vorresti ordinare le colonne ...) usa in ogni azione del record (come inserire o aggiungere) sempre i nomi delle colonne, in questo modo, non avrai mai errori in qualche modo nel tuo codice dopo aver modificato la tabella.
michel.iamit,

5
A proposito: valore di default non può essere aggiunto in ALTER TABLE per alcuni fieldtypes: sqlite.org/lang_altertable.html
michel.iamit

9
non dimenticare di ricreare gli indici
Jan Turoň,

5
dovrai anche ricreare i trigger
Christopher K.

7
Non dimenticare le potenziali violazioni di vincolo causate da chiavi esterne: "... ma possono invocare azioni di chiave esterna o violazioni di vincolo". (vedi sqlite.org/foreignkeys.html#fk_schemacommands ); come soluzione alternativa puoi disabilitare le chiavi esterne nel frattempo: PRAGMA foreign_keys = ON;(vedi sqlite.org/foreignkeys.html#fk_enable )
Trinimon

112

Non aggiungi colonne tra altre colonne in SQL, le aggiungi semplicemente. La loro collocazione dipende totalmente dal DBMS. Il posto giusto per garantire che le colonne escano nell'ordine corretto è quando si select.

In altre parole, se li vuoi nell'ordine {name,colnew,qty,rate}, usi:

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

Con SQLite, è necessario utilizzare alter table, ad esempio:

alter table mytable add column colnew char(50)

2
SELECT * FROM mytable?
EML

Qual è il valore predefinito impostato se non lo specifichiamo nelle righe esistenti della nuova colonna?
Jacob,

12
Ci sono pochissimi casi d'uso in cui dovresti farlo select *. A volte è utile per i programmi che vogliono fare la scoperta di tabelle ma, per la stragrande maggioranza degli usi, dovresti specificare esplicitamente ciò che vuoi e quindi l'ordine in cui lo desideri.
paxdiablo,

4
È folle come questa non sia la "risposta accettata". La stessa domanda originale dimostra una completa mancanza di comprensione del funzionamento di un RDBMS.
Vada Poché,

12

È possibile aggiungere una nuova colonna con la query

ALTER TABLE TableName ADD COLUMN COLNew CHAR(25)

Ma verrà aggiunto alla fine, non tra le colonne esistenti.


11

SQLite ha un supporto ALTER TABLE limitato che è possibile utilizzare per aggiungere una colonna alla fine di una tabella o per modificare il nome di una tabella.

Se desideri apportare modifiche più complesse alla struttura di una tabella, dovrai ricreare la tabella. È possibile salvare i dati esistenti in una tabella temporanea, eliminare la tabella precedente, creare la nuova tabella, quindi copiare nuovamente i dati dalla tabella temporanea.

Ad esempio, supponiamo di avere una tabella denominata "t1" con i nomi delle colonne "a" e "c" e di voler inserire la colonna "b" da questa tabella. I seguenti passaggi illustrano come ciò potrebbe essere fatto:

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;

Ora sei pronto per inserire i tuoi nuovi dati in questo modo:

UPDATE t1 SET b='blah' WHERE a='key'

Nei miei test, la riga INSERT INTO t1 SELECT a,c FROM t1_backup;causa l'errore: "la tabella t1 ha 3 colonne ma sono stati forniti 2 valori: INSERISCI IN t1 SELECT a, c FROM t1_backup;". La linea corretta dovrebbe essereINSERT INTO t1 (a,c) SELECT a,c FROM t1_backup;
JnLlnd

5
ALTER TABLE {tableName} ADD COLUMN COLNew {type};
UPDATE {tableName} SET COLNew = {base on {type} pass value here};

Questo aggiornamento è necessario per gestire il valore null, inserendo un valore predefinito come richiesto. Come nel tuo caso, devi chiamare la SELECTquery e otterrai l'ordine delle colonne, come già detto paxdiablo :

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

e secondo me, il nome della tua colonna per ottenere il valore dal cursore:

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

quindi se l'indice cambia la tua applicazione non dovrà affrontare alcun problema.

Questo è il modo sicuro nel senso che altrimenti, se si sta utilizzando CREATE temptableo RENAME tableo CREATE, ci sarebbe un'alta probabilità di perdita di dati se non gestiti con cura, ad esempio nel caso in cui le transazioni avvengano mentre la batteria si sta esaurendo.


4

Stavo affrontando lo stesso problema e il secondo metodo proposto nella risposta accettata, come notato nei commenti, può essere problematico quando si tratta di chiavi esterne.

La mia soluzione è di esportare il database in un file sql assicurandomi che le istruzioni INSERT includano i nomi delle colonne. Lo faccio usando DB Browser per SQLite che ha una funzionalità utile per questo. Dopodiché devi solo modificare l'istruzione create table e inserire la nuova colonna nel punto desiderato e ricreare il db.

In * nix come i sistemi è solo qualcosa sulla falsariga di

cat db.sql | sqlite3 database.db

Non so quanto sia fattibile con database molto grandi, ma ha funzionato nel mio caso.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.