是什么导致外键错配错误?

Dam*_*mon 12 sql sqlite constraints foreign-keys

我有一个sqlite数据库结构如下:

CREATE TABLE IF NOT EXISTS Patient 
( PatientId INTEGER PRIMARY KEY AUTOINCREMENT );

CREATE TABLE IF NOT EXISTS Event 
( 
PatientId INTEGER REFERENCES Patient( PatientId ),
DateTime TEXT,
EventTypeCode TEXT,
PRIMARY KEY( PatientId, DateTime, EventTypeCode )
);

CREATE TABLE IF NOT EXISTS Reading 
( 
PatientId INTEGER REFERENCES Patient( PatientId ),
DateTime TEXT REFERENCES Event (DateTime),
EventTypeCode TEXT REFERENCES Event (EventTypeCode),
Value REAL,
PRIMARY KEY( PatientId, DateTime, EventTypeCode )
);
Run Code Online (Sandbox Code Playgroud)

我插入患有Id#1的患者

然后我跑:

INSERT INTO Event (PatientId, DateTime, EventTypeCode) VALUES (1, '2011-01-23 19:26:59', 'R')
Run Code Online (Sandbox Code Playgroud)

哪个有效

然后我跑:

INSERT INTO Reading (PatientId, DateTime, EventTypeCode, Value) VALUES (1, '2011-01-23 19:26:59', 'R', 7.9)
Run Code Online (Sandbox Code Playgroud)

它给了我一个外键不匹配.在所有情况下,患者ID均为"1",日期时间和类型代码在第2次和第3次查询中匹配.我不明白什么是不匹配,但我实际定义外键有点新,我不知道我做错了什么.

no.*_*ing 39

我对SQLite并不熟悉,但是有点谷歌.文件说

如果数据库模式包含需要查看多个表定义以识别的外键错误,则在创建表时不会检测到这些错误.相反,此类错误会阻止应用程序准备以使用外键的方式修改子表或父表的内容的SQL语句.更改内容时报告的错误是"DML错误",更改架构时报告的错误是"DDL​​错误".因此,换句话说,需要查看子项和父项的配置错误的外键约束是DML错误.外键DML错误的英语错误消息通常是"外键不匹配",但如果父表不存在,也可以是"没有这样的表".如果出现以下情况,可能会报告外键DML错误:

  • 父表不存在,或
  • 外键约束中指定的父键列不存在,或
  • 外键约束中指定的父键列不是父表的主键,并且不受使用CREATE TABLE中指定的整理顺序的唯一约束的约束,或者
  • 子表引用父级的主键而不指定主键列,父级中的主键列数与子键列的数量不匹配.

我怀疑你可能会在该列表中遇到#3.

此外,虽然其他数据库可能支持使用非唯一索引作为外键引用(请参阅此处的答案),但在我看来,这是一个糟糕的设计选择.我会重组以便这样做

  1. Reading.PatientId引用,Event.PatientId以便完整的复合键EventReadingor 引用,
  2. EventIdEvent表中添加一个自动增量的主键,并将其用作表中的外键Reading(这样您只有EventIdValue不足,Reading并且可以使用PatientId, DateTime, EventTypeCodeEvent).

我建议#2,这样就可以避免冗余PatientId, DateTimeEventTypeCode两个EventReading.