首页 文章

ALTER TABLE添加列,如果不是SQLite中的EXISTS

提问于
浏览
70

我们最近需要在一些现有的SQLite数据库表中添加列 . 这可以通过ALTER TABLE ADD COLUMN完成 . 当然,如果表已被更改,我们希望不管它 . 不幸的是,SQLite不支持 ALTER TABLE 上的 IF NOT EXISTS 子句 .

我们当前的解决方法是执行ALTER TABLE语句并忽略任何"duplicate column name"错误,就像this Python example(但在C中) .

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

我希望将表定义放在一个地方,而不是在.sql和.cpp文件之间进行拆分 . 有没有办法在纯SQLite SQL中为 ALTER TABLE ADD COLUMN IF NOT EXISTS 编写变通方法?

6 回答

  • 0

    我有一个99%的纯SQL方法 . 我们的想法是对架构进行版本控制 . 您可以通过两种方式执行此操作:

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

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

    这样,当软件启动时,它可以检查数据库模式,如果需要,运行 ALTER TABLE 查询,然后递增存储的版本 . 这比尝试各种更新"blind"要好得多,特别是如果您的数据库多年来增长和变化几次 .

  • 25

    一种解决方法是仅创建列并捕获列已存在时出现的异常/错误 . 添加多个列时,请将它们添加到单独的ALTER TABLE语句中,以便一个副本不会阻止创建其他列 .

    使用sqlite-net,我们做了类似的事情 . 它's not perfect, since we can' t区分重复的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));
        }
    }
    
  • 10

    SQLite还支持名为“table_info”的pragma语句,该语句在表中每列返回一行,其中包含列的名称(以及有关该列的其他信息) . 您可以在查询中使用它来检查缺少的列,如果不存在则更改表 .

    PRAGMA table_info(foo_table_name)
    

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

  • 51

    如果您在数据库升级语句中执行此操作,则最简单的方法是在尝试添加可能已存在的字段时捕获引发的异常 .

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

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

    如果您're having this problem in flex/adobe air and find yourself here first, i'已找到解决方案,并已将其发布在相关问题上:ADD COLUMN to sqlite db IF NOT EXISTS - flex/air sqlite?

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

相关问题