ALTER TABLE添加列如果不在SQLite中存在

最近我们需要将列添加到一些现有的SQLite数据库表中。 这可以通过ALTER TABLE ADD COLUMN 。 当然,如果桌子已经被改变了,我们想要放弃它。 不幸的是,SQLite不支持ALTER TABLE上的IF NOT EXISTS子句。

我们目前的解决方法是执行ALTER TABLE语句并忽略任何“重复的列名”错误,就像这个Python例子 (但在C ++中)。

但是,我们常用的设置数据库模式的方法是使用包含CREATE TABLE IF NOT EXISTSCREATE INDEX IF NOT EXISTS语句的.sql脚本,该脚本可以使用sqlite3_execsqlite3命令行工具执行。 我们不能把ALTER TABLE放在这些脚本文件中,因为如果这个语句失败了,它后面的任何东西都不会被执行。

我想在一个地方有表格定义,而不是分割.sql和.cpp文件。 有没有办法编写一个解决方法来ALTER TABLE ADD COLUMN IF NOT EXISTS在纯SQLite SQL的ALTER TABLE ADD COLUMN IF NOT EXISTS

我有一个99%纯SQL方法。 这个想法是为你的模式版本。 你可以用两种方法来做到这一点:

  • 使用'user_version'pragma命令( PRAGMA user_version )为您的数据库模式版本存储增量编号。

  • 将您的版本号存储在您自己定义的表格中。

这样,当软件启动时,它可以检查数据库模式,如果需要,运行你的ALTER TABLE查询,然后增加存储的版本。 这远比尝试各种更新“盲目”更好,特别是如果您的数据库多年来增长和改变几次。

SQLite还支持一个名为“table_info”的pragma语句,它在表中以列的名称(以及有关列的其他信息)的每列返回一行。 你可以在查询中使用这个来检查缺less的列,如果不存在,修改表。

 PRAGMA table_info(foo_table_name) 

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

一种解决方法是只创build列并捕获列已经存在的exception/错误。 添加多个列时,将它们添加到单独的ALTER TABLE语句中,以便一个副本不会阻止创build其他列。

用sqlite-net ,我们做了这样的事情。 这并不完美,因为我们无法区分重复的sqlite错误和其他sqlite错误。

 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)); } } 

threre是PRAGMA的一个方法,是table_info(table_name),它返回表的所有信息。

这里是实现如何使用它来检查列是否存在,

 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; } 

如果您是在数据库升级语句中执行此操作,则最简单的方法可能是捕获抛出的exception,如果您试图添加可能已经存在的字段。

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

如果你在flex / adobe air中遇到这个问题,并且先find你自己,我已经find了一个解决scheme,并且把它发布到一个相关的问题上: ADD COLUMN to sqlite db IF NOT EXISTS – flex / air sqlite?

我的评论在这里: https : //stackoverflow.com/a/24928437/2678219