【发布时间】:2016-01-28 19:41:37
【问题描述】:
我的表中有一个触发器“更新后”,但我需要知道列如何变化。 我不想这样做:
IF OLD.*column* <> NEW.*column* THEN ...
有人有窍门吗?
【问题讨论】:
-
这是我知道的唯一技巧...
标签: mysql triggers sql-update
我的表中有一个触发器“更新后”,但我需要知道列如何变化。 我不想这样做:
IF OLD.*column* <> NEW.*column* THEN ...
有人有窍门吗?
【问题讨论】:
标签: mysql triggers sql-update
没有技巧。如果要检测某列的值发生了变化,需要显式比较OLD.col和NEW.col的值。
SQL 的一个怪癖是三值布尔逻辑。对 NULL 值的不等式测试永远不会返回 TRUE。 (在布尔上下文中计算的表达式可以返回以下三个值之一:TRUE、FALSE 或 NULL。
foo <> NULL --> NULL
NULL <> NULL --> NULL
foo <> bar --> TRUE
如果您想检测列的值是否已更改,包括对 NULL 值的更改或从 NULL 值更改,则不等式测试不会删除它。
一个技巧是使用空安全比较运算符(宇宙飞船符号 <=>),即使被比较的一个或两个值都是 NULL,它也只会返回 TRUE 或 FALSE,检测差异:
IF NOT (NEW.col <=> OLD.col) THEN
-- value of col was modified
END IF;
另一个技巧是使用 SQL 语句来帮助生成触发器主体中需要的一些代码。引用 information_schema 数据库中的 columns 表。这是一个简短的示例,但可以扩展为包括其他语句和END IF。可以将此返回的结果粘贴到文本编辑器中,以帮助您构建触发器主体。
SELECT CONCAT(' IF NOT (NEW.`',c.column_name,'` <=> OLD.`',c.column_name,'`) THEN') AS i
FROM information_schema.columns c
WHERE c.table_name = 'mytable'
AND c.table_schema = 'mydatabase'
ORDER BY c.ordinal_position
返回类似的东西
--------------------------------------------------------------
IF NOT (NEW.`id` <=> OLD.`id`) THEN
IF NOT (NEW.`created` <=> OLD.`created`) THEN
IF NOT (NEW.`display_name` <=> OLD.`display_name`) THEN
如果您有很多列,这将非常有用。
除此之外,实际上并没有任何其他“技巧”。
【讨论】: