游标内的动态 SQL

Posted

技术标签:

【中文标题】游标内的动态 SQL【英文标题】:Dynamic SQL within cursor 【发布时间】:2010-08-21 22:51:04 【问题描述】:

下面我根据查询输出更改表和创建列的动态 sql 出现错误。

查询:

DECLARE
   CURSOR c1 is select distinct WP_NO from temp;
   cnum VARCHAR2(255);

BEGIN

  FOR cnum in c1 
  LOOP
    EXECUTE IMMEDIATE 'Alter table temp_col add (:1 varchar2(255))' using cnum;
  END LOOP;  

  COMMIT;

END;

错误:

PLS-00457:表达式必须是 SQL 类型

【问题讨论】:

【参考方案1】:

这是因为bind variables are not allowed in DDL statements。

考虑尝试不使用绑定变量:

DECLARE
  CURSOR c1 is select distinct WP_NO from temp;
  cnum VARCHAR2(255);
BEGIN
  FOR cnum in c1 
  LOOP
    EXECUTE IMMEDIATE 'Alter table temp_col add ('|| cnum ||' varchar2(255))';
  END LOOP;  

  COMMIT;
END;

【讨论】:

完全正确。任何地方都不允许绑定变量。 根据 temp.WP_NO aka cnum 的来源,您可能需要对其进行清理以防止 SQL 注入攻击。【参考方案2】:

您与 cnum 符号有冲突,您将其用作局部变量和游标的当前行。

你可能想要这个:

DECLARE
   CURSOR c1 is select distinct WP_NO from temp;

BEGIN

  FOR current_row in c1 
  LOOP
    EXECUTE IMMEDIATE 'Alter table temp_col add (:1 varchar2(255))' using current_row.WP_NO;
  END LOOP;  

  COMMIT;

END;

如您所见,您无需声明在 for 循环中使用的 current_row 变量。

【讨论】:

这里不能使用绑定变量。 两个答案都不起作用(尽管 OMG 小马对绑定变量是正确的)。正确的解决方案是: begin FOR x in (select distinct WP_NO from temp) loop execute immediate 'alter table temp_col add '|| x.wp_no || 'varchar2(255)';结束循环;结束;

以上是关于游标内的动态 SQL的主要内容,如果未能解决你的问题,请参考以下文章

游标和动态SQL

动态 SQL 和游标相关问题

在 MySQL 中使用动态 SQL 创建游标

动态sql

从动态 SQL 打开游标时出错

oracle动态查询通过sql获取游标变量