Sqlite veritabanına sütun silmek veya eklemek istiyorum
Sütunu silmek için aşağıdaki sorguyu kullanıyorum.
ALTER TABLE TABLENAME DROP COLUMN COLUMNNAME
Ama hata veriyor
System.Data.SQLite.SQLiteException: SQLite error
near "DROP": syntax error
Sqlite veritabanına sütun silmek veya eklemek istiyorum
Sütunu silmek için aşağıdaki sorguyu kullanıyorum.
ALTER TABLE TABLENAME DROP COLUMN COLUMNNAME
Ama hata veriyor
System.Data.SQLite.SQLiteException: SQLite error
near "DROP": syntax error
Yanıtlar:
SQLite sınırlı bir ALTER TABLE alt kümesini destekler. SQLite'deki ALTER TABLE komutu, kullanıcının bir tabloyu yeniden adlandırmasına veya var olan bir tabloya yeni bir sütun eklemesine olanak tanır. Bir sütunu yeniden adlandırmak, bir sütunu kaldırmak veya tabloya kısıtlama eklemek veya kaldırmak mümkün değildir.
Yapabilirsin:
PRAGMA foreign_keys=OFF
. Bu durumda, bu diziyi yaptıktan sonra PRAGMA foreign_keys=ON
yabancı anahtarları yeniden etkinleştirmek için aramalısınız .
RENAME COLUMN
desteklenir. L sqlite.org/releaselog/3_25_0.html
Bunu yapmak için Sqlite'ın önerilen yolunu temel alan bir Java uygulaması yazdım:
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;");
}
Tablonun sütun almak için "PRAGMA table_info" kullandım:
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;
}
Aslında blogumda yazdım, orada daha fazla açıklama görebilirsiniz:
http://udinic.wordpress.com/2012/05/09/sqlite-drop-column-support/
INSERT
ifade yapmak yerine , yeni tabloyu aşağıdakileri yaparak da oluşturabilirsiniz:"CREAT TABLE" + tableName + "AS SELECT " + columnsSeperated + " FROM " + tableName + "_old;"
Diğerlerinin işaret ettiği gibi
Bir sütunu yeniden adlandırmak, bir sütunu kaldırmak veya tabloya kısıtlama eklemek veya kaldırmak mümkün değildir.
kaynak : http://www.sqlite.org/lang_altertable.html
Her zaman yeni bir tablo oluşturabilir ve sonra eski tabloyu bırakabilirsiniz. Bu geçici çözümü bir örnekle açıklamaya çalışacağım .
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
Şimdi sütunu height
bu tablodan kaldırmak istiyorsunuz .
Adlı başka bir tablo oluştur new_person
sqlite> CREATE TABLE new_person(
...> id INTEGER PRIMARY KEY,
...> first_name TEXT,
...> last_name TEXT,
...> age INTEGER
...> ) ;
sqlite>
Şimdi verileri eski tablodan kopyalayın
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>
Şimdi Bırak person
masa ve yeniden adlandırma new_person
içinperson
sqlite> DROP TABLE IF EXISTS person ;
sqlite> ALTER TABLE new_person RENAME TO person ;
sqlite>
Yani şimdi bir .schema
yaparsan, göreceksin
sqlite>.schema
CREATE TABLE "person"(
id INTEGER PRIMARY KEY,
first_name TEXT,
last_name TEXT,
age INTEGER
);
CREATE TABLE new_person AS SELECT id, first_name, last_name, age FROM person;
http://www.sqlite.org/lang_altertable.html
Şemada da görebileceğiniz gibi, yalnızca KOLON EKLE desteklenir. Yine de (biraz ağır) bir çözüm var: http://www.sqlite.org/faq.html#q11
SQLite 3'te belirli bir sütunu bırakamayız. Bkz. SSS .
Diğerleri işaret gibi, SQLite'nın ALTER TABLE
ifadesi yok değil desteklemek DROP COLUMN
ve bunu yapmak için standart reçete kısıtlamaları ve indeksleri korumaz.
İşte tüm temel kısıtlamaları ve endeksleri korurken bunu genel olarak yapmak için bazı python kodu .
Lütfen kullanmadan önce veritabanınızı yedekleyin!Bu işlev, orijinal CREATE TABLE ifadesine dokundurmaya dayanır ve potansiyel olarak biraz güvensizdir - örneğin, bir tanımlayıcı gömülü virgül veya parantez içeriyorsa yanlış bir şey yapar.
Herkes SQL ayrıştırmak için daha iyi bir yol katkıda isterdi, bu harika olurdu!
GÜNCELLEME Açık kaynaksqlparse
paketinikullanarak ayrıştırmanın daha iyi bir yolunu buldum. Burada yayınlayacağım herhangi bir ilgi varsa, sadece bir yorum bırakın ...
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
Kod otomatik olarak tablo oluşturma sorgusu üretir böylece @Udinic cevap yeniden yazdı . Ayrıca gerek yok . Ayrıca bunu bir işlem içinde yapmak zorundadır .ConnectionSource
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();
}
}
SQLite için DB Tarayıcı sütun eklemenize veya bırakmanıza izin verir.
Ana görünümde sekmesinde Database Structuretablo adını tıklayın. Modify TableSütunu / alanı seçip kaldırabileceğiniz yeni bir pencere açan bir düğme etkinleştirilir.
User2638929 yanıtını geliştirdim ve şimdi sütun türünü, birincil anahtarı, varsayılan değeri vb.
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. Burada kullandım android.arch.persistence.db.SupportSQLiteDatabase
, ancak kullanım için kolayca değiştirebilirsinizandroid.database.sqlite.SQLiteDatabase
Sütun adlarını değiştirmek için SQlite Yöneticisi'ni kullanabilirsiniz. Tablo adına sağ tıklayın ve Tabloyu Düzenle'yi seçin. Burada tablo yapısını bulacaksınız ve kolayca yeniden adlandırabilirsiniz.
SQLite, ALTER TABLE için sınırlı desteğe sahip olduğundan, yalnızca tablonun sonuna sütun ekleyebilir VEYA SQLite'de TABLE_NAME DEĞİŞTİRİN.
İşte SQLITE'DAN KOLON NASIL SİLME En İyi Cevap?
SQLite tablosundan sütun silme sayfasını ziyaret edin
Alternatif olarak:
Şema içeren bir tablonuz varsa
CREATE TABLE person(
id INTEGER PRIMARY KEY,
first_name TEXT,
last_name TEXT,
age INTEGER,
height INTEGER
);
CREATE TABLE...AS
gibi bir ifade kullanabilirsiniz CREATE TABLE person2 AS SELECT id, first_name, last_name, age FROM person;
, yani istemediğiniz sütunları dışarıda bırakın. Ardından orijinal person
tabloyu bırakın ve yenisini yeniden adlandırın.
Bu yöntem bir tablo hiçbir PRIMARY KEY ve hiçbir kısıtlamaları üretir unutmayın. Bunları korumak için, yeni bir tablo oluşturmak için başkalarının açıkladığı yöntemleri kullanın veya geçici bir tabloyu ara olarak kullanın .
Farklı bir soruya verilen bu yanıt bir sütunu değiştirmeye yöneliktir , ancak çok sayıda sütununuz varsa ve INSERT ifadeniz için çoğunu elle yeniden yazmak istemiyorsanız, cevabın bir bölümünün de yararlı bir yaklaşım sağlayabileceğine inanıyorum:
https://stackoverflow.com/a/10385666
Veritabanınızı yukarıdaki bağlantıda açıklandığı gibi dökebilir, ardından "döküm oluştur" ifadesini ve bu dökümden "ekle" şablonunu alabilir, ardından SQLite SSS girişindeki "Mevcut bir sütunu nasıl ekleyebilir veya silebilirim?" SQLite tablosunda. " (SSS bu sayfanın başka bir yerine bağlanmıştır.)
Http://www.sqlite.org/faq.html#q11 adresindekiPython
bilgilere dayalı olarak uygulama .
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)
Bu komut dosyası önce rasgele geçici tablo oluşturur ve bırakılacaklar dışında yalnızca gerekli sütunların verilerini ekler. Daha sonra geçici tabloyu temel alarak özgün tabloyu geri yükler ve geçici tabloyu bırakır.
Benim çözümüm, sadece bu yöntemi çağırmak gerekiyor.
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;");
}
Ve sütunları almak için yardımcı yöntem:
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;
}
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+";");
}
}
}
}
ve sadece bir yöntem çağırın
DeleteColFromTable("Database name","Table name","Col name which want to delete");
Artık sütunları işlemek için SQLite için DB tarayıcıyı da kullanabilirsiniz
sütun eklemek için örnek: -
alter table student add column TOB time;
Burada öğrenci olduğunu tablo_ismi ve TOB olan sütun_ismi eklenecek.
Çalışıyor ve test ediliyor.