【发布时间】:2015-03-17 00:17:04
【问题描述】:
我有一个包含 ID 和用户名(以及其他详细信息)的用户表,还有几个其他表使用各种列名 (CONSTRAINT some_name FOREIGN KEY (columnname) REFERENCES "user" (userid)) 引用此表。我需要做的是将用户名添加到引用表中(准备删除整个用户表)。这当然可以通过单个ALTER TABLE 和UPDATE 轻松完成,并且使用触发器使这些保持最新也(相当)容易。但让我有些烦恼的是触发功能。我可以为每个表使用单独的函数,但这似乎是多余的,因此我为此创建了一个通用函数:
CREATE OR REPLACE FUNCTION public.add_username() RETURNS trigger AS
$BODY$
DECLARE
sourcefield text;
targetfield text;
username text;
existing text;
BEGIN
IF (TG_NARGS != 2) THEN
RAISE EXCEPTION 'Need source field and target field parameters';
END IF;
sourcefield = TG_ARGV[0];
targetfield = TG_ARGV[1];
EXECUTE 'SELECT username FROM "user" WHERE userid = ($1).' || sourcefield INTO username USING NEW;
EXECUTE format('SELECT ($1).%I', targetfield) INTO existing USING NEW;
IF ((TG_OP = 'INSERT' AND existing IS NULL) OR (TG_OP = 'UPDATE' AND (existing IS NULL OR username != existing))) THEN
CASE targetfield
WHEN 'username' THEN
NEW.username := username;
WHEN 'modifiername' THEN
NEW.modifiername := username;
WHEN 'creatorname' THEN
NEW.creatorname := username;
.....
END CASE;
END IF;
RETURN NEW;
END;
$BODY$
LANGUAGE 'plpgsql' VOLATILE;
并使用触发功能:
CREATE TRIGGER some_trigger_name BEFORE UPDATE OR INSERT ON my_schema.my_table FOR EACH ROW EXECUTE PROCEDURE public.add_username('userid', 'username');
其工作方式是触发函数通过 TG_ARGV 接收原始源字段名称(例如 userid)和目标字段名称(username)。然后这些用于填写(可能)缺失的信息。所有这一切都很好,但我怎样才能摆脱CASE-mess?当我事先不知道字段的名称(或者更确切地说可能是很多东西)时,有没有办法动态修改 NEW 记录中的值?它在targetfield 参数中,但显然NEW.targetfield 不起作用,也不是NEW[targetfield] 之类的东西(例如Javascript)。
任何想法如何实现?除了使用例如 PL/Python..
【问题讨论】:
标签: postgresql plpgsql