MySQL存储过程:在游标声明中使用变量作为数据库名称
我需要使用一个变量来指示在游标声明中要查询的数据库。这是代码的一小段:
CREATE PROCEDURE `update_cdrs_lnp_data`(IN dbName VARCHAR(25), OUT returnCode SMALLINT)
cdr_records:BEGIN
DECLARE cdr_record_cursor CURSOR FOR
SELECT cdrs_id, called, calling FROM dbName.cdrs WHERE lrn_checked = 'N';
# Setup logging
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
#call log_debug('Got exception in update_cdrs_lnp_data');
SET returnCode = -1;
END;
如您所见,我尝试使用变量 dbName 来指示查询应在哪个数据库中发生。然而,MySQL 不允许这样做。我还尝试了诸如以下的操作:
CREATE PROCEDURE `update_cdrs_lnp_data`(IN dbName VARCHAR(25), OUT returnCode SMALLINT)
cdr_records:BEGIN
DECLARE cdr_record_cursor CURSOR FOR
SET @query = CONCAT("SELECT cdrs_id, called, calling FROM " ,dbName, ".cdrs WHERE lrn_checked = 'N' ");
PREPARE STMT FROM @query;
EXECUTE STMT;
# Setup logging
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
#call log_debug('Got exception in update_cdrs_lnp_data');
SET returnCode = -1;
END;
当然这也不起作用,因为 MySQL 只允许在游标声明中使用标准 SQL 语句。
任何人都可以想出一种方法,通过传入应该受影响的数据库的名称来在多个数据库中使用相同的存储过程吗?
I need to use a variable to indicate what database to query in the declaration of a cursor. Here is a short snippet of the code :
CREATE PROCEDURE `update_cdrs_lnp_data`(IN dbName VARCHAR(25), OUT returnCode SMALLINT)
cdr_records:BEGIN
DECLARE cdr_record_cursor CURSOR FOR
SELECT cdrs_id, called, calling FROM dbName.cdrs WHERE lrn_checked = 'N';
# Setup logging
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
#call log_debug('Got exception in update_cdrs_lnp_data');
SET returnCode = -1;
END;
As you can see, I'm TRYING to use the variable dbName to indicate in which database the query should occur within. However, MySQL will NOT allow that. I also tried things such as :
CREATE PROCEDURE `update_cdrs_lnp_data`(IN dbName VARCHAR(25), OUT returnCode SMALLINT)
cdr_records:BEGIN
DECLARE cdr_record_cursor CURSOR FOR
SET @query = CONCAT("SELECT cdrs_id, called, calling FROM " ,dbName, ".cdrs WHERE lrn_checked = 'N' ");
PREPARE STMT FROM @query;
EXECUTE STMT;
# Setup logging
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
#call log_debug('Got exception in update_cdrs_lnp_data');
SET returnCode = -1;
END;
Of course this doesn't work either as MySQL only allows a standard SQL statement in the cursor declaration.
Can anyone think of a way to use the same stored procedure in multiple databases by passing in the name of the db that should be affected?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
Vijay Jadhav的答案是MySQL解决此限制的正确方法。实际上,你需要 3 个 proc 来完成它:
proc1 使用 Vijay Jadhav 的方式,像数据收集器一样工作。您需要将变量传递给 proc1 并让它为 proc2 创建 tmp 表。 Vijay 的方式有一个限制,他应该使用“CREATE TEMPORARY TABLE tmp_table_name SELECT ...”创建一个临时表。因为临时表是线程安全的。
proc2 在 proc1 创建的 tmp 表上声明游标。由于 tmp 表已知并硬编码到声明中,因此不再出现“找不到表”错误。
proc3 的工作方式类似于“main”函数,所有参数都需要发送到 proc1 和 proc2。 proc3 只需先调用 proc1,然后使用每个 proc 所需的参数调用 proc2。
ps 需要将系统变量“sql_notes”设置为 0,否则 proc1 将在 DROP TABLE 命令上停止。
这是我的例子:
The answer of Vijay Jadhav is the right way to solve this limitation by MySQL. Actually, you need 3 proc to accomplish it:
proc1 using Vijay Jadhav's way, works like a data collector. You need to pass the variables to proc1 and let it create the tmp table for proc2. There is one limiation of Vijay's way, he should create a TEMPORARY table by using "CREATE TEMPORARY TABLE tmp_table_name SELECT ...". Because temporary table is thread safe.
proc2 declare the cursor on the tmp table which is created by proc1. Since the tmp table is already known and hard coded into the declaration, no more "table not found" error.
proc3 works like a "main" function, with all the parameters need to be sent to proc1 and proc2. proc3 simply calls proc1 first and then proc2 with the parameters need by each proc.
p.s Need to set system variable "sql_notes" to 0, otherwise proc1 will stop on DROP TABLE command.
Here is my example:
不,你不能在游标中这样做。
也许只是准备好的陈述就可以完成这项工作? :
No, you can't do that in cursors.
Maybe just prepared statements may do the job? :
尝试在不同的过程中使用准备好的语句创建(临时)表。
...
然后在“测试”过程中从该表中选择数据。
Try to create (temporary) table using prepared statement in a different procedure.
...
And then select data from that table in your 'test' procedure.
对此的回答是,这是不可能做到的。不能在游标声明中使用变量。我很欣赏 noonex 的回应。然而,他的解决方案不允许我浏览结果。它只是执行查询。
The answer to this is that it cannot be done. You cannot use variables in the cursor declaration. I appreciate noonex's response. However, his solution does not allow me to walk through the results. It simply executes the query.
创建过程测试(在 dbName varchar(40) 中)
读取 SQL 数据 <- 此行返回将允许您浏览结果
开始
...
$结果=调用测试(“mysql”);
create procedure test(in dbName varchar(40))
READS SQL DATA <- this line returns will allow you to walk through the results
begin
...
$result = call test("mysql");