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

Assign value to Variable and call in multiple commands

我需要为来自 select 查询输出的变量赋值,并将该变量调用到 sql 命令中

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

我尝试将 SELECT 查询的值分配给 v_pdb 并调用 'alter session set container=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;
/

我只是想从 "select name from v$pdbs where con_id=3 and OPEN_MODE='READ WRITE'"

中获取变量 v_pdb 的值

并调用 v_pdb 如下:

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

我认为问题出在动态 SQL 中的尾随 semi-colon。动态 SQL 不包括尾随 semi-colon -- 因为动态 SQL 是单个语句,所以不需要 statement-separator。

删除尾随 semi-colon(和 "show" 命令(客户端命令))后,一切正常。但我不知道有什么好方法可以让 DBMS_OUTPUT 继续,除非你已经在给定的 PDB 中。在本示例中已将其删除。

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 现在在那里。

我认为它实际上与您的 pdb 变量没有任何关系...

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

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

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

变成

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

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

  1. Exclude statement terminators from dynamic SQL: 正如其他人提到的,从 SQL 中使用的语句末尾删除 ;动态 SQL.
  2. 转义字符串:字符串中的字符串需要转义。字符串 'DATA' 应该是 ''DATA''.
  3. 注意完整的错误信息:总是显示整个错误信息,包括行号和列号。该信息恰好指出了问题所在。
  4. 使用尽可能小的例子:一个smaller example的错误会更少,更容易找到真正的问题。在简化示例的过程中,您可能会自己找到答案。