Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sqlite/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 约束到其引用的子集的关系表_Sql_Sqlite_Foreign Keys_Subset - Fatal编程技术网

Sql 约束到其引用的子集的关系表

Sql 约束到其引用的子集的关系表,sql,sqlite,foreign-keys,subset,Sql,Sqlite,Foreign Keys,Subset,假设我有下表: create table foo ( id integer primary key, mode integer not null check (mode in (1, 2)) ); 现在我想存储关于这个表中记录的附加信息,但只存储那些mode=1的记录。我认为我可以这样做的方式如下: create table foo_bar ( id integer primary key, foo_id integer, _mode inte

假设我有下表:

create table foo (
  id    integer  primary key,
  mode  integer  not null check (mode in (1, 2))
);
现在我想存储关于这个表中记录的附加信息,但只存储那些mode=1的记录。我认为我可以这样做的方式如下:

create table foo_bar (
  id      integer  primary key,
  foo_id  integer,
  _mode   integer  not null default (1) check (_mode = 1),

  foreign key (foo_id, _mode) references foo(id, mode)
);
也就是说,我们在foo_栏中有一个虚拟列,它总是强制等于1,并包含在带有foo的外键约束中

但是,这不仅不适用于pragma foreign_keys=ON;,但是,在foo中插入多个值时,可能会违反外键约束

这是我使用的SQLite 3.17中的一个bug吗?这很重要,还是我做错了

没有外键的另一个选项可能是使用触发器:

create trigger bad_mode
before insert on foo_bar when (select mode from foo where id = NEW.foo_id) <> 1
begin
  select raise(fail, "Invalid mode");
end;

……但这似乎有点恶心

我认为您可以改进设计,不需要FK以外的约束:

首先,foo.mode可以是另一个表的外键,比如modes,无需使用检查约束。将值1和2存储在那里

第二个表,比如bar_模式,可以有一个字段模式,一个FK到模式。将值1存储在此表中

最后,foo_bar.foo_id是FK到foo.id,foo_bar.mode是FK到bar_modes.mode

让我知道你的想法

M=3,N=5的SQL Server示例

报告说:

通常,外键约束的父键是父表的主键。如果它们不是主键,则父键列必须共同受唯一约束或具有唯一索引

缺少唯一约束是导致外键不匹配错误的原因


无法在检查约束中使用子查询,因此强制执行mode=1约束的唯一方法是将其作为外键约束的一部分,或使用触发器。

谢谢。检查foo.mode只是为了说明我的观点;在我的实际模式中,正如您所建议的,我确实有一个引用的模式表。无论如何,我认为一个不同的模式可能是可行的,但是我认为我应该将模式关系分解到一个新表中,而不是按照您的建议。这适用于我的用例,我只对子集中的一种模式感兴趣,但它不是一个通用的解决方案。什么是通用问题,您正在寻找通用的解决方案?我不是在寻找通用的解决方案,但假设您有N个模式,foo_bar只允许来自M个模式的foo记录,其中MI正在编辑答案以附加SQL代码SQL server,请查看实况。你能解释一下问题出在哪里吗?在我的例子中,M=3,N=5。不,我看不出任何语义是如何以这种方式丢失的。插入foo_bar id、foo_id、其他数据值300、5000,‘foo 5000的数据’起作用,但这应该是约束失败。foo_栏的要点是,它只允许模式为1、2或3的foo.id记录。您的模式对此没有任何约束,但有趣的是,MS SQL Server似乎与@CL指出的SQLite存在相同的问题。也就是说,需要将外部引用字段定义为复合主键或唯一。了解以下信息非常有用。。。尽管如此,在经历了这一切之后,我很想把这个问题正常化!谢谢:
create trigger bad_mode
before insert on foo_bar when (select mode from foo where id = NEW.foo_id) <> 1
begin
  select raise(fail, "Invalid mode");
end;
create table modes (
    id int primary key
)

create table foo (
  id    int  primary key,
  mode  int  not null foreign key references modes(id)
);

create table bar_modes (
  id int primary key foreign key references modes(id)
)

create table foo_bar (
  id int primary key,
  foo_id int foreign key references foo(id),
  other_data varchar(20)
)

insert modes (id) values(1)
insert modes (id) values(2)
insert modes (id) values(3)
insert modes (id) values(4)
insert modes (id) values(5)

insert bar_modes (id) values (1)
insert bar_modes (id) values (2)
insert bar_modes (id) values (3)

insert foo (id, mode) values (1000, 1)
insert foo (id, mode) values (2000, 2)
insert foo (id, mode) values (2500, 2)
insert foo (id, mode) values (5000, 5)

insert foo_bar (id, foo_id, other_data) values (100, 1000, 'data for foo 1000')
insert foo_bar (id, foo_id, other_data) values (200, 2000, 'data for foo 2000')
insert foo_bar (id, foo_id, other_data) values (250, 2500, 'data for foo 2500')