如何使用触发函数将行的值从一列移动到另一列?

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(nameab 列),备份 table 应该移动到“下一个”列。像 name1name2a1a2b1b2name2name3 等。因此,例如,如果我将 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