it-swarm.com.de

Wie lösche ich eine Spalte in SQLITE?

Ich möchte eine Spalte in der SQLite-Datenbank löschen oder hinzufügen

Ich verwende folgende Abfrage zum Löschen der Spalte.

ALTER TABLE TABLENAME DROP COLUMN COLUMNNAME

Aber es gibt Fehler 

System.Data.SQLite.SQLiteException: SQLite error
near "DROP": syntax error
201
Sandip

ALTER TABLE SQLite

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 aus einer Tabelle hinzuzufügen oder zu entfernen.

Sie können:

  1. erstellen Sie eine neue Tabelle als die, die Sie ändern möchten.
  2. kopiere alle Daten,
  3. alte Tabelle fallen lassen,
  4. das neue umbenennen.
307
Michał Powaga

Ich habe eine Java-Implementierung geschrieben, die auf der von Sqlite empfohlenen Vorgehensweise basiert:

private void dropColumn(SQLiteDatabase db,
        ConnectionSource connectionSource,
        String createTableCmd,
        String tableName,
        String[] colsToRemove) throws Java.sql.SQLException {

    List<String> updatedTableColumns = getTableColumns(tableName);
    // Remove the columns we don't want anymore from the table's list of columns
    updatedTableColumns.removeAll(Arrays.asList(colsToRemove));

    String columnsSeperated = TextUtils.join(",", updatedTableColumns);

    db.execSQL("ALTER TABLE " + tableName + " RENAME TO " + tableName + "_old;");

    // Creating the table on its new format (no redundant columns)
    db.execSQL(createTableCmd);

    // Populating the table with the data
    db.execSQL("INSERT INTO " + tableName + "(" + columnsSeperated + ") SELECT "
            + columnsSeperated + " FROM " + tableName + "_old;");
    db.execSQL("DROP TABLE " + tableName + "_old;");
}

Um die Tabellenspalte zu erhalten, habe ich die "PRAGMA table_info" verwendet:

public List<String> getTableColumns(String tableName) {
    ArrayList<String> columns = new ArrayList<String>();
    String cmd = "pragma table_info(" + tableName + ");";
    Cursor cur = getDB().rawQuery(cmd, null);

    while (cur.moveToNext()) {
        columns.add(cur.getString(cur.getColumnIndex("name")));
    }
    cur.close();

    return columns;
}

Ich habe tatsächlich in meinem Blog darüber geschrieben, Sie können dort weitere Erklärungen sehen:

http://udinic.wordpress.com/2012/05/09/sqlite-drop-column-support/

42
Udinic

Wie andere darauf hingewiesen haben 

Es ist nicht möglich, eine Spalte umzubenennen, eine Spalte zu entfernen oder oder .__ hinzuzufügen. entfernen Sie Einschränkungen aus einer Tabelle.

quelle: http://www.sqlite.org/lang_altertable.html

Sie können zwar immer eine neue Tabelle erstellen und dann die ältere Tabelle löschen. Ich werde versuchen, diese Problemumgehung anhand eines Beispiels zu erklären.

sqlite> .schema
CREATE TABLE person(
 id INTEGER PRIMARY KEY, 
 first_name TEXT,
 last_name TEXT, 
 age INTEGER, 
 height INTEGER
);
sqlite> select * from person ; 
id          first_name  last_name   age         height    
----------  ----------  ----------  ----------  ----------
0           john        doe         20          170       
1           foo         bar         25          171       

Nun möchten Sie die Spalte height aus dieser Tabelle entfernen.

Erstellen Sie eine weitere Tabelle mit dem Namen new_person 

sqlite> CREATE TABLE new_person(
   ...>  id INTEGER PRIMARY KEY, 
   ...>  first_name TEXT, 
   ...>  last_name TEXT, 
   ...>  age INTEGER 
   ...> ) ; 
sqlite> 

Kopieren Sie nun die Daten aus der alten Tabelle 

sqlite> INSERT INTO new_person
   ...> SELECT id, first_name, last_name, age FROM person ;
sqlite> select * from new_person ;
id          first_name  last_name   age       
----------  ----------  ----------  ----------
0           john        doe         20        
1           foo         bar         25        
sqlite>

