【问题标题】:Issue with substituting variable and cursor in stored procedure在存储过程中替换变量和游标的问题
【发布时间】:2017-06-22 05:50:11
【问题描述】:

所以我知道,为了在 select 语句中替换游标,我们需要在 prepare 语句之前定义它。我可以在那里替换变量,但我对游标有相同的问题。

例如,下面的语句应该正确地替换 table 的变量值,并且应该创建一个 table 作为 trial_data。

SET @user := 'trial';
SET @group := 'data';
SET @table := CONCAT(@user, '_', @group);
SET @stat = CONCAT('CREATE TABLE ',@table,' as SELECT @user, @group;');
PREPARE stmt from @stat;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

但是,当我尝试在带有游标的存储过程中应用相同的逻辑时,我遇到了如下错误 -

01:13:52    call cursor_ROWPERROW() Error Code: 1064. You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'NULL' at line 1    0.000 sec

在这种情况下,我试图通过替换变量和游标的值来动态创建表。在这里,我尝试根据我从信息架构中识别的另一个表中的相同列动态创建 PD_yyyyy_xxxxx 表。

DROP PROCEDURE IF EXISTS cursor_ROWPERROW;
DELIMITER $$
CREATE PROCEDURE cursor_ROWPERROW()
BEGIN
    DECLARE cursor_COL VARCHAR(50);
    DECLARE cursor_TAB VARCHAR(50);
    DECLARE tab VARCHAR(100);
    DECLARE col1 VARCHAR(50);
    DECLARE col2 VARCHAR(50);
    DECLARE done INT DEFAULT 0;
    DECLARE cursor_i CURSOR FOR SELECT COLUMN_NAME, TABLE_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA='xxxxx' AND TABLE_NAME='yyyyy' AND COLUMN_NAME = 'zzzzz';
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
    OPEN cursor_i;
    read_loop: LOOP
        FETCH cursor_i INTO cursor_COL, cursor_TAB;
        SET tab := CONCAT('PD', '_', @cursor_TAB, '_' , @cursor_COL);
        SET col1 := CONCAT(@cursor_COL);
        SET col2 := CONCAT(@cursor_COL, '_', 'value');
        IF done THEN
            LEAVE read_loop;
        END IF;
        SET @dyn_sql := CONCAT('CREATE TABLE ',@tab,' AS SELECT Codevalue as ',@col1,', valueLabel as ',@col2,' from valuesets14 where varName = cursor_COL and TableName = cursor_TAB;');
        PREPARE stmt_dyn_view FROM @dyn_sql;
        EXECUTE stmt_dyn_view;
        DEALLOCATE PREPARE stmt_dyn_view;
    END LOOP;
    CLOSE cursor_i;
END;
$$

DELIMITER ;

尽管我将整个 SET @dyn_sql 块替换为如下所示的 select 语句,但它运行良好并为我提供了我想要为其创建多个表的确切数据集。请注意,我引用的表中没有一个值是 NULL,所以我似乎缺少游标替换的东西。

SELECT Codevalue as ',@col1,', valueLabel as ',@col2,' from valuesets14 where varName = cursor_COL and TableName = cursor_TAB;

谁能帮我解决这个问题?

【问题讨论】:

    标签: mysql loops variables stored-procedures cursor


    【解决方案1】:

    问题在于您混淆了引用变量的各种方式。声明它们时应省略 @ 符号...

    read_loop: LOOP
        FETCH cursor_i INTO cursor_COL, cursor_TAB;
        SET tab := CONCAT('PD', '_', cursor_TAB, '_' , cursor_COL);
        SET col1 := CONCAT(cursor_COL);
        SET col2 := CONCAT(cursor_COL, '_', 'value');
        IF done THEN
            LEAVE read_loop;
        END IF;
        SET @dyn_sql := CONCAT('CREATE TABLE ',tab,' AS SELECT Codevalue as ',col1,', valueLabel as ',col2,' from valuesets14 where varName = cursor_COL and TableName = cursor_TAB;');
        PREPARE stmt_dyn_view FROM @dyn_sql;
        EXECUTE stmt_dyn_view;
        DEALLOCATE PREPARE stmt_dyn_view;
    END LOOP;
    

    【讨论】:

      【解决方案2】:

      感谢 Nigel 的想法,但是,我仍然遇到了另一个问题,即它抱怨的游标变量替换

      call cursor_ROWPERROW(): Error Code: 1054. Unknown column 'zzzzz' in 'where clause'
      

      因此,基本上,它无法替换光标值,因此我遵循您提到的相同方法并在文本周围加上引号,因此使用选择查询来查看它试图生成的查询我使用下面的 SQL解决了我的问题。

      DROP PROCEDURE IF EXISTS cursor_ROWPERROW;
      DELIMITER $$
      CREATE PROCEDURE cursor_ROWPERROW()
      BEGIN
          DECLARE cursor_COL VARCHAR(50);
          DECLARE cursor_TAB VARCHAR(50);
          DECLARE tab VARCHAR(100);
          DECLARE col1 VARCHAR(50);
          DECLARE col2 VARCHAR(50);
          DECLARE done INT DEFAULT 0;
          DECLARE cursor_i CURSOR FOR SELECT COLUMN_NAME, TABLE_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA='xxxxx' AND TABLE_NAME='yyyyy' AND COLUMN_NAME = 'zzzzz';
          DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
          OPEN cursor_i;
          read_loop: LOOP
              FETCH cursor_i INTO cursor_COL, cursor_TAB;
              SET tab := CONCAT('PD', '_', cursor_TAB, '_' , cursor_COL);
              SET col1 := CONCAT(cursor_COL);
              SET col2 := CONCAT(cursor_COL, '_', 'value');
              IF done THEN
                  LEAVE read_loop;
              END IF;
              SET @dyn_sql := CONCAT('CREATE TABLE ',tab,' AS SELECT Codevalue as ',col1,', valueLabel as ',col2,' from valuesets14 where varName = "',cursor_COL,'" and TableName = "',cursor_TAB,'";');
              PREPARE stmt_dyn_view FROM @dyn_sql;
              #SELECT @dyn_sql;
              EXECUTE stmt_dyn_view;
              DEALLOCATE PREPARE stmt_dyn_view;
          END LOOP;
          CLOSE cursor_i;
      END;
      $$
      
      DELIMITER ;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-03-13
        • 1970-01-01
        • 2019-12-01
        • 1970-01-01
        • 2018-12-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多