ALTER TABLE ADD COLUMN IF NOT EXISTS in SQLite

匿名 (未验证) 提交于 2019-12-03 02:08:02

问题:

We've recently had the need to add columns to a few of our existing SQLite database tables. This can be done with ALTER TABLE ADD COLUMN. Of course, if the table has already been altered, we want to leave it alone. Unfortunately, SQLite doesn't support an IF NOT EXISTS clause on ALTER TABLE.

Our current workaround is to execute the ALTER TABLE statement and ignore any "duplicate column name" errors, just like this Python example (but in C++).

However, our usual approach to setting up database schemas is to have a .sql script containing CREATE TABLE IF NOT EXISTS and CREATE INDEX IF NOT EXISTS statements, which can be executed using sqlite3_exec or the sqlite3 command-line tool. We can't put ALTER TABLE in these script files because if that statement fails, anything after it won't be executed.

I want to have the table definitions in one place and not split between .sql and .cpp files. Is there a way to write a workaround to ALTER TABLE ADD COLUMN IF NOT EXISTS in pure SQLite SQL?

回答1:

I have a 99% pure SQL method. The idea is to version your schema. You can do this in two ways:

  • Use the 'user_version' pragma command (PRAGMA user_version) to store an incremental number for your database schema version.

  • Store your version number in your own defined table.

In this way, when the software is started, it can check the database schema and, if needed, run your ALTER TABLE query, then increment the stored version. This is by far better than attempting various updates "blind", especially if your database grows and changes a few times over the years.



回答2:

One workaround is to just create the columns and catch the exception/error that arise if the column already exist. When adding multiple columns, add them in separate ALTER TABLE statements so that one duplicate does not prevent the others from being created.

With sqlite-net, we did something like this. It's not perfect, since we can't distinguish duplicate sqlite errors from other sqlite errors.

Dictionary<string, string> columnNameToAddColumnSql = new Dictionary<string, string> {     {         "Column1",         "ALTER TABLE MyTable ADD COLUMN Column1 INTEGER"     },     {         "Column2",         "ALTER TABLE MyTable ADD COLUMN Column2 TEXT"     } };  foreach (var pair in columnNameToAddColumnSql) {     string columnName = pair.Key;     string sql = pair.Value;      try     {         this.DB.ExecuteNonQuery(sql);     }     catch (System.Data.SQLite.SQLiteException e)     {         _log.Warn(e, string.Format("Failed to create column [{0}]. Most likely it already exists, which is fine.", columnName));     } } 


回答3:

SQLite also supports a pragma statement called "table_info" which returns one row per column in a table with the name of the column (and other information about the column). You could use this in a query to check for the missing column, and if not present alter the table.

PRAGMA table_info(foo_table_name) 

http://www.sqlite.org/pragma.html#pragma_table_info



回答4:

threre is a method of PRAGMA is table_info(table_name), it returns all the information of table.

Here is implementation how to use it for check column exists or not,

public boolean isColumnExists (String table, String column) {         Cursor cursor = db.rawQuery("PRAGMA table_info("+ table +")", null);         if (cursor != null) {             while (cursor.moveToNext()) {                 String name = cursor.getString(cursor.getColumnIndex("name"));                 if (column.equalsIgnoreCase(name)) {                     return true;                 }             }         }          return false;     } 


回答5:

If you are doing this in a DB upgrade statement, perhaps the simplest way is to just catch the exception thrown if you are attempting to add a field that may already exist.

try {    db.execSQL("ALTER TABLE " + TABLE_NAME + " ADD COLUMN foo TEXT default null"); } catch (SQLiteException ex) {    Log.w(TAG, "Altering " + TABLE_NAME + ": " + ex.getMessage()); } 


回答6:

In case you're having this problem in flex/adobe air and find yourself here first, i've found a solution, and have posted it on a related question: ADD COLUMN to sqlite db IF NOT EXISTS - flex/air sqlite?

My comment here: https://stackoverflow.com/a/24928437/2678219



易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!