Wie benenne ich eine Spalte in einer SQLite-Datenbanktabelle um?


296

Ich müsste einige Spalten in einigen Tabellen in einer SQLite-Datenbank umbenennen. Ich weiß, dass zuvor eine ähnliche Frage zum Stackoverflow gestellt wurde, aber es war für SQL im Allgemeinen, und der Fall von SQLite wurde nicht erwähnt.

Aus der SQLite-Dokumentation für ALTER TABLE geht hervor, dass es nicht möglich ist, so etwas "einfach" zu machen (dh eine einzelne ALTER TABLE-Anweisung).

Ich habe mich gefragt, ob jemand eine generische SQL-Methode kennt, um so etwas mit SQLite zu tun.


Sie können es mit dem DB-Browser für SQLite ziemlich einfach tun
Matt G

1
Bitte erwägen Sie, diese Antwort als akzeptiert zu markieren
Evan Carroll

Antworten:


66

Dies wurde gerade mit 2018-09-15 (3.25.0) behoben

Verbessert den ALTER TABLEBefehl:

  • Unterstützung für das Umbenennen von Spalten in einer Tabelle mithilfe von ALTER TABLEtable hinzufügen RENAME COLUMN oldname TO newname.
  • Die Funktion zum Umbenennen von Tabellen wurde korrigiert, sodass auch Verweise auf die umbenannte Tabelle in Triggern und Ansichten aktualisiert werden.

Die neue Syntax finden Sie unter ALTER TABLE

Die RENAME COLUMN TOSyntax ändert den Spaltennamen der Tabelle tabellenname in neuen Spaltennamen. Der Spaltenname wird sowohl in der Tabellendefinition selbst als auch in allen Indizes, Triggern und Ansichten geändert, die auf die Spalte verweisen. Wenn die Änderung des Spaltennamens zu einer semantischen Mehrdeutigkeit in einem Trigger oder einer Ansicht führen würde, RENAME COLUMNschlägt dies mit einem Fehler fehl und es werden keine Änderungen angewendet.

Geben Sie hier die Bildbeschreibung ein Bildquelle: https://www.sqlite.org/images/syntax/alter-table-stmt.gif

Beispiel:

CREATE TABLE tab AS SELECT 1 AS c;

SELECT * FROM tab;

ALTER TABLE tab RENAME COLUMN c to c_new;

SELECT * FROM tab;

db-fiddle.com Demo


Android-Unterstützung

Wie des Schreibens, 27 Androids API SQLite Paket Version 3.19 verwendet .

Basierend auf der aktuellen Version, die Android verwendet, und dass dieses Update in Version 3.25.0 von SQLite verfügbar ist, würde ich sagen, dass Sie etwas warten müssen (ungefähr API 33), bevor die Unterstützung für Android hinzugefügt wird.

Und selbst dann, wenn Sie Versionen unterstützen müssen, die älter als die API 33 sind, können Sie diese nicht verwenden.


8
Ich implementiere für eine Android-Migration und leider zeigt IntelliJ eine Warnung an, dass es sich nicht um einen gültigen SQL-Befehl handelt. database.execSQL("ALTER TABLE content RENAME COLUMN archiveCount TO dismissCount"). COLUM ist rot hervorgehoben und es steht TO erwartet, hat 'COLUMN' . Leider ist Android immer noch auf SQLite Version 3.19 , weshalb dies bei mir nicht funktioniert.
Adam Hurwitz

1
bearbeitet: Ich habe auf gefunden system.data.sqlite.org/index.html/doc/trunk/www/faq.wiki#q1 , dass die 1.0.109.x) ist eigentlich mit SQLite 3.24 und die System.Data.SQLite Die Verwendung von SQLite 3.25 soll in diesem Monat veröffentlicht werden.
Rychlmoj

1
Zu Ihrer Information, dies muss leider noch von der SQLite-Bibliothek von Android implementiert werden . Hoffentlich werden sie bald aktualisiert.
Adam Hurwitz

3
Ich habe einen Abschnitt für den Android-Support hinzugefügt, um zu verhindern, dass andere ihre Hoffnungen wecken. Basierend auf der aktuellen Verwendung von SQLite 3.19 durch Android 27 müssen wir bis ungefähr API 33 warten, bevor diese Funktion zu Android hinzugefügt wird, und selbst dann wird sie nur in den neuesten Versionen unterstützt. Seufzer.
Joshua Pinter

