Postgresql 使用函数和检查约束或约束触发器为多个表设置外键?
我有一个简单的问题。请不要问为什么 我有两个表,data1和data2。它们都有主键id列。每个表中的值保证在两个表中都是唯一的。这是由检查约束强制执行的 我有第三个表(data3),它有一个列,该列应该只包含存在于data1.id或data2.id中的值。我无法使用常规外键强制执行此操作。所以我写了一个函数,它通过一个检查约束来实现这一点 有没有更好的方法使用触发器约束来实现这一点Postgresql 使用函数和检查约束或约束触发器为多个表设置外键?,postgresql,Postgresql,我有一个简单的问题。请不要问为什么 我有两个表,data1和data2。它们都有主键id列。每个表中的值保证在两个表中都是唯一的。这是由检查约束强制执行的 我有第三个表(data3),它有一个列,该列应该只包含存在于data1.id或data2.id中的值。我无法使用常规外键强制执行此操作。所以我写了一个函数,它通过一个检查约束来实现这一点 有没有更好的方法使用触发器约束来实现这一点 drop schema if exists test cascade; create schema test;
drop schema if exists test cascade;
create schema test;
CREATE FUNCTION test.right_bit_shift()
RETURNS bigint IMMUTABLE LANGUAGE SQL AS
'SELECT 2::bigint';
create or replace function test.ufn_get_type_id(id bigint) returns bigint as $$
select id >> 2;
$$ language sql
;
create table test.data1(name text);
alter table test.data1 add column id bigint primary key constraint id_chk check(test.ufn_get_type_id(id) =1) no inherit ;
create table test.data2(name text);
alter table test.data2 add column id bigint primary key constraint id_chk check(test.ufn_get_type_id(id) =0) no inherit ;
insert into test.data1(id, name) values(5,'101');
insert into test.data2(id, name) values(1,'001');
create table test.table_lookup(type_id bigint, table_name text);
insert into test.table_lookup(type_id, table_name)
values
(1, 'test.data1'),
(0, 'test.data2');
create or replace function test.ufn_get_existence_sql(_id bigint) returns text as $$
select
'select exists(select 1 from '||table_name||' where id = '||_id||');'
from test.table_lookup where type_id = test.ufn_get_type_id(_id);
$$
language sql;
create or replace function test.ufn_id_exists (id_to_check bigint) returns boolean as $$
declare res bool;
begin
execute test.ufn_get_existence_sql(id_to_check) into res;
return res;
end;
$$
language plpgsql;
create table test.data3(name text, fk_id bigint constraint fk_id check ( test.ufn_id_exists(fk_id) ));
你完全可以使用触发器来实现这一点。定义在插入或更新表
data3
之前触发的触发器,并检查data3中的引用列是否存在于data1.id或data2.id中。如果没有,您可以引发异常
一种更简单的方法是添加外部约束,使用与引用表一样多的列和外键。在表3中,您可以添加一个data2_id列,该列具有对data2.id的外键引用,以及另一个列data3_id,该列具有对data3.id的外键引用。这些列必须可以为null,因为虽然data2\u id不为null,但data3\u id为null。所以我发现了这个
它声明检查约束应该是不可变的,而我的检查约束肯定不是。它可能会导致恢复转储等问题
因此,似乎最好的方法是插入和更新触发器。为什么不能使用外部约束?@KedarLimaye如果您认为可以使用外键,请提供一个答案。虽然对某些表使用多列,但我无法防止使用该方法产生空值。