Wstawić nową kolumnę do tabeli w sqlite?


354

Mam tabeli z kolumnami name, qty, rate. Teraz muszę dodać nową kolumnę COLNewmiędzy kolumnami namei qty. Jak dodać nową kolumnę między dwiema kolumnami?

Odpowiedzi:


677

Masz dwie opcje. Po pierwsze, możesz po prostu dodać nową kolumnę z następującymi elementami:

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

Po drugie, i bardziej skomplikowane, ale tak naprawdę umieściłby kolumnę tam, gdzie chcesz, byłaby zmiana nazwy tabeli:

ALTER TABLE {tableName} RENAME TO TempOldTable;

Następnie utwórz nową tabelę z brakującą kolumną:

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

I wypełnij go starymi danymi:

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

Następnie usuń starą tabelę:

DROP TABLE TempOldTable;

Wolałbym drugą opcję, ponieważ w razie potrzeby całkowicie zmienisz nazwę wszystkiego.


26
Chciałbym wybrać pierwszą opcję i użyć opcji domyślnej z opcji secend ALTER TABLE {tableName} ADD COLUMN COLNew {type} DEFAULT {defaultValue}; Co ważniejsze: (zastanawiając się, dlaczego chcesz zamówić kolumny ...) używaj w każdej akcji rekordu (jak wstawianie lub dodawanie) zawsze nazw kolumn, w ten sposób nigdy nie popełnisz błędów w kodzie po zmianie tabeli.
michel.iamit

5
Nawiasem mówiąc: nie można dodać wartości domyślnej w ALTER TABLE dla niektórych typów pól: sqlite.org/lang_altertable.html
michel.iamit

9
nie zapomnij odtworzyć indeksów
Jan Turoň

5
trzeba będzie również odtworzyć wyzwalacze
Christopher K.,

7
Nie zapominaj o potencjalnych naruszeniach ograniczeń spowodowanych przez klucze obce: „... ale mogą wywoływać działania na kluczach obcych lub naruszenia ograniczeń”. (patrz sqlite.org/foreignkeys.html#fk_schemacommands ); w celu obejścia tego problemu możesz w międzyczasie wyłączyć klucze obce: PRAGMA foreign_keys = ON;(patrz sqlite.org/foreignkeys.html#fk_enable )
Trinimon

112

Nie dodajesz kolumn między innymi kolumnami w SQL, po prostu dodajesz je. Ich umieszczenie zależy całkowicie od DBMS. Właściwym miejscem, aby upewnić się, że kolumny wychodzą w odpowiedniej kolejności, jest moment, w którym Ty select.

Innymi słowy, jeśli chcesz je w kolejności {name,colnew,qty,rate}, użyj:

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

W przypadku SQLite musisz użyć alter table, czego przykładem jest:

alter table mytable add column colnew char(50)

2
SELECT * FROM mytable?
EML

Jaka jest wartość domyślna ustawiona, jeśli nie określimy jej w istniejących wierszach nowej kolumny?
Jakub

12
Jest bardzo niewiele przypadków użycia, w których powinieneś robić select *w ogóle. Czasami jest to przydatne dla programów, które chcą odkrywać tabele, ale w zdecydowanej większości zastosowań powinieneś wyraźnie określać, czego chcesz, a zatem kolejność, w jakiej chcesz.
paxdiablo

4
To szalone, że to nie jest „zaakceptowana odpowiedź”. Samo oryginalne pytanie pokazuje całkowity brak zrozumienia, jak działa RDBMS.
Vada Poché

12

Możesz dodać nową kolumnę do zapytania

ALTER TABLE TableName ADD COLUMN COLNew CHAR(25)

Ale zostanie dodany na końcu, a nie pomiędzy istniejącymi kolumnami.


11

SQLite ma ograniczoną obsługę ALTER TABLE, której można użyć do dodania kolumny na końcu tabeli lub do zmiany nazwy tabeli.

Jeśli chcesz wprowadzić bardziej złożone zmiany w strukturze tabeli, musisz odtworzyć tabelę. Możesz zapisać istniejące dane do tabeli tymczasowej, upuścić starą tabelę, utworzyć nową tabelę, a następnie skopiować dane z tabeli tymczasowej.

Załóżmy na przykład, że masz tabelę o nazwie „t1” z nazwami kolumn „a” i „c” oraz że chcesz wstawić kolumnę „b” z tej tabeli. Poniższe kroki ilustrują, jak można to zrobić:

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;

Teraz możesz wstawić nowe dane w następujący sposób:

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

W moich testach wiersz INSERT INTO t1 SELECT a,c FROM t1_backup;powoduje błąd: „tabela t1 ma 3 kolumny, ale podano 2 wartości: WSTAWIĆ DO t1 WYBIERZ a, c Z t1_backup;”. Prawidłowa linia powinna brzmiećINSERT 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};

Ta aktualizacja jest wymagana do obsługi wartości zerowej i wprowadzania wartości domyślnej zgodnie z wymaganiami. Tak jak w twoim przypadku, musisz wywołać SELECTzapytanie, a otrzymasz kolejność kolumn, jak już powiedział paxdiablo :

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

i moim zdaniem, nazwa kolumny, aby uzyskać wartość z kursora:

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

więc jeśli indeks się zmieni, aplikacja nie napotka żadnych problemów.

Jest to bezpieczny sposób w tym sensie, że w przeciwnym razie, jeśli używasz CREATE temptablelub RENAME tablelub CREATE, istnieje duża szansa na utratę danych, jeśli nie zostanie ostrożnie potraktowana, na przykład w przypadku, gdy transakcje występują, gdy bateria się wyczerpie.


4

Miałem do czynienia z tym samym problemem, a druga metoda zaproponowana w zaakceptowanej odpowiedzi, jak zauważono w komentarzach, może być problematyczna w przypadku kluczy obcych.

Moim obejściem jest wyeksportowanie bazy danych do pliku SQL, upewniając się, że instrukcje INSERT zawierają nazwy kolumn. Robię to za pomocą DB Browser for SQLite, który ma do tego przydatną funkcję. Następnie wystarczy edytować instrukcję tworzenia tabeli i wstawić nową kolumnę tam, gdzie chcesz, i ponownie utworzyć db.

W * nix podobnych systemach jest po prostu coś w stylu

cat db.sql | sqlite3 database.db

Nie wiem, jak to możliwe w przypadku bardzo dużych baz danych, ale w moim przypadku zadziałało.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.