2012-09-14 75 views
2

此问题涉及不允许“创建”权限的环境。 的版本是: Oracle数据库10g和PL/SQL 8.0.0.1480使用EXECUTE IMMEDIATE和带变量的连接字符串

下面是一个小样本,以显示我想要一个集合中完成这是循环通过一组“领域”和填充他们有一些价值。每个'字段'具有相同的根名称'MyCol_',后跟一个数字。

例如:MyCol_1,MyCol_2,...,MyCol_n。

我可以建立我的连接,但我不能让EXECUTE IMMEDIATE工作。

我可以运行这些线路,其中“MyCol_1”是一个硬编码值:

MyCol_1.EXTEND;   
MyCol_1(1) := 'abc'; 

但是,当我与一个连接字符串替换这些硬编码值失败

v_LoopCounter:=1;   
v_MyTestCode := 'MyCol_' || v_LoopCounter || '.EXTEND' ; 
DBMS_OUTPUT.PUT_LINE('Present value of v_MyTestCode: '||v_MyTestCode); 
execute immediate v_MyTestCode;  -- <<<-- ERRORS ON THIS LINE <<<-- 

错误介绍的是: ORA-00900:无效的SQL语句

我试图跟踪该网站给出的建议是: http://docs.oracle.com/cd/B10501_01/appdev.920/a97269/pc_13dyn.htm

...将动态SQL语句存储在字符串中,其中必须有 为主变量或带引号的文字。将SQL语句 存储在字符串中时,省略关键字EXEC SQL和';'声明 终止符。

而且还建议来自: http://www.databasejournal.com/features/oracle/article.php/2109681/EXECUTE-IMMEDIATE-option-for-Dynamic-SQL-and-PLSQL.htm

我试过在EXECUTE IMMEDIATE如EXEC许多变化,EXECUTE没有任何成功。

这是完整的代码示例。这只是一些测试代码来尝试和调试此问题。我希望这不会分散使用EXECUTE IMMEDIATE和串联字符串的问题。我试图保持示例代码简单和有据可查。希望这有助于解释这种情况。

DECLARE 

    TYPE MyNestedTable IS TABLE of varchar2(100);  

    MyCol_1 MyNestedTable; 
    MyCol_2 MyNestedTable; 

    v_LoopCounter NUMBER; 

    v_MyTestCode VARCHAR2(200); 
    v_SomeValue VARCHAR2(200); 

BEGIN 

    MyCol_1 := MyNestedTable(); 
    MyCol_2 := MyNestedTable(); 

    v_LoopCounter:=1; 

    v_MyTestCode := 'MyCol_' || v_LoopCounter || '.EXTEND' ; 
    DBMS_OUTPUT.PUT_LINE('Present value of v_MyTestCode: '||v_MyTestCode); 
    EXECUTE IMMEDIATE v_MyTestCode;  -- <<<-- ERRORS ON THIS LINE <<<-- 

    v_SomeValue := 'abc'; 
    v_MyTestCode := 'MyCol_' || v_LoopCounter || ':= '||v_SomeValue; 
    DBMS_OUTPUT.PUT_LINE('Present value of v_MyTestCode: '||v_MyTestCode); 
    EXECUTE IMMEDIATE v_MyTestCode;  -- <<<-- ERRORS ON THIS LINE <<<-- 


     MyCol_2.EXTEND; 
     MyCol_2(1) := 200; 
     DBMS_OUTPUT.PUT_LINE('MyCol_2 '||MyCol_2(1));  
     DBMS_OUTPUT.PUT_LINE('MyCol_1 '|| ', '||'MyCol_2 ');   DBMS_OUTPUT.PUT_LINE(MyCol_1(1)|| ', '||MyCol_2(1)); 

END; 
+0

@ Yahia- 对不起,我不明白。 [quote]'EXECUTE IMMEDIATE'SELECT:1 FROM DUAL'USING MyCol_1;'[/ quote] 似乎仍然将MyCol_1作为硬编码名称。 我应该用'DUAL'来做点什么 – user1652509

+0

看起来你想要做一个动态的PL/SQL,它需要一个'begin ... end;'。但更重要的是,动态SQL和动态PL/SQL运行在不同的范围内,并且只能看到SQL对象以及传递给它的变量。我认为你可以将一个变量作为一个OUT参数传递并设置它,但是你最好不要重新考虑你的设计。 –

+0

你说你想“循环访问集合中的一组'字段'”,但你的示例试图通过几个不同的集合(而不是集合中的“字段”)循环(没有LOOP stmt)。你想让MyCol_x代表一个集合,一行还是一个元素?很难确定你在这里的真正目标。 – tbone

回答

3

Collection.EXTEND不是全部的SQL声明,它是用于扩展集合的PLSQL语句。话虽如此下面的代码将永远不会与工作

v_LoopCounter:=1;   
v_MyTestCode := 'MyCol_' || v_LoopCounter || '.EXTEND' ; 
execute immediate v_MyTestCode; 

然而,如果动态SQL是整个PLSQL存根/匿名块,EXECUTE IMMEDIATE将在这项工作。像

v_LoopCounter:=1;   
v_MyTestCode := 'begin MyCol_' || v_LoopCounter || '.EXTEND;end;' ; 
execute immediate v_MyTestCode; 

这可以达到目的,但是,如果上述是从一个存储过程本身内完成则.EXTEND的范围是有问题的(即未测试)。你可以尝试看看它是否有效。

+0

大家好 - 感谢您的帮助和见解。 @安妮 - 你的答案是我正在寻找的概念。 我被困在这个项目的一些不可移动的障碍,比如没有'创建'权限,所以这导致了一些非常酷刑的逻辑来编码的情况。我会重新修改逻辑和代码,试着通过这个来找到答案。 再次感谢。 – user1652509