আমি স্ক্লাইট ডাটাবেসে কলাম মুছতে বা যুক্ত করতে চাই
আমি কলামটি মুছতে নিম্নলিখিত প্রশ্নগুলি ব্যবহার করছি।
ALTER TABLE TABLENAME DROP COLUMN COLUMNNAME
কিন্তু এটি ত্রুটি দেয়
System.Data.SQLite.SQLiteException: SQLite error
near "DROP": syntax error
আমি স্ক্লাইট ডাটাবেসে কলাম মুছতে বা যুক্ত করতে চাই
আমি কলামটি মুছতে নিম্নলিখিত প্রশ্নগুলি ব্যবহার করছি।
ALTER TABLE TABLENAME DROP COLUMN COLUMNNAME
কিন্তু এটি ত্রুটি দেয়
System.Data.SQLite.SQLiteException: SQLite error
near "DROP": syntax error
উত্তর:
টেবিল এসকিউএলাইট পরিবর্তন করুন
SQLite ALTER TABLE এর একটি সীমিত উপসেট সমর্থন করে। এসকিউএলাইটে ALTER TABLE কমান্ড ব্যবহারকারীকে একটি সারণির নাম পরিবর্তন করতে বা বিদ্যমান সারণীতে একটি নতুন কলাম যুক্ত করতে দেয়। কোনও কলামের নাম পরিবর্তন করা, কোনও কলাম সরিয়ে ফেলা বা সারণী থেকে সীমাবদ্ধতা যুক্ত করা বা সরিয়ে ফেলা সম্ভব নয়।
আপনি পারেন:
PRAGMA foreign_keys=OFF। এই ক্ষেত্রে, এই সিকোয়েন্সটি PRAGMA foreign_keys=ONকরার পরে বিদেশী কীগুলি পুনরায় সক্ষম করার জন্য অবশ্যই অবশ্যই কল করতে হবে ।
RENAME COLUMNসমর্থিত। 🎉 sqlite.org/releaselog/3_25_0.html
স্ক্লাইটের এটি করার প্রস্তাবিত পদ্ধতির উপর ভিত্তি করে আমি একটি জাভা প্রয়োগ লিখেছি:
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;");
}
টেবিলের কলামটি পেতে, আমি "PRAGMA টেবিল_ইনফো" ব্যবহার করেছি:
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;
}
আমি আমার ব্লগে এটি সম্পর্কে লিখেছিলাম, আপনি সেখানে আরও ব্যাখ্যা দেখতে পারেন:
http://udinic.wordpress.com/2012/05/09/sqlite-drop-column-support/
INSERTবিবৃতি দেওয়ার পরিবর্তে , আপনি একটি করেও নতুন টেবিলটি তৈরি করতে পারেন"CREAT TABLE" + tableName + "AS SELECT " + columnsSeperated + " FROM " + tableName + "_old;"
অন্যরা যেমন উল্লেখ করেছে
কোনও কলামের নাম পরিবর্তন করা, কোনও কলাম সরিয়ে ফেলা বা সারণী থেকে সীমাবদ্ধতা যুক্ত করা বা সরিয়ে ফেলা সম্ভব নয়।
উত্স: http://www.sqlite.org/lang_altertable.html
আপনি সর্বদা একটি নতুন টেবিল তৈরি করতে পারেন এবং তারপরে পুরানোটিকে ড্রপ করতে পারেন। আমি এই উদাহরণটি একটি উদাহরণ দিয়ে ব্যাখ্যা করার চেষ্টা করব ।
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
এখন আপনি heightএই টেবিল থেকে কলামটি সরাতে চান ।
নামক আরেকটি টেবিল তৈরি করুন new_person
sqlite> CREATE TABLE new_person(
...> id INTEGER PRIMARY KEY,
...> first_name TEXT,
...> last_name TEXT,
...> age INTEGER
...> ) ;
sqlite>
এখন পুরানো টেবিল থেকে তথ্য অনুলিপি করুন
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>
এখন personটেবিলটি ফেলে দিন এবং নাম পরিবর্তন new_personকরুনperson
sqlite> DROP TABLE IF EXISTS person ;
sqlite> ALTER TABLE new_person RENAME TO person ;
sqlite>
সুতরাং এখন আপনি যদি একটি করেন .schema, আপনি দেখতে পাবেন
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
আপনি যেমন চিত্রটিতে দেখতে পাচ্ছেন, কেবল ADOL COLUMN সমর্থিত। এখানে একটি (ভারী ভারী) কাজ রয়েছে, যদিও: http://www.sqlite.org/faq.html#q11
আমরা এসকিউএলাইট 3 এ একটি নির্দিষ্ট কলামটি ফেলে দিতে পারি না the এফএকিউ দেখুন ।
অন্যরা যেমন উল্লেখ করেছে, স্ক্লাইটের ALTER TABLEবক্তব্য সমর্থন করে নাDROP COLUMN এবং এটি করার মানক রেসিপি বাধা ও সূচকগুলি সংরক্ষণ করে না।
সমস্ত মূল সীমাবদ্ধতা এবং সূচকগুলি বজায় রেখে সাধারণভাবে এটি করার জন্য এখানে অজগর কোডের কিছু রয়েছে ।
দয়া করে ব্যবহার করার আগে আপনার ডাটাবেসটিকে ব্যাক-আপ করুন! এই ফাংশনটি মূল ক্রেটিট টেবিল স্টেটমেন্টের চিকিত্সা করার উপর নির্ভর করে এবং সম্ভবত কিছুটা অনিরাপদ - উদাহরণস্বরূপ যদি কোনও সনাক্তকারীতে এম্বেড করা কমা বা প্রথম বন্ধনী থাকে তবে এটি ভুল কাজ করবে।
যদি কেউ এসকিউএলকে বিশ্লেষণ করার জন্য আরও ভাল উপায়ে অবদান রাখার চিন্তা করে তবে তা দুর্দান্ত হবে!
আপডেট আমি ওপেন-সোর্সsqlparseপ্যাকেজব্যবহার করে পার্স করার আরও ভাল উপায় খুঁজে পেয়েছি। যদি কোনও আগ্রহ থাকে তবে আমি এটি এখানে পোস্ট করব, কেবল এটির জন্য জিজ্ঞাসা করুন একটি মন্তব্য ...
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
আমি @ ইউদিনিক উত্তরটি পুনরায় লিখেছিলাম যাতে কোডটি স্বয়ংক্রিয়ভাবে টেবিল তৈরির ক্যোয়ারী উত্পন্ন করে । এটিরও দরকার নেই 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();
}
}
এসকিউএলাইটের জন্য ডিবি ব্রাউজার আপনাকে কলাম যুক্ত করতে বা ছাড়ার অনুমতি দেয়।
মূল দৃশ্যে, ট্যাবে Database Structure, টেবিলের নামটিতে ক্লিক করুন। একটি বোতাম Modify Tableসক্ষম হয়ে যায়, যা একটি নতুন উইন্ডো খুলবে যেখানে আপনি কলাম / ক্ষেত্রটি নির্বাচন করতে এবং এটিকে সরাতে পারবেন।
কলামের নাম পরিবর্তন করার জন্য আপনি SQlite প্রশাসক ব্যবহার করতে পারেন। টেবিলের নামটিতে ডান ক্লিক করুন এবং সম্পাদনা সারণী নির্বাচন করুন re এখানে আপনি টেবিলের কাঠামোটি পাবেন এবং আপনি সহজেই এর নাম পরিবর্তন করতে পারেন।
যেহেতু এসকিউএলাইটের টেবিলের সীমাবদ্ধ সমর্থন রয়েছে তাই আপনি কেবলমাত্র টেবিলের শেষে কলাম যুক্ত করতে পারেন বা এসকিউএলাইটে ট্যাবলেট পরিবর্তন করতে পারেন।
এসকিউএলটি থেকে কলম কীভাবে মুছে ফেলা যায় তার সেরা উত্তর এখানে?
পরিদর্শন SQLite টেবিল থেকে মুছে ফেলুন কলাম
বিকল্প হিসাবে:
আপনার যদি স্কিমা সহ একটি টেবিল থাকে
CREATE TABLE person(
id INTEGER PRIMARY KEY,
first_name TEXT,
last_name TEXT,
age INTEGER,
height INTEGER
);
আপনি CREATE TABLE...ASযেমন একটি বিবৃতি ব্যবহার করতে পারেন CREATE TABLE person2 AS SELECT id, first_name, last_name, age FROM person;, যেমন আপনি চান না কলামগুলি ছেড়ে দিন। তারপরে মূল personটেবিলটি ফেলে দিন এবং নতুনটির নাম পরিবর্তন করুন।
নোট করুন যে এই পদ্ধতির উত্পাদন করে একটি টেবিলের কোনও প্রাথমিক কী নেই এবং কোনও বাধা নেই। এগুলি সংরক্ষণ করার জন্য, অন্যরা একটি নতুন টেবিল তৈরি করার জন্য বর্ণিত পদ্ধতিগুলি ব্যবহার করুন বা একটি মধ্যবর্তী হিসাবে অস্থায়ী টেবিলটি ব্যবহার করুন ।
ভিন্ন প্রশ্নের এই উত্তরটি একটি কলামকে সংশোধন করার দিকে লক্ষ্যযুক্ত , তবে আমি বিশ্বাস করি যে আপনার কাছে প্রচুর কলাম রয়েছে এবং আপনার INSERT বিবৃতিটি হাতে না নিয়ে সেগুলির বেশিরভাগটি পুনরায় টাইপ করতে না চাইলে উত্তরের একটি অংশ একটি কার্যকর দৃষ্টিভঙ্গিও পেতে পারে:
https://stackoverflow.com/a/10385666
উপরের লিঙ্কটিতে বর্ণিত হিসাবে আপনি আপনার ডাটাবেসটি ডাম্প করতে পারেন, তারপরে সেই ডাম্প থেকে "টেবিল তৈরি করুন" বিবরণ এবং একটি "সন্নিবেশ" টেমপ্লেটটি ধরে ফেলুন, তারপরে এসকিউএলএফএইএকিউ এন্ট্রি-র নির্দেশাবলী অনুসরণ করুন "আমি কীভাবে বিদ্যমান থেকে কলাম যুক্ত করব বা মুছব? এসকিউএলাইটে টেবিল। (FAQ এই পৃষ্ঠার অন্য কোথাও লিঙ্কযুক্ত।)
Http://www.sqlite.org/faq.html#q11Python এ তথ্যের ভিত্তিতে বাস্তবায়ন ।
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)
এই স্ক্রিপ্টটি প্রথমে এলোমেলো অস্থায়ী টেবিল তৈরি করে এবং বাদ দেওয়া হবে কেবলমাত্র প্রয়োজনীয় কলামগুলির ডেটা .োকায়। তারপরে অস্থায়ী টেবিলের উপর ভিত্তি করে মূল টেবিলটি পুনরুদ্ধার করে এবং অস্থায়ী টেবিলটি ড্রপ করে।
আমার সমাধান, কেবল এই পদ্ধতিটি কল করা দরকার।
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;");
}
এবং কলামগুলি পেতে সহায়তার পদ্ধতি:
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;
}
আমি ব্যবহারকারীর 2638929 উত্তরটি উন্নত করেছি এবং এখন এটি কলামের ধরণ, প্রাথমিক কী, ডিফল্ট মান ইত্যাদি সংরক্ষণ করতে পারে
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();
}
}
পুনশ্চ. আমি এখানে ব্যবহার করেছি android.arch.persistence.db.SupportSQLiteDatabase, তবে আপনি সহজেই ব্যবহারের জন্য এটি পরিবর্তন করতে পারেনandroid.database.sqlite.SQLiteDatabase
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+";");
}
}
}
}
এবং শুধু একটি পদ্ধতি কল
DeleteColFromTable("Database name","Table name","Col name which want to delete");
কলামগুলি ম্যানিপুলেট করতে আপনি এখন এসকিউএলাইটের জন্য ডিবি ব্রাউজারও ব্যবহার করতে পারেন
কলাম যুক্ত করার উদাহরণ: -
alter table student add column TOB time;
এখানে ছাত্র হয় TABLE_NAME এবং Tob হয় COLUMN_NAME যোগ করা।
এটি কাজ করছে এবং পরীক্ষিত হচ্ছে।