我想知道是否有人偶然发现了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=?
答案 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
值,尤其是null
和tgt_count
,因为这些列没有默认值。
您还可以尝试从change_id
语句中删除NOT NULL
约束并运行更新,以验证CREATE TABLE variant
是否是相关约束。