如果SQLite数据库不存在该列,则添加列 - Flex / Air SQLite?

14

我有一个使用本地sqlite数据库的flex/air应用程序,在初始应用程序启动时创建。

我添加了一些功能到应用程序中,并且在此过程中,我不得不向一个数据库表中添加一个新字段。我的问题是如何让应用程序创建一个已经存在的表中的一个新字段?

这是创建表的行:

stmt.text = "CREATE TABLE IF NOT EXISTS tbl_status ("+"status_id INTEGER PRIMARY KEY AUTOINCREMENT,"+" status_status TEXT)";

现在我想添加一个status_default字段。

谢谢!

感谢 - MPelletier

我添加了你提供的代码,它确实添加了该字段,但是下次重新启动应用程序时,我会收到一个错误 -“status_default”已经存在。

那么我该如何在你提供的行中添加IF NOT EXISTS语句呢?


你为什么没有在http://www.sqlite.org上检查SQLite SQL语法呢?ALTER TABLE命令的语法添加新列时没有任何IF NOT EXISTS类型的修饰符,这意味着你只能在自己的代码中处理异常/错误。 - Lasse V. Karlsen
Adam,我已经更新了我的答案。请看下面。 - MPelletier
4个回答

36
ALTER TABLE tbl_status ADD COLUMN status_default TEXT;

http://www.sqlite.org/lang_altertable.html

话虽如此,在SQLite中添加列是有限制的。您只能在表格的最后一列之后添加列。

至于检查列是否已经存在,PRAGMA table_info(tbl_status);将返回一个列出表格各个列的表格。

添加内容:

我一直在使用一种数据库设计策略,使我能够区分哪些修改是必要的。为此,您需要一个新表(称其为DBInfo),其中包含一个字段(整数,称其为SchemaVersion)。或者,SQLite中还有一个名为user_version的内部值,可以使用PRAGMA命令进行设置。程序启动时,您的代码可以检查模式版本号并相应地逐个版本地应用更改。

假设有一个名为UpdateDBSchema()的函数。此函数将检查您的数据库模式版本,处理不存在DBInfo的情况,并确定数据库处于版本0。此函数的其余部分可以是一个大开关,其中包含不同版本,嵌套在循环中(或其他可用于您选择的平台的结构中)。

对于这个第一版,需要一个 UpgradeDBVersion0To1() 函数,该函数将创建这个新表 (DBInfo),添加你的 status_default 字段,并将 SchemaVersion 设置为 1。在你的代码中,添加一个常量来指示最新的模式版本,比如说 LATEST_DB_VERSION,并将其设置为 1。这样,你的代码和数据库都有一个模式版本,如果它们不相等,你就知道需要同步它们。
当你需要对模式进行另一个更改时,请将 LATEST_DB_VERSION 常量设置为 2,并创建一个新的 UpgradeDBVersion1To2() 函数来执行所需的更改。
这样,你的程序可以轻松移植,可以连接和升级旧数据库等。

用户可以随时设置和更改他们的默认值,因此我无法给出固定值。 - Adam
再次感谢MPelletier,那真的帮了我很多! - Adam
这是RoundhousE的实现方式。https://github.com/chucknorris/roundhouse/wiki - Clay
请提供必要的查询。很多困难在于将您提到的所有内容拼凑在一起。 - Timothy Gonzalez
OP没有要求数据库迁移策略。他们问的是如何在添加列语句中加入条件。你提到了数据所在位置,但没有展示如何写条件化的查询。问题仍然没有得到解答。所需的是一个简单的幂等查询。 - Timothy Gonzalez
显示剩余2条评论

3

我知道这是一个老问题... 不过。

我在Adobe AIR中的SQLite实现中遇到了这个确切的问题。我认为可以使用PRAGMA命令来解决,但由于Adobe AIR的实现不支持PRAGMA命令,我们需要另一种替代方案。

我所做的,我认为值得在这里分享的是:

var sql:SQLStatement = new SQLStatement();
sql.sqlConnection = pp_db.dbConn;
sql.text = "SELECT NewField FROM TheTable";
sql.addEventListener(SQLEvent.RESULT, function(evt:SQLEvent):void {
});

sql.addEventListener(SQLErrorEvent.ERROR, function(err:SQLErrorEvent):void {
    var sql:SQLStatement = new SQLStatement();
    sql.sqlConnection = pp_db.dbConn;
    sql.text = "ALTER TABLE TheTable ADD COLUMN NewField NUMERIC;";
    sql.execute();
    sql.addEventListener(SQLEvent.RESULT, function (evt:SQLEvent):void {
    });
});
sql.execute();

希望这对某些人有所帮助。

如果 pragma 不可用,这将很有帮助,但 MPelletier 提出的解决方案是任何开发人员在处理数据库版本控制和升级时都应该采取的方法。 - Fadi Chamieh
在OP的情况下,PRAGMA不可用,因此将其发布为此特定情况的正确解决方案。 - stevesweets

1

有时我执行命令时会出现“重复列”的异常。这只是一个快速解决方案,不是完美的。


0

我曾经使用这个问题的答案解决了一个类似的问题: SQLite中ALTER TABLE ADD COLUMN IF NOT EXISTS

使用内置的user_version参数来跟踪您的更新。您可以使用以下方式设置它:

PRAGMA user_version = 1

你可以使用以下代码来检索它:

PRAGMA user_version

基本上是获取 user_version (默认为 0),检查它是否为 0。如果是,执行您的更新并将其设置为 1。如果您将来有更多更新,请检查它是否为 1,执行更新并将其设置为 0。以此类推...


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接