How to run PL/SQL in a PDB without setting container to the PDB We normally run a SQL in a PDB after alter session set container=pdbname; If you want to run a SQL in a different PDB, you type that command again specifying the second PDB's name, if the user has "set container" privilege, which sys and system do. But you can't do that inside PL/SQL, even as sys. Through whatever logic, Oracle reasons that setting container to a different one in PL/SQL code poses a security risk even though doing that in straight SQL does not. This is annoying because sometimes we really want to do something in each PDB without separately logging in from outside. This means this code for i in (select name from v$pdbs) loop execute immediate('alter session set container='||i.name); --do something, maybe for monitoring purposes end loop; won't work; you'll get ORA-01031 insufficient privilege. Fortunately, an Oracle white paper https://www.oracle.com/technetwork/database/multitenant/learn-more/multitenant-security-concepts-12c-2402462.pdf pp.9-10 provides skeleton code that allows us to do what we want. After some fiddling, I made this code work: set serveroutput on format wrapped declare cur integer := dbms_sql.open_cursor(security_level=>1); dummy integer; result varchar2(20); sqltxt varchar2(100) := 'select distinct policy_name from audit_unified_enabled_policies'; begin for i in (select name from v$pdbs where name!='PDB$SEED') loop dbms_output.put_line('PDB: ' || i.name); dbms_sql.parse(c=>cur,statement=>sqltxt,container=>i.name,language_flag=>dbms_sql.native); dbms_sql.define_column(cur, 1, result, 20); dummy := dbms_sql.execute(cur); while not (dbms_sql.fetch_rows(cur)<=0) loop dbms_sql.column_value(cur, 1, result); dbms_output.put_line(' auditing policy: ' || result); end loop; end loop; dbms_sql.close_cursor(cur); end; / The output should be like PDB: MYPDB1 auditing policy: ORA_LOGON_FAILURES auditing policy: ORA_SECURECONFIG PDB: MYPDB2 auditing policy: ORA_LOGON_FAILURES auditing policy: ORA_SECURECONFIG The above code finds the auditing policies of each PDB. The SQL is run in CDB and always stays in CDB; "show con_name" before and after you run the code should show "CDB$ROOT". The procedure dbms_sql.parse has the new argument 'container' that allows us to parse and later executes a SQL in a PDB even though dbms_sql itself is run in CDB.