我正在学习在 PostgreSQL 中使用触发器,但遇到此代码的问题:
CREATE OR REPLACE FUNCTION checkAdressen() RETURNS TRIGGER AS $$
DECLARE
adrCnt int = 0;
BEGIN
SELECT INTO adrCnt count(*) FROM Adresse
WHERE gehoert_zu = NEW.kundenId;
IF adrCnt < 1 OR adrCnt > 3 THEN
RAISE EXCEPTION 'Customer must have 1 to 3 addresses.';
ELSE
RAISE EXCEPTION 'No exception';
END IF;
END;
$$ LANGUAGE plpgsql;
在新创建所有表后,我使用此过程创建了一个触发器,因此它们都是空的。然而,count(*)上面代码中的函数返回 1。当我SELECT count(*) FROM adresse;在 PL/pgSQL 之外运行时,我得到 0。我尝试使用该FOUND变量,但它总是正确的。
更奇怪的是,当我在表中插入一些值然后再次删除它们以使它们再次为空时,代码按预期工作并count(*)返回 0。此外,如果我省略WHERE gehoert_zu = NEW.kundenId,则count(*)返回 0,这意味着我得到更多结果WHERE子句比没有。
- 编辑:
这是我如何使用该过程的示例:
CREATE TABLE kunde (
kundenId int PRIMARY KEY
);
CREATE TABLE adresse (
id int PRIMARY KEY,
gehoert_zu int REFERENCES kunde
);
CREATE CONSTRAINT TRIGGER adressenKonsistenzTrigger AFTER INSERT ON Kunde
DEFERRABLE INITIALLY DEFERRED
FOR EACH ROW
EXECUTE PROCEDURE checkAdressen();
INSERT INTO kunde VALUES (1);
INSERT INTO adresse VALUES (1,1);
看起来我DEFERRABLE INITIALLY DEFERRED弄错了。我假设触发器将在第一个INSERT语句之后执行,但它发生在第二个语句之后,尽管插入不在BEGIN;- COMMIT;- 块内。
根据PostgreSQL 文档,如果不在这样的块内,每次都会自动提交插入,因此在提交adresse第一条INSERT语句时不应该有条目。
谁能指出我的错误?
- 编辑:
触发器DEFERRABLE INITIALLY DEFERRED似乎工作正常。我的错误是假设由于我没有使用BEGIN--BlockCOMMIT每个插入都将在自己的事务中执行,并且每次都在之后执行触发器。
然而,即使没有BEGIN-COMMIT所有插入都会被捆绑到一个事务中,然后触发器会被执行。鉴于这种行为,使用BEGIN-有什么意义COMMIT?