SQL需要外部列中的文本值

SQL需要外部列中的文本值,sql,postgresql,foreign-keys,Sql,Postgresql,Foreign Keys,外键约束中是否可能需要特定的文字值 比如说 CREATE TABLE a ( id bigserial primary key, b_id bigint not null, foreign key (b_id, true) references b(id, flag) ); CREATE TABLE b ( id bigserial primary key, flag boolean ); 如果我们希望要求a中的行仅引用b中的行,且标志设置为true,则问题中的语法无效(

外键约束中是否可能需要特定的文字值

比如说

CREATE TABLE a (
  id bigserial primary key,
  b_id bigint not null,
  foreign key (b_id, true) references b(id, flag)
);

CREATE TABLE b (
  id bigserial primary key,
  flag boolean
);

如果我们希望要求
a
中的行仅引用
b
中的行,且标志设置为
true

,则问题中的语法无效(请参阅)。您可以通过以下方式获得所需的效果:

CREATE TABLE b (
    id bigserial,
    flag boolean,
    primary key(id, flag)
);

CREATE TABLE a (
    id bigserial primary key,
    b_id bigint not null,
    flag boolean default true check (flag),
    foreign key (b_id, flag) references b(id, flag)
);
你可能想要这样的东西。为了便于阅读,我去掉了多余的
a.id

CREATE TABLE b (
  id bigserial not null,
  flag boolean not null,
  primary key (id),
  unique (id, flag)
);
id
上的主键约束可防止重复的id号。
id,flag
上的重叠约束允许这对列成为外键约束的目标

CREATE TABLE a (
  b_id bigint not null,
  flag boolean not null default true
    check (flag = true),
  primary key (b_id, flag),
  foreign key (b_id, flag) references b (id, flag)
    on delete cascade
);
为了使
a
中的一行仅引用
b
flag
为true的行,
a
中的每一行必须将
flag
设置为true。
标志
上的默认值和检查约束保证了这一点

现在,让我们尝试插入一些行

insert into b (flag) values (true);
insert into b (flag) values (true);
insert into b (flag) values (false);
到目前为止,一切顺利。现在是a的几行

insert into a (b_id, flag) values (1, true);
insert into a (b_id, flag) values (2, true);
但这一次应该失败

insert into a (b_id, flag) values (3, true);

--ERROR:  insert or update on table "a" violates foreign key constraint "a_b_id_fkey"
--DETAIL:  Key (b_id, flag)=(3, t) is not present in table "b".
insert into a (b_id, flag) values (3, false);

--ERROR:  new row for relation "a" violates check constraint "a_flag_check"
--DETAIL:  Failing row contains (3, f).
这一次应该失败

insert into a (b_id, flag) values (3, true);

--ERROR:  insert or update on table "a" violates foreign key constraint "a_b_id_fkey"
--DETAIL:  Key (b_id, flag)=(3, t) is not present in table "b".
insert into a (b_id, flag) values (3, false);

--ERROR:  new row for relation "a" violates check constraint "a_flag_check"
--DETAIL:  Failing row contains (3, f).
还有一件事

您需要考虑在更新表b中的标志时希望发生什么。你不能级联更新;这将导致
a
中的一行引用b中具有
false
的行

update b set flag = false where id = 1 and flag = true;
-- ERROR:  update or delete on table "b" violates foreign key constraint "a_b_id_fkey" on table "a"
-- DETAIL:  Key (id, flag)=(1, t) is still referenced from table "a".

如何处理这一问题取决于应用程序。在某些应用程序中,当
b
中的行更新为
false
时,删除
a
中的行可能是合适的。在其他应用程序中,仅撤销
b
上的更新权限可能是合适的。(还有其他选择。)在任何情况下,您都需要编写触发器。

我认为这是不可能的。也许您可以将一个helper列添加为be,并将值设置为_id或null,并且在a中有一个引用B中helper列的FK