Smi*_*ley 1 postgresql triggers function plpgsql
我对 Postgres 非常陌生,现在我的任务是创建一个在插入后触发的触发器。基本上,我会让脚本执行插入操作,触发触发器,该触发器会根据 Insert 语句中的参数从另一个表中抓取一个字段,然后使用另一个表中的值更新新插入的记录。
INSERT INTO "TableA" VALUES ('ABC-101', 'John Doe', '')
PersonID | Name | Address
------------------------------
ABC-101 John Doe
Run Code Online (Sandbox Code Playgroud)
CREATE OR REPLACE FUNCTION fn_getaddress()
RETURNS trigger AS
$BODY$
DECLARE
PersonID TEXT;
BEGIN
PersonID := TG_ARGV[0];
UPDATE "TableA"
SET "Address" = (SELECT "Address"
FROM "TableB"
WHERE "PersonID" = PersonID);
RETURN null;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
Run Code Online (Sandbox Code Playgroud)
这是我的触发器:
CREATE TRIGGER tr_getaddress
AFTER INSERT
ON TableA
FOR EACH ROW
EXECUTE PROCEDURE fn_getaddress(personid);
Run Code Online (Sandbox Code Playgroud)
所以基本上,我在 TableB 中有一个字段(比如地址),我需要抓取它以完成 TableA 中的记录。我正在使用一个 ID 来引用从 TableB 中获取的地址。
您不需要将值传递给触发器。触发器可以通过隐式记录完全访问插入行中的所有列new。
您也不需要UPDATE语句来更改插入的行。您只需为new记录中的字段赋值:
CREATE OR REPLACE FUNCTION fn_getaddress()
RETURNS trigger AS
$BODY$
DECLARE
l_address text;
BEGIN
SELECT "Address"
into l_address
FROM "TableB"
WHERE "PersonID" = new."PersonID"
new."Address" := l_address;
RETURN new; --<<< important
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
Run Code Online (Sandbox Code Playgroud)
但是,您不能更改after触发器中插入的行,您需要一个before触发器:
CREATE TRIGGER tr_getaddress
BEFORE INSERT --<<< important
ON "TableA"
FOR EACH ROW
EXECUTE PROCEDURE fn_getaddress(); --<< no parameter necessary
Run Code Online (Sandbox Code Playgroud)
但是像这样复制数据通常是一个非常糟糕的主意。如果您需要来自两个表的信息,为什么不加入这两个表?
与你的问题无关,但你真的应该避免那些可怕的引用标识符。他们的麻烦比他们值得