代码之家  ›  专栏  ›  技术社区  ›  user1652509

将EXECUTE IMMEDIATE与带变量的串联字符串一起使用

  •  2
  • user1652509  · 技术社区  · 12 年前

    这个问题是关于不允许“创建”权限的环境。 版本为: Oracle数据库10g和PL/SQL 8.0.0.1480

    下面是一个小示例,展示了我试图实现的目标,即循环遍历集合中的一组字段,并用一些值填充它们。每个字段都有相同的根名称MyCol_,后跟一个数字。

    例如:MyCol_1,MyCol_2,我的Col_n。

    我能够建立我的串联,但我无法获得 立即执行 工作。

    我可以运行以下行,其中“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;
    
    1 回复  |  直到 12 年前
        1
  •  3
  •   Anjan Biswas    12 年前

    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;
    

    这可能起到了一定的作用,但如果以上操作是在存储的proc中完成的,那么 .EXTEND 有问题(即未经测试)。你可以试着看看它是否有效。