android sqlite外键更新失败

时间:2015-03-06 03:07:28

标签: android database sqlite

我想知道是否有人偶然发现了sqlite外键的奇怪行为。

当我更新指向另一个表主键parcours(eid)并声明为外键的键变体(parcours_id)时,会出现问题。

所涉及的表格是:

CREATE TABLE parcours(
    eid character varying(36) PRIMARY KEY,
    name character varying(50),
    comment text,
    location_id character varying(36),
    owner_id character varying(36),
    change_id integer NOT NULL,
    change_flag smallint NOT NULL DEFAULT 1,
    CONSTRAINT fk_location_id FOREIGN KEY (location_id)
      REFERENCES location (eid) 
      ON UPDATE CASCADE 
      ON DELETE RESTRICT
)



CREATE TABLE variant (
    eid character varying(36) PRIMARY KEY,
    parcours_id character varying(36) NOT NULL,
    name character varying(50),
    comment text,
    created TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
    active smallint NOT NULL DEFAULT 1,
    selected smallint NOT NULL DEFAULT 0,
    tgt_count integer NOT NULL,
    owner_id  character varying(36) 
      DEFAULT '687baa6e-556f-43f2-897a-f1dfb371541a',
    change_id integer NOT NULL,
    change_flag smallint NOT NULL DEFAULT 1,
    CONSTRAINT fk_parcours_id FOREIGN KEY (parcours_id)
    REFERENCES parcours (eid) 
      ON UPDATE CASCADE 
      ON DELETE RESTRICT 
)

从variant(parcours_id)到parcours(eid)的外键关系在插入时非常有效,但在更新时失败

android.database.sqlite.SQLiteException: foreign key mismatch: , while compiling: UPDATE variant SET parcours_id=?,name=?,comment=?,created=?,active=?,selected=?,tgt_count=?,owner_id=?,change_id=?,change_flag=? WHERE eid=?

现在这个问题有点哲学,因为此时我不需要更新密钥变量(parcours_id),因为它没有改变。我决定只在一直更新除主键之外的所有字段时实现更新功能。一般来说,我不认为有问题的价值会发生变化,所以我可以将其从更新中删除。

在我看来,我的实现是正常的,因为如果我在数据库上禁用外键而不更改任何其他工作,则外键会正确更新,并且更新后数据库的完整性将保持不变。

对我而言,这证明问题不是由我的实现引起的,但似乎是对sqlite如何处理外部密钥更新的一般误解。

有什么建议吗?

编辑: 从更新中删除密钥变体(parcours_id)后,我仍然得到一个SQLITE异常:

android.database.sqlite.SQLiteConstraintException: error code 19: constraint failed

SQL语句是:

UPDATE variant SET name=?,comment=?,created=?,active=?,selected=?,tgt_count=?,owner_id=?,change_id=?,change_flag=? WHERE eid=?

1 个答案:

答案 0 :(得分:0)

  

从variant(parcours_id)到parcours(eid)的外键关系在插入时非常有效,但在更新时失败

android.database.sqlite.SQLiteException: foreign key mismatch: , while compiling: UPDATE variant SET parcours_id=?,name=?,comment=?,created=?,active=?,selected=?,tgt_count=?,owner_id=?,change_id=?,change_flag=? WHERE eid=?

鉴于您的外键约束,如果您parcours_id语句中为UPDATE语句设置的值eid中的值不存在,则更新应该失败{1}}中任意行的{1}}列。例如:

parcours

SELECT eid FROM parcours ORDER BY eid;

eid ----- a b c 应该失败,因为UPDATE variant SET parcours_id = 'zzz' WHERE eid = '123';中的zzz列中不存在值eid

另一方面,

parcours应该可以正常工作,因为值UPDATE variant SET parcours_id = 'b' WHERE eid = '123';确实存在。

我刚刚使用您的b语句(也创建了假CREATE TABLE表)测试了此行为,并且它按预期工作。您可以将location语句中使用的parcours_id值与UPDATE variant的输出进行比较以进行验证。

有关详细信息,请参阅Sqlite Foreign Key Support

  

编辑:从更新中删除密钥变体(parcours_id)后,我仍然得到一个SQLITE异常:

SELECT eid FROM parcours ORDER BY eid;

这可能与其他约束有关,例如android.database.sqlite.SQLiteConstraintException: error code 19: constraint failed 。检查您在NOT NULL语句中传递的参数是否包含任何UPDATE值,尤其是nulltgt_count,因为这些列没有默认值。

您还可以尝试从change_id语句中删除NOT NULL约束并运行更新,以验证CREATE TABLE variant是否是相关约束。