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

时间:2011-03-06 02:29:34

标签: sql sqlite foreign-keys constraints

我有一个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 )
);

我插入患有Id#1的患者

然后我跑:

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

哪个有效

然后我跑:

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

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

1 个答案:

答案 0 :(得分:35)

我对SQLite不熟悉,但对Google turned up this有点兴趣。文档说

  

如果数据库架构包含   需要的外键错误   看着不止一张桌子   识别的定义,然后是那些   当没有检测到错误   表已创建。相反,这样   错误阻止了应用程序   准备修改的SQL语句   孩子或父母的内容   表格使用外国的方式   键。内容出现时报告的错误   改变了“DML错误”和错误   模式更改时报告   是“DDL​​错误”。所以,换句话说,   配置错误的外键约束   需要同时看着孩子   和父是DML错误。 英语   外键的语言错误消息   DML错误通常是“外键”   不匹配“但也可以”没有这样的   表“如果父表没有   存在。外键DML错误可能是   是   报道如果:

     
      
  • 父表不存在,或
  •   
  • 外键约束中指定的父键列不存在,   或
  •   
  • 外键约束中指定的父键列不是   父表的主键和   不受限制   使用中指定的整理顺序   CREATE TABLE,或
  •   
  • 子表不引用父表的主键   指定主键列和   中的主键列数   父母的数量不匹配   子键列。
  •   

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

此外,虽然其他数据库可能支持使用非唯一索引作为外键引用(see answers here),但在我看来,这是一个糟糕的设计选择。我会重组以便

  1. Reading.PatientId引用Event.PatientId,以便Event引用Reading中的完整复合键,或
  2. EventId自动增量主键添加到Event表,并将其用作Reading表中的外键(这样您只有EventId以及Value下的Reading,您可以PatientId, DateTime, EventTypeCode获取Event
  3. 我建议#2,以便您可以避免PatientId, DateTimeEventTypeCodeEventReading的冗余。