繁体   English   中英

关系表仅限于其裁判员的子集

[英]Relational table that is constrained to a subset of its referee

说我有下表:

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_bar中有一个伪列,该伪列始终始终等于1,并使用foo将其包含在外键约束中。

但是,这不仅不起作用(使用pragma foreign_keys = ON; ),而且在foo插入多个值时,也可能违反外键约束!

sqlite> insert into foo(mode) values (1);
sqlite> insert into foo(mode) values (2);
sqlite> select * from foo;
1|1
2|2
sqlite> insert into foo_bar(foo_id) values (1);
Error: foreign key mismatch - "foo_bar" referencing "foo"
sqlite> insert into foo_bar(foo_id) values (2);
Error: foreign key mismatch - "foo_bar" referencing "foo"
sqlite> insert into foo(mode) values (1), (2);
Error: foreign key mismatch - "foo_bar" referencing "foo"

这是SQLite中的错误(我正在使用3.17,这很重要),还是我做错了?

没有外键的另一种选择是使用触发器:

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;

...但这似乎有点毛病!

文件说:

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

缺少UNIQUE约束是导致“外键不匹配”错误的原因。


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

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

  • 首先, foo.mode可以是另一个表的外键,例如modes ,不需要使用检查约束。 您将在其中存储值1和2。

  • 第二个表,说bar_modes ,可以有一个场mode中,FK到modes 您将在表中存储值1。

  • 最后, foo_bar.foo_id为FK到foo.idfoo_bar.mode为FK到bar_modes.mode

让我知道你的想法!

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

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')

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM