38

我有一个已克隆的数据库,现在所有日志记录触发器都指向原始模式中的日志表。我需要一次性删除所有这些(有几十个),以便我可以重新创建它们。如何用一个命令来完成?

4

9 回答 9

66
SELECT Concat('DROP TRIGGER ', Trigger_Name, ';') FROM  information_schema.TRIGGERS WHERE TRIGGER_SCHEMA = 'your_schema';

复制并粘贴生成的sql

于 2015-05-20T03:48:01.390 回答
33

这是一个老问题,但由于它是在我的搜索中不断出现的问题,我想我会在这里发布一个解决方案。在我的情况下,我需要创建一个完整的文件,mysqldump然后删除所有触发器,然后重新添加它们。DROP TRIGGER在附加触发器的转储之前,我可以通过使用以下命令将语句附加到我的转储中来做到这一点。

mysql -u [db user] -p[db password] --skip-column-names [db name] -e 'SHOW TRIGGERS;' | cut -f1 | sed -r 's/(.*)/DROP TRIGGER IF EXISTS \1;/' >> dump.sql

要在同一命令中实际删除所有触发器(正如@Stephen Crosby 在评论中提到的那样),您可以像这样将其通过管道传回 MySQL:

mysql -u [db user] -p[db password] --skip-column-names [db name] -e 'SHOW TRIGGERS;' | cut -f1 | sed -r 's/(.*)/DROP TRIGGER IF EXISTS \1;/' | mysql -u [db user] -p[db password] [db name]
于 2014-02-13T20:42:00.440 回答
8

不幸的是,这在常规 SQL 语句或存储过程中是不可能的。

解决方案

删除所有触发器的最简单解决方案可能是 bash 脚本:

echo "select concat('drop trigger ', trigger_name, ';')
  from information_schema.triggers where trigger_schema = 'your_database'" |
  mysql --defaults-extra-file=.mysql.conf --disable-column-names | 
  mysql --defaults-extra-file=.mysql.conf

这需要一个凭证文件 ( .mysql.conf),如下所示:

[client]
database=your_database
user=your_username
password=your_password

推理

尝试从存储过程中删除触发器将失败。我猜这是因为变量只能保存一个字符串并且drop trigger需要一个触发器名称(不是包含触发器名称的字符串):

create procedure drop_a_trigger()
begin
  declare var1 varchar(1024);
  set var1 = "my_second_trigger";

  drop trigger my_first_trigger;       // OK
  drop trigger address_update_before;  // ERROR 1360 (HY000): Trigger does not exist

end //
delimiter ;

call drop_a_trigger();

MySQL 论坛上有两个关于此的主题:

他们都得出了相同的结论,即即使使用存储过程也无济于事。

于 2013-05-06T11:39:56.157 回答
7

使用一条 SQL 语句无法删除 MySQL 数据库中的所有触发器。

但是使用以下 SQL 代码,您可以构建所有“DROP TRIGGER”语句的列表(<your_schema>替换为您的架构名称,例如您的数据库名称):

-- set `group_concat_max_len`
SET @@session.group_concat_max_len = @@global.max_allowed_packet;

-- select all the triggers and build the `DROP TRIGGER` SQL
-- replace <your_schema> with your schema name (e.g. your database name)
SELECT GROUP_CONCAT(sql_string SEPARATOR '\n')
FROM (
    SELECT CONCAT('DROP TRIGGER IF EXISTS `', TRIGGER_NAME, '`;') AS sql_string,'1'
    FROM information_schema.TRIGGERS WHERE TRIGGER_SCHEMA = '<your_schema>'
    ) AS sql_strings
GROUP BY '1';

上一个查询的结果将产生如下内容:

DROP TRIGGER IF EXISTS `trigger1`;
DROP TRIGGER IF EXISTS `trigger2`;
(...)

并且您可以使用这些 SQL 语句最终删除所有触发器。

服务器系统变量group_concat_max_len是 GROUP_CONCAT() 函数的最大允许结果长度(以字节为单位)。因为默认是 1024,所以如果我们有很多触发器,我们需要增加它以避免截断结果。我只是使用了服务器系统变量max_allowed_pa​​cket的值,但通常任何大整数都可以。请参阅另一个问题

于 2015-08-21T17:52:37.570 回答
3
SELECT Trigger_Name
FROM `information_schema`.`TRIGGERS`
WHERE TRIGGER_SCHEMA = 'your_schema';

将结果复制到剪贴板

使用 ^ 和 S 标记为每个触发器转换Trigger_nameDROP TRIGGER <trigger_name>;reg.expressions 的开始和结束

作为 sql 脚本运行

于 2014-06-18T08:26:20.197 回答
0

不确定是否存在用于此目的的单个命令。

但这是我前段时间的做法

  1. 编写脚本以获取数据库中的触发器列表。
  2. 在 dropTrigger.sql 文件中创建连接列表
  3. 运行 dropTrigger.SQL 文件

要获取触发器列表,您可以在信息模式中使用SHOW 触发器或 触发器表

于 2012-09-28T11:12:39.660 回答
0

使用 MAMP 的 MAC:

需要对我们接受的答案进行一些小的调整。首先,我们需要在 MAMP 中定位 mysql。其次,sed -r不适用于Mac,请sed -E改用。假设标准 MAMP 设置,不更改 root 用户默认值,只需将 [db name] 替换为您的 db,然后复制并粘贴到终端并按 Enter。

/Applications/MAMP/Library/bin/mysql -u root -proot --skip-column-names [db name] -e 'SHOW TRIGGERS;' | cut -f1 | sed -E 's/(.*)/DROP TRIGGER IF EXISTS \1;/' | /Applications/MAMP/Library/bin/mysql -u root -proot [db name]

(如果您已更新您的 root 密码,只需将“root”-p替换为您的密码即可

于 2015-04-07T14:36:05.690 回答
0

如果您想使用查询删除它们而不需要将数据库 sqldump 到文件中:

select concat('drop trigger ', trigger_name, ';') from information_schema.triggers where trigger_schema = 'your_schema'; 然后,您需要导出结果(我发现 CSV 最简单)并在这些结果中运行查询。

于 2016-07-18T00:49:48.483 回答
-4

快速回答是“不”。

但是您可以将逻辑封装在一个存储过程中:使用动态 SQL 循环获取所有触发器并删除所有触发器。

之后你可以执行:call delete_all_triggers_api(schema_name);

于 2012-09-28T11:48:16.327 回答