我遇到了非常奇怪的错误。从PostgreSQL服务器版本9迁移到<strong>8.4</strong> PostgreSQL触发器引发错误55000
简短说明:
如果插入之前,给定表的触发器为每一行或更新和条件语句一个使用(如果其他)TG_OP值检查和OLD对象,以下
ERROR: record "old" is not assigned yet
DETAIL: The tuple structure of a not-yet-assigned record is indeterminate.
详细描述:
doinng INSERT当错误引起3210有以下DB结构:
CREATE TABLE table1
(
id serial NOT NULL,
name character varying(256),
CONSTRAINT table1_pkey PRIMARY KEY (id)
)
WITH (OIDS=FALSE);
CREATE OR REPLACE FUNCTION exemplary_function()
RETURNS trigger AS
$BODY$ BEGIN
IF TG_OP = 'INSERT' OR OLD.name <> NEW.name THEN
NEW.name = 'someName';
END IF;
RETURN NEW;
END;
$BODY$
LANGUAGE plpgsql VOLATILE COST 100;
CREATE TRIGGER trigger1
BEFORE INSERT OR UPDATE
ON table1
FOR EACH ROW EXECUTE PROCEDURE exemplary_function();
和下面的SQL查询触发错误:
INSERT INTO table1 (name) VALUES ('other name')
好像解析器不停止在TG_OP = 'INSERT'
条件(它应该,因为这是事实),但检查另一个并触发错误。 有趣的是,我只能在8.4版本上重现它。
对于INSERT语句,OLD不存在。 (你已经知道了;其他人访问这里可能不会)。为了测试,可能需要重写'TG_OP ='INSERT''和'OLD.name <> NEW.name'单独的条件语句。即,将OLD.name <> NEW.name'移动到ELSE子句或ELSEIF子句。 – 2013-05-08 15:44:50
@ MikeSherrill'Catcall',你是对的,但这是关键。把它分成单独的条件就可以完成这项工作,但重点是将它集于一身。在真实的例子中,我是这样做的临时解决方案,但我不得不复制 - 粘贴整块代码... – Wiktor 2013-05-08 15:51:59
如果工作,我的下一个测试可能是添加parens以保证正确的优先级:IF(TG_OP ='INSERT ')OR(OLD.name <> NEW.name)THEN'。话虽如此,我并不知道8.4中的优先级错误,但我以前一直不知道这样的东西。 – 2013-05-08 15:56:10