我想创建每次更改任何列时触发的触发器 - 无论是新更新还是新插入。我创造了这样的东西:
CREATE TRIGGER textsearch
BEFORE INSERT OR UPDATE
ON table
FOR EACH ROW
EXECUTE PROCEDURE trigger();
和trigger()函数的主体是:
BEGIN
NEW.ts := (
SELECT COALESCE(a::text,'') || ' ' ||
COALESCE(b::int,'') || ' ' ||
COALESCE(c::text,'') || ' ' ||
COALESCE(d::int, '') || ' ' ||
COALESCE(e::text,'')
FROM table
WHERE table.id = new.id);
RETURN NEW;
END
我希望很清楚我想做什么。
我的问题是触发器仅在更新时触发,而不是在插入时触发。我猜这不行,因为我有INSFORE INSERT或UPDATE,但是如果我把它改成AFTER INSERT或UPDATE那么它既不适用于INSERT也不适用于UPDATE。
答案 0 :(得分:1)
您需要直接使用NEW
记录:
BEGIN
NEW.ts := concat_ws(' ', NEW.a::text, NEW.b::TEXT, NEW.c::TEXT);
RETURN NEW;
END;
concat_ws
优于||
的优势在于concat_ws
会以不同的方式处理NULL
值。 'foo'||NULL
的结果将产生NULL
,这很可能不是您想要的。 concat_ws
将使用空字符串NULL
值。
答案 1 :(得分:0)
它不起作用,因为你在函数内部调用SELECT。
当它运行BEFORE INSERT
时,没有要选择的行,是吗?
实际上,BEFORE UPDATE
无论如何你都会看到该行的“旧”版本,不是吗?
只需直接使用字段:NEW.a
等,而不是选择。
作为编辑 - 这是一个显示触发器功能可以看到的示例。正如您在BEFORE触发器中所期望的那样,这是非常的。
BEGIN;
CREATE TABLE tt (i int, t text, PRIMARY KEY (i));
CREATE FUNCTION trigfn() RETURNS TRIGGER AS $$
DECLARE
sv text;
BEGIN
SELECT t INTO sv FROM tt WHERE i = NEW.i;
RAISE NOTICE 'new value = %, selected value = %', NEW.t, sv;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER trigtest BEFORE INSERT OR UPDATE ON tt FOR EACH ROW EXECUTE PROCEDURE trigfn();
INSERT INTO tt VALUES (1,'a1');
UPDATE tt SET t = 'a2' WHERE i = 1;
ROLLBACK;
答案 2 :(得分:0)
我必须改变你的coalesce来改为使用整数占位符。正如a_horse_with_no_name所提到的,这可能会以null值结束,但您可以看到如何运行您的特定代码示例。我收录了#34; RAISE NOTICE"这些行仅用于调试目的。
根据您提供的信息,以下内容适用于我:
CREATE TABLE my_table (id SERIAL NOT NULL,a TEXT,b INTEGER,c TEXT,d INTEGER,e TEXT);
CREATE OR REPLACE FUNCTION my_triggered_procedure() RETURNS trigger AS $$
BEGIN
if(TG_OP = 'UPDATE' OR TG_OP = 'INSERT') THEN
NEW.ts := (SELECT COALESCE(a::text,'') || ' ' ||
COALESCE(b::int,0) || ' ' ||
COALESCE(c::text,'') || ' ' ||
COALESCE(d::int, 0) || ' ' ||
COALESCE(e::text,'')
FROM my_table
WHERE id=NEW.id);
RAISE NOTICE 'INSERT OR UPDATE with new ts = %',NEW.ts;
RETURN NEW;
ELSIF (TG_OP = 'DELETE') THEN
OLD.ts := ' ';
RAISE NOTICE 'DELETED old id: %',OLD.id;
RETURN OLD;
END IF;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER text_search
AFTER INSERT OR UPDATE OR DELETE
ON my_table
FOR EACH ROW
EXECUTE PROCEDURE my_triggered_procedure();
INSERT INTO my_table (a,b,c,d,e) VALUES('text11',12,'text21',3,'text4');
>NOTICE: INSERT OR UPDATE with new ts = text11 12 text21 3 text4
>INSERT 0 1
DELETE FROM my_table WHERE id=24;
>NOTICE: DELETED ID = 24
>DELETE 1