mysql需用old.字段名 new.字段名判断真实变更,因!=在null时返回unknown;postgresql必须用is distinct from;sql server的update(字段名)仅表示被set而非值变,须叠加显式比较;所有数据库触发器中应避免查表和嵌套if。

MySQL里用OLD.字段名 NEW.字段名判断真实变更
MySQL不支持UPDATE(字段名)语法,直接写会报Unknown function 'UPDATE'。必须显式比对新旧值,且不能用!=——因为NULL != 'abc'返回UNKNOWN,IF条件不成立,变更就被漏掉。
推荐统一用(安全等于),它把NULL当普通值处理:OLD.email NEW.email在email从NULL变'a@b.com'时返回0(即FALSE),配合IF NOT就能精准捕获变化。
多个字段合并判断时,别嵌套IF,写成:IF NOT (OLD.status NEW.status AND OLD.updated_at NEW.updated_at),后续加字段也只需追加AND OLD.xxx NEW.xxx。
PostgreSQL必须用IS DISTINCT FROM而非!=
PostgreSQL里!=遇到NULL同样失效:NULL != NULL结果是NULL,不是TRUE或FALSE,IF块直接跳过。唯一可靠写法是OLD.phone IS DISTINCT FROM NEW.phone——它天然把NULL和非NULL视为不同,且能正确处理NULL→'123'、'123'→NULL两类变更。
复杂类型如JSONB或ARRAY也适用IS DISTINCT FROM,无需序列化或转字符串;
如果要用NOTIFY发通知,只传主键ID:NOTIFY order_status_change, NEW.id::text,别试图塞新旧值进去——第二个参数上限8000字节,且监听端得自己查表还原上下文。
魔搭GPT(ModelScopeGPT)是一款AI视频创作工具,阿里达摩院推出的大小模型协同的智能助手,具备作诗、绘画、视频生成、语音播放等多模态能力。
SQL Server的UPDATE(字段名)只表示字段被SET,不等于值变了
UPDATE(字段名)是SQL Server专属函数,但它只检查该字段是否出现在SET子句里,哪怕SET email = email这种无效赋值也算“被更新”。所以不能单靠它判断真实变更。
必须叠加值比对:IF UPDATE(email) AND (OLD.email NEW.email OR (OLD.email IS NULL) (NEW.email IS NULL))——但这样写太啰嗦且易错。
更稳妥的做法是:先用UPDATE(字段名)快速过滤掉没被修改的字段,再用显式比较确认值是否真变;
注意OLD/NEW在SQL Server里叫deleted/inserted逻辑表,需用SELECT TOP 1取值,不能直接OLD.email引用。
所有数据库都得避开触发器内查表和嵌套IF
批量更新100行,触发器里写SELECT COUNT(*) FROM logs WHERE user_id = NEW.user_id,就会执行100次查询——性能断崖式下跌。
触发器只适合做轻量操作:比如自动更新updated_at、递增version、校验必填字段是否为NULL;
需要关联查询或发HTTP请求的逻辑,一律挪到应用层或异步任务;
多个字段监控别堆IF嵌套,用布尔表达式一次覆盖:(OLD.a IS DISTINCT FROM NEW.a) OR (OLD.b IS DISTINCT FROM NEW.b);
最容易被忽略的是NULL语义——无论哪种数据库,只要字段可能为空,就绝不能依赖!=或。










