Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/83.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/9.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
如何在PostgreSQL中生成对引用表具有约束的外键_Sql_Postgresql_Constraints - Fatal编程技术网

如何在PostgreSQL中生成对引用表具有约束的外键

如何在PostgreSQL中生成对引用表具有约束的外键,sql,postgresql,constraints,Sql,Postgresql,Constraints,假设我有下列表格 CREATE TABLE plugins ( id int primary key, type text); insert into plugins values (1,'matrix'); insert into plugins values (2,'matrix'); insert into plugins values (3,'function'); insert into plugins values (4,'function'); CREATE TABLE mat

假设我有下列表格

CREATE TABLE plugins (
id int primary key,
type text);

insert into plugins values (1,'matrix');
insert into plugins values (2,'matrix');
insert into plugins values (3,'function');
insert into plugins values (4,'function');

CREATE TABLE matrix_params (
id int primary key,
pluginid int references plugins (id)
);
这一切都按预期进行,但我想添加一个额外的约束,即矩阵参数只能引用具有“matrix”类型的pluginid。所以

insert into matrix_params values (1,1);
应该成功但是

insert into matrix_params values (2,3);
应该失败


矩阵参数的简单约束不起作用,因为它无法知道插件表中对应的类型。

对此可以使用检查约束。不能将查询置于检查约束中,但可以调用函数;因此,我们构建了一个简单的函数,告诉我们
pluginid
是否是矩阵:

create or replace function is_matrix(int) returns boolean as $$
    select exists (
        select 1
        from plugins
        where id   = $1
          and type = 'matrix'
    );
$$ language sql;
并将其包装在检查约束中:

alter table matrix_params add constraint chk_is_matrix check (is_matrix(pluginid));
然后:


FK负责引用完整性和级联。

在引用表中使用复合键,并在引用表中使用
检查
约束,例如

CREATE TABLE plugins (
id int primary key,
type text, 
UNIQUE (type, id)
);

CREATE TABLE matrix_params (
id int primary key,
plugintype text DEFAULT 'matrix' NOT NULL
   CHECK (plugintype = 'matrix'),
pluginid int NOT NULL,
FOREIGN KEY (plugintype, pluginid)
   references plugins (type, id)
);

处理此问题的一种方法是使用可序列化事务


如果在矩阵参数行引用插件行后更新了类型,则不会处于所需状态;否则这会起作用。@kgrittn:您可以在
插件
上添加一个更新触发器(如果您的PostgreSQL版本支持,当old.type='matrix'和new.type!=old.type
条件时,可能带有
),如果更新违反了
is_matrix
条件,则该触发器可能引发异常。这可能有点难看。这会将一个表的主键更改为问题中未指定的内容,并在另一个表的每一行中添加一个不必要的列。@kgrittn:我没有更改任何主键:我已向引用的表添加了一个额外的超键。引用表中添加的列允许使用行级
检查
约束(使用外键),因此在上下文中是必要的。但如果你觉得麻烦的话,它可以通过视图“隐藏”。我认为这是一个有效的解决方案。当您通过plugintype来考虑它时,pluginid实际上并不是一个键,因为在plugins表中不允许使用(1,'foo')、(1,'bar)。在我的例子中,我试图使用一个常量作为键的一部分,postgres不喜欢它。我更喜欢选择的答案,因为它不需要修改数据类型就可以完成任务。对不起,你说得对。我想我应该在早上发布之前等待咖啡因的加入。好吧,如果没有一些非规范化(冗余地将数据存储在矩阵参数中)或者声明一个真正稳定的函数是不可变的,它带有一定的风险,那么这不可能是一个外键。(当你对数据库撒谎时,它迟早会报复你。)因此,唯一真正准确的答案是它无法做到。但这不是很有帮助。这是一种非常常见的用例类型,可序列化事务正是要解决的问题。也许我的链接应该在这里:
CREATE TABLE plugins (
id int primary key,
type text, 
UNIQUE (type, id)
);

CREATE TABLE matrix_params (
id int primary key,
plugintype text DEFAULT 'matrix' NOT NULL
   CHECK (plugintype = 'matrix'),
pluginid int NOT NULL,
FOREIGN KEY (plugintype, pluginid)
   references plugins (type, id)
);