我有功能检查强制参与如下:
CREATE FUNCTION member_in_has_address()
RETURNS BOOLEAN AS $$
BEGIN
RETURN EXISTS (SELECT *
FROM address a, member_details b
WHERE b.member_id = a.member_id);
END;
$$ LANGUAGE plpgsql;
Run Code Online (Sandbox Code Playgroud)
然后从CHECK约束调用
ALTER TABLE member_details
ADD CONSTRAINT member_in_has_address_check
CHECK (member_in_has_address());
Run Code Online (Sandbox Code Playgroud)
要在标准SQL中创建deferred约束,它将是:
ALTER TABLE member_details
ADD CONSTRAINT member_in_has_address_check
INITIALLY DEFERRED
CHECK (member_in_has_address());
Run Code Online (Sandbox Code Playgroud)
我怎么能在PostgreSQL中做同样的事情?
背景:http://jeffkemponoracle.com/2011/03/11/handling-unique-constraint-violations-by-hibernate
我们的表是:
BOND_PAYMENTS (BOND_PAYMENT_ID, BOND_NUMBER, PAYMENT_ID)
Run Code Online (Sandbox Code Playgroud)
BOND_PAYMENT_ID上有主键约束,(BOND_NUMBER,PAYMENT_ID)上有唯一约束.
该应用程序使用Hibernate,并允许用户查看链接到特定Bond的所有付款; 它允许他们创建新链接,并删除现有链接.一旦他们在页面上做了所有他们想要的更改,他们就会点击"保存",Hibernate会在数据库上运行所需的SQL.显然,Hibernate可以找出需要删除的记录,需要插入哪些记录,并保持其余部分不变.不幸的是,它首先执行INSERT,然后执行DELETE.
如果用户删除了付款的链接,然后改变主意并重新插入指向同一付款的链接,Hibernate很乐意尝试插入然后将其删除.由于这些插入/删除作为单独的SQL语句运行,因此Oracle会在第一个插入时立即验证约束并发出违反ORA-00001唯一约束的情况.
我们只知道两种选择:
选项2不太合适,因为约束提供了极好的保护,可以防止可能允许保存不一致数据的令人讨厌的应用程序错误.我们选择了1.
ALTER TABLE bond_payments ADD
CONSTRAINT bond_payment_uk UNIQUE (bond_number, payment_id)
DEFERRABLE INITIALLY DEFERRED;
Run Code Online (Sandbox Code Playgroud)
缺点是为警告此约束而创建的索引现在是一个非唯一索引,因此查询的效率可能稍低.我们已经确定这对于这个特殊情况并没有那么大的损害.另一个缺点(由Gary建议)可能会遇到特定的Oracle错误 - 虽然我相信由于应用程序的工作方式,我们会免疫(至少大部分).
我们还应该考虑其他选择吗?
我在2个表上有一个循环外键,所以我使用deferrable最初推迟如下:
uni=# create table vorlesungen (vnr integer primary key, gelesenvon integer);
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "vorlesungen_pkey" for table "vorlesungen"
CREATE TABLE
uni=# create table professoren (pnr integer primary key, lieblingsvo integer);
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "professoren_pkey" for table "professoren"
CREATE TABLE
uni=# alter table professoren add constraint vfk foreign key (lieblingsvo) references vorlesungen (vnr) deferrable initially deferred;
ALTER TABLE
uni=# alter table vorlesungen add constraint pfk foreign key …
Run Code Online (Sandbox Code Playgroud)