这可能吗?我有兴趣了解在UPDATE请求中指定了哪些列,而不管事实上,正在发送的新值可能是也可能不是存储在数据库中的。
我想这样做的原因是因为我们有一个表可以从多个来源接收更新。以前,我们没有记录更新来源的来源。现在,该表存储哪些来源已经执行了最新的更新。我们可以更改一些来源来发送标识符,但这不是一切的选择。所以我想能够识别UPDATE请求何时没有标识符,因此我可以用默认值替换。
像@ A.H。在他的评论中写道,如果“源”没有“发送标识符”,列将不会更改。那么你不能检测当前的UPDATE是由与最后一个相同的源完成的,还是根本没有更改列的源。换句话说:这不能正常工作。
如果“源”可以通过these session information functions中的任何一个来识别,你可以使用它。喜欢:
NEW.column = session_user;
无条件地为每一次更新。
一般解决方案
我找到了一个如何解决原来的问题。在列不更新的任何更新(不在UPDATE的SET列表中),该列将被设置为默认值。
关键要素是Postgresql 9.0中引入的per-column triggers:
The trigger will only fire if at least one of the listed columns is
mentioned as a target of the UPDATE command.
这是我找到的唯一简单的方法来区分列是否更新与旧值相同的新值,而不是更新。
可以解析current_query()
返回的文本。
我假设列coligned NOT NULL。
>步骤1:如果不变,将col设置为NULL:
CREATE OR REPLACE FUNCTION trg_tbl_upbef_step1() RETURNS trigger AS $BODY$ BEGIN IF OLD.col = NEW.col THEN NEW.col := NULL; -- "impossible" value END IF; RETURN NEW; END; $BODY$ LANGUAGE plpgsql;
> Step2:恢复旧值触发器将仅被触发,如果该值实际更新:
CREATE OR REPLACE FUNCTION trg_tbl_upbef_step2() RETURNS trigger AS $BODY$ BEGIN IF NEW.col IS NULL THEN NEW.col := OLD.col; END IF; RETURN NEW; END; $BODY$ LANGUAGE plpgsql;
>步骤3:现在我们可以识别缺少的更新,并设置一个默认值:
CREATE OR REPLACE FUNCTION trg_tbl_upbef_step3() RETURNS trigger AS $BODY$ BEGIN IF NEW.col IS NULL THEN NEW.col := 'default value'; END IF; RETURN NEW; END; $BODY$ LANGUAGE plpgsql;
实现触发器,step2是每列触发器:
CREATE TRIGGER upbef_step1 BEFORE UPDATE ON tbl FOR EACH ROW EXECUTE PROCEDURE trg_tbl_upbef_step1(); CREATE TRIGGER upbef_step2 BEFORE UPDATE OF col ON tbl -- key element FOR EACH ROW EXECUTE PROCEDURE trg_tbl_upbef_step2(); CREATE TRIGGER upbef_step3 BEFORE UPDATE ON tbl FOR EACH ROW EXECUTE PROCEDURE trg_tbl_upbef_step3();
触发器的名称是相关的,因为它们将按字母顺序被触发!
如果我们有一些类似“per-not-column”的触发器,或任何其他方式可以轻松地检查触发器中UPDATE的目标列表,那么可以简化这个过程。
如果您的列可以为NULL,请使用任何其他“不可能”的温度。值并检查NULL另外:
IF OLD.col IS NOT DISTINCT FROM NEW.col THEN NEW.col := '#impossible_value#'; END IF;