用相应的值更新 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.name
和 A.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?
我有两个 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.name
和 A.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?