如何在不影响客户端的前提下快速删除含大量触发器的表行?
嘿,这个需求非常典型——既要快速删除数据,又不想触发表上的触发器,同时还不能影响其他客户端的正常使用,对吧?你想要的那种单语句带触发器禁用的写法,不同数据库的实现方式略有不同,我给你分主流数据库整理了方案:
不同数据库的具体实现
MySQL/MariaDB
MySQL没有直接在DELETE语句里嵌入禁用触发器的语法,但可以用会话级别的临时设置来实现,这个设置只会对你当前的数据库连接生效,完全不会影响其他客户端:
-- 先保存当前的SQL模式,方便后续恢复 SET @original_sql_mode = @@session.sql_mode; -- 开启当前会话的触发器禁用模式 SET @@session.sql_mode = CONCAT(@@session.sql_mode, ',NO_TRIGGERS'); -- 执行你的删除操作 DELETE FROM mySchem.myTable WHERE id = 99; -- 恢复原来的SQL模式,避免影响后续操作 SET @@session.sql_mode = @original_sql_mode;
注意:这个NO_TRIGGERS模式是MySQL 8.0.19及以上版本才支持的,如果是旧版本,建议用事务包裹临时重命名触发器的操作,但这种方法风险略高,优先升级版本或者用会话级设置。
PostgreSQL
PostgreSQL完美支持你想要的单语句写法,直接在DELETE后面加DISABLE TRIGGER子句即可,这个操作仅对当前DELETE语句生效:
-- 禁用当前删除操作的所有触发器 DELETE FROM mySchem.myTable WHERE id = 99 DISABLE TRIGGER ALL;
如果你只想禁用特定的某个触发器(而不是全部),把ALL换成触发器名称就行:
DELETE FROM mySchem.myTable WHERE id = 99 DISABLE TRIGGER my_target_trigger;
SQL Server
SQL Server没有单语句禁用触发器的语法,但可以用事务包裹临时禁用/启用触发器的操作,保证原子性,不会影响其他客户端:
BEGIN TRANSACTION; -- 临时禁用表上的所有触发器 ALTER TABLE mySchem.myTable DISABLE TRIGGER ALL; -- 执行删除 DELETE FROM mySchem.myTable WHERE id = 99; -- 立刻恢复触发器 ALTER TABLE mySchem.myTable ENABLE TRIGGER ALL; COMMIT TRANSACTION;
这个操作全程在事务里完成,触发器只会被禁用极短时间,其他客户端几乎感知不到。
Oracle
Oracle可以通过会话级设置或者表级临时禁用触发器来实现,推荐用事务包裹表级操作,更安全:
BEGIN TRANSACTION; -- 禁用目标表的所有触发器 ALTER TABLE mySchem.myTable DISABLE ALL TRIGGERS; -- 执行删除 DELETE FROM mySchem.myTable WHERE id = 99; -- 恢复触发器 ALTER TABLE mySchem.myTable ENABLE ALL TRIGGERS; COMMIT TRANSACTION;
如果你只想对当前会话禁用触发器,也可以用:
ALTER SESSION SET DISABLE_TRIGGERS = TRUE; DELETE FROM mySchem.myTable WHERE id = 99; ALTER SESSION SET DISABLE_TRIGGERS = FALSE;
内容的提问来源于stack exchange,提问作者Jaytt Correa




