【发布时间】:2013-05-17 16:38:09
【问题描述】:
我正在尝试检查要插入系统的房间在该日期是否已经出租。我已经考虑过计算与房间号和日期匹配的行,然后回滚交易。但我收到以下错误,即使我已更改代码以引发用户定义的异常:
ERROR: cannot begin/end transactions in PL/pgSQL HINT: Use a BEGIN block with an EXCEPTION clause instead. CONTEXT: PL/pgSQL function "checkRoom"() line 17 at SQL statement
CREATE OR REPLACE FUNCTION "checkRoom"() RETURNS TRIGGER AS
$BODY$
DECLARE
counter integer;
BEGIN
SELECT COUNT("num_sesion")
FROM "Sesion"
INTO counter
WHERE "Room_Name"=NEW."Room_Name" AND "Date"=NEW."Date";
IF (counter> 0) THEN -- Probably counter>1 as it's triggered after the transaction..
raise notice 'THERE'S A ROOM ALREADY!!';
raise exception 'The room is rented at that date';
END IF;
RETURN new;
EXCEPTION
WHEN raise_exception THEN
ROLLBACK TRANSACTION;
RETURN new;
END;$BODY$
LANGUAGE plpgsql VOLATILE NOT LEAKPROOF;
然后我创建触发器:
CREATE TRIGGER "roomOcupied" AFTER INSERT OR UPDATE OF "Room_Name", "Date"
ON "Sesion" FOR EACH ROW
EXECUTE PROCEDURE "checkRoom"();
距离我上一次使用 SQL 已经 2 年了,plsql 和 plpgsql 之间的变化让我抓狂。
【问题讨论】:
-
我从来没有使用过 plpgsql,但你仍然在做 ROLLBACK TRANSACTION。你只能引发错误,事务应该被任何调用它的东西回滚。我认为:P
-
您不需要显式回滚。除非您捕获异常并处理它,否则它会自动完成。
-
错误信息说明了一切:您不能在 PL/pgSQL 函数内提交或回滚。任何控制执行插入或更新的事务都需要回滚事务。
-
感谢 cmets,但问题仍然存在 :( 触发器被激活,然后异常来了,但问题是插入没有被系统回滚,即使我更改了触发器执行时刻到之前。出于这个原因,我尝试手动执行此操作。我从异常中收到消息,但有 1 行受到影响(添加的那一行):注意:已经有房间了!查询成功返回:受影响的一行,11 毫秒执行时间。
标签: sql postgresql triggers plpgsql unique-constraint