oracle sql动态查询以选择游标中的列

Posted

技术标签:

【中文标题】oracle sql动态查询以选择游标中的列【英文标题】:oracle sql dynamic query to select column in cursor 【发布时间】:2014-01-31 15:09:01 【问题描述】:

我已经声明了以下光标和变量:

l_level           VARCHAR2(100);
l_level_value     VARCHAR2(100);
l_select_clause   CLOB;
CURSOR l_data IS
    SELECT LEVEL1, LEVEL2, LEVEL3 
     FROM  LEVELS;

然后我遍历光标:

FOR c1line IN l_data
LOOP
    CASE WHEN c1line.LEVEL1 IS NULL THEN l_level := 'c1line.LEVEL2'
         WHEN c1line.LEVEL2 IS NULL THEN l_level := 'c1line.LEVEL3'
         WHEN c1line.LEVEL3 IS NULL THEN l_level := 'c1line.LEVEL4'
         ELSE l_level := NULL
    END CASE;
END LOOP;

l_select_clause := 'SELECT ' || l_level || ' INTO l_level_value FROM dual;';

EXECUTE IMMEDIATE l_select_clause;

然后我还有一些其他语句根据变量l_level_value中选择的内容执行

我的问题是在执行我的程序时出现以下错误:

ORA-00904: "C1LINE"."LEVEL2": 标识符无效 ORA-06512:在“MY_PROCEDURE”,第 110 行 ORA-06512: 在第 2 行

有谁知道我做错了什么? 谢谢

【问题讨论】:

哪一行失败了? C1LINE 是否声明为 l_data%rowtype?我不认为你的 CASE WHEN 是正确的——只要 c1lin1.level1 为 not NULL,它就会将 l_level 设置为 NULL。我认为应该是:l_level := coalesce(c1line.level1,c1line.level2,c1line.level3,c1line.level4). 【参考方案1】:

关于实际错误c1line.LEVEL1,你动态打开游标?在您显示的代码中似乎有效

那么..

EXECUTE IMMEDIATE 接受绑定变量,而 INTO 应该只在 Execution 之后。值得一提的是,查询字符串中不需要分号(;

l_select_clause := 'SELECT ' || l_level || '  FROM dual';

EXECUTE IMMEDIATE l_select_clause INTO l_level_value;

【讨论】:

l_level 中的值很重要。ORA-00904: "C1LINE"."LEVEL2" 显示,您将字符串 C1LINE.LEVEL2 打包在 l_level 中?如您的代码所示,您只需从 C1LINE.LEVEL2 分配值。您在发布时错过/修改了某些部分。 对不起,你完全正确。我已经编辑了原始帖子。 现在,正如您已经猜到的那样,'c1line.LEVEL2' 不是有效的列,除非您有一个表(别名)C1LINE1 和列 LEVEl2。当您从 Dual 查询时,显然它以错误结尾。【参考方案2】:

我的问题是,你真的需要动态脚本吗?我的意思是可以执行相同的操作

FOR c1line IN l_data
LOOP
    CASE WHEN c1line.LEVEL1 IS NULL THEN l_level_value := c1line.LEVEL2
         WHEN c1line.LEVEL2 IS NULL THEN l_level_value := c1line.LEVEL3
         WHEN c1line.LEVEL3 IS NULL THEN l_level_value := c1line.LEVEL4
         ELSE l_level_value := NULL
    END CASE;
END LOOP;

为什么要采取两个步骤?先给l_level赋值,再给l_level_value赋值相同的值?那也用动态脚本?

永远记住,动态脚本应该是最后也是最后一个选项。你应该避免它。

【讨论】:

嗯,动态 SQL 可以让你的代码大大变小。但你是对的,在很多情况下根本不需要。 是的,动态 SQL 可以使代码更小。但它也可能引发您所经历的严重错误。

以上是关于oracle sql动态查询以选择游标中的列的主要内容,如果未能解决你的问题,请参考以下文章

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

如何提高Oracle中动态sql的查询性能

PL/SQL:clob 字符串中的动态查询。如何打开游标?

Oracle动态游标实现动态SQL循环遍历,和静态游标的比较。

oracle sql中的动态数据透视

oracle sql中的动态数据透视