1
@ JoshuaPinter Danke, dass du meine Antwort erweitert hast.
Lukasz Szozda

448

Angenommen, Sie haben eine Tabelle und müssen "colb" in "col_b" umbenennen:

Zuerst benennen Sie die alte Tabelle um:

ALTER TABLE orig_table_name RENAME TO tmp_table_name;

Erstellen Sie dann die neue Tabelle basierend auf der alten Tabelle, jedoch mit dem aktualisierten Spaltennamen:

CREATE TABLE orig_table_name (
  col_a INT
, col_b INT
);

Kopieren Sie dann den Inhalt gegenüber der Originaltabelle.

INSERT INTO orig_table_name(col_a, col_b)
SELECT col_a, colb
FROM tmp_table_name;

Lassen Sie zum Schluss den alten Tisch fallen.

DROP TABLE tmp_table_name;

All dies in ein BEGIN TRANSACTION;und einwickeln COMMIT;ist wahrscheinlich auch eine gute Idee.


51
Und vergessen Sie nicht Ihre Indizes.
Tom Mayfield

11
Sehr wichtig ist, dass im obigen Beispielcode eine Transaktion fehlt. Sie sollten das Ganze in BEGIN / END (oder ROLLBACK) einschließen, um sicherzustellen, dass die Umbenennung entweder erfolgreich oder gar nicht abgeschlossen ist.
Roger Binns

4
Jeder, der dies in Android tun möchte, kann Transaktionen mit SQLiteDatabase.beginTransaction ()
bmaupin

7
Der Code in der Antwort enthält nichts, was Indizes kopiert. Wenn Sie eine leere Tabelle erstellen und Daten darin ablegen, werden nur Struktur und Daten kopiert. Wenn Sie Metadaten (Indizes, Fremdschlüssel, Einschränkungen usw.) möchten, müssen Sie auch Anweisungen ausgeben, um sie in der ersetzten Tabelle zu erstellen.
Tom Mayfield

17
Der SQLite- .schemaBefehl ist praktisch, um die CREATE TABLEAnweisung anzuzeigen, aus der die vorhandene Tabelle besteht. Sie können die Ausgabe übernehmen, nach Bedarf ändern und ausführen, um die neue Tabelle zu erstellen. Dieser Befehl zeigt auch die erforderlichen CREATE INDEXBefehle zum Erstellen der Indizes an, die die Bedenken von Thomas abdecken sollten. Führen Sie diesen Befehl unbedingt aus, bevor Sie Änderungen vornehmen.
Mike DeSimone

56

Beim Stöbern fand ich dieses grafische Multiplattform-Tool (Linux | Mac | Windows) namens DB Browser for SQLite , mit dem man Spalten auf sehr benutzerfreundliche Weise umbenennen kann!

Bearbeiten | Tabelle ändern | Wählen Sie Tabelle | Feld bearbeiten. Klick klick! Voila!

Wenn jedoch jemand eine programmatische Vorgehensweise teilen möchte, würde ich mich freuen zu wissen!


1
Es gibt auch ein Firefox-Add-On, das dasselbe tut . Klicken Sie mit der rechten Maustaste auf die Spalte, die Sie umbenennen möchten, und wählen Sie "Spalte bearbeiten".
Jacob Hacker

1
Sogar in openSUSE ist es als Paket verfügbar: software.opensuse.org/package/sqlitebrowser

Es ist komisch, dass es so viele Stimmen hat. Wir sprechen hier über Programmierung (Code). Warum hast du diese Antwort überhaupt hier gepostet?
Benutzer25

2
In meiner Frage wird nicht erwähnt, wie dies mit Code gemacht werden soll. Ich wollte nur wissen, wie man eine Spalte in einer SQLite-Datenbank umbenennt.
Joce

@joce ich liebe dich !!! (wie ein Bruder) hat mich dazu gebracht, das Feld zu wechseln, voila. Ich hatte eine MS Access-Tabelle nach SQLite exportiert und eines der Felder hatte eine Ziffer vor: 3YearLetterSent. Visual Studio hat die Klasse aus der Tabelle erstellt, aber an der Ziffer "3" vor dem Feldnamen erstickt. Ich weiß das, habe nur nicht zugesehen.
JustJohn

