如何使用一条SQL语句删除MySQL数据库中的所有触发器?
我克隆了一个DB,现在所有日志触发器都指向原始模式中的日志表。我需要一次删除所有这些文件(有几十个),以便重新创建它们。如何使用一个命令完成此操作?不确定是否存在用于此目的的单个命令 但我以前是这样做的如何使用一条SQL语句删除MySQL数据库中的所有触发器?,mysql,triggers,Mysql,Triggers,我克隆了一个DB,现在所有日志触发器都指向原始模式中的日志表。我需要一次删除所有这些文件(有几十个),以便重新创建它们。如何使用一个命令完成此操作?不确定是否存在用于此目的的单个命令 但我以前是这样做的 编写脚本以获取数据库中的触发器列表 在dropTrigger.sql文件中创建关联列表 运行dropTrigger.SQL文件 要获取触发器列表,您可以使用或快速回答为“否” 但您可以将逻辑封装在一个存储过程中:获取所有触发器并使用动态SQL删除循环中的所有触发器 之后可以执行:调用delete
之后可以执行:
调用delete\u all\u triggers\u api(schema\u name)代码>不幸的是,这在常规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
),如下所示:
推理
尝试从存储过程中删除触发器将失败。我猜这是因为变量只能保存一个字符串,而drop trigger
需要一个触发器名称(而不是包含触发器名称的字符串):
MySQL论坛上有两个关于此的帖子:
他们都得出了相同的结论,即即使使用存储过程也无济于事。这是一个老问题,但由于它一直出现在我的搜索中,我想我应该在这里发布一个解决方案。在我的例子中,我需要创建一个包含完整的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]
将结果复制到剪贴板
将Trigger\u name
转换为DROP Trigger代码>对于每个触发器,使用“^”和S标记作为带有reg.表达式的行的开始和结束
使用MAMP:
我们需要对公认的答案做一些小的调整。首先,我们需要在MAMP中以mysql为目标。其次,sed-r
不适用于Mac,请改用sed-E
。假设使用标准的MAMP设置,不更改根用户默认值,只需将[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密码,只需将-p
后面的“root”替换为您的密码即可
SELECT Concat('DROP TRIGGER ', Trigger_Name, ';') FROM information_schema.TRIGGERS WHERE TRIGGER_SCHEMA = 'your_schema';
复制并粘贴生成的sql不可能使用一条sql语句删除MySQL数据库中的所有触发器
但是,使用以下SQL代码,您可以构建所有“DROP TRIGGER”语句的列表(替换为您的架构名称,例如数据库名称)):
您可以使用这些SQL语句最终删除所有触发器
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
服务器系统变量是组_CONCAT()允许的最大结果长度(字节)函数。因为默认值为1024,所以如果有很多触发器,我们需要增加它以避免截断结果。我只使用了服务器系统变量的值,但通常可以使用任何大整数。请参阅。如果您想使用查询删除它们,而不需要将数据库转储到文件中:
选择concat('drop trigger',trigger_name',;'))
来自信息_schema.triggers,其中触发器_schema='your_schema';
然后,您需要导出结果(我发现CSV是最简单的)并在这些结果中运行查询。我喜欢它。但您也可以直接将其返回mysql,而不是文件:而不是“>>dump.sql”您可以使用“|mysql-u[db user]-p[db password]”这在很大程度上取决于您的使用情况。对我来说,它是从用于更新我们的开发数据库的从属数据库创建转储文件。这只是转储文件的一部分。我不想对生产数据库运行此操作,但这是更新生产数据库本地副本以供开发的过程的一部分。这将非常方便但是如果您确实想在同一个数据库上运行它。请注意,BSD和OS X用户将需要使用sed-E
而不是sed-r
。根据答案,sed-r
不起作用似乎很奇怪。我没有要测试的Mac,但这似乎很奇怪。您不能在存储过程中使用准备好的语句删除吗扳机?这是目前为止最好的答案你在哪里做过朋友?(y)
/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]
SELECT Concat('DROP TRIGGER ', Trigger_Name, ';') FROM information_schema.TRIGGERS WHERE TRIGGER_SCHEMA = '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`;
(...)