【问题标题】:foreign key mismatch on delete command for unrelated record无关记录的删除命令外键不匹配
【发布时间】:2013-06-05 11:40:37
【问题描述】:

我定义了以下 5 个表,其中在第一个 4 中插入了一些记录。这是使用启用了外键约束的 sqlite 3.7.1.7。

create table if not exists subject (id varchar(50) primary key,desc varchar(100));
insert into subject (id,desc) values ("subject1","test subject");

create table if not exists subjectlevel (id_subject_id varchar(50) references subject(id) on delete cascade, id integer not null, desc varchar(100) not null, questmcmaxselections integer not null, primary key (id_subject_id,id));

insert into subjectlevel (id_subject_id,id,desc,questmcmaxselections) values ("subject1",1,"test subject1 level 1",4);

insert into subjectlevel (id_subject_id,id,desc,questmcmaxselections) values ("subject1",2,"test subject1 level 2",4);

create table if not exists questmc (id integer primary key, text varchar(300) not null, includeallanswers int not null, subject_id varchar(50), subjectlevel_id integer, foreign key (subject_id, subjectlevel_id) references subjectlevel (id_subject_id,id) on delete cascade); 

insert into questmc (text,includeallanswers,subject_id,subjectlevel_id) values ("this is a _ question", 1, "subject1",1);

create table if not exists questmcselection (id integer primary key, text varchar(100) not null, subject_id varchar(50), subjectlevel_id integer, foreign key (subject_id, subjectlevel_id) references subjectlevel (id_subject_id,id) on delete cascade);

insert into questmcselection (text,subject_id,subjectlevel_id) values ("this is a solution","subject1",1);

create table if not exists questmc_questmcselection(id integer primary key, answer integer not null, questmc_id integer, questmcselection_id integer, subject_id varchar(50), subjectlevel_id integer, foreign key (questmc_id) references questmc(id) on delete cascade, foreign key (questmcselection_id) references questmcselection (id) on delete cascade, foreign key (subject_id,subjectlevel_id) references questmc (subject_id,subjectlevel_id) on delete cascade, foreign key (subject_id,subjectlevel_id) references questmcselection (subject_id,subjectlevel_id));

如果我尝试删除 subjectlevel 表中的第二条记录,只要定义了表 questmc_questmcselection,就会收到外键不匹配错误。

sqlite> delete from subjectlevel where id=2;
Error: foreign key mismatch - "questmc_questmcselection" referencing "questmcselection"

questmc、questmcselection 和 questmc_questmcselection 没有应防止此删除的相关现有记录。知道为什么会发生此错误吗?

【问题讨论】:

  • 它似乎不像 questmc_questmcselection 表上定义的最后 2 个外键。我删除了最后一个,然后是倒数第二个(两个 (subject_id,subjectlevel_id) 键),所以这导致了一个问题,“sqlite 3.7.1.7 是否支持多个外键链接到同一个表?
  • 也许我应该问一个更大的问题。我有一个多项选择 (mc) 问题表和一个选择表,其中包含可以跨问题重复使用的选项。我需要它们之间的 n:n 链接。但是,问题和选择记录都定义了主题和主题级别。我需要确保 n:n 链接只允许相同类型的链接。我怎样才能在数据库级别做到这一点?

标签: sqlite foreign-keys mismatch


【解决方案1】:

此错误与此特定的 subjectlevel 记录无关。

您的问题是您的表缺少the required indexes。 这在之前没有报告,因为 DELETE 语句是第一个需要 SQLite 检查数据库架构一致性的命令。

【讨论】:

  • 我对 SQLite 完全陌生,对 SQL 也有些陌生。完成这项工作需要哪些索引?
  • 我不知道我想要做的事情在数据库级别是否可行。表 A 有一个 id 和一个 type 字段。表 B 有一个 id 和一个 type 字段。在这两种情况下,id 都是主键,type 的值来自相同的值集。表 C 提供了 A&B 之间的 n:n 链接。但是,如果记录 A&B 具有相同的类型,我只想要一个链接。
  • 在 CL 的帮助下得到了它。表 A 和 B 应在其键中包含 id 和 type。这是 CL 所指的唯一索引。表 C 应包括 3 个字段(aid、bid、type)和 2 个 fkey 约束,如下所示。外键 (aid,type) 参考 A (id,type), 外键 (bid,type) 参考 B (id,type) 这允许您将 A 和 B 中的 2 条记录链接到表 C 中,前提是它们共享相同的类型价值。感谢您的帮助 CL。
【解决方案2】:

基于 CL 的回答 -

sqlite> create table parent(a);
sqlite> create table child(a, FOREIGN KEY (a) REFERENCES parent(a));
sqlite> pragma foreign_keys = ON;
sqlite> insert into parent values(3);
sqlite> insert into child values (3);
Error: foreign key mismatch - "child" referencing "parent"
sqlite> create unique index p_a on parent(a);
sqlite> insert into child values (3);
sqlite> _

来自文档:

通常,外键约束的父键是主键 的父表。如果 [not],则父键列必须是 共同受 UNIQUE 约束或具有 UNIQUE 索引 [使用] 排序规则序列...在 CREATE TABLE 父表的语句。

即另一种选择是:

sqlite> create table parent(a, b, UNIQUE (a, b));
sqlite> create table child (x, y, FOREIGN KEY (x, y) REFERENCES parent(a, b));

(这也突出了多列外键;它们也适用于索引...)

【讨论】:

    猜你喜欢
    • 2020-02-29
    • 2019-06-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多