53

Es ist zwar richtig, dass es keine ALTER COLUMN gibt. Wenn Sie jedoch nur die Spalte umbenennen, die NOT NULL-Einschränkung löschen oder den Datentyp ändern möchten, können Sie die folgenden Befehle verwenden:

Hinweis: Diese Befehle können Ihre Datenbank möglicherweise beschädigen. Stellen Sie daher sicher, dass Sie über ein Backup verfügen

PRAGMA writable_schema = 1;
UPDATE SQLITE_MASTER SET SQL = 'CREATE TABLE BOOKS ( title TEXT NOT NULL, publication_date TEXT)' WHERE NAME = 'BOOKS';
PRAGMA writable_schema = 0;

Sie müssen entweder Ihre Verbindung schließen und erneut öffnen oder die Datenbank staubsaugen, um die Änderungen erneut in das Schema zu laden.

Zum Beispiel:

Y:\> sqlite3 booktest  
SQLite version 3.7.4  
Enter ".help" for instructions  
Enter SQL statements terminated with a ";"  
sqlite> create table BOOKS ( title TEXT NOT NULL, publication_date TEXT NOT NULL);  
sqlite> insert into BOOKS VALUES ("NULLTEST",null);  
Error: BOOKS.publication_date may not be NULL  
sqlite> PRAGMA writable_schema = 1; 
sqlite> UPDATE SQLITE_MASTER SET SQL = 'CREATE TABLE BOOKS ( title TEXT NOT NULL, publication_date TEXT)' WHERE NAME = 'BOOKS';  
sqlite> PRAGMA writable_schema = 0;  
sqlite> .q  

Y:\> sqlite3 booktest  
SQLite version 3.7.4  
Enter ".help" for instructions  
Enter SQL statements terminated with a ";"  
sqlite> insert into BOOKS VALUES ("NULLTEST",null);  
sqlite> .q  

FOLGENDE REFERENZEN:


pragma writable_schema
Wenn dieses Pragma aktiviert ist, die SQLITE_MASTER-Tabellen, in denen die Datenbank mit normalen UPDATE-, INSERT- und DELETE-Anweisungen geändert werden kann. Warnung: Der Missbrauch dieses Pragmas kann leicht zu einer beschädigten Datenbankdatei führen.

alter table
SQLite unterstützt eine begrenzte Teilmenge von ALTER TABLE. Mit dem Befehl ALTER TABLE in SQLite kann der Benutzer eine Tabelle umbenennen oder einer vorhandenen Tabelle eine neue Spalte hinzufügen. Es ist nicht möglich, eine Spalte umzubenennen, eine Spalte zu entfernen oder Einschränkungen zu einer Tabelle hinzuzufügen oder daraus zu entfernen.

ALTER TABLE SYNTAX


3
Gefährlich, aber immer noch wahrscheinlich die direkteste Antwort imo.
Tek

2
Ja, extrem schnell - Gefährlich bedeutet nur "
Noah

6
Das SQLite-Dateiformat ist sehr einfach und deshalb ist dieser Vorgang gültig. Das Dateiformat enthält nur zwei Informationssätze zu einer Tabelle: den eigentlichen Befehl CREATE TABLE als Klartext und die Zeilen, deren Werte in der Reihenfolge der Felder aus dem Befehl CREATE angezeigt werden. Dies bedeutet, dass der SQLite-Code die Datenbank öffnet, jeden CREATE-Befehl analysiert und seine Spalteninformationen dynamisch im Speicher erstellt. Jeder Befehl, der den Befehl CREATE so ändert, dass die gleiche Anzahl von Spalten angezeigt wird, funktioniert auch dann, wenn Sie den Typ oder die Einschränkungen ändern.
Thomas Tempelmann

3
@ThomasTempelmann Das Hinzufügen von Einschränkungen, die vom Dataset nicht erfüllt werden, führt jedoch zu Problemen, da der Abfrageplaner davon ausgeht, dass Einschränkungen gelten.
Fuz

