UPDATing外键关系中的引用和引用列

时间:2011-06-07 20:31:36

标签: postgresql foreign-keys constraints

我有以下测试用例:

DROP SCHEMA IF EXISTS test CASCADE;
CREATE SCHEMA test;

CREATE TABLE test.quz (
  foo int,
  bar int,
  PRIMARY KEY ( foo, bar )
);
CREATE TABLE test.quuz (
  foo int,
  bar int,
  baz int,
  PRIMARY KEY ( foo, bar ),
  FOREIGN KEY ( foo, bar ) REFERENCES test.quz MATCH FULL
);

INSERT INTO test.quz VALUES ( 1, 2 );
INSERT INTO test.quuz VALUES ( 1, 2, 3 );

然而,即使deferred这似乎不起作用。

BEGIN;
  SET CONSTRAINTS ALL DEFERRED;
  UPDATE test.quz SET bar = 100 where bar = 2;
  UPDATE test.quuz SET bar = 100 where bar = 2;
  COMMIT;
END;

有什么理由吗?这个任务可以在没有手动删除和重新插入行的简洁性的情况下完成吗?

1 个答案:

答案 0 :(得分:1)

DEFERRABLE表示在每个语句的末尾检查约束。 DEFERRABLE INITIALLY DEFERRED表示在事务结束时检查约束。

这适用于您的情况:

CREATE TABLE test.quuz (
  foo int,
  bar int,
  baz int,
  PRIMARY KEY ( foo, bar ),
  FOREIGN KEY ( foo, bar ) REFERENCES test.quz MATCH FULL DEFERRABLE INITIALLY DEFERRED
);

...

BEGIN;
  UPDATE test.quz SET bar = 100 where bar = 2;
  UPDATE test.quuz SET bar = 100 where bar = 2;
COMMIT;

这也可能有用:

CREATE TABLE test.quuz (
  foo int,
  bar int,
  baz int,
  PRIMARY KEY ( foo, bar ),
  FOREIGN KEY ( foo, bar ) REFERENCES test.quz MATCH FULL DEFERRABLE
);

...

BEGIN;
  SET CONSTRAINTS ALL DEFERRED;
  UPDATE test.quz SET bar = 100 where bar = 2;
  UPDATE test.quuz SET bar = 100 where bar = 2;
COMMIT;

除非我误解,否则您的定义中的问题是您不会将约束标记为可延迟。因此,Postgres将它们视为NOT DEFERRABLE INITIALLY IMMEDIATE(即,尽管有SQL标准,但Postgres中的默认值,其理由是它最快),而不管SET CONSTRAINTS(仅影响可延迟约束)。