SQLite3 Update语句无效

时间:2011-07-08 09:36:13

标签: iphone sql cocoa-touch sqlite

我不是SQL专家,但在iPhone应用程序中有一个错误,其中UPDATE语句对数据库没有影响。 我一直在使用FireFox的SQLlite manger插件通过在db上重复修改和运行UPDATE来尝试dbug。我还运行了语句彻底和SQL Validator,它说它符合核心SQL标准。

你能否发现下面的陈述有什么问题?

UPDATE sections
SET
    title = 'What is acne ? ABC',
    text = 'Pus on your face',
    created = '2010-03-10 18:46:55',
    modified = '2011-07-04 17:38:44',
    position = 1,
    condition_id = 4
WHERE id = 10;

3 个答案:

答案 0 :(得分:2)

在SQLite和Mozilla,Google,Adobe等人的各种实现方式中处理数字主键的方式存在一些混淆和不一致,这些数据库的表是在这些实现之外创建的,并且主键被定义为整数输入但不是“INTEGER”[verbatim] - 也就是说,它们被定义为INT或INT16或INT32等。

        INTEGER PRIMARY KEY in mothership SQLite is an alias for the rowid.
        INT PRIMARY KEY in mothership SQLite is not an alias for the rowid.

联盟成员(或任何实施者)可能会也可能不会遵循此规则。 (当然,SQLite属于公共领域。)

请参阅此处的第2.0节:http://www.sqlite.org/datatypes.html

并在此处查看有关RowId和主键的部分:http://www.sqlite.org/lang_createtable.html#rowid

  

如果是PRIMARY KEY列,则只变为整数主键   声明的类型名称正好是“INTEGER”。其他整数类型的名称   “INT”或“BIGINT”或“SHORT INTEGER”或“UNSIGNED INTEGER”导致   主键列表现为具有整数的普通表列   亲和力和唯一索引,不是rowid的别名。 [重点   加入]

不遵守规则的实施者可能甚至没有意识到他们首先违反了规则,因为它是一种“陷阱”的神秘规则。无论如何,这实际上意味着一个实现可以将提供的值视为rowid的别名而另一个实现可能不会。如果给定值10,则可以检索rowid = 10的元组,并且可以检索指定列的值= 10的元组。这当然会导致查询中的虚假结果 - 并且它们可能看起来非常好并且可行的结果,但他们错了。

考虑以下简单测试:使用旗舰SQLite的实用程序,而不是其中一个实现者提供的实用程序,执行以下DDL和DML语句;然后,在您的实现中,打开数据库并再次执行DML语句以比较DML结果:

        CREATE TABLE TEST
        ("id" INT PRIMARY KEY, "name" text)  -- ** NOTE "INT" not "INTEGER"

        INSERT INTO TEST
        (id, name)
        VALUES
        (7,'seven')


         ** *** N.B. THE ROWID OF THE ROW INSERTED ABOVE =  1  *** **


        select rowid, id, name from test

       result:  1 | 7 | seven


        select * from TEST 

        result:  7 | seven


        select * from TEST where id = 7

        result:  ?????  [ymmv]



        select * from TEST where id = 1


        result: ?????  [ymmv]

取决于特定实现如何处理INT主键,上面的第三个select语句(从TEST中选择*,其中id = 7)可能返回一行,或者它可能不返回任何内容!

如果实现将INT PK视为行id的别名,那么就没有rowid = 7的行,因此它不会返回任何内容。如果实现将INT PK视为正常值,它将找到该行。

现在,如果要在表TEST中插入更多行,最终会创建一个rowid = 7的行。在其中一个任意实现中,当你使用where where子句时,其中id = 7 ---你可能认为你正在处理id = 7的元组,但你实际上是在寻找rowid = 7的元组。你会得到错误的元组,你可能没有意识到。考虑将子表连接到父表时的可能性:子表包含外键值7.内连接从父表返回什么元组?这取决于实现是否尊重INT和INTEGER主键之间的区别。

去年,我为Adobe AIR,BTW详细记录了这一点,并在SQLite新闻组上进行了报道。某些实现可能已在过渡期间改变了行为。

创建SQLite表时,最好对主键使用INTEGER [verbatim],而不是任何其他已识别的int类型。

答案 1 :(得分:0)

如果您的查询正确,那么您需要确保2件事。

  1. 你有没有写过这样的finalize_statement?

    sqlite3_finalize(selectStatement);
    
  2. 2.如果您在模拟器中进行测试。您确定要按以下路径检查数据库更新吗?

    /user/Libary/Application Support/iPhone Simulator/Your_Version_Number/Applications/YOUR_APPLICATION_GUID/Documents
    

    希望这有帮助。

答案 2 :(得分:0)

查询中唯一让我觉得值得进一步调查的是[title]值中的问号。删除它,看看是否有任何改变。也许它在整个过程中被错误地解析为参数占位符。