我有一张叫做赋值的表。我希望能够使用assignments.column或homework.column读取/写入此表中的所有列,我该怎么做?
我知道这不是你通常会做的事情。我需要能够在短时间内提供向后兼容性。
我们有一个iOS应用程序,目前直接对数据库进行postgresql查询。我们正在更新所有应用以使用API。在构建API的过程中,开发人员决定更改表的名称,因为我们(愚蠢地)认为我们不需要向后兼容。
现在,V1.0和API都需要能够写入此表,所以我以后不必做一些伏都教来稍后传输/合并数据... 我们正在使用Ruby on Rails获取API。
答案 0 :(得分:13)
答案 1 :(得分:1)
以您正在进行的工作为基础:
CREATE OR REPLACE FUNCTION trg_ia_insupdel()
RETURNS TRIGGER AS
$func$
DECLARE
_tbl CONSTANT regclass := 'iassignments_assignments';
_cols text;
_vals text;
BEGIN
CASE TG_OP
WHEN 'INSERT' THEN
INSERT INTO iassignments_assignments
VALUES NEW;
RETURN NEW;
WHEN 'UPDATE' THEN
SELECT INTO _cols, _vals
string_agg(quote_ident(attname), ', ') -- incl. pk col!
,string_agg('n.' || quote_ident(attname), ', ')
FROM pg_attribute
WHERE attrelid = _tbl -- _tbl converted to oid automatically
AND attnum > 0 -- no system columns
AND NOT attisdropped; -- no dropped (dead) columns
EXECUTE format('
UPDATE %s t
SET (%s) = (%s)
FROM (SELECT ($1).*) n
WHERE t.published_assignment_id
= ($2).published_assignment_id' -- match to OLD value of pk
, _tbl, _cols, _vals) -- _tbl converted to text automatically
USING NEW, OLD;
RETURN NEW;
WHEN 'DELETE' THEN
DELETE FROM iassignments_assignments
WHERE published_assignment_id = OLD.published_assignment_id;
RETURN OLD;
END CASE;
RETURN NULL; -- control should never reach this
END
$func$ LANGUAGE plpgsql;
CREATE TRIGGER insupbef
INSTEAD OF INSERT OR UPDATE OR DELETE ON assignments_published
FOR EACH ROW EXECUTE PROCEDURE trg_ia_insupdel();
动态SQL(在UPDATE
部分中)并不是绝对必要的,只是为了自动覆盖对表格布局的未来更改。表格和pk的名称仍然是硬编码的。
在没有sub-block的情况下更简单且可能更便宜(与您一样)。
使用(SELECT ($1).*)
代替较短的VALUES $1
来保留列名。
我的命名约定:我为触发器函数添加了trg_
,后跟一个表示目标表的缩写,最后是一个或多个标记ins
,up
和del
分别用于INSERT
,UPDATE
和DELETE
。触发器的名称是功能名称的副本,剥离了前两个部分。这纯粹是一种惯例和品味的问题,但事实证明这对我来说很有用,因为名字说明了目的并且仍然足够短。
在已经提到的相关答案中有更多解释:
Update multiple columns in a trigger function in plpgsql
答案 2 :(得分:0)
到目前为止,这是我使用触发功能的地方,我们将非常感谢任何反馈。它是http://vibhorkumar.wordpress.com/2011/10/28/instead-of-trigger/和Update multiple columns in a trigger function in plpgsql
的组合表:iassignments_assignments
列:
published_assignment_id
name
filepath
filename
link
teacher
due date
description
published
classrooms
查看:assignments_published - SELECT * FROM iassignments_assignments
assignments_published的触发功能
CREATE OR REPLACE FUNCTION assignments_published_trigger_func()
RETURNS TRIGGER
LANGUAGE plpgsql
AS $function$
BEGIN
IF TG_OP = 'INSERT' THEN
EXECUTE format('INSERT INTO %s SELECT ($1).*', 'iassignments_assignments')
USING NEW;
RETURN NEW;
ELSIF TG_OP = 'UPDATE' THEN
DECLARE
tbl = 'iassignments_assignments';
cols text;
vals text;
BEGIN
SELECT INTO cols, vals
string_agg(quote_ident(attname), ', ')
,string_agg('x.' || quote_ident(attname), ', ')
FROM pg_attribute
WHERE attrelid = tbl
AND NOT attisdropped -- no dropped (dead) columns
AND attnum > 0; -- no system columns
EXECUTE format('
UPDATE %s t
SET (%s) = (%s)
FROM (SELECT ($1).*) x
WHERE t.published_assignment_id = ($2).published_assignment_id'
, tbl, cols, vals)
USING NEW, OLD;
RETURN NEW;
END
ELSIF TG_OP = 'DELETE' THEN
DELETE FROM iassignments_assignments WHERE published_assignment_id=OLD.published_assignment_id;
RETURN NULL;
END IF;
RETURN NEW;
END;
$function$;
<强>触发强>
CREATE TRIGGER assignments_published_trigger
INSTEAD OF INSERT OR UPDATE OR DELETE ON
assignments_published FOR EACH ROW EXECUTE PROCEDURE assignments_published_trigger_func();
表:iassignments_classes
列:
class_assignment_id
guid
assignment_published_id
查看:assignments_class - SELECT * FROM assignments_classes
assignments_class的触发器功能
**一旦我收到对方的反馈并知道它的创建,我就会创建这个功能,所以我(希望)需要对此功能进行很少的更改。
<强>触发强>
CREATE TRIGGER assignments_class_trigger
INSTEAD OF INSERT OR UPDATE OR DELETE ON
assignments_class FOR EACH ROW EXECUTE PROCEDURE assignments_class_trigger_func();