2014-01-31 59 views
0

选择专栏中,我已经声明了以下光标和变量:的Oracle SQL动态查询到光标

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号线

有谁知道我做错了? 谢谢

+0

它失败的是什么? 'C1LINE'声明为'l_data%rowtype'吗?我不认为你的CASE WHEN是正确的 - 它会将l_level设置为NULL,只要c1lin1.level1是** not ** NULL。我认为它应该是:'l_level:= coalesce(c1line.level1,c1line.level2,c1line.level3,c1line.level4)'。 – Joe

回答

1

关于实际错误c1line.LEVEL1,你动态地打开游标?它似乎是在你的代码有效,你已经证明

然后..

EXECUTE IMMEDIATE接受绑定变量,而INTO应该只有执行之后。更何况,分号(;)不需要在查询字符串

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

EXECUTE IMMEDIATE l_select_clause INTO l_level_value; 
+0

感谢OracleUSer,但是当我尝试你的方法时,我得到了完全相同的错误...... – GreenyMcDuff

+0

'l_level'里面的值很重要..'ORA-00904:“C1LINE”。“LEVEL2”'显示,你打包String'C1LINE .LEVEL2'在l_level里面?当你的代码显示时,你只需从C1LINE.LEVEL2中分配值。您在发布时错过了/修改了某个部分。 –

+0

对不起,你完全正确。我编辑了原文。 – GreenyMcDuff

0

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

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?这也使用动态脚本?

一定要记住,动态脚本应该是最后一个和最后一个选项。你应该避免它。

+0

那么,动态SQL可以让你的代码**更小**。但是你是对的,在许多情况下,它根本不是需要的。 –

+0

是的,动态SQL *可以*使代码更小。但它也可以抛出令人讨厌的错误,正如你所经历的那样。 –