Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/55.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何批量更改MySQL触发器定义器_Mysql_Triggers - Fatal编程技术网

如何批量更改MySQL触发器定义器

如何批量更改MySQL触发器定义器,mysql,triggers,Mysql,Triggers,我一直在开发我们的内部开发服务器,并在MySQL 5.6.13服务器上创建MySQL触发器。我现在的问题是触发器(总共大约200个)是在内部服务器上使用as DEFINER=root@%创建的 现在我想转到实时生产服务器。但是,在我们的实时服务器上,我们不允许root用户进行此访问。因此,如何批量更改所有触发器,使其读取DEFINER=root@localhost一种方法: 1) 将触发器定义转储到文件中 #mysqldump-uroot-p--triggers--add drop trigge

我一直在开发我们的内部开发服务器,并在MySQL 5.6.13服务器上创建MySQL触发器。我现在的问题是触发器(总共大约200个)是在内部服务器上使用as DEFINER=
root
@
%
创建的

现在我想转到实时生产服务器。但是,在我们的实时服务器上,我们不允许root用户进行此访问。因此,如何批量更改所有触发器,使其读取DEFINER=
root
@
localhost

一种方法:

1) 将触发器定义转储到文件中

#mysqldump-uroot-p--triggers--add drop trigger--no create info\
--无数据--无创建数据库--跳过opt test>/tmp/triggers.sql
2) 在您喜爱的编辑器中打开
triggers.sql
文件,并使用
Find and Replace
功能更改
DEFINER
s。保存更新的文件

3) 从文件中重新创建触发器

#mysql
接受的答案对我不起作用,因为我的大多数客户机都托管在5.5版本的服务器上,对此我无能为力,而

在我的头撞上这个之后,我刚刚进入phpMyAdmin,它在触发器编辑页面上公开了定义者,我只是为20个左右错误的触发器编辑了定义者-phpMyAdmin将删除并用新的定义者重新创建触发器

我发现的另一个选项是执行一个完整的mysqldump,编辑生成的文件,使用它创建一个新的数据库,然后使用像Navicat这样的工具执行结构同步,返回到原始数据库,在生成的比较列表中只选择所需的触发器。这对我来说是一个更长的过程,因为我只需要编辑20个触发器,但如果我必须更新数百个触发器,这将更快。

不使用--add drop trigger选项:

currentUserDefiner='root'
currentHostDefiner='localhost'
newUserDefiner='user'
newHostDefiner='localhost'
db='myDb'
mysqldump -u root --triggers --no-create-info --no-data --no-create-db --skip-opt $db \
| perl -0777 -pe 's/(\n\/\*.+?50003 TRIGGER `([^`]+)`)/\nDROP TRIGGER \2;\1/g' \
| perl -0777 -pe 's/(DEFINER[^`]+)'$currentUserDefiner'(`@`)'$currentHostDefiner'/\1'$newUserDefiner'\2'$newHostDefiner'/gi' \
> out.sql
mysql -u root < out.sql
currentUserDefiner='root'
currentHostDefiner='localhost'
newUserDefiner='user'
newHostDefiner='localhost'
db='myDb'
mysqldump-u root--triggers--no create info--no data--no create db--skip opt$db\
|perl-0777-pe的/(\n\/\*.+?50003触发器`([^`]+)`)/\nDROP触发器\2\1/g'\
|perl-0777-pe的/(定义者[^`]+)'$currentUserDefiner'(`@`)'$currentHostDefiner'/\1'$newUserDefiner'\2'$newHostDefiner'/gi'\
>out.sql
mysql-u root
另一种方法是使用此Java实用程序。注意,这是一项正在进行的工作,因为当前版本1.0清除了一些服务器变量。

主题的另一个变体是使用MySQL Workbench中的选项转储整个数据库,在一个功能强大的编辑器中打开转储,找到替换为所需的“定义者”,然后使用MyQSL Workbench导入,导入屏幕上选择的“转储结构选项”(v6.2)。

我知道这是一篇老文章,但也许它能帮助一些人

我使用此sql查询生成DROP和CREATE命令:

SELECT CONCAT("DROP TRIGGER ", trigger_name, ";", " CREATE TRIGGER ", TRIGGER_NAME, " AFTER ", EVENT_MANIPULATION, " ON ", EVENT_OBJECT_SCHEMA, ".", EVENT_OBJECT_TABLE, " FOR EACH ROW ", ACTION_STATEMENT, ";") AS sqlCommand FROM information_schema.triggers WHERE EVENT_OBJECT_SCHEMA = "yourdatabase";
当我把生产数据库带到我的开发机器上,用foreach遍历所有命令并自动重新创建触发器时,我在我的应用程序中使用了这个。这让我可以选择自动化它