Löschen Sie nun die person-Tabelle und benennen Sie new_person in person um.

sqlite> DROP TABLE IF EXISTS person ; 
sqlite> ALTER TABLE new_person RENAME TO person ;
sqlite>

Wenn Sie also einen .schema ausführen, werden Sie sehen

sqlite>.schema
CREATE TABLE "person"(
 id INTEGER PRIMARY KEY, 
 first_name TEXT, 
 last_name TEXT, 
 age INTEGER 
);
16
Tasdik Rahman

http://www.sqlite.org/lang_altertable.html

Wie Sie im Diagramm sehen können, wird nur ADD COLUMN unterstützt. Es gibt jedoch eine (ziemlich schwere) Problemumgehung: http://www.sqlite.org/faq.html#q11

12
LeleDumbo

Wir können eine bestimmte Spalte in SQLite 3 nicht löschen. Siehe FAQ .

Ich habe die @Udinic-Antwort neu geschrieben, damit der Code die Tabellenerstellungsabfrage automatisch generiert. Es braucht auch keine ConnectionSource. Es muss dies auch innerhalb einer transaction tun.

public static String getOneTableDbSchema(SQLiteDatabase db, String tableName) {
    Cursor c = db.rawQuery(
            "SELECT * FROM `sqlite_master` WHERE `type` = 'table' AND `name` = '" + tableName + "'", null);
    String result = null;
    if (c.moveToFirst()) {
        result = c.getString(c.getColumnIndex("sql"));
    }
    c.close();
    return result;
}

public List<String> getTableColumns(SQLiteDatabase db, String tableName) {
    ArrayList<String> columns = new ArrayList<>();
    String cmd = "pragma table_info(" + tableName + ");";
    Cursor cur = db.rawQuery(cmd, null);

    while (cur.moveToNext()) {
        columns.add(cur.getString(cur.getColumnIndex("name")));
    }
    cur.close();

    return columns;
}

private void dropColumn(SQLiteDatabase db, String tableName, String[] columnsToRemove) {
    db.beginTransaction();
    try {
        List<String> columnNamesWithoutRemovedOnes = getTableColumns(db, tableName);
        // Remove the columns we don't want anymore from the table's list of columns
        columnNamesWithoutRemovedOnes.removeAll(Arrays.asList(columnsToRemove));

        String newColumnNamesSeparated = TextUtils.join(" , ", columnNamesWithoutRemovedOnes);
        String sql = getOneTableDbSchema(db, tableName);
        // Extract the SQL query that contains only columns
        String oldColumnsSql = sql.substring(sql.indexOf("(")+1, sql.lastIndexOf(")"));

        db.execSQL("ALTER TABLE " + tableName + " RENAME TO " + tableName + "_old;");
        db.execSQL("CREATE TABLE `" + tableName + "` (" + getSqlWithoutRemovedColumns(oldColumnsSql, columnsToRemove)+ ");");
        db.execSQL("INSERT INTO " + tableName + "(" + newColumnNamesSeparated + ") SELECT " + newColumnNamesSeparated + " FROM " + tableName + "_old;");
        db.execSQL("DROP TABLE " + tableName + "_old;");
        db.setTransactionSuccessful();
    } catch {
        //Error in between database transaction 
    } finally {
        db.endTransaction();
    }


}
4
soshial

Wie andere darauf hingewiesen haben, unterstützt die ALTER TABLE-Anweisung von sqlite nichtDROP COLUMN, und das Standardrezept dafür führt nicht zu Einschränkungen und Indizes.

Hier ist ein Python-Code, um dies generisch zu tun, während erhaltendalle Schlüsseleinschränkungen und -indizes enthält. 

Bitte sichern Sie Ihre Datenbank vor der Verwendung! Diese Funktion basiert auf dem Doktorat der ursprünglichen CREATE TABLE-Anweisung und ist möglicherweise ein bisschen unsicher - zum Beispiel wird die falsche Aktion ausgeführt, wenn ein Bezeichner ein eingebettetes Komma oder eine Klammer enthält.

Wenn sich jemand dafür interessieren würde, die SQL besser zu analysieren, wäre das großartig!

