如何使用触发函数将行的值从一列移动到另一列?
How to move values of a row, from a column to another with a trigger function?
我有两个 table。一个主要 table 和一种“备份”table.
主要 table 看起来像这样:
id | name | a | b
int | text | int | int
-------+----------+-------+-------
1 | Joe | 100 | 10
2 | Bill | 200 | 40
3 | Frank | 200 | 20
4 | Jack | 100 | 10
备份 table 如下所示:
id | name1 | a1 | b1 | name2 | a2 | b2 | name3 | a3 | b3
int | text | int | int | text | int | int | text | int | int
-------+----------+-------+-------+--------+------+-----+--------+-----+----
1 | Joe | 100 | 10 | | | | | |
2 | Bill | 200 | 40 | | | | | |
3 | Frank | 200 | 20 | | | | | |
4 | Jack | 100 | 10 | | | | | |
我在这里想要的是,如果我更新我的主要 table(name
或 a
或 b
列),备份 table 应该移动到“下一个”列。像 name1
到 name2
、a1
到 a2
、b1
到 b2
、name2
到 name3
等。因此,例如,如果我将 Joe
更新为 Don
,备份 table 将如下所示:
UPDATE myschema.maintable
SET name = 'Don'
WHERE id = 1;
id | name1 | a1 | b1 | name2 | a2 | b2 | name3 | a3 | b3
int | text | int | int | text | int | int | text | int | int
-------+----------+-------+-------+--------+------+-----+--------+-----+----
1 | Don | 100 | 10 | Joe | 100 | 10 | | |
2 | Bill | 200 | 40 | | | | | |
3 | Frank | 200 | 20 | | | | | |
4 | Jack | 100 | 10 | | | | | |
现在我知道这是一种非常糟糕的备份方式table,但不幸的是它超出了我的控制范围,这就是我必须这样做的方式。
我已经尝试并期望工作的是:
CREATE OR REPLACE FUNCTION table_update_func()
RETURNS TRIGGER AS
$BODY$
BEGIN
UPDATE myschema.backuptable
SET
name3 = name2,
a3 = a2,
b3 = b2,
name2 = name1,
b2 = a1,
b2 = b1,
name1 = name,
a1 = a,
b1 = b
FROM myschema.maintable
WHERE maintable.id = backuptable.id;
RETURN NULL;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
CREATE TRIGGER table_update_trig
BEFORE UPDATE
ON myschema.maintable
FOR EACH ROW
WHEN (OLD.* IS DISTINCT FROM NEW.*)
EXECUTE PROCEDURE table_update_func();
如果我在 maintale
中更新某些内容,它运行时不会出现错误,但它会移动每一行中的列,而不仅仅是我更新的列。我哪里做错了?我很确定我的条件WHERE maintable.id = backup.id;
不好,但我不知道该如何解决这个问题。
您正在将主table 中的每一行加入备份table,这就是为什么您总是更新备份table 中的所有行。您在那里不需要 FROM 子句,因为您在 new
记录中有可用的 UPDATE 行的 ID。
CREATE OR REPLACE FUNCTION table_update_func()
RETURNS TRIGGER AS
$BODY$
BEGIN
UPDATE myschema.backuptable
SET name3 = name2,
a3 = a2,
b3 = b2,
name2 = name1,
b2 = a1,
b2 = b1,
name1 = new.name, -- reference the values of the new record here
a1 = new.a,
b1 = new.b
WHERE backuptable.id = new.id; --<< no FROM clause necessary
RETURN new; --<< IMPORTANT for a BEFORE UPDATE trigger!
END;
$BODY$
LANGUAGE plpgsql VOLATILE
我有两个 table。一个主要 table 和一种“备份”table.
主要 table 看起来像这样:
id | name | a | b
int | text | int | int
-------+----------+-------+-------
1 | Joe | 100 | 10
2 | Bill | 200 | 40
3 | Frank | 200 | 20
4 | Jack | 100 | 10
备份 table 如下所示:
id | name1 | a1 | b1 | name2 | a2 | b2 | name3 | a3 | b3
int | text | int | int | text | int | int | text | int | int
-------+----------+-------+-------+--------+------+-----+--------+-----+----
1 | Joe | 100 | 10 | | | | | |
2 | Bill | 200 | 40 | | | | | |
3 | Frank | 200 | 20 | | | | | |
4 | Jack | 100 | 10 | | | | | |
我在这里想要的是,如果我更新我的主要 table(name
或 a
或 b
列),备份 table 应该移动到“下一个”列。像 name1
到 name2
、a1
到 a2
、b1
到 b2
、name2
到 name3
等。因此,例如,如果我将 Joe
更新为 Don
,备份 table 将如下所示:
UPDATE myschema.maintable
SET name = 'Don'
WHERE id = 1;
id | name1 | a1 | b1 | name2 | a2 | b2 | name3 | a3 | b3
int | text | int | int | text | int | int | text | int | int
-------+----------+-------+-------+--------+------+-----+--------+-----+----
1 | Don | 100 | 10 | Joe | 100 | 10 | | |
2 | Bill | 200 | 40 | | | | | |
3 | Frank | 200 | 20 | | | | | |
4 | Jack | 100 | 10 | | | | | |
现在我知道这是一种非常糟糕的备份方式table,但不幸的是它超出了我的控制范围,这就是我必须这样做的方式。
我已经尝试并期望工作的是:
CREATE OR REPLACE FUNCTION table_update_func()
RETURNS TRIGGER AS
$BODY$
BEGIN
UPDATE myschema.backuptable
SET
name3 = name2,
a3 = a2,
b3 = b2,
name2 = name1,
b2 = a1,
b2 = b1,
name1 = name,
a1 = a,
b1 = b
FROM myschema.maintable
WHERE maintable.id = backuptable.id;
RETURN NULL;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
CREATE TRIGGER table_update_trig
BEFORE UPDATE
ON myschema.maintable
FOR EACH ROW
WHEN (OLD.* IS DISTINCT FROM NEW.*)
EXECUTE PROCEDURE table_update_func();
如果我在 maintale
中更新某些内容,它运行时不会出现错误,但它会移动每一行中的列,而不仅仅是我更新的列。我哪里做错了?我很确定我的条件WHERE maintable.id = backup.id;
不好,但我不知道该如何解决这个问题。
您正在将主table 中的每一行加入备份table,这就是为什么您总是更新备份table 中的所有行。您在那里不需要 FROM 子句,因为您在 new
记录中有可用的 UPDATE 行的 ID。
CREATE OR REPLACE FUNCTION table_update_func()
RETURNS TRIGGER AS
$BODY$
BEGIN
UPDATE myschema.backuptable
SET name3 = name2,
a3 = a2,
b3 = b2,
name2 = name1,
b2 = a1,
b2 = b1,
name1 = new.name, -- reference the values of the new record here
a1 = new.a,
b1 = new.b
WHERE backuptable.id = new.id; --<< no FROM clause necessary
RETURN new; --<< IMPORTANT for a BEFORE UPDATE trigger!
END;
$BODY$
LANGUAGE plpgsql VOLATILE