给变量赋值并调用多个命令

时间:2019-05-21 21:54:56

标签: oracle plsql sqlplus

我需要为选择查询输出中的变量分配一个值,并将该变量调用到sql命令中

例如:我从v $ pdbs获取PDB_NAME并将值分配给v_pdb         我想在多个sql命令中使用v_pdb来针对PDB运行

我试图将SELECT查询中的值分配给v_pdb,并在“更改会话集容器= v_pdb”中调用v_pdb;看起来像在工作,但我收到ORA-00922:缺少或无效的选项错误

set serveroutput on;
declare
v_sql varchar2(80);
v_pdb varchar2(30);
BEGIN
  FOR pdb IN (select name from v$pdbs where con_id=3 and OPEN_MODE='READ WRITE') 
  LOOP
    v_sql := 'alter session set container='||pdb.name;
    DBMS_OUTPUT.PUT_LINE('Executing: ' || v_sql);
    --execute immediate 'alter session set container='||pdb.name||';';
    execute immediate v_sql;
    --v_sql := 'show con_name';
    --execute immediate 'show con_name';
    --execute immediate v_sql;
    v_sql := 'create tablespace APPDATA datafile '+DATA' size 1G autoextend on next 100M maxsize 5G ENCRYPTION USING 'AES256' DEFAULT STORAGE (ENCRYPT)';
    DBMS_OUTPUT.PUT_LINE('Executing: ' || v_sql);
    execute immediate v_sql;
    v_sql := 'drop user bigschema cascade';
    DBMS_OUTPUT.PUT_LINE('Executing: ' || v_sql);
    --execute immediate 'drop user bigschema cascade'; 
    execute immediate v_sql;
    v_sql := 'create user bigschema identified by B67_kuca_ecdf default tablespace APPDATA temporary tablespace TEMP profile DEFAULT account unlock';
    DBMS_OUTPUT.PUT_LINE('Executing: ' || v_sql);
    execute immediate v_sql;
    v_sql := 'alter user bigschema quota unlimited on APPDATA';
    DBMS_OUTPUT.PUT_LINE('Executing: ' || v_sql);
    execute immediate v_sql;
    v_sql := 'grant dba to bigschema';
    DBMS_OUTPUT.PUT_LINE('Executing: ' || v_sql);
    execute immediate v_sql;
    v_sql := 'conn bigschema/"B67_kuca_ecdf"@'||pdb.name;
    DBMS_OUTPUT.PUT_LINE('Executing: ' || v_sql);
    execute immediate v_sql;
    v_sql := 'drop table MV2OCI';
    DBMS_OUTPUT.PUT_LINE('Executing: ' || v_sql);
    execute immediate v_sql;
    v_sql := 'create table MV2OCI tablespace APPDATA as select * from dba_objects';
    DBMS_OUTPUT.PUT_LINE('Executing: ' || v_sql);
    execute immediate v_sql;
    v_sql := 'alter table MV2OCI nologging';
    DBMS_OUTPUT.PUT_LINE('Executing: ' || v_sql);
    execute immediate v_sql;
    v_sql := 'show user';
    DBMS_OUTPUT.PUT_LINE('Executing: ' || v_sql);
    execute immediate v_sql;
    v_sql := 'insert into MV2OCI select * from dba_objects';
    DBMS_OUTPUT.PUT_LINE('Executing: ' || v_sql);
    execute immediate v_sql;
    v_sql := 'insert into MV2OCI select * from MV2OCI';
    DBMS_OUTPUT.PUT_LINE('Executing: ' || v_sql);
    execute immediate v_sql;
 END LOOP;
END;
/

我只是想从“从v $ pdbs中选择名称,其中con_id = 3并且OPEN_MODE ='READ WRITE'”中获取变量v_pdb的值

并按如下所示调用v_pdb:

更改会话集容器= v_pdb; 运行其他sql命令 ... ......

3 个答案:

答案 0 :(得分:1)

我相信问题出在动态SQL的尾部分号。动态SQL不包括结尾的分号-由于动态SQL是单个语句,因此不需要语句分隔符。

删除结尾的分号(和“ show”命令(客户端命令))后,此方法正常。但是除非您已经在给定的PDB中,否则我不知道让DBMS_OUTPUT前进的好方法。在此示例中已将其删除。

declare
    v_sql varchar2(80);
BEGIN
    FOR pdb IN (select name from v$pdbs where con_id=3 and OPEN_MODE='READ WRITE')
        LOOP
            v_sql := 'alter session set container='||pdb.name;
            execute immediate V_SQL;
            DBMS_OUTPUT.ENABLE;
            v_sql := 'CREATE TABLE TEST_TABLE(LOREM_IPSUM NUMBER)';
            execute immediate V_SQL;
        END LOOP;
END;
/

结果:

PL/SQL procedure successfully completed.

导航到PDB,TEST_TABLE现在在那里。

答案 1 :(得分:1)

我认为它实际上与您的pdb变量无关...

使用立即执行时,不能有;;在字符串中

因此,对于您的每个执行立即声明,请删除;例如

execute immediate 'alter session set container='||pdb.name||';';

成为

execute immediate 'alter session set container='||pdb.name;

答案 2 :(得分:1)

有几种方法可以改善代码和编码过程:

  1. 从动态SQL中排除语句终止符:如其他人所述,从动态SQL中使用的SQL语句末尾删除;
  2. 转义字符串:字符串中的字符串需要转义。字符串'DATA'应该是''DATA''
  3. 请注意完整的错误消息:始终显示 entire 错误消息,包括行号和列号。该信息恰好指出了问题所在。
  4. 使用最小的示例smaller example的错误较少,因此更容易发现实际问题。并且在简化示例的过程中,您可能会自己找到答案。