小编典典

SQLlite3更新语句无效

sql

我不是SQL专家,但在iPhone应用程序中存在一个错误,其中UPDATE语句对数据库没有影响。我一直在为FireFox使用SQLlite管理器插件,通过反复修改和在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;

阅读 231

收藏
2021-04-14

共1个答案

小编典典

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

仅当声明的类型名称恰好是“ INTEGER”时,PRIMARY KEY列才成为整数主键。其他整数类型名称(例如“ 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主键,上面的第三条选择语句(在id = 7的TEST中选择*)可能返回一行 ,也可能什么都不返回!

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

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

去年,我为Adobe AIR,BTW进行了详细记录,并在SQLite新闻组中进行了报道。某些实现可能已在此期间更改了行为。

创建SQLite表时,最好将INTEGER [verbatim]用作主键,而不要使用其他任何公认的int类型。

2021-04-14