PostgreSQL触发器RAISE EXCEPTION适用于INSERT但不适用于UPDATE

时间:2014-03-13 15:27:29

标签: postgresql triggers plpgsql

我在PostgreSQL 9.3中定义了一个触发器,它根据attribute_group_attribute.default_value的值检查attribute_type.max_length的长度:


CREATE OR REPLACE FUNCTION trigger_function()
  RETURNS trigger AS 
$BODY$
DECLARE
    is_longer_than_max_length BOOLEAN;
BEGIN
    IF (NEW.default_value IS NOT NULL) THEN
        SELECT length(NEW.default_value) > attribute_type.max_length 
        INTO is_longer_than_max_length FROM attribute_group_attribute 
        JOIN attribute ON NEW.attribute_id = attribute.id JOIN attribute_type 
        ON attribute.attribute_type_id = attribute_type.id;

        IF (is_longer_than_max_length) THEN
            RAISE EXCEPTION 'Attribute type with id % has max length of %, 
            while attribute default value % has a length of %.', 
            attribute_type.id, attribute_type.max_length, NEW.default_value,
            length(NEW.default_value) USING ERRCODE='20808';
        END IF;
    END IF;
    RETURN NEW;
END
$BODY$
  LANGUAGE 'plpgsql' SECURITY INVOKER
;

CREATE TRIGGER trigger_name BEFORE INSERT OR UPDATE ON attribute_group_attribute 
FOR EACH ROW EXECUTE PROCEDURE trigger_function()
;

触发器在INSERT上正常工作并提升EXCEPTION。但在UPDATE我收到此错误:


ERROR:  missing FROM-clause entry for table "attribute_type" at character 8
QUERY:  SELECT attribute_type.id
CONTEXT:  PL/pgSQL function trg_func_attr_group_attr_attr_type() line 8 at RAISE

2 个答案:

答案 0 :(得分:1)

查询:

SELECT length(NEW.default_value) > attribute_type.max_length 
INTO is_longer_than_max_length FROM attribute_group_attribute 
JOIN attribute ON NEW.attribute_id = attribute.id JOIN attribute_type 
ON attribute.attribute_type_id = attribute_type.id;

没有感觉。 attribute_group_attribute子句中有FROM,但此表没有过滤器。

您需要以下内容:

SELECT length(NEW.default_value) > attribute_type.max_length 
INTO is_longer_than_max_length 
FROM attribute 
JOIN attribute_type ON attribute.attribute_type_id = attribute_type.id
WHERE NEW.attribute_id = attribute.id;

您还需要先选择attribute_type.id, attribute_type.max_length到函数变量中,然后才能在RAISE EXCEPTION语句中使用它们。

答案 1 :(得分:0)

Igor Romanchenko's suggestions的帮助下,我提出了这个能够实现我想要的解决方案:


CREATE OR REPLACE FUNCTION trigger_function()
  RETURNS trigger AS 
$BODY$
DECLARE
    attribute_type_id numeric(12,0);
    attribute_type_max_length numeric(9,0);
    is_longer_than_max_length BOOLEAN;
BEGIN
    IF (NEW.default_value IS NOT NULL) THEN
        SELECT attribute_type.id, attribute_type.max_length, 
        length(NEW.default_value) > attribute_type.max_length 
        INTO attribute_type_id, attribute_type_max_length, 
        is_longer_than_max_length FROM attribute_group_attribute 
        JOIN attribute ON NEW.attribute_id = attribute.id JOIN attribute_type 
        ON attribute.attribute_type_id = attribute_type.id;
        IF (is_longer_than_max_length) THEN
            RAISE EXCEPTION 'Attribute type with id % has max length of %, while 
            attribute default value % has a length of %.', attribute_type_id,
            attribute_type_max_length, NEW.default_value, 
            length(NEW.default_value) USING ERRCODE='20808';
        END IF;
    END IF;
    RETURN NEW;
END
$BODY$
  LANGUAGE 'plpgsql' SECURITY INVOKER
;

CREATE TRIGGER trigger_name BEFORE INSERT OR UPDATE ON attribute_group_attribute 
FOR EACH ROW EXECUTE PROCEDURE trigger_function()
;