用相应的值更新 table 的每一行

Update each row of a table with the corresponding value

我有两个 Postgres tables:

create table A(
   id_A  serial not null,
   column_A  varchar  null;
   ...);

create table B(
   id_B  serial  not null,
   id_A  int4  not null,
   name  varchar  null,
   keywords  varchar  null,
   ...);

table A 的一个元素关联到 table B 的多个元素并且 table B 的一个元素关联到 table A.

的一个元素

table B 中的列关键字是 B.nameA.column_A 列值的串联:

B.keywords := B.name || A.column_A

如果更新了 A.column_A 的值,如何使用触发器更新 table B 中每行的 B.keywords 列?

换句话说,我想做这样的事情(伪代码):

FOR EACH ROW current_row IN TABLE B
   UPDATE B SET keywords = (SELECT B.name || A.column_A
                            FROM B INNER JOIN A ON B.id_A = A.id_A
                            WHERE B.id_B = current_row.id_B)
   WHERE id_B = current_row.id_B;

您的触发器必须在更新 A 时调用一个函数:

CREATE OR REPLACE FUNCTION update_b()
  RETURNS TRIGGER
AS $$
BEGIN
  UPDATE B
  SET keywords = name || NEW.column_A
  WHERE id_A = NEW.id_A;
  return NEW;
END
$$ LANGUAGE plpgsql;


CREATE TRIGGER update_b_trigger AFTER UPDATE OF column_A
ON A
FOR EACH ROW
EXECUTE PROCEDURE update_b();

在 table B 上添加触发器 BEFORE INSERT OR UPDATE 以设置关键字可能也很有用。

你的方法被设计破坏了。不要试图使派生值在 table 中保持最新。这对于并发访问是不安全的。可能会出现各种并发症。您膨胀 table B(和备份)并损害写入性能。

而是使用 VIEW (or a MATERIALIZED VIEW):

CREATE VIEW ab AS
SELECT B.*, concat_ws(', ', B.name, A.column_A) AS keywords
FROM   B
LEFT   JOIN A USING (id_A);

使用下面更新的 table 定义,参照完整性得到保证,您可以使用 [INNER] JOIN 而不是 LEFT [OUTER] JOIN

或者甚至一个简单的查询就足够了...

无论哪种方式,您需要 table PRIMARY KEY constraint in table A and a FOREIGN KEY constraint B:

CREATE TABLE A (
   id_A     serial PRIMARY KEY,
   column_A varchar
   ...);


CREATE TABLE B (
   id_B  serial PRIMARY KEY,
   id_A  int4 NOT NULL REFERENCES A(id_A),
   name  varchar
   --  and *no* redundant "keywords" column!
   ...);

关于连接字符串:

  • How to concatenate columns in a Postgres SELECT?

而且我不会使用 CaMeL 大小写标识符:

  • Are PostgreSQL column names case-sensitive?