UPDATEIch habe einen besseren Weg gefunden, mit dem Open-Source-Paket sqlparse zu parsen. Wenn Interesse besteht, werde ich es hier posten. Hinterlasse einfach einen Kommentar und frage danach ...

import re
import random

def DROP_COLUMN(db, table, column):
    columns = [ c[1] for c in db.execute("PRAGMA table_info(%s)" % table) ]
    columns = [ c for c in columns if c != column ]
    sql = db.execute("SELECT sql from sqlite_master where name = '%s'" 
        % table).fetchone()[0]
    sql = format(sql)
    lines = sql.splitlines()
    findcol = r'\b%s\b' % column
    keeplines = [ line for line in lines if not re.search(findcol, line) ]
    create = '\n'.join(keeplines)
    create = re.sub(r',(\s*\))', r'\1', create)
    temp = 'tmp%d' % random.randint(1e8, 1e9)
    db.execute("ALTER TABLE %(old)s RENAME TO %(new)s" % { 
        'old': table, 'new': temp })
    db.execute(create)
    db.execute("""
        INSERT INTO %(new)s ( %(columns)s ) 
        SELECT %(columns)s FROM %(old)s
    """ % { 
        'old': temp,
        'new': table,
        'columns': ', '.join(columns)
    })  
    db.execute("DROP TABLE %s" % temp)

def format(sql):
    sql = sql.replace(",", ",\n")
    sql = sql.replace("(", "(\n")
    sql = sql.replace(")", "\n)")
    return sql
3
spam_eggs

Implementierung in Python basierend auf Informationen unter http://www.sqlite.org/faq.html#q11 .

import sqlite3 as db
import random
import string

QUERY_TEMPLATE_GET_COLUMNS = "PRAGMA table_info(@table_name)"
QUERY_TEMPLATE_DROP_COLUMN = """
  BEGIN TRANSACTION;
  CREATE TEMPORARY TABLE @tmp_table(@columns_to_keep);
  INSERT INTO @tmp_table SELECT @columns_to_keep FROM @table_name;
  DROP TABLE @table_name;
  CREATE TABLE @table_name(@columns_to_keep);
  INSERT INTO @table_name SELECT @columns_to_keep FROM @tmp_table;
  DROP TABLE @tmp_table;
  COMMIT;
"""

def drop_column(db_file, table_name, column_name):
    con = db.connect(db_file)
    QUERY_GET_COLUMNS = QUERY_TEMPLATE_GET_COLUMNS.replace("@table_name", table_name)
    query_res = con.execute(QUERY_GET_COLUMNS).fetchall()
    columns_list_to_keep = [i[1] for i in query_res if i[1] != column_name]
    columns_to_keep = ",".join(columns_list_to_keep)
    tmp_table = "tmp_%s" % "".join(random.sample(string.ascii_lowercase, 10))
    QUERY_DROP_COLUMN = QUERY_TEMPLATE_DROP_COLUMN.replace("@table_name", table_name)\
        .replace("@tmp_table", tmp_table).replace("@columns_to_keep", columns_to_keep)
    con.executescript(QUERY_DROP_COLUMN)
    con.close()

drop_column(DB_FILE, TABLE_NAME, COLUMN_NAME)

Dieses Skript erstellt zuerst eine zufällige temporäre Tabelle und fügt Daten nur der erforderlichen Spalten außer derjenigen ein, die gelöscht wird. Stellt dann die ursprüngliche Tabelle basierend auf der temporären Tabelle wieder her und löscht die temporäre Tabelle.

1
Akif

Ich denke, was Sie tun möchten, ist die Datenbankmigration. Das Löschen einer Spalte ist in SQLite nicht vorhanden. Sie können jedoch mithilfe der ALTER-Tabellenabfrage eine zusätzliche Spalte hinzufügen.

1
Subha_26

Da SQLite die Unterstützung für ALTER TABLE begrenzt hat, können Sie in SQLite nur die Spalte am Ende der Tabelle OR CHANGE TABLE_NAME hinzufügen.

Hier ist die beste Antwort, WIE SPALTE VON SQLITE LÖSCHEN?

visit Spalte aus der SQLite-Tabelle löschen

1
Gaurav Singla

