CREATE TABLE accounts (
id SERIAL PRIMARY KEY,
email TEXT,
verified BOOLEAN DEFAULT FALSE,
...
);
CREATE OR REPLACE FUNCTION fn_reset_verified() RETURNS TRIGGER AS $$
BEGIN
IF (
OLD.email != NEW.email -- do nothing if no change
) THEN
RAISE NOTICE 'UPDATE';
UPDATE users SET verified=FALSE WHERE id=NEW.id;
END IF;
RETURN NEW;
END; $$ language 'plpgsql';
CREATE TRIGGER reset_verified AFTER UPDATE OF email ON accounts
FOR EACH ROW
WHEN (OLD.email != NEW.email) -- only when email changed
EXECUTE PROCEDURE fn_reset_verified();
Based on above schema, I wish to create trigger to automatic update verified to false if user change email. It work well for below statement:
UPDATE accounts SET email='newemail@email.com' WHERE id=1;
My problem come in when I intend update the email and set verified to TRUE at same time like below statement:
UPDATE accounts SET email='verified@email.com', verified=TRUE WHERE id=1;
If verified is been set in update statement, I should skip the function. Maybe condition as below:
WHEN (OLD.email != NEW.email AND STATEMENT.verified IS NULL)
So is there any way I can get the update statement or involved column?
答案 0 :(得分:0)
首先,您不应该在该表的更新触发器中的表上调用UPDATE
。有可能你将无限循环(不是在这种特殊情况下,但无论如何),通常有更好的方法来实现同样的事情。
在您的情况下,您会在电子邮件地址更改时触发BEFORE UPDATE
触发器,并检查/修改该触发器中的verified
列:
CREATE OR REPLACE FUNCTION fn_reset_verified() RETURNS TRIGGER AS $$
BEGIN
-- Below condition does not have to be checked because of WHEN clause in trigger
IF (
OLD.email != NEW.email -- do nothing if no change
) THEN
RAISE NOTICE 'UPDATE';
NEW.verified := ...;
END IF;
RETURN NEW;
END; $$ language 'plpgsql';
CREATE TRIGGER reset_verified BEFORE UPDATE OF email ON accounts
FOR EACH ROW
WHEN (OLD.email != NEW.email) -- only when email changed
EXECUTE PROCEDURE fn_reset_verified();
但是,没有逻辑可以确定在触发器内设置NEW.verified
的内容。问题是,NEW
变量在设置具有新值的列之后保存新行的所有列的值,而不仅仅是由命令修改的那些值。因此,如果NEW.verified = true
无法知道调用触发器的命令是否为:
UPDATE accounts SET email = 'newemail@email.com', verified = true WHERE id = 1;
或
UPDATE accounts SET email = 'newemail@email.com' WHERE id = 1;
因此NEW.verified
可以引用旧的电子邮件地址或新的电子邮件地址,该地址在UPDATE
命令中专门标记为已验证。
您唯一的选择是更改您的逻辑:如果电子邮件地址发生变化,则需要在之后进行验证,因此NEW.verified = false
。