Jus*_*oel 2 mysql variables stored-procedures cursor
我需要使用一个变量来指示在游标声明中要查询的数据库.以下是代码的简短片段:
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;
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,我正在尝试使用变量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;
Run Code Online (Sandbox Code Playgroud)
当然这不起作用,因为MySQL只允许游标声明中的标准SQL语句.
有人能想到通过传入应该受影响的数据库名称在多个数据库中使用相同存储过程的方法吗?
Vijay Jadhav的答案是解决MySQL限制的正确方法.实际上,你需要3个proc来完成它:
proc1使用Vijay Jadhav的方式,就像一个数据收集器.您需要将变量传递给proc1并让它为proc2创建tmp表.Vijay方式有一个限制,他应该使用"CREATE TEMPORARY TABLE tmp_table_name SELECT ..."创建一个TEMPORARY表.因为临时表是线程安全的.
proc2将游标声明在proc1创建的tmp表上.由于tmp表已经知道并且硬编码到声明中,因此不再出现"table not found"错误.
proc3的工作方式类似于"main"函数,所有参数都需要发送到proc1和proc2.proc3首先调用proc1然后调用每个proc所需的参数proc2.
ps需要将系统变量"sql_notes"设置为0,否则proc1将在DROP TABLE命令上停止.
这是我的例子:
CREATE PROCEDURE `proc1`(SourceDBName CHAR(50), SourceTableName CHAR(50))
BEGIN
DECLARE SQLStmt TEXT;
SET @SQLStmt = CONCAT('DROP TEMPORARY TABLE IF EXISTS tmp_table_name');
PREPARE Stmt FROM @SQLStmt;
EXECUTE Stmt;
DEALLOCATE PREPARE Stmt;
SET @SQLStmt = CONCAT('CREATE TEMPORARY TABLE tmp_table_name SELECT ... FROM ',SourceDBName,'.',SourceTableName,' WHERE ... ');
PREPARE Stmt FROM @SQLStmt;
EXECUTE Stmt;
DEALLOCATE PREPARE Stmt;
END$$
CREATE PROCEDURE `proc2`(TargetDBName CHAR(50), TargetTemplateTableName CHAR(50))
BEGIN
DECLARE done INT DEFAULT 0;
DECLARE FieldValue CHAR(50);
DECLARE CursorSegment CURSOR FOR SELECT ... FROM tmp_table_name;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
OPEN CursorSegment;
REPEAT
FETCH CursorSegment INTO FieldValue;
IF NOT done THEN
...
END IF;
UNTIL done END REPEAT;
CLOSE CursorSegment;
END$$
CREATE PROCEDURE `proc3`(SourceDBName CHAR(50), SourceTableName CHAR(50), TargetDBName CHAR(50), TargetTemplateTableName CHAR(50))
BEGIN
CALL proc1(SourceDBName, SourceTableName);
CALL proc2(TargetDBName, TargetTemplateTableName);
END$$
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
21574 次 |
| 最近记录: |