DB Browser für SQLite ermöglicht das Hinzufügen oder Löschen von Spalten.

1
rams

sie können Sqlitebrowser verwenden. Im Browsermodus kann für die jeweilige Datenbank und die Tabelle unter der Registerkarte "Datenbankstruktur" nach der Option Tabelle ändern die entsprechende Spalte entfernt werden.

0
iamigham

Diese Antwort auf eine andere Frage bezieht sich auf das Ändern einer Spalte, aber ich glaube, ein Teil der Antwort könnte auch einen nützlichen Ansatz ergeben, wenn Sie viele Spalten haben und die meisten von ihnen nicht manuell neu eingeben möchten Ihre INSERT-Anweisung: 

https://stackoverflow.com/a/10385666

Sie können Ihre Datenbank wie im obigen Link beschrieben sichern, dann die Anweisung "create table" und eine Vorlage "insert" aus diesem Speicherauszug entnehmen und dann den Anweisungen im SQLite FAQ -Eintrag folgen Spalten aus einer vorhandenen Tabelle in SQLite. " (FAQ ist an anderer Stelle auf dieser Seite verlinkt.)

0
burpgrass

Sie können den SQlite-Administrator verwenden, um die Spaltennamen zu ändern. Klicken Sie mit der rechten Maustaste auf den Tabellennamen und wählen Sie Tabelle bearbeiten aus. Hier finden Sie die Tabellenstruktur, die Sie leicht umbenennen können.

0
Tushar Baxi
public void DeleteColFromTable(String DbName, String TableName, String ColName){
    SQLiteDatabase db = openOrCreateDatabase(""+DbName+"", Context.MODE_PRIVATE, null);
    db.execSQL("CREATE TABLE IF NOT EXISTS "+TableName+"(1x00dff);");
    Cursor c = db.rawQuery("PRAGMA table_info("+TableName+")", null);
    if (c.getCount() == 0) {

    } else {
        String columns1 = "";
        String columns2 = "";
        while (c.moveToNext()) {
            if (c.getString(1).equals(ColName)) {
            } else {
                columns1 = columns1 + ", " + c.getString(1) + " " + c.getString(2);
                columns2 = columns2 + ", " + c.getString(1);
            }
            if (c.isLast()) {
                db.execSQL("CREATE TABLE IF NOT EXISTS DataBackup (" + columns1 + ");");
                db.execSQL("INSERT INTO DataBackup SELECT " + columns2 + " FROM "+TableName+";");
                db.execSQL("DROP TABLE "+TableName+"");
                db.execSQL("ALTER TABLE DataBackup RENAME TO "+TableName+";");
            }
        }
    }
}

und rufen Sie einfach eine Methode an

DeleteColFromTable("Database name","Table name","Col name which want to delete");
0
Sagar Makhija

Ich habe user2638929 verbessert und kann jetzt den Spaltentyp, den Primärschlüssel, den Standardwert usw. beibehalten. 

