PostgreSQL的规则和nextval()/串行问题(非常特定于PostgreSQL)
当我使用重写规则将一个insert拆分为一个表,再拆分为另两个表的insert,其中一个插入值的默认值为nextval“some_sequence”,两个表的序列相同,那么两个表中插入的默认值是不同的。这可能是由于重写规则简单地替换了文本。相反,我希望先解析默认值,然后将相同的值写入两个表 这里是一个您可能猜到的示例,我尝试使用规则实现专门化/泛化:PostgreSQL的规则和nextval()/串行问题(非常特定于PostgreSQL),postgresql,rules,Postgresql,Rules,当我使用重写规则将一个insert拆分为一个表,再拆分为另两个表的insert,其中一个插入值的默认值为nextval“some_sequence”,两个表的序列相同,那么两个表中插入的默认值是不同的。这可能是由于重写规则简单地替换了文本。相反,我希望先解析默认值,然后将相同的值写入两个表 这里是一个您可能猜到的示例,我尝试使用规则实现专门化/泛化: -- first and third commands can be skipped if id is defined as serial cre
-- first and third commands can be skipped if id is defined as serial
create sequence parents_id_seq;
create table Parents(
id integer default(nextval('parents_id_seq')) primary key,
type varchar(50) not null check(type in ('Child1', 'Child2')),
unique (id, type),
attribute1 varchar(50) not null unique check(length(attribute1) > 0)
);
alter sequence parents_id_seq owned by parents.id;
第一类儿童的特定数据保存在
create table Partial_Children1(
id integer default(nextval('parents_id_seq')) primary key,
type varchar(50) not null check(type = 'Child1'),
foreign key (id, type) references Parents(id, type),
attribute2 varchar(50) not null check(length(attribute2) > 0)
);
接下来,我定义了一个视图Children1,它连接上面的两个表。我通过明确说明PostgreSQL如何根据文档定义视图来重写该视图
create table Children1(
id int default(nextval('parents_id_seq')),
type varchar(50) not null check(type in ('Child1')),
attribute1 varchar(50) not null check(length(attribute1) > 0),
attribute2 varchar(50) not null check(length(attribute2) > 0)
);
create rule "_RETURN" as on select to Children1 do instead
select p.*, c.attribute2
from Parents p
join Partial_Children1 c
on p.id = c.id;
最后,我遇到的重写规则是:
create rule ct_i_children1 as
on insert to Children1
do instead (
insert into Parents(attribute1, type)
values(new.attribute1, 'Child1');
insert into Partial_Children1(attribute2, type)
values(new.attribute2, 'Child1');
);
正在尝试使用插入数据
insert into Children1 (attribute1, attribute2)
values ('a1', 'a2'),
('b1', 'b2');
生成错误消息
ERROR: insert or update on table "partial_children1" violates foreign key constraint "partial_children1_id_fkey"
DETAIL: Key (id,type)=(3,Child1) is not present in table "parents".
解决此问题的一种方法是将重写规则的第二次插入替换为
insert into Partial_Children1(id, attribute2, type)
select p.id, new.attribute2, p.type
from Parents p
where p.attribute1 = new.attribute1
但这取决于attribute1的唯一性,我不想将其强加于此。另一种解决方案是首先将值插入到临时表中,然后从中选择两次,以便插入到两个表中。但由于性能原因,我不喜欢它
有人知道如何仅使用规则而不使用触发器在两个表中获得相同的默认值吗?规则会为您做到这一点-它们会在执行查询之前重写查询 只要您有一个用于基本子项1的实际表,我认为您就可以使用触发器而不是规则来完成相同的任务。来自文档 规则系统会修改查询 考虑规则,以及 然后将修改后的查询传递给 查询计划器,用于计划和 执行 因此,它首先重写查询,而不执行任何操作 如果不同时插入多条记录,则可以使其正常工作:
create or replace rule ct_i_children1 as
on insert to Children1
do instead (
insert into Parents(id, attribute1, type)
values(nextval('parents_id_seq'), new.attribute1, 'Child1');
insert into Partial_Children1(id, attribute2, type)
values(currval('parents_id_seq'), new.attribute2, 'Child1');
);
然后你可以做:
insert into Children1 (attribute1, attribute2) values ('a1', 'a2');
insert into Children1 (attribute1, attribute2) values ('b1', 'b2');
但不是
insert into Children1 (attribute1, attribute2)
values ('a1', 'a2'),
('b1', 'b2');
所以你真的不应该在复杂的currval调用中使用规则系统
另外,请查看这些页面上的评论:
另一个提示:postgresql邮件列表的支持与数据库引擎本身一样出色
顺便问一下:您知道postgresql支持开箱即用的继承吗
小结:您应该使用触发器或避免多行插入 嗯,我想是的。但我想我至少错过了“不触发”部分,很抱歉。谢谢链接。他们解决不了问题,但至少我不再感到孤独;-。内置继承并没有提供我想要的东西。