在这种情况下,我有两个表。一个是我的 "热同步 "表,它是近乎实时地将数据从我的Salesforce Org同步到Postgres表的双向同步。当源系统(Salesforce)中的数据发生变化时,它会更新Postgres上的那个表。
在Postgres的这个表上,我有一个触发器,运行一些逻辑。基本上,它检查触发它的记录是否有符合某些业务逻辑的发送日期,将该行复制到另一个schematable中以 "存档"。
这一切都能正常工作。
然而我需要做的是,一旦这条记录被复制到另一个表中,我需要更新记录热同步表的状态。由于它是双向的,这将使Salesforce中的数据能够反映我从Postgres端进行的更改。
我是否可以将这个更新语句放在发起的触发器内,或者这样做会不会引起递归问题?
CREATE FUNCTION salesforce.archivelogicfunc()
RETURNS trigger
LANGUAGE 'plpgsql'
COST 100
VOLATILE NOT LEAKPROOF
AS $BODY$ BEGIN
IF (DATE(NEW.et4ae5__datesent__c) < NOW() - INTERVAL '180 days'
AND DATE(NEW.et4ae5__datesent__c) > NOW() - INTERVAL '540 days')
THEN
INSERT INTO archive.individualemailresult__c
(dateopened__c,
numberoftotalclicks__c,
datebounced__c,
fromname__c,
hardbounce__c,
fromaddress__c,
softbounce__c,
name,
lastmodifieddate,
opened__c,
ownerid,
subjectline__c,
isdeleted,
contact__c,
systemmodstamp,
lastmodifiedbyid,
datesent__c,
dateunsubscribed__c,
createddate,
createdbyid,
lead__c,
tracking_as_of__c,
numberofuniqueclicks__c,
senddefinition__c,
mergeid__c,
triggeredsenddefinition__c,
sfid,
id,
_hc_lastop,
_hc_err,
isarchived)
VALUES
(NEW.et4ae5__dateopened__c,
NEW.et4ae5__numberoftotalclicks__c,
NEW.et4ae5__datebounced__c,
NEW.et4ae5__fromname__c,
NEW.et4ae5__hardbounce__c,
NEW.et4ae5__fromaddress__c,
NEW.et4ae5__softbounce__c,
NEW.name,
NEW.lastmodifieddate,
NEW.et4ae5__opened__c,
NEW.ownerid,
NEW.et4ae5__subjectline__c,
NEW.isdeleted,
NEW.et4ae5__contact__c,
NEW.systemmodstamp,
NEW.lastmodifiedbyid,
NEW.et4ae5__datesent__c,
NEW.et4ae5__dateunsubscribed__c,
NEW.createddate,
NEW.createdbyid,
NEW.et4ae5__lead__c,
NEW.et4ae5__tracking_as_of__c,
NEW.et4ae5__numberofuniqueclicks__c,
NEW.et4ae5__senddefinition__c,
NEW.et4ae5__mergeid__c,
NEW.et4ae5__triggeredsenddefinition__c,
NEW.sfid,
NEW.id,
NEW._hc_lastop,
NEW._hc_err,
NEW.isarchived__c)
ON CONFLICT (id)
DO NOTHING;
-- Update SF to reflect the archive
UPDATE salesforce."et4ae5__individualemailresult__c" SET isarchived__c = true, isdeleted = true WHERE id = NEW.id;
END IF;
RETURN NULL;
END;
$BODY$;
ALTER FUNCTION salesforce.archivelogicfunc()
OWNER TO ....;
我的理解是 NEW.*
只会包含首先导致触发器被触发的记录。因此,如果我的触发器是针对一条记录而触发的,那么更新语句中的 NEW.id
应该只更新源表上的一条记录?
试图确保触发器不会因为更新语句而再次触发,造成一些我不期望的递归循环。
我关心的是
on conflict
但更新后会再次运行,再次等。原先的触发器被启动 AFTER INSERT/UPDATE
.
触发器:
CREATE TRIGGER archivelogic_firetrigger
AFTER INSERT OR UPDATE
ON salesforce.et4ae5__individualemailresult__c
FOR EACH ROW
EXECUTE PROCEDURE salesforce.archivelogicfunc();
更新。我添加了一个 WHEN
条件下,我的触发器。在基本的测试中,它似乎是有效的,但如果有建议,愿意接受任何其他的建议。
CREATE TRIGGER archivelogic_firetrigger
AFTER INSERT OR UPDATE
ON salesforce.et4ae5__individualemailresult__c
FOR EACH ROW
WHEN (pg_trigger_depth() = 0) // <-- Added to prevent recursion
EXECUTE PROCEDURE salesforce.archivelogicfunc();
最简单的就是把它做成一个 "热同步 "表。before
触发器,并将更新替换为
NEW.isarchived__c = true;
NEW. isdeleted = true;
[...]
RETURN NEW;
否则,你可以在运行触发器之前对行进行过滤:只有当isarchived__c和isdeleted没有改变时,才会被调用(虽然这可能很危险,想象一下有人更新了所有字段)。
CREATE TRIGGER archivelogic_firetrigger
AFTER INSERT OR UPDATE
ON salesforce.et4ae5__individualemailresult__c
FOR EACH ROW
WHEN (NEW.isarchived__c IS NOT DISTINCT FROM OLD.isarchived__c
AND NEW.isdeleted IS NOT DISTINCT FROM OLD.isdeleted )
EXECUTE PROCEDURE salesforce.archivelogicfunc();