private static void dropColumn(SupportSQLiteDatabase database, String tableName, List<String> columnsToRemove){
    List<String> columnNames = new ArrayList<>();
    List<String> columnNamesWithType = new ArrayList<>();
    List<String> primaryKeys = new ArrayList<>();
    String query = "pragma table_info(" + tableName + ");";
    Cursor cursor = database.query(query);
    while (cursor.moveToNext()){
        String columnName = cursor.getString(cursor.getColumnIndex("name"));

        if (columnsToRemove.contains(columnName)){
            continue;
        }

        String columnType = cursor.getString(cursor.getColumnIndex("type"));
        boolean isNotNull = cursor.getInt(cursor.getColumnIndex("notnull")) == 1;
        boolean isPk = cursor.getInt(cursor.getColumnIndex("pk")) == 1;

        columnNames.add(columnName);
        String tmp = "`" + columnName + "` " + columnType + " ";
        if (isNotNull){
            tmp += " NOT NULL ";
        }

        int defaultValueType = cursor.getType(cursor.getColumnIndex("dflt_value"));
        if (defaultValueType == Cursor.FIELD_TYPE_STRING){
            tmp += " DEFAULT " + "\"" + cursor.getString(cursor.getColumnIndex("dflt_value")) + "\" ";
        }else if(defaultValueType == Cursor.FIELD_TYPE_INTEGER){
            tmp += " DEFAULT " + cursor.getInt(cursor.getColumnIndex("dflt_value")) + " ";
        }else if (defaultValueType == Cursor.FIELD_TYPE_FLOAT){
            tmp += " DEFAULT " + cursor.getFloat(cursor.getColumnIndex("dflt_value")) + " ";
        }
        columnNamesWithType.add(tmp);
        if (isPk){
            primaryKeys.add("`" + columnName + "`");
        }
    }
    cursor.close();

    String columnNamesSeparated = TextUtils.join(", ", columnNames);
    if (primaryKeys.size() > 0){
        columnNamesWithType.add("PRIMARY KEY("+ TextUtils.join(", ", primaryKeys) +")");
    }
    String columnNamesWithTypeSeparated = TextUtils.join(", ", columnNamesWithType);

    database.beginTransaction();
    try {
        database.execSQL("ALTER TABLE " + tableName + " RENAME TO " + tableName + "_old;");
        database.execSQL("CREATE TABLE " + tableName + " (" + columnNamesWithTypeSeparated + ");");
        database.execSQL("INSERT INTO " + tableName + " (" + columnNamesSeparated + ") SELECT "
                + columnNamesSeparated + " FROM " + tableName + "_old;");
        database.execSQL("DROP TABLE " + tableName + "_old;");
        database.setTransactionSuccessful();
    }finally {
        database.endTransaction();
    }
}

PS. Ich habe hier Android.Arch.persistence.db.SupportSQLiteDatabase verwendet, aber Sie können ihn leicht für die Verwendung Android.database.sqlite.SQLiteDatabase ändern.

0

Meine Lösung muss nur diese Methode aufrufen.

public static void dropColumn(SQLiteDatabase db, String tableName, String[] columnsToRemove) throws Java.sql.SQLException {
    List<String> updatedTableColumns = getTableColumns(db, tableName);
    updatedTableColumns.removeAll(Arrays.asList(columnsToRemove));
    String columnsSeperated = TextUtils.join(",", updatedTableColumns);

    db.execSQL("ALTER TABLE " + tableName + " RENAME TO " + tableName + "_old;");
    db.execSQL("CREATE TABLE " + tableName + " (" + columnsSeperated + ");");
    db.execSQL("INSERT INTO " + tableName + "(" + columnsSeperated + ") SELECT "
            + columnsSeperated + " FROM " + tableName + "_old;");
    db.execSQL("DROP TABLE " + tableName + "_old;");
}

Und Hilfsmethode, um die Spalten zu erhalten:

public static List<String> getTableColumns(SQLiteDatabase db, String tableName) {
    ArrayList<String> columns = new ArrayList<>();
    String cmd = "pragma table_info(" + tableName + ");";
    Cursor cur = db.rawQuery(cmd, null);

    while (cur.moveToNext()) {
        columns.add(cur.getString(cur.getColumnIndex("name")));
    }
    cur.close();

    return columns;
}
0
user2638929

Als Alternative:

Wenn Sie eine Tabelle mit Schema haben

CREATE TABLE person(
  id INTEGER PRIMARY KEY,
  first_name TEXT,
  last_name TEXT,
  age INTEGER,
  height INTEGER
);

sie können eine CREATE TABLE...AS-Anweisung wie CREATE TABLE person2 AS SELECT id, first_name, last_name, age FROM person; verwenden, d. h. die Spalten, die Sie nicht möchten, weglassen. Dann lassen Sie die ursprüngliche person-Tabelle fallen und benennen Sie die neue um.

Beachten Sie, dass diese Methode dazu führt, dass eine Tabelle keinen PRIMARY KEY und keine Einschränkungen hat. Um diese zu erhalten, verwenden Sie die beschriebenen Methoden, um eine neue Tabelle zu erstellen, oder verwenden Sie eine temporäre Tabelle als Zwischenstufe.

0
karkarlawawa

beispiel zum Hinzufügen einer Spalte: -

alter table student add column TOB time;

hier student ist table_name undTOBist spaltenname, der hinzugefügt werden soll.

Es funktioniert und getestet.

0