PHP/Laravel中的示例:

    $this->info('DROP and CREATE TRIGGERS');
    $pdo = DB::connection()->getPdo();
    $sql = 'SELECT CONCAT("DROP TRIGGER ", trigger_name, ";", " CREATE TRIGGER ", TRIGGER_NAME, " AFTER ", EVENT_MANIPULATION, " ON ", EVENT_OBJECT_SCHEMA, ".", EVENT_OBJECT_TABLE, " FOR EACH ROW ", ACTION_STATEMENT, ";") AS sqlCommand FROM information_schema.triggers WHERE EVENT_OBJECT_SCHEMA = "mydatabase";';
    $stmt = $pdo->prepare($sql, [PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => true]);
    $stmt->execute();
    $result = $stmt->fetchAll(PDO::FETCH_ASSOC);
    $stmt->closeCursor();

    foreach($result as $rs){
        $pdo = DB::unprepared($rs['sqlCommand']);
        break;
    }
提示:我必须使用pdo,因为mysql缓冲区查询问题,如前所述

与我对视图所做的相同(这里您可以使用ALTER TABLE):

希望有帮助。

运行此sql语句(用所需触发器替换tablename和triggername):

选择CONCAT('DROP TRIGGER IF EXISTS`',TRIGGER_name',`;',CHAR(13),'DELIMITER$$',CHAR(13),'CREATE TRIGGER`',TRIGGER_name',`',ACTION_timening',EVENT_MANIPULATION',ON',EVENT_OBJECT_SCHEMA',EVENT_OBJECT TABLE',FOR EACH ROW',ACTION_语句,$$,CHAR DELIMITER(13),'DELIMITER;')作为命令
来自信息\u schema.triggers
其中EVENT\u OBJECT\u SCHEMA='tablename'
触发器名称='triggername';

然后修改结果并执行它。

我可以通过关闭MySQL服务器更新触发器定义器,然后更新table.TRG文件(这些是文本文件,在其中查找定义器并创建定义器),然后重新启动MySQL来更新触发器定义器。我只需要为一个表执行此操作,但如果有很多表,我会编写一个sed脚本或类似的脚本。如果服务器无法关闭,则以下操作应能非常顺利地工作,对活动的干扰很小(免责声明-我没有对其进行测试):

对于每个表:

  • 锁表t写
  • 冲洗台t
  • 在TRG文件上执行sed魔术
  • 解锁表t

在Mac上,我在使用Zend Server的Mac OS X上收到消息“未知选项:--add drop trigger”。这仅在某些环境下有效。不适用于centOS上的社区5.5.36。。。“mysqldump:unknown option'--add drop trigger'”--add drop trigger是在5.6.0中添加的-通过这个sed脚本传递结果:
sed-e的/DEFINER[]*=[]*[^*]*\*/\*/'
我必须删除
--跳过opt
,才能工作。如果有人偶然发现了这一点。但这是一个非常有用的答案,在2021年仍然有效。您当然可以编辑转储创建的文件,并添加“drop trigger if exists name of triger;”是的,但那需要更多的打字。如果我没有一个好的数据库比较工具,那将是如何做到这一点。否则很好。这里的讨论推迟了几年,但我会将查询改为:
SELECT CONCAT(“DROP TRIGGER”,TRIGGER_name,”;“,“CREATE TRIGGER”,TRIGGER_name,”,ACTION_TIMING,”,EVENT_操纵,“ON”,EVENT_OBJECT_SCHEMA,”,EVENT_OBJECT_TABLE,“FOR EACH ROW”,ACTION_STATEMENT,“;”)作为来自information_schema.triggers的sqlCommand,其中EVENT_OBJECT_schema=“yourdatabase”这允许“BEFORE”触发器工作。实际上它不是tablename,而是dbname。
    $pdo = DB::connection()->getPdo();
    $sql = 'SELECT CONCAT("ALTER DEFINER=`homestead` VIEW ", table_name," AS ", view_definition,";") AS sqlCommand FROM  information_schema.views WHERE table_schema="mydatabase";';
    $stmt = $pdo->prepare($sql, [PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => true]);
    $stmt->execute();
    $result = $stmt->fetchAll(PDO::FETCH_ASSOC);
    $stmt->closeCursor();
    $this->info('View definer changed');

    foreach($result as $rs){
        $pdo = DB::unprepared($rs['sqlCommand']);
    }