mysql动态查询执行

mysql动态查询执行,mysql,database,Mysql,Database,我试图编写MySQL脚本,删除一些按模式选择的表,但我的过程无法编译。谁能告诉我它有什么问题吗 delimiter # drop procedure if exists drop_audit_tables # create procedure drop_audit_tables() begin declare done int default false; declare cmd varchar(4000); declare cmds cursor for select 'drop

我试图编写MySQL脚本,删除一些按模式选择的表,但我的过程无法编译。谁能告诉我它有什么问题吗

delimiter #
drop procedure if exists drop_audit_tables #
create procedure drop_audit_tables()
begin
  declare done int default false;
  declare cmd varchar(4000);
  declare cmds cursor for select 'drop table [' + table_name + ']' from information_schema.tables where table_name like '%_audit';
  declare continue handler for not found set done = true;
  open cmds;
  tLoop: loop
    fetch cmds into cmd;
    if done then
      leave tLoop;
    end if;
    PREPARE STMT FROM cmd;
    EXECUTE STMT;
    DEALLOCATE PREPARE STMT;
  end loop tLoop;
  close cmds;
end #
错误消息:

[42000][1064]您的SQL语法有错误;检查与您的MySQL服务器版本对应的手册,了解使用near'cmd的正确语法;执行STMT;解除分配准备STMT;端环tLoop;在第13行合上“cm”:

declare cmds cursor for select 'drop table [' + table_name + ']' from information_schema.tables where table_name like '%_audit';
。。使用
表\u名称
,而不首先定义它

首先尝试使用以下内容定义它:

create procedure drop_audit_tables(IN table_name VARCHAR(64))

您可能想考虑从存储过程中直接获取变量并将其放入到特定查询中的安全性含义。 不过,还是要在某个地方定义

table\u name
。在这种情况下,
table_name
将作为存储过程的参数提供。然后,您的任务是收集一个表名数组,并在for/foreach循环中运行此代码

基本(非健壮)PHP(PDO) 反正是这样的

将参数指定为IN、OUT或INOUT仅对过程有效。对于函数,参数始终被视为IN参数

准备要由PDOStatement::execute()方法执行的SQL语句。SQL语句可以包含零个或多个命名(:name)或问号(?)参数标记,在执行该语句时,实值将被替换


这样的解决方案会让你的生活更轻松。您只需要定义一个查找审计表的基本查询。更少的代码。更简单。

您可以避免光标:

mysql>删除表(如果存在)`one_audit`;
查询正常,0行受影响(0.00秒)
mysql>删除表(如果存在)`two_audit`;
查询正常,0行受影响(0.01秒)
mysql>删除表(如果存在)`three_audit`;
查询正常,0行受影响(0.00秒)
mysql>创建表`one_audit`(`a`INT);
查询正常,0行受影响(0.00秒)
mysql>创建表'two_audit'('a`INT);
查询正常,0行受影响(0.00秒)
mysql>创建表'three_audit'('a`INT);
查询正常,0行受影响(0.00秒)
mysql>SET@`drop\u tables`:=(
->挑选
->CONCAT('如果存在,则删除表格',
->组_CONCAT(CONCAT('`','表名','`')分隔符','))
->从
->`information\u schema`.`表`
->在哪里
->`TABLE_SCHEMA`=数据库()和
->`TABLE_TYPE`='BASE TABLE'和
->`TABLE_NAME`类似于'%\u audit'
-> );
查询正常,0行受影响(0.00秒)
mysql>选择@drop_tables`;
+--------------------------------------------------------------+
|@“放下桌子”|
+--------------------------------------------------------------+
|如果存在“一次审核”、“三次审核”、“两次审核”,则删除表|
+--------------------------------------------------------------+
一行一组(0.00秒)
mysql>从@drop_tables'准备'exec';
查询正常,0行受影响(0.00秒)
编写的声明
mysql>执行'exec';
查询正常,0行受影响(0.00秒)
mysql>取消分配PREPARE`exec`;
查询正常,0行受影响(0.00秒)
必须小心使用系统变量

更新

使用光标:

分隔符#
DROP PROCEDURE(如果存在)` DROP_audit_表格`#
创建过程“删除审核表”()
开始
声明'done'布尔默认值为0;
声明'cmd`VARCHAR(4000);
声明的“cmds”游标
挑选
CONCAT('DROP TABLE IF EXISTS`,'TABLE_NAME`,'`'))
从…起
`信息_schema`.`表`
哪里
`表_SCHEMA`=数据库()和
`表类型“=”基本表“和
`表_名称`像“%”审计“;
为未找到的集合“done”声明CONTINUE处理程序:=1;
打开“cmds”;
`tLoop`:LOOP
将'cmds'提取到'cmd'中;
如果“完成”,那么
关闭“cmds”;
留下'tLoop';
如果结束;
SET@`cmd`:=`cmd`;
从@`cmd`中准备`STMT`;
执行'STMT';
取消分配“STMT”;
结束循环'tLoop';
SET@`cmd`:=NULL;
结束#
调用“删除”审计表`#
定界符;

可准备的stmt

preparable\u stmt是字符串文字或用户变量,用于 包含SQL语句的文本


我从未使用过游标,但我可以说
从cmd准备STMTcmd
不是表示有效SQL命令的字符串,则code>可能会失败。我看到您的
将cmds提取到cmd中行,但这真的是个好主意吗?该行是否实际将SQL命令放入
cmd
,或第三条
声明的结果集。只是想帮忙。Anthony。如果存在drop\u audit\u tables
,我可能会在运行
drop过程后等待更改分隔符。
['+table\u name+'].
来自哪里?table_name来自哪里?假设table_name是准备语句的动态部分。但是,同样地,
table\u name
从何而来?您在某些地方使用sql server语法['+table\u name+']”我只会问第一个
table\u name
引用来自何处,从而允许它被连接。@AnthonyRutledge:Column
table\u name
TABLES
table<代码>从“信息”模式中选择“表格名称”。“表格”。请详细说明一下好吗?@AnthonyRutledge:
表格提供了有关数据库中表格的信息。
。看这里,但没有看到它将如何提供您所说的表名。没有聚合函数操作。我想你知道的比我多。
/* Get the audit tables. */
$stmt   = $pdo->query(`CALL get_audit_tables()`)
$tables = $stmt->fetch();
$stmt->close()

$stmt = $pdo->prepare('CALL drop_audit_tables(:table)')

/* Drop each audit table. */
foreach($tables as $table)
{
    $stmt->bindParam(:table, $table, PDO::PARAM_STR)
    $stmt->execute();
}

$stmt->close();