dan*_*n04 77 sqlite alter-table
我们最近需要在一些现有的SQLite数据库表中添加列.这可以通过以下方式完成ALTER TABLE ADD COLUMN.当然,如果表已被更改,我们希望不管它.不幸的是,SQLite不支持一个IF NOT EXISTS子句ALTER TABLE.
我们当前的解决方法是执行ALTER TABLE语句并忽略任何"重复列名"错误,就像这个Python示例(但在C++中).
然而,我们通常的做法来建立数据库模式是有含.SQL脚本CREATE TABLE IF NOT EXISTS和CREATE INDEX IF NOT EXISTS语句,可以使用执行sqlite3_exec或sqlite3命令行工具.我们不能放入ALTER TABLE这些脚本文件,因为如果该语句失败,它之后的任何内容都不会被执行.
我希望将表定义放在一个地方,而不是在.sql和.cpp文件之间进行拆分.有没有办法ALTER TABLE ADD COLUMN IF NOT EXISTS在纯SQLite SQL中编写变通方法?
MPe*_*ier 55
我有一个99%的纯SQL方法.我们的想法是对架构进行版本控制.您可以通过两种方式执行此操作:
使用'user_version'pragma命令(PRAGMA user_version)存储数据库模式版本的增量编号.
将您的版本号存储在您自己定义的表中.
通过这种方式,当软件启动时,它可以检查数据库模式,并在需要时运行ALTER TABLE查询,然后增加存储的版本.这比尝试各种更新"盲目"要好得多,特别是如果您的数据库增长并且多年来改变了几次.
ang*_*sen 29
一种解决方法是仅创建列并捕获列已存在时出现的异常/错误.添加多个列时,请将它们添加到单独的ALTER TABLE语句中,以便一个副本不会阻止创建其他列.
使用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));
}
}
Run Code Online (Sandbox Code Playgroud)
Rob*_*key 26
SQLite还支持名为"table_info"的pragma语句,该语句在表中每列返回一行,其中包含列的名称(以及有关该列的其他信息).您可以在查询中使用它来检查缺少的列,如果不存在则更改表.
PRAGMA table_info(foo_table_name)
Run Code Online (Sandbox Code Playgroud)
http://www.sqlite.org/pragma.html#pragma_table_info
小智 20
如果您在数据库升级语句中执行此操作,则最简单的方法是在尝试添加可能已存在的字段时捕获引发的异常.
try {
db.execSQL("ALTER TABLE " + TABLE_NAME + " ADD COLUMN foo TEXT default null");
} catch (SQLiteException ex) {
Log.w(TAG, "Altering " + TABLE_NAME + ": " + ex.getMessage());
}
Run Code Online (Sandbox Code Playgroud)
Kru*_*hah 11
threre是一个PRAGMA的方法是table_info(table_name),它返回表的所有信息.
这是实现如何使用它来检查列是否存在,
public boolean isColumnExists (String table, String column) {
boolean isExists = false
Cursor cursor;
try {
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)) {
isExists = true;
break;
}
}
}
} finally {
if (cursor != null && !cursor.isClose())
cursor.close();
}
return isExists;
}
Run Code Online (Sandbox Code Playgroud)
您也可以在不使用循环的情况下使用此查询,
cursor = db.rawQuery("PRAGMA table_info("+ table +") where name = " + column, null);
Run Code Online (Sandbox Code Playgroud)
小智 5
对于那些想要使用pragma table_info()'s 结果作为更大 SQL 的一部分的人。
select count(*) from
pragma_table_info('<table_name>')
where name='<column_name>';
Run Code Online (Sandbox Code Playgroud)
关键部分是使用pragma_table_info('<table_name>')而不是pragma table_info('<table_name>').
这个答案的灵感来自@Robert Hawkey 的回复。我将其发布为新答案的原因是我没有足够的声誉将其发布为评论。