2
@ThomasTempelmann Das Entfernen von Einschränkungen ist immer in Ordnung. Das Hinzufügen von Einschränkungen ist in Ordnung, wenn die Einschränkung von allen Zeilen erfüllt wird, Sie dies jedoch unbedingt überprüfen müssen.
Fuz

18

Vor kurzem musste ich das in SQLite3 mit einer Tabelle namens points mit der Spalte id, lon, lat tun . Wenn die Tabelle importiert wurde, wurden fälschlicherweise die Werte für den Breitengrad in der Spalte lon und umgekehrt gespeichert. Daher wäre es naheliegend, diese Spalten umzubenennen. Der Trick war also:

create table points_tmp as select id, lon as lat, lat as lon from points;
drop table points;
alter table points_tmp rename to points;

Ich hoffe das wäre nützlich für dich!


Diese Methode kopiert den PK-Wert nicht ordnungsgemäß und erstellt automatisch die ausgeblendete Zeilen-ID-Spalte. Nicht unbedingt ein Problem, wollte aber darauf hinweisen, weil es für mich zu einem Problem wurde.
TPoschel

4
Wäre es nicht einfacher, "UPDATE points SET lon = lat, lat = lon;" durchzuführen?
kstep

1
Diese Antwort führt den Vorgang in der richtigen Reihenfolge durch. Erstellen Sie zuerst die temporäre Tabelle und füllen Sie sie aus. Zerstören Sie dann das Original .
Xeoncross

14

Zitieren der SQLite-Dokumentation :

SQLite unterstützt eine begrenzte Teilmenge von ALTER TABLE. Mit dem Befehl ALTER TABLE in SQLite kann der Benutzer eine Tabelle umbenennen oder einer vorhandenen Tabelle eine neue Spalte hinzufügen. Es ist nicht möglich, eine Spalte umzubenennen, eine Spalte zu entfernen oder Einschränkungen zu einer Tabelle hinzuzufügen oder daraus zu entfernen.

Sie können natürlich eine neue Tabelle mit dem neuen Layout erstellen SELECT * FROM old_tableund die neue Tabelle mit den Werten füllen, die Sie erhalten.


7

Zunächst einmal ist dies eines der Dinge, die mich überrascht ins Gesicht schlagen: Das Umbenennen einer Spalte erfordert das Erstellen einer völlig neuen Tabelle und das Kopieren der Daten von der alten Tabelle in die neue Tabelle ...

Die GUI, auf der ich gelandet bin, um SQLite-Operationen auszuführen, ist Base . Es hat ein geschicktes Protokollfenster, das alle ausgeführten Befehle anzeigt. Wenn Sie eine Spalte über Base umbenennen, wird das Protokollfenster mit den erforderlichen Befehlen gefüllt:

Basisprotokollfenster

Diese können dann einfach kopiert und dort eingefügt werden, wo Sie sie benötigen. Für mich ist das eine ActiveAndroid- Migrationsdatei. Eine nette Geste ist auch, dass die kopierten Daten nur die SQLite-Befehle enthalten, nicht die Zeitstempel usw.

Hoffentlich spart das einigen Leuten Zeit.


FYI, wenn Sie sind mit ActiveAndroid , können Sie die weglassen BEGIN TRANSACTION;und COMMIT;Linien, wie ActiveAndroid Griffe , die von selbst aus .
Joshua Pinter

6

FALL 1: SQLite 3.25.0+

Nur die Version 3.25.0 von SQLite unterstützt das Umbenennen von Spalten. Wenn Ihr Gerät diese Anforderung erfüllt, sind die Dinge ganz einfach. Die folgende Abfrage würde Ihr Problem lösen:

ALTER TABLE "MyTable" RENAME COLUMN "OldColumn" TO "NewColumn";

FALL 2: Ältere SQLite-Versionen

Sie müssen einen anderen Ansatz verfolgen, um das Ergebnis zu erhalten, das möglicherweise etwas schwierig ist

Wenn Sie beispielsweise eine Tabelle wie diese haben:

CREATE TABLE student(Name TEXT, Department TEXT, Location TEXT)

Und wenn Sie den Namen der Spalte ändern möchten Location

Schritt 1: Benennen Sie die ursprüngliche Tabelle um:

ALTER TABLE student RENAME TO student_temp;

Schritt 2: Erstellen Sie nun eine neue Tabelle studentmit dem richtigen Spaltennamen:

CREATE TABLE student(Name TEXT, Department TEXT, Address TEXT)

Schritt 3: Kopieren Sie die Daten aus der ursprünglichen Tabelle in die neue Tabelle:

INSERT INTO student(Name, Department, Address) SELECT Name, Department, Location FROM student_temp;

Hinweis: Der obige Befehl sollte nur aus einer Zeile bestehen.

Schritt 4: Legen Sie die Originaltabelle ab:

DROP TABLE student_temp;

Mit diesen vier Schritten können Sie jede SQLite-Tabelle manuell ändern. Beachten Sie, dass Sie auch alle Indizes, Viewer oder Trigger für die neue Tabelle neu erstellen müssen.


1
Wie aktualisiere ich die SQLite-Datenbankversion auf 3.29.0 in Android Studio? Ich verwende API Level 28.
Nathani Software

Die SQLite-Version wird von dem Gerät definiert, auf dem die App arbeitet. Es ist geräteabhängig.
Febin Mathew

1
Für Leute, die altes SQLite verwenden, wird von den vier oben genannten Schritten abgeraten. Siehe den Abschnitt "Achtung" unter sqlite.org/lang_altertable.html .
Jeff

3

Ändern Sie die Tabellenspalte <ID> in <_id>

 String LastId = "id";

    database.execSQL("ALTER TABLE " + PhraseContract.TABLE_NAME + " RENAME TO " + PhraseContract.TABLE_NAME + "old");
    database.execSQL("CREATE TABLE " + PhraseContract.TABLE_NAME
    +"("
            + PhraseContract.COLUMN_ID + " INTEGER PRIMARY KEY,"
            + PhraseContract.COLUMN_PHRASE + " text ,"
            + PhraseContract.COLUMN_ORDER  + " text ,"
            + PhraseContract.COLUMN_FROM_A_LANG + " text"
    +")"
    );
    database.execSQL("INSERT INTO " +
            PhraseContract.TABLE_NAME + "("+ PhraseContract.COLUMN_ID +" , "+ PhraseContract.COLUMN_PHRASE + " , "+ PhraseContract.COLUMN_ORDER +" , "+ PhraseContract.COLUMN_FROM_A_LANG +")" +
            " SELECT " + LastId +" , "+ PhraseContract.COLUMN_PHRASE + " , "+ PhraseContract.COLUMN_ORDER +" , "+ PhraseContract.COLUMN_FROM_A_LANG +
            " FROM " + PhraseContract.TABLE_NAME + "old");
    database.execSQL("DROP TABLE " + PhraseContract.TABLE_NAME + "old");

3

Erstellen Sie eine neue Spalte mit dem gewünschten Spaltennamen: COLNew.

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

Kopieren Sie den Inhalt der alten Spalte COLOld in die neue Spalte COLNew.

INSERT INTO {tableName} (COLNew) SELECT {COLOld} FROM {tableName}

Hinweis: In der obigen Zeile sind Klammern erforderlich.


2

Wie bereits erwähnt, gibt es ein Tool SQLite Database Browser, das dies tut. Dieses Tool führt ein Protokoll aller vom Benutzer oder der Anwendung ausgeführten Vorgänge. Wenn Sie dies einmal tun und das Anwendungsprotokoll anzeigen, wird der betreffende Code angezeigt. Kopieren Sie die Abfrage und fügen Sie sie nach Bedarf ein. Hat für mich gearbeitet. Hoffe das hilft


2

Aus der offiziellen Dokumentation

Ein einfacheres und schnelleres Verfahren kann optional für einige Änderungen verwendet werden, die den Inhalt auf der Festplatte in keiner Weise beeinflussen. Das folgende einfachere Verfahren eignet sich zum Entfernen von CHECK- oder FOREIGN KEY- oder NOT NULL-Einschränkungen, zum Umbenennen von Spalten oder zum Hinzufügen oder Entfernen oder Ändern von Standardwerten für eine Spalte.

  1. Starten Sie eine Transaktion.

  2. Führen Sie PRAGMA schema_version aus, um die aktuelle Versionsnummer des Schemas zu ermitteln. Diese Nummer wird für Schritt 6 unten benötigt.

  3. Aktivieren Sie die Schema-Bearbeitung mit PRAGMA writable_schema = ON.

  4. Führen Sie eine UPDATE-Anweisung aus, um die Definition von Tabelle X in der Tabelle sqlite_master zu ändern: UPDATE sqlite_master SET sql = ... WHERE type = 'table' AND name = 'X';

    Achtung: Wenn Sie eine solche Änderung an der Tabelle sqlite_master vornehmen, wird die Datenbank beschädigt und unlesbar, wenn die Änderung einen Syntaxfehler enthält. Es wird empfohlen, die UPDATE-Anweisung sorgfältig in einer separaten leeren Datenbank zu testen, bevor sie in einer Datenbank mit wichtigen Daten verwendet wird.

  5. Wenn sich die Änderung an Tabelle X auch auf andere Tabellen oder Indizes auswirkt oder Trigger Ansichten innerhalb des Schemas sind, führen Sie UPDATE-Anweisungen aus, um auch diese anderen Tabellenindizes und -ansichten zu ändern. Wenn sich beispielsweise der Name einer Spalte ändert, müssen alle FOREIGN KEY-Einschränkungen, Trigger, Indizes und Ansichten, die auf diese Spalte verweisen, geändert werden.

    Achtung: Wenn Sie erneut Änderungen an der Tabelle sqlite_master vornehmen, wird die Datenbank beschädigt und unlesbar, wenn die Änderung einen Fehler enthält. Testen Sie diese gesamte Prozedur sorgfältig in einer separaten Testdatenbank, bevor Sie sie in einer Datenbank mit wichtigen Daten verwenden, und / oder erstellen Sie Sicherungskopien wichtiger Datenbanken, bevor Sie diese Prozedur ausführen.

  6. Erhöhen Sie die Versionsnummer des Schemas mit PRAGMA schema_version = X, wobei X eins mehr ist als die alte Versionsnummer des Schemas in Schritt 2 oben.

  7. Deaktivieren Sie die Schema-Bearbeitung mit PRAGMA writable_schema = OFF.

  8. (Optional) Führen Sie PRAGMA Integritätsprüfung aus, um sicherzustellen, dass die Schemaänderungen die Datenbank nicht beschädigt haben.

  9. Übernehmen Sie die in Schritt 1 oben gestartete Transaktion.


PRAGMA Integrity_check erkennt keine Fehler mit dem Schema.
Graymatter

und was ist das problem damit?
Mohammad Yahia

1

Eine Option, wenn Sie es zur Not erledigen müssen und wenn Ihre ursprüngliche Spalte mit einer Standardeinstellung erstellt wurde, besteht darin, die gewünschte neue Spalte zu erstellen, den Inhalt darauf zu kopieren und die alte Spalte im Grunde zu "verlassen" (sie bleibt erhalten) vorhanden, aber Sie verwenden / aktualisieren es einfach nicht usw.)

Ex:

alter table TABLE_NAME ADD COLUMN new_column_name TYPE NOT NULL DEFAULT '';
update TABLE_NAME set new_column_name = old_column_name;
update TABLE_NAME set old_column_name = ''; -- abandon old column, basically

Dies hinterlässt eine Spalte (und wenn sie mit NOT NULL, aber ohne Standard erstellt wurde, schlagen zukünftige Einfügungen, die sie ignorieren, möglicherweise fehl), aber wenn es sich nur um eine Wegwerftabelle handelt, sind die Kompromisse möglicherweise akzeptabel. Verwenden Sie andernfalls eine der anderen hier genannten Antworten oder eine andere Datenbank, in der Spalten umbenannt werden können.



-3

sqlite3 yourdb .dump> /tmp/db.txt
edit /tmp/db.txt Spaltenname in Zeile
erstellen ändern sqlite2 yourdb2 </tmp/db.txt
mv / move yourdb2 yourdb


3
Ihre Antwort liefert keine Informationen, eine Reihe von Codes / Anweisungen spucken aus, ohne zusätzliche Informationen darüber, warum Sie glauben, dass es funktionieren wird oder was passieren wird, wenn Sie es ausführen
RGLSV
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.