Postgres 触发器以在类似导数 table 上插入更新删除
Postgres Trigger to INSERT UPDATE DELETE on similar derivative table
描述:
- 我是运行宁
postgresql 13
- 我在不同的模式下有两个表,
t1
和 t2
。
t2
是 t1
的导数,因为它们共享相同的东西
列和数据,但 t2
始终位于 t1
的下游
有效性。
- 两个表中的行共享相同的主键,我认为这将用作它们之间的 link。
提问:
- 我想创建一个触发器来反映
t1
中的任何更改并同步 t2
相同。
- 我从
INSERT
或UPDATE
开始,但如果很容易添加DELETE
,我也想实现它。
触发代码:
-- Trigger for t1 to t2 --
CREATE OR REPLACE FUNCTION t1_schema.sync_trigger()
RETURNS TRIGGER AS
$$
BEGIN
INSERT INTO t2_schema.t2 (col1, col2, col3)
VALUES (NEW.col1, NEW.col2, NEW.col3);
RETURN NEW;
END
$$ LANGUAGE plpgsql;
CREATE TRIGGER t1t2_test_sync
AFTER INSERT OR UPDATE ON t1_schema.t1
FOR EACH ROW
EXECUTE PROCEDURE t1_schema.sync_trigger()
当我执行此代码并在 t1
上执行测试 UPDATE
时,t2
上的同一行未反映更改或给我任何错误。
我试过:
- 离散标记所有行更新为
NEW.
格式,但 运行 进入 t2
中主键列不可编辑的问题。
- 在
VALUES
子句后添加一个 WHERE
子句,类似于 WHERE primary_key=NEW.primary_key
,但出现错误。
- 我看到的另一个选项是在
INSERT
,或在触发器中添加 WHEN
子句,但两者都没有
成功了。
(A) 基于触发器的解决方案
更新 t1
中的行时可能会出现错误,因为您的触发器函数试图在 t2
中插入新行,而该行已被相同的人插入到 t2
中插入t1
时触发函数。您需要复制和专门化您的触发器函数,一个用于插入,一个用于更新,一个用于删除,因为在 t2
上触发的处理方式不同 :
CREATE OR REPLACE FUNCTION t1_schema.sync_trigger_insert()
RETURNS TRIGGER AS
$$
BEGIN
INSERT INTO t2_schema.t2 (col1, col2, col3)
VALUES (NEW.col1, NEW.col2, NEW.col3);
RETURN NEW;
END
$$ LANGUAGE plpgsql;
CREATE TRIGGER t1t2_test_sync_insert
AFTER INSERT ON t1_schema.t1
FOR EACH ROW EXECUTE PROCEDURE t1_schema.sync_trigger_insert() ;
CREATE OR REPLACE FUNCTION t1_schema.sync_trigger_update()
RETURNS TRIGGER AS
$$
BEGIN
UPDATE t2
SET col1 = NEW.col1
, col2 = NEW.col2
, col3 = NEW.col3
WHERE primary_key_t2 = NEW. primary_key_t1 ; -- primary_key_t2 must be replaced by the set of columns which are in the primary key of t2 with AND operators, the same for NEW.primary_key_t1
RETURN NEW;
END
$$ LANGUAGE plpgsql;
CREATE TRIGGER t1t2_test_sync_update
AFTER UPDATE ON t1_schema.t1
FOR EACH ROW EXECUTE PROCEDURE t1_schema.sync_trigger_update() ;
CREATE OR REPLACE FUNCTION t1_schema.sync_trigger_delete()
RETURNS TRIGGER AS
$$
BEGIN
DELETE FROM t2
WHERE primary_key_t2 = NEW. primary_key_t1 ; -- primary_key_t2 must be replaced by the set of columns which are in the primary key of t2 with AND operators, the same for NEW.primary_key_t1
RETURN OLD; -- NEW is not available for triggers ON DELETE
END
$$ LANGUAGE plpgsql;
CREATE TRIGGER t1t2_test_sync_delete
AFTER DELETE ON t1_schema.t1
FOR EACH ROW EXECUTE PROCEDURE t1_schema.sync_trigger_delete() ;
(B) 基于外键的解决方案
t2 (col1,col2,col3)
上的外键引用 t1 (col1, col2, col3)
和选项 ON UPDATE CASCADE ON DELETE CASCADE
可能会以更简单有效的方式提供您预期的结果,请参阅 manual。在这种情况下,您不再需要触发器 ON UPDATE
和 ON DELETE
,但您仍然需要触发器 ON INSERT
.
您最好的方法是不要将 t2 创建为table。而是在 t1 上将其创建为 VIEW。这完全消除了使它们保持同步的触发器,因为实际源是相同的。遵循仅在 1 个位置存储单个数据点的概念。请记住,如果您将一件单品存放在 2 个地方,其中 1 个在某些时候会出错。 (参见 demo)。
create view soq2.t2 as
select *
from soq1.t1;
此外,如果您需要更改列名,请在创建视图期间使用别名;
create view soq2.t2a as
select t1_id as t2_id
, name as t2_name
, status as t2_status
from soq1.t1;
描述:
- 我是运行宁
postgresql 13
- 我在不同的模式下有两个表,
t1
和t2
。 t2
是t1
的导数,因为它们共享相同的东西 列和数据,但t2
始终位于t1
的下游 有效性。- 两个表中的行共享相同的主键,我认为这将用作它们之间的 link。
提问:
- 我想创建一个触发器来反映
t1
中的任何更改并同步t2
相同。 - 我从
INSERT
或UPDATE
开始,但如果很容易添加DELETE
,我也想实现它。
触发代码:
-- Trigger for t1 to t2 --
CREATE OR REPLACE FUNCTION t1_schema.sync_trigger()
RETURNS TRIGGER AS
$$
BEGIN
INSERT INTO t2_schema.t2 (col1, col2, col3)
VALUES (NEW.col1, NEW.col2, NEW.col3);
RETURN NEW;
END
$$ LANGUAGE plpgsql;
CREATE TRIGGER t1t2_test_sync
AFTER INSERT OR UPDATE ON t1_schema.t1
FOR EACH ROW
EXECUTE PROCEDURE t1_schema.sync_trigger()
当我执行此代码并在 t1
上执行测试 UPDATE
时,t2
上的同一行未反映更改或给我任何错误。
我试过:
- 离散标记所有行更新为
NEW.
格式,但 运行 进入t2
中主键列不可编辑的问题。 - 在
VALUES
子句后添加一个WHERE
子句,类似于WHERE primary_key=NEW.primary_key
,但出现错误。 - 我看到的另一个选项是在
INSERT
,或在触发器中添加WHEN
子句,但两者都没有 成功了。
(A) 基于触发器的解决方案
更新 t1
中的行时可能会出现错误,因为您的触发器函数试图在 t2
中插入新行,而该行已被相同的人插入到 t2
中插入t1
时触发函数。您需要复制和专门化您的触发器函数,一个用于插入,一个用于更新,一个用于删除,因为在 t2
上触发的处理方式不同 :
CREATE OR REPLACE FUNCTION t1_schema.sync_trigger_insert()
RETURNS TRIGGER AS
$$
BEGIN
INSERT INTO t2_schema.t2 (col1, col2, col3)
VALUES (NEW.col1, NEW.col2, NEW.col3);
RETURN NEW;
END
$$ LANGUAGE plpgsql;
CREATE TRIGGER t1t2_test_sync_insert
AFTER INSERT ON t1_schema.t1
FOR EACH ROW EXECUTE PROCEDURE t1_schema.sync_trigger_insert() ;
CREATE OR REPLACE FUNCTION t1_schema.sync_trigger_update()
RETURNS TRIGGER AS
$$
BEGIN
UPDATE t2
SET col1 = NEW.col1
, col2 = NEW.col2
, col3 = NEW.col3
WHERE primary_key_t2 = NEW. primary_key_t1 ; -- primary_key_t2 must be replaced by the set of columns which are in the primary key of t2 with AND operators, the same for NEW.primary_key_t1
RETURN NEW;
END
$$ LANGUAGE plpgsql;
CREATE TRIGGER t1t2_test_sync_update
AFTER UPDATE ON t1_schema.t1
FOR EACH ROW EXECUTE PROCEDURE t1_schema.sync_trigger_update() ;
CREATE OR REPLACE FUNCTION t1_schema.sync_trigger_delete()
RETURNS TRIGGER AS
$$
BEGIN
DELETE FROM t2
WHERE primary_key_t2 = NEW. primary_key_t1 ; -- primary_key_t2 must be replaced by the set of columns which are in the primary key of t2 with AND operators, the same for NEW.primary_key_t1
RETURN OLD; -- NEW is not available for triggers ON DELETE
END
$$ LANGUAGE plpgsql;
CREATE TRIGGER t1t2_test_sync_delete
AFTER DELETE ON t1_schema.t1
FOR EACH ROW EXECUTE PROCEDURE t1_schema.sync_trigger_delete() ;
(B) 基于外键的解决方案
t2 (col1,col2,col3)
上的外键引用 t1 (col1, col2, col3)
和选项 ON UPDATE CASCADE ON DELETE CASCADE
可能会以更简单有效的方式提供您预期的结果,请参阅 manual。在这种情况下,您不再需要触发器 ON UPDATE
和 ON DELETE
,但您仍然需要触发器 ON INSERT
.
您最好的方法是不要将 t2 创建为table。而是在 t1 上将其创建为 VIEW。这完全消除了使它们保持同步的触发器,因为实际源是相同的。遵循仅在 1 个位置存储单个数据点的概念。请记住,如果您将一件单品存放在 2 个地方,其中 1 个在某些时候会出错。 (参见 demo)。
create view soq2.t2 as
select *
from soq1.t1;
此外,如果您需要更改列名,请在创建视图期间使用别名;
create view soq2.t2a as
select t1_id as t2_id
, name as t2_name
, status as t2_status
from soq1.t1;