{"id":125,"date":"2015-08-25T22:34:42","date_gmt":"2015-08-25T22:34:42","guid":{"rendered":"http:\/\/oradistrict.com\/?p=125"},"modified":"2015-08-25T22:34:42","modified_gmt":"2015-08-25T22:34:42","slug":"multitenant-commonality","status":"publish","type":"post","link":"https:\/\/oradistrict.com\/?p=125","title":{"rendered":"Multitenant &#8211; Commonality"},"content":{"rendered":"<h1>Oracle Database 12c &#8211; Multitenant &#8211; Common users and roles<\/h1>\n<p>It&#8217;s time to use common users and roles.<\/p>\n<h2>Introduction<\/h2>\n<p>Starting point for this article is presented in a table below.<\/p>\n<table class=\"table table-hover table-striped\">\n<tr>\n<th>Attribute<\/th>\n<th>Value<\/th>\n<\/tr>\n<tr>\n<td>Software<\/td>\n<td>\n\tOracle Linux 6.5 (64 bit for x86)<\/p>\n<hr>\n<p>\tOracle Database 12.1.0.2.0 (64 bit for Linux 6.5)<\/p>\n<hr>\n<p>\tInstallation and configuration of this software is described in this article: http:\/\/oradistrict.com\/?p=11<br \/>\n    Additional tests on this installation and CDB\/PDB &#8211; more details can be found here: http:\/\/oradistrict.com\/?p=108\n\t<\/td>\n<\/tr>\n<tr>\n<td>Databases<\/td>\n<td>One container database:<br \/>tcdb<\/td>\n<\/tr>\n<tr>\n<td>glogin.sql file<\/td>\n<td>Add couple new lines inside your login script for sql*plus. Most of the time you really don&#8217;t care about time zone in your test database.<br \/>\n    set termout off<br \/>\n    alter session set nls_timestamp_tz_format = &#8216;yyyy-mm-dd hh24:mi:ss&#8217;;<br \/>\n    alter session set nls_timestamp_format = &#8216;yyyy-mm-dd hh24:mi:ss&#8217;;<br \/>\n    alter session set nls_date_format = &#8216;yyyy-mm-dd hh24:mi:ss&#8217;;<br \/>\n    set linesize 92<br \/>\n    set pagesize 250<br \/>\n    set termout on\n\t<\/td>\n<\/tr>\n<tr>\n<td>Scripts used in this guide<\/td>\n<td>.\/mt\/container121.sql &#8211; list containers (CDB + seed + PDBs) in your CDB<br \/>\n    .\/sap\/mysession121.sql &#8211; list details about your session by SID<br \/>\n    .\/mt\/cusers121.sql &#8211; list all users in CDB<br \/>\n    .\/mt\/cusersonm121.sql &#8211; list only non-Oracle managed users with IDs<br \/>\n    .\/mt\/cusersonml121 &#8211; list only local non-Oracle managed users with IDs<br \/>\n    .\/iad\/databaseproperties112.sql &#8211; list all database properties on container level only (dba view)<br \/>\n    .\/mt\/cdatabaseproperties121.sql &#8211; show all PDBs properties (or current PDB)<br \/>\n    .\/mt\/cobject121.sql &#8211; list of all objects owned by pointed user across all PDBs<br \/>\n    .\/mt\/cobjectpriv121.sql &#8211; privileges granted on objects to users<br \/>\n    .\/mt\/ctable121.sql &#8211; list tables owned by pointed user across all PDBs<br \/>\n    .\/mt\/cprivilege121.sql &#8211; list of privileges granted to user or role<br \/>\n    .\/mt\/crole121.sql &#8211; list all roles and privileges granted to this role<br \/>\n    .\/mt\/cdata121 &#8211; container data attributes across containers granted to common users<br \/>\n    All scripts can be downloaded from my github project: <a href=\"https:\/\/github.com\/oradistrict\/toolbox\" target=\"_blank\">Oradistrict Toolbox<\/a> &#8211; download, unzip and use trunk directory to start menu via odv.sql. Most of those scripts reside under position 9 in the menu &#8211; enjoy!\n    <\/td>\n<\/tr>\n<tr>\n<td>oracle user shell<\/td>\n<td>It&#8217;s good to use aliases in shell &#8211; for example:<br \/>\n    alias sql=&#8221;sqlplus \/ as sysdba&#8221;<br \/>\n    provide easy way to login internally as sysdba. You can put it in your .bash_profile or .profile file.<\/td>\n<\/tr>\n<tr>\n<td>references<\/td>\n<td><a href=\"http:\/\/docs.oracle.com\/database\/121\/DBSEG\/toc.htm\">Security Guide<\/a><br \/>\n    <a href=\"http:\/\/docs.oracle.com\/database\/121\/SQLRF\/toc.htm\">SQL Language Reference<\/a><br \/>\n    <a href=\"http:\/\/docs.oracle.com\/database\/121\/ADMIN\/toc.htm\">Administrator&#8217;s Guide<\/a><br \/>\n    <a href=\"http:\/\/docs.oracle.com\/database\/121\/REFRN\/toc.htm\">Reference<\/a><br \/>\n    <a href=\"http:\/\/docs.oracle.com\/database\/121\/CNCPT\/toc.htm\">Concepts<\/a><br \/>\n    <a href=\"http:\/\/docs.oracle.com\/database\/121\/ERRMG\/e60000.htm\">Error Messages &#8211; ORA-65056 (container data usage)<\/a>\n    <\/td>\n<\/tr>\n<\/table>\n<h2>Common user<\/h2>\n<p>To create a new common user start with logging to cdb$root container as sys and list available containers. Remember to setup your environment before doing so.<\/p>\n<pre class=\"brush: bash; title: ; notranslate\" title=\"\">\r\n. oraenv\r\nsql\r\n<\/pre>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nalter pluggable database all open read write;\r\nstart mt\/container121\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nKey for column names\r\nCID - Container ID\r\n\r\n CID Container name               DbID Size in MB Open mode  Open time              Res\r\n---- -------------------- ------------ ---------- ---------- ---------------------- ---\r\n   1 CDB$ROOT                918792381          0 READ WRITE 2015-08-23 09:14:50    NO\r\n   2 PDB$SEED               4034246255        845 READ ONLY  2015-08-23 09:14:50    NO\r\n   3 PIPBOY                 3788905833        927 READ WRITE 2015-08-23 09:21:44    NO\r\n   4 SPECIAL                 510174438        911 READ WRITE 2015-08-23 09:21:44    NO\r\n   5 MOLERAT_CLONE          2993991422       1315 READ WRITE 2015-08-23 09:21:44    NO\r\n   6 MOLERAT_CLONE37        2904160425       1315 READ WRITE 2015-08-23 09:21:44    NO\r\n<\/pre>\n<p>Make sure that you&#8217;re connected with cdb$root container:<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nstart sap\/mysession121\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nUser Name    OS User        Program                    Service Name Machine\r\n------------ -------------- -------------------------- ------------ ----------------\r\nSYS          oracle         sqlplus@odone (TNS V1-V3)  SYS$USERS    odone\r\n\r\n\r\nContainer Name\r\n------------------------------------------------\r\nCDB$ROOT\r\n<\/pre>\n<p>As sys common user we&#8217;ve got required privileges: create user and set container (with admin option to grant it to the new user). Issue the command to create new common user.<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\ncreate user &quot;c##ArthurMaxson&quot;\r\n  identified by secret123\r\n  container = all;\r\n<\/pre>\n<p>Container parameter can be set only to value all which is default and cannot be changed. The same is true for container = current during creation of local user &#8211; the only valid and default value for local user when using connection with PDB.<\/p>\n<p>Check database users using .\/mt\/cusers121.sql script. This script lists all users in the database (if your PDB is closed users from this PDB wont be enlisted as this output is based on CDB_* view). Focus on last part of this report with a query which lists only non-Oracle managed users.<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nstart mt\/cusers121\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nKey for column names\r\nC - Common user\r\nOM - Oracle Maintained\r\n\r\n~~ only non-system users (non-oracle maintained) ~~\r\n\r\nContainer Name  User name                Account status     Created date        C OM\r\n--------------- ------------------------ ------------------ ------------------- - --\r\nCDB$ROOT        c##ArthurMaxson          OPEN               2015-08-23 10:47:10 Y N\r\nPIPBOY          MAXSTONE                 OPEN               2015-04-13 11:30:50 N N\r\nPIPBOY          c##ArthurMaxson          OPEN               2015-08-23 10:47:11 Y N\r\nSPECIAL         MAXSTONE                 OPEN               2015-04-13 11:30:50 N N\r\nSPECIAL         c##ArthurMaxson          OPEN               2015-08-23 10:47:11 Y N\r\nMOLERAT_CLONE   AGNES                    OPEN               2015-04-19 10:54:57 N N\r\nMOLERAT_CLONE   LEWIS                    OPEN               2015-04-19 10:54:57 N N\r\nMOLERAT_CLONE   c##ArthurMaxson          OPEN               2015-08-23 10:47:11 Y N\r\nMOLERAT_CLONE37 AGNES                    OPEN               2015-04-19 10:54:57 N N\r\nMOLERAT_CLONE37 LEWIS                    OPEN               2015-04-19 10:54:57 N N\r\nMOLERAT_CLONE37 NEWDBA                   OPEN               2015-06-10 00:03:59 N N\r\nMOLERAT_CLONE37 c##ArthurMaxson          OPEN               2015-08-23 10:47:11 Y N\r\n<\/pre>\n<p>Common user &#8220;c##ArthurMaxson&#8221; is present separately with individual user id in each container according to PDB user id numeration. Interesting thing is that I&#8217;ve managed to create this user in two different times for root and PDBs &#8211; this suggests that common user is created as a normal user in each container and only managed differently according to container clause of alter\/create user commands. Off course, you would not find such suggestion in Oracle documentation. Consider result of this script:<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nstart mt\/cusersonm121\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nKey for column names\r\nC - Common user\r\n\r\n~~ all users ~~\r\n~~ only non-system users (non oracle maintained) ~~\r\n\r\n CnID Container Name      User Id User name                Account status     C\r\n----- --------------- ----------- ------------------------ ------------------ -\r\n    1 CDB$ROOT                112 c##ArthurMaxson          OPEN               Y\r\n    3 PIPBOY                  102 MAXSTONE                 OPEN               N\r\n    3 PIPBOY                  118 c##ArthurMaxson          OPEN               Y\r\n    4 SPECIAL                 102 MAXSTONE                 OPEN               N\r\n    4 SPECIAL                 115 c##ArthurMaxson          OPEN               Y\r\n    5 MOLERAT_CLONE            70 AGNES                    OPEN               N\r\n    5 MOLERAT_CLONE            71 LEWIS                    OPEN               N\r\n    5 MOLERAT_CLONE            84 c##ArthurMaxson          OPEN               Y\r\n    6 MOLERAT_CLONE37          70 AGNES                    OPEN               N\r\n    6 MOLERAT_CLONE37          71 LEWIS                    OPEN               N\r\n    6 MOLERAT_CLONE37          74 NEWDBA                   OPEN               N\r\n    6 MOLERAT_CLONE37          84 c##ArthurMaxson          OPEN               Y\r\n<\/pre>\n<p>User id is related with PDB &#8211; commonality assure us that separation between PDBs is maintained. For end users this common user have the same id in PDB&#8217;s 5 and 6. The same could happen for two non-CDB&#8217;s. Local users agnes and lewis has the same ids in different PDBs but they are still two separate users without any common database objects. They can have different passwords and schema objects &#8211; totally separated.<\/p>\n<p>As we are using a common user and have necessary privileges to switch between session PDB context &#8211; we will do so. Switch to molerat_clone PDB and check the result of the same script.<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nalter session set container = molerat_clone;\r\nstart mt\/cusersonm121\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\n CnID Container Name      User Id User name                Account status     C\r\n----- --------------- ----------- ------------------------ ------------------ -\r\n    5 MOLERAT_CLONE            70 AGNES                    OPEN               N\r\n    5 MOLERAT_CLONE            71 LEWIS                    OPEN               N\r\n    5 MOLERAT_CLONE            73 c##ArthurMaxson          OPEN               Y\r\n<\/pre>\n<p>Right now we can see something that would be normal for non-CDB database. Only one set of database users. To see this result I&#8217;ve used cdb_users and v$containers views from which in PDB I can only query information that is related with this one PDB (*this is not a rule for all dictionary objects, check more about object links and metadata links in Oracle Database Concepts for details &#8211; link added to reference part above). To confirm that statement I&#8217;ve checked how many containers are visible in presented views:<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nselect count(0) &quot;Number of users&quot;, con_id\r\n  from cdb_users\r\n group by con_id;\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nNumber of users  CnID\r\n--------------- -----\r\n             22     5\r\n<\/pre>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nselect count(0) &quot;Number of containers&quot;, con_id\r\n  from v$containers\r\n group by con_id;\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nNumber of containers  CnID\r\n-------------------- -----\r\n                   1     5\r\n<\/pre>\n<p>To summarize, I could create a common user because:<\/p>\n<ul>\n<li>I was using cdb$root session during execution of create user command<\/li>\n<li>I had required privileges (create user)<\/li>\n<li>I&#8217;ve used container=all (with or without this clause it has to be used)<\/li>\n<li>I&#8217;ve named my user with prefix c## (this could be C## too)<\/li>\n<li>Oracle does not recommend creating objects in common user schema &#8211; this is a kind of odd recommendation (check in Database Security Guide, chapter 2 about creating common and local users)<\/li>\n<\/ul>\n<p>There are two more rules related with common users which I&#8217;m going to check with next commands. Before going back to root container check if similar command (to the first one in this tutorial) can be executed as common users sys from molerat_clone PDB:<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nshow con_name\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nCON_NAME\r\n------------------------------\r\nMOLERAT_CLONE\r\n<\/pre>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\ncreate user &quot;c##RogerMaxson&quot;\r\n  identified by secret123\r\n  container = all;\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nERROR at line 2:\r\nORA-65050: Common DDLs only allowed in CDB$ROOT\r\n<\/pre>\n<p>This error confirms that we can&#8217;t create common user from PDB session and, moreover, we cannot issue ANY common DDL from anywhere else than cdb$root container. Just to check another rule try this command:<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\ncreate user &quot;c##RogerMaxson&quot;\r\n  identified by secret123\r\n  container = current;\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nERROR at line 1:\r\nORA-65094: invalid local user or role name\r\n<\/pre>\n<p>Prefix c## is reserved only for common users and roles &#8211; this is why we cannot use them on PDB level. Container parameter value current is valid only for local users, check this command to be sure, that creating new user is available from common user sys:<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\ncreate user &quot;RogerMaxson&quot;\r\n  identified by secret123\r\n  container = current;\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nUser created.\r\n<\/pre>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nstart mt\/cusersonm121\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nKey for column names\r\nC - Common user\r\n\r\n~~ all users ~~\r\n~~ only non-system users (non oracle maintained) ~~\r\n\r\n CnID Container Name      User Id User name                Account status     C\r\n----- --------------- ----------- ------------------------ ------------------ -\r\n    5 MOLERAT_CLONE            70 AGNES                    OPEN               N\r\n    5 MOLERAT_CLONE            71 LEWIS                    OPEN               N\r\n    5 MOLERAT_CLONE            84 c##ArthurMaxson          OPEN               Y\r\n    5 MOLERAT_CLONE            85 RogerMaxson              OPEN               N\r\n<\/pre>\n<p>Now, we can go back to root container and check if we are able to skip naming requirements.<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nalter session set container = cdb$root;\r\ncreate user &quot;JohnMaxson&quot;\r\n  identified by secret123\r\n  container = all;\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nERROR at line 1:\r\nORA-65096: invalid common user or role name\r\n<\/pre>\n<p>Last combination of attempt to create local user in root container:<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\ncreate user &quot;JohnMaxson&quot;\r\n  identified by secret123\r\n  container = current;\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nERROR at line 2:\r\nORA-65049: creation of local user or role is not allowed in CDB$ROOT\r\n<\/pre>\n<p>This concludes topic of user name requirements and container clause issued from active session in root and PDB container.<\/p>\n<p>Now I&#8217;ll try to set default tablespace for a common user.<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\ncreate user c##vree\r\n  identified by secret123\r\n  default tablespace users;\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nERROR at line 1:\r\nORA-65048: error encountered when processing the current DDL statement in pluggable\r\ndatabase PIPBOY\r\nORA-00959: tablespace 'USERS' does not exist\r\n<\/pre>\n<p>And this is where I&#8217;ve got users tablespace:<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nselect ts#, name, con_id\r\n  from v$tablespace\r\n where name in ('USERS');\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\n       TS# Container name        CnID\r\n---------- -------------------- -----\r\n         4 USERS                    1\r\n         4 USERS                    5\r\n         4 USERS                    6\r\n<\/pre>\n<p>This is how my containers looks like (con_id and cid are the same identifier of PDB in CDB):<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nstart mt\/container121\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nKey for column names\r\nCID - Container ID\r\n\r\n CID Container name               DbID Size in MB Open mode  Open time              Res\r\n---- -------------------- ------------ ---------- ---------- ---------------------- ---\r\n   1 CDB$ROOT                918792381          0 READ WRITE 2015-08-23 09:14:50    NO\r\n   2 PDB$SEED               4034246255        845 READ ONLY  2015-08-23 09:14:50    NO\r\n   3 PIPBOY                 3788905833        927 READ WRITE 2015-08-23 09:21:44    NO\r\n   4 SPECIAL                 510174438        911 READ WRITE 2015-08-23 09:21:44    NO\r\n   5 MOLERAT_CLONE          2993991422       1315 READ WRITE 2015-08-23 09:21:44    NO\r\n   6 MOLERAT_CLONE37        2904160425       1315 READ WRITE 2015-08-23 09:21:44    NO\r\n<\/pre>\n<p>I&#8217;ve created pipboy PDB with default tablespace vault13. Tablespace users is not part of neither pipboy or special PDBs. This is why Oracle throws an error and stopped on first problem with pipboy PDB. When we omit default tablespace clause common user receives default tablespace along to the one identified in PDB properties (value for DEFAULT_PERMANENT_TABLESPACE). We can check it using another script. First for the root and then for pipboy PDB.<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nstart iad\/databaseproperties112\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nProperty name            Property value           Property description\r\n------------------------ ------------------------ ------------------------------------------\r\nDBTIMEZONE               +02:00                   DB time zone\r\nDEFAULT_EDITION          ORA$BASE                 Name of the database default edition\r\nDEFAULT_PERMANENT_TABLES USERS                    Name of default permanent tablespace\r\nPACE\r\n(...)\r\n<\/pre>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nalter session set container = pipboy;\r\nstart iad\/databaseproperties112\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nProperty name            Property value           Property description\r\n------------------------ ------------------------ ------------------------------------------\r\nDBTIMEZONE               +02:00                   DB time zone\r\nDEFAULT_EDITION          ORA$BASE                 Name of the database default edition\r\nDEFAULT_PERMANENT_TABLES VAULT13                  Name of default permanent tablespace\r\nPACE\r\n(...)\r\n<\/pre>\n<p>The same is true for temporary tablespace name. If PDB uses different one and we would like to declare which one common user should use then, in case if this temporary tablespace does not exists in PDB, we&#8217;ll receive similar error.<\/p>\n<h2>Common user objects<\/h2>\n<p>Using the same session I&#8217;ll try to create a new table in root container.<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nalter session set container = cdb$root;\r\ngrant create session, create table to &quot;c##ArthurMaxson&quot;;\r\n<\/pre>\n<p>Both privileges are granted locally &#8211; I&#8217;ll discuss this topic a bit later. More important is that&#8230; here comes the classic:<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nalter user &quot;c##ArthurMaxson&quot; quota unlimited on users;\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nERROR at line 1:\r\nORA-65048: error encountered when processing the current DDL statement in pluggable\r\ndatabase PIPBOY\r\nORA-00959: tablespace 'USERS' does not exist\r\n<\/pre>\n<p>This is the consequence of previous tests when I wanted to create a new user with a default tablespace which is not present in all PDBs. We need to remember about common scope of this command (in some commands container clause default value vary so this is some kind of inconsequence from Oracle). Anyway, I can solve this problem globally (which isn&#8217;t pretty but &#8220;it works&#8221;) or locally.<\/p>\n<p>I can switch between PDBs and assign correct quota in local scope using container = current clause, in this case, for root container:<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nalter user &quot;c##ArthurMaxson&quot; quota unlimited on users container = current;\r\n<\/pre>\n<p>What is interesting about user quotas that to stop showing it in cdb_ts_quotas (or dba_ts_quotas if you prefer non-CDB nomenclature) we need to set quota to 0 (zero).<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nalter user &quot;c##ArthurMaxson&quot; quota 0 on users container = current;\r\n<\/pre>\n<p>It is somewhat interesting in context of container_data clause which I&#8217;m going to describe later. You can always use burnmaster to get all required quota in just one shot:<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\ngrant unlimited tablespace to &quot;c##ArthurMaxson&quot; container = all;\r\nconnect &quot;c##ArthurMaxson&quot;\/secret123@tcdb\r\ncreate table am_table\r\n(\r\n  id number(12),\r\n  blast_radius number(30)\r\n);\r\ninsert into am_table values (1, 200000000);\r\ncommit;\r\nselect * from am_table;\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\n        ID BLAST_RADIUS\r\n---------- ------------\r\n         1    200000000\r\n<\/pre>\n<p>Now, I&#8217;ll try to check the same query on PDB level, for example, in special PDB:<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nconnect &quot;c##ArthurMaxson&quot;\/secret123@special\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nERROR:\r\nORA-01045: user c##ArthurMaxson lacks CREATE SESSION privilege; logon denied\r\n<\/pre>\n<p>Earlier privilege has been granted only on cdb$root level. To allow login on special PDB we need to either grant locally the same privilege or commonly from root level. I&#8217;m going for a second option.<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nconnect \/ as sysdba\r\ngrant create session, create table to &quot;c##ArthurMaxson&quot; container = all;\r\n<\/pre>\n<p>And now back to special PDB:<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nconnect &quot;c##ArthurMaxson&quot;\/secret123@special\r\nselect * from am_table;\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nERROR at line 1:\r\nORA-00942: table or view does not exist\r\n<\/pre>\n<p>Right now am_table exists only in root container. Against the documentation we can create objects in root container but we won&#8217;t have much use of it. Oracle managed schemas like apex, spatial or text schemas are shared between all PDBs from root container. One cannot do the same with his own objects.<\/p>\n<p>I&#8217;m going to create this table in special PDB too.<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\ncreate table am_table\r\n(\r\n  id number(12),\r\n  blast_radius number(30)\r\n);\r\ninsert into am_table values (1, 200000000);\r\ncommit;\r\nselect * from am_table;\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\n        ID BLAST_RADIUS\r\n---------- ------------\r\n         1    200000000\r\n<\/pre>\n<p>Now we can go back to root container where we check, where Arthur Maxson tables are.<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nconn \/ as sysdba\r\nstart mt\/cobject121\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nAdd %% if needed for owner name. Search is case insensitive.\r\n\r\nInput objects owner: %arthur%\r\nObjects with owner LIKE %arthur%\r\n\r\nContainer name   Object type          Object name                    Status\r\n---------------- -------------------- ------------------------------ -------\r\nCDB$ROOT         TABLE                AM_TABLE                       VALID\r\nSPECIAL          TABLE                AM_TABLE                       VALID\r\n<\/pre>\n<p>And one more check for tables owned by our user:<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nstart mt\/ctable121\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nAdd %% if needed for owner name. Search is case insensitive.\r\n\r\nInput objects owner: %arthur%\r\nTables with owner LIKE %arthur%\r\n\r\nContainer name   Table name                     Tablespace name\r\n---------------- ------------------------------ ------------------------------\r\nCDB$ROOT         AM_TABLE                       USERS\r\nSPECIAL          AM_TABLE                       VAULT13\r\n<\/pre>\n<p>As a bonus I&#8217;ll try to export this user from this database and import it to another PDB. To be more precise &#8211; I&#8217;ll try to export common user from special and import to pipboy (there are the same default tablespaces vault13)<\/p>\n<p>Exit from sql*plus, create a new directory on a file system, create directory object in PDB and make a simple export using Data Pump.<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nexit\r\n<\/pre>\n<pre class=\"brush: bash; title: ; notranslate\" title=\"\">\r\nmkdir -p \/u02\/expdp\/tcdb\r\nsqlplus system\/manager@special\r\n<\/pre>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\ncreate directory amexpdir as '\/u02\/expdp\/tcdb';\r\nexit\r\n<\/pre>\n<p>Create export parameter file as we need it to use case sensitive name.<\/p>\n<pre class=\"brush: bash; title: ; notranslate\" title=\"\">\r\nvi \/u02\/expdp\/tcdb\/amexp.par\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nuserid=system\/manager@special\r\ndirectory=amexpdir\r\nschemas='&quot;c##ArthurMaxson&quot;'\r\ndumpfile=amexp.dmp\r\nlogfile=amexp.log\r\nlogtime=all\r\n<\/pre>\n<p>And export the c##ArthurMaxson user.<\/p>\n<pre class=\"brush: bash; title: ; notranslate\" title=\"\">\r\nexpdp parfile=\/u02\/expdp\/tcdb\/amexp.par\r\n<\/pre>\n<p>In parameter file I&#8217;ve used new parameter logtime &#8211; it provides timestamp for each operation logged by expdp. This way we can find out how much time Oracle spent on export of each object.<\/p>\n<p>As you can see in log only PDB definition have been taken under consideration during the export. What about the import?<\/p>\n<p>First of all I would like to see what DDLs are inside the dump file. Create impdp parfile for tests.<\/p>\n<pre class=\"brush: bash; title: ; notranslate\" title=\"\">\r\nvi \/u02\/expdp\/tcdb\/amimpt.par\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nuserid=system\/manager@special\r\ndirectory=amexpdir\r\nschemas='&quot;c##ArthurMaxson&quot;'\r\ndumpfile=amexp.dmp\r\nlogfile=amexpimpt.log\r\nlogtime=all\r\nsqlfile=ameximpt.sql\r\n<\/pre>\n<p>And &#8220;import&#8221; the c##ArthurMaxson user.<\/p>\n<pre class=\"brush: bash; title: ; notranslate\" title=\"\">\r\nimpdp parfile=\/u02\/expdp\/tcdb\/amimpt.par\r\n<\/pre>\n<p>Check generated ameximpt.sql file. You can see that only PDB related commands are available. So, commonality is not important here &#8211; impdp ignore PDB level, it is related with a database, just like in previous versions of the database (non-CDBs). Even when you skip schemas parameter and let it go as full import it doesn&#8217;t matter &#8211; in sql file you still won&#8217;t find common user definition and it is aligned with the rules &#8211; on PDB level you are not able to issue common command (container = all) &#8211; this is why it&#8217;s useless to try to import common user to PDB &#8211; it is possible to create common user only in root container but from root container you won&#8217;t see PDBs data. This way common users in PDBs are exported similarly to the way old exp tool handled things in the past.<\/p>\n<p>First, I&#8217;ll try to import the data to the same user but in different PDB. New parameter file need to be prepared. Remember to create the same directory in pipboy PDB.<\/p>\n<pre class=\"brush: bash; title: ; notranslate\" title=\"\">\r\nvi \/u02\/expdp\/tcdb\/amimpc.par\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nuserid=system\/manager@pipboy\r\ndirectory=amexpdir\r\nschemas='&quot;c##ArthurMaxson&quot;'\r\ndumpfile=amexp.dmp\r\nlogfile=amexpimpc.log\r\nlogtime=all\r\n<\/pre>\n<pre class=\"brush: bash; title: ; notranslate\" title=\"\">\r\nsqlplus system\/manager@pipboy\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\ncreate directory amexpdir as '\/u02\/expdp\/tcdb';\r\nexit\r\n<\/pre>\n<pre class=\"brush: bash; title: ; notranslate\" title=\"\">\r\nimpdp parfile=\/u02\/expdp\/tcdb\/amimpc.par\r\nsql\r\n<\/pre>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nstart mt\/ctable121\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nInput objects owner: %arthur%\r\nTables with owner LIKE %arthur%\r\n\r\nContainer name   Table name                     Tablespace name\r\n---------------- ------------------------------ ------------------------------\r\nCDB$ROOT         AM_TABLE                       USERS\r\nPIPBOY           AM_TABLE                       VAULT13\r\nSPECIAL          AM_TABLE                       VAULT13\r\n<\/pre>\n<p>Import have been possible as target user alredy exists in pipboy PDB (as he is a common user). And another attempt with conversion to local user. Usually expdp export metadata too. I should be able to automatically create this user. But let&#8217;s check if it is true in this case too.<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nexit\r\n<\/pre>\n<pre class=\"brush: bash; title: ; notranslate\" title=\"\">\r\nvi \/u02\/expdp\/tcdb\/amimpcl.par\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nuserid=system\/manager@pipboy\r\ndirectory=amexpdir\r\nschemas='&quot;c##ArthurMaxson&quot;'\r\nremap_schema='&quot;c##ArthurMaxson&quot;':arthurmaxson\r\ndumpfile=amexp.dmp\r\nlogfile=amexpimpcl.log\r\nlogtime=all\r\n<\/pre>\n<pre class=\"brush: bash; title: ; notranslate\" title=\"\">\r\nimpdp parfile=\/u02\/expdp\/tcdb\/amimpcl.par\r\n<\/pre>\n<p>And here, during the import I&#8217;ve received an error related with use of remap_schema &#8211; right now I&#8217;ll leave it as it is. I even tried to import as sysdba in pipboy &#8211; without any luck.<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nUDI-00014: invalid value for parameter, 'remap_schema'\r\n<\/pre>\n<p>From time to time I encounter some problems with case sensitivity &#8211; maybe it&#8217;s on of those nasty problems.<\/p>\n<p>Again, to be sure, I&#8217;ve created another user called c##arma with the same privileges and one table, created export and now I&#8217;m trying to reimport it with remap schema (this time name is without &#8220;&#8221;).<\/p>\n<pre class=\"brush: bash; title: ; notranslate\" title=\"\">\r\nsql\r\n<\/pre>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\ncreate user c##arma\r\n  identified by secret123\r\n  container = all;\r\ngrant create session, create table to c##arma container = all;\r\ngrant unlimited tablespace to c##arma container = all;\r\nconnect c##arma\/secret123@special\r\ncreate table am_table\r\n(\r\n  id number(12),\r\n  blast_radius number(30)\r\n);\r\ninsert into am_table values (1, 200000000);\r\ncommit;\r\nselect * from am_table;\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\n        ID BLAST_RADIUS\r\n---------- ------------\r\n         1    200000000\r\n<\/pre>\n<p>My armaexp.par export parameter file looks like this:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nuserid=system\/manager@special\r\ndirectory=amexpdir\r\nschemas='c##arma'\r\ndumpfile=armaexp.dmp\r\nlogfile=armaexp.log\r\nlogtime=all\r\n<\/pre>\n<p>Exporting schema:<\/p>\n<pre class=\"brush: bash; title: ; notranslate\" title=\"\">\r\nexpdp parfile=\/u02\/expdp\/tcdb\/armaexp.par\r\n<\/pre>\n<p>You can see that I had too add &#8221; for schema name. Without single quote I&#8217;ve received an error:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nORA-39001: invalid argument value\r\nORA-39170: Schema expression 'C' does not correspond to any schemas.\r\n<\/pre>\n<p>Ok, now it&#8217;s time for import with remapping of c##arma user. Here is my armaimpcl.par parameter file (similar to the one used with c##ArthurMaxstone user) and the result.<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nuserid=&quot;sys\/manager@pipboy as sysdba&quot;\r\ndirectory=amexpdir\r\nschemas='c##arma'\r\nremap_schema='c##arma':otheruser\r\ndumpfile=armaexp.dmp\r\nlogfile=armaexpimpcl.log\r\nlogtime=all\r\n<\/pre>\n<pre class=\"brush: bash; title: ; notranslate\" title=\"\">\r\nimpdp parfile=\/u02\/expdp\/tcdb\/armaimpcl.par\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nUDI-00014: invalid value for parameter, 'remap_schema'\r\n<\/pre>\n<p>So&#8230; looks like Oracle don&#8217;t manage in any way to remap exported common user. Interesting. Now we know, why it is not recommended to use common users schema to hold any data in it &#8211; we can have serious troubles with moving those schemas elsewhere. Maybe database link could be a solution here &#8211; but we should remember about restrictions related with moving data via database link. Anyway, I hope that we won&#8217;t find any surprises like this one inside database engine.<\/p>\n<p>I&#8217;ve even tried to create destination user for remap clause &#8211; without any success.<\/p>\n<pre class=\"brush: bash; title: ; notranslate\" title=\"\">\r\nsqlplus system\/manager@pipboy\r\n<\/pre>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\ncreate user otheruser identified by secret123;\r\ngrant create table, create session to otheruser;\r\ngrant read, write on directory amexpdir to otheruser;\r\ngrant unlimited tablespace to otheruser;\r\n<\/pre>\n<p>Last attempt was to use newly created user to remap table, armaimptr.par parameter file:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nuserid=otheruser\/secret123@pipboy\r\ndirectory=amexpdir\r\ntables='c##arma.am_table'\r\nremap_table='c##arma.am_table':otheruser.am_table\r\ndumpfile=armaexp.dmp\r\nlogfile=armaexpimptr.log\r\nlogtime=all\r\n<\/pre>\n<pre class=\"brush: bash; title: ; notranslate\" title=\"\">\r\nimpdp parfile=\/u02\/expdp\/tcdb\/armaimptr.par\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nUDI-00014: invalid value for parameter, 'remap_table'\r\n<\/pre>\n<p>Toying with remap_table parameter leads me even to a state, where Oracle finished the import but probably sees table name as &#8216;c&#8217; with remap defined as:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nremap_table=\\'&quot;C##ARMA&quot;.&quot;AM_TABLE&quot;\\':otheruser.am_table\r\n<\/pre>\n<p>I assume that it is not possible to import common user objects to other schemas using remap clause. I&#8217;ve tried other escape options too &#8211; no luck in all attempts.<\/p>\n<h2>Local user<\/h2>\n<p>If you think about users from 11g version and earlier you should see a user related with only one database (but many instances in RAC). Oracle now calls that kind of database as a non-CDB database. In PDBs local users means: available only for this PDB. PDBs are separated entities and should be treated by end users as such. When we create a user in special PDB then there is no way to use this username and password in another PDB, like pipboy. So, common users can use their privileges and login across all PDB (if create session is granted commonly or locally in each PDB) and local users stays the same like the old kind of users from earlier releases of Oracle Database.<\/p>\n<p>I&#8217;ll create four users. Two in special PDB: machete and dominic. And another two in pipboy PDB: machete and mechanist. Machete has no problem with existence in two PDBs at once.<\/p>\n<pre class=\"brush: bash; title: ; notranslate\" title=\"\">\r\nsqlplus system\/manager@special\r\n<\/pre>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\ncreate user machete identified by dominic;\r\ngrant create table, create session to machete;\r\nalter user machete quota 32m on vault13;\r\ncreate user dominic identified by machete;\r\ngrant create table, create session to dominic;\r\nalter user dominic quota 32m on vault13;\r\nconnect machete\/dominic@special\r\ncreate table canterbury\r\n(\r\n  id number(10),\r\n  newname varchar2(40)\r\n);\r\ninsert into canterbury values (123, '123');\r\ncommit;\r\nconnect dominic\/machete@special\r\ncreate table canterbury_dom\r\n(\r\n  id number(10),\r\n  newname varchar2(40)\r\n);\r\ninsert into canterbury_dom values (123, '123');\r\ncommit;\r\n<\/pre>\n<p>And another two local users on pipboy PDB.<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nconnect system\/manager@pipboy\r\ncreate user machete identified by dominic;\r\ngrant create table, create session to machete;\r\nalter user machete quota 32m on vault13;\r\ncreate user mechanist identified by mechanist;\r\ngrant create table, create session to mechanist;\r\nalter user mechanist quota 32m on vault13;\r\nconnect machete\/dominic@pipboy\r\ncreate table canterbury_pb\r\n(\r\n  id number(10),\r\n  newname varchar2(40)\r\n);\r\ninsert into canterbury_pb values (123, '123');\r\ncommit;\r\nconnect mechanist\/mechanist@pipboy\r\ncreate table canterbury_mech\r\n(\r\n  id number(10),\r\n  newname varchar2(40)\r\n);\r\ninsert into canterbury_mech values (123, '123');\r\ncommit;\r\n<\/pre>\n<p>Now we can go back to root container and see summary about users and objects that we&#8217;ve just created.<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nconnect \/ as sysdba\r\nstart mt\/cusersonml121\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nKey for column names\r\nC - Common user\r\n\r\n~~ all users ~~\r\n~~ only non-system users (non oracle maintained and local) ~~\r\n\r\n CnID Container Name      User Id User name                Account status     C\r\n----- --------------- ----------- ------------------------ ------------------ -\r\n    3 PIPBOY                  102 MAXSTONE                 OPEN               N\r\n    3 PIPBOY                  121 OTHERUSER                OPEN               N\r\n    3 PIPBOY                  122 MACHETE                  OPEN               N\r\n    3 PIPBOY                  123 MECHANIST                OPEN               N\r\n    4 SPECIAL                 102 MAXSTONE                 OPEN               N\r\n    4 SPECIAL                 118 MACHETE                  OPEN               N\r\n    4 SPECIAL                 119 DOMINIC                  OPEN               N\r\n    5 MOLERAT_CLONE            70 AGNES                    OPEN               N\r\n    5 MOLERAT_CLONE            71 LEWIS                    OPEN               N\r\n    5 MOLERAT_CLONE            85 RogerMaxson              OPEN               N\r\n    6 MOLERAT_CLONE37          70 AGNES                    OPEN               N\r\n    6 MOLERAT_CLONE37          71 LEWIS                    OPEN               N\r\n    6 MOLERAT_CLONE37          74 NEWDBA                   OPEN               N\r\n<\/pre>\n<p>New users are present in different PDBs. Just to highlight the basics:<\/p>\n<ul>\n<li>I was using container = current during creation all of the users &#8211; it&#8217;s automatically implied when connected to PDB and no container clause is given<\/li>\n<li>I had required privileges (create user)<\/li>\n<li>I&#8217;ve named my user <b>without<\/b> prefix c## &#8211; local user cannot have his name started with c##<\/li>\n<li>I cannot use the same name for role and user &#8211; and I cannot use the same name for local and common user (because of prefix rule with common users and roles)<\/li>\n<\/ul>\n<p>One more overview about database users objects, for example, tables that belongs to machete:<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nstart mt\/ctable121\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nTables with owner LIKE machete\r\n\r\nContainer name   Table name                     Tablespace name\r\n---------------- ------------------------------ ------------------------------\r\nPIPBOY           CANTERBURY_PB                  VAULT13\r\nSPECIAL          CANTERBURY                     VAULT13\r\n<\/pre>\n<p>We can connect directly to pipboy PDB and check contents of canterbury_pb table. To do so we need to use service name that is registered with a listener from our CDB. No entries in tnsnames.ora is created automatically when PDB is created from command line &#8211; it&#8217;s good to remember to add appropriate lines with configuration right away after creation.<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nconnect machete\/dominic@pipboy\r\nselect *\r\n  from canterbury_pb;\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\n        ID NEWNAME\r\n---------- ----------------------------------------\r\n       123 123\r\n<\/pre>\n<p>I&#8217;ll add two more rows and commit my changes. Than I&#8217;m going to switch to another PDB.<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\ninsert into canterbury_pb values (234, 'invisible');\r\ninsert into canterbury_pb values (345, 'rows');\r\ncommit;\r\nselect *\r\n  from canterbury_pb;\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\n        ID NEWNAME\r\n---------- ----------------------------------------\r\n       123 123\r\n       234 invisible\r\n       345 rows\r\n<\/pre>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nconnect machete\/dominic@special\r\ncreate table canterbury_pb\r\n(\r\n  id number(10),\r\n  newname varchar2(40)\r\n);\r\ninsert into canterbury_pb values (123, 'new table is right here');\r\ncommit;\r\nselect *\r\n  from canterbury;\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\n        ID NEWNAME\r\n---------- ----------------------------------------\r\n       123 123\r\n<\/pre>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nselect *\r\n  from canterbury_pb;\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\n        ID NEWNAME\r\n---------- ----------------------------------------\r\n       123 new table is right here\r\n<\/pre>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nexit\r\n<\/pre>\n<p>I could create new table canterbury_pb in special PDB as namespaces are not shared between PDBs. Table in one PDB can have the same name like any other table in different PDB. CDB_* views shows information across PDBs but cannot access data inside those tables. To emphasize it: root container have only access to the metadata but the data and real definition of user table is inside PDB. Only common objects that are shared as linked objects shows the same contents in all PDB. User is not able to create a table (even in root container) and use it in all PDBs to make DMLs on it. It&#8217;s not possible with common user, it&#8217;s not possible with local user.<\/p>\n<p>For local users PDB means the same like standalone or non-CDB database &#8211; difference for administrator is that internally we can login only to root container and then switch session container. To connect directly to PDB we need a service registered in a listener.<\/p>\n<p>PDB were created to be as much as possible similar in use to standard database (without enabled multitenant option).<\/p>\n<h2>Privileges granted commonly and locally<\/h2>\n<p>To grant a privilege commonly means to give someone permission to do some activity in all PDBs, including root container. First of all I&#8217;ll drop users which are not needed any more.<\/p>\n<pre class=\"brush: bash; title: ; notranslate\" title=\"\">\r\nsql\r\n<\/pre>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\ndrop user c##arma;\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nORA-65048: error encountered when processing the current DDL statement in pluggable\r\ndatabase SPECIAL\r\nORA-01922: CASCADE must be specified to drop 'C##ARMA'\r\n<\/pre>\n<p>Error is related with existing table owned by c##arma common user in special PDB. Cascade option is required to successfully execute drop command.<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\ndrop user c##arma cascade;\r\ndrop user &quot;c##ArthurMaxson&quot; cascade;\r\n<\/pre>\n<p>My scenario is to create a new common user who could be a global junior administrator. His responsibility will be creating local users and giving them some minimum privileges.<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\ncreate user c##jadm identified by secret123;\r\ngrant create session, create table, create view,\r\n      create sequence, create trigger, create procedure,\r\n      create synonym\r\n   to c##jadm\r\n with admin option container = all;\r\ngrant create user, alter user\r\n   to c##jadm container = all;\r\n<\/pre>\n<p>Next command will not complete with success because this is an attempt of giving a common privilege (related only with PDBs) using container = current. This is the default value for grant command and even when in root container one have to remember, that this is the default for privileges.<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\ngrant set containter to c##jadm;\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nORA-00990: missing or invalid privilege\r\n<\/pre>\n<p>Add container clause and watch the magic.<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\ngrant set container to c##jadm container = all;\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nGrant succeeded.\r\n<\/pre>\n<p>Even though the error message is right it could be a bit more precise, especially when dealing with new functionality like multitenant option.<\/p>\n<p>Ok, it&#8217;s time to check how this user operate and what are his privileges in each PDB. Start with script that lists c##jadm common user privileges:<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nstart mt\/cprivilege121\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nKey for column names\r\nC - common privilege?\r\nAO - admin option granted?\r\n\r\nAdd %% if needed for grantee name. Search is case insensitive.\r\n\r\nInput grantee name: %jadm%\r\nPrivileges and roles granted to LIKE %jadm%\r\n\r\nContainer name     Grantee                Privilege                                AO C\r\n------------------ ---------------------- ---------------------------------------- -- -\r\nCDB$ROOT           C##JADM                ALTER USER                               N  Y\r\nCDB$ROOT           C##JADM                CREATE PROCEDURE                         Y  Y\r\nCDB$ROOT           C##JADM                CREATE SEQUENCE                          Y  Y\r\nCDB$ROOT           C##JADM                CREATE SESSION                           Y  Y\r\nCDB$ROOT           C##JADM                CREATE SYNONYM                           Y  Y\r\nCDB$ROOT           C##JADM                CREATE TABLE                             Y  Y\r\nCDB$ROOT           C##JADM                CREATE TRIGGER                           Y  Y\r\nCDB$ROOT           C##JADM                CREATE USER                              N  Y\r\nCDB$ROOT           C##JADM                CREATE VIEW                              Y  Y\r\nCDB$ROOT           C##JADM                SET CONTAINER                            N  Y\r\n(...)\r\nPIPBOY             C##JADM                ALTER USER                               N  Y\r\nPIPBOY             C##JADM                CREATE PROCEDURE                         Y  Y\r\nPIPBOY             C##JADM                CREATE SEQUENCE                          Y  Y\r\nPIPBOY             C##JADM                CREATE SESSION                           Y  Y\r\nPIPBOY             C##JADM                CREATE SYNONYM                           Y  Y\r\nPIPBOY             C##JADM                CREATE TABLE                             Y  Y\r\nPIPBOY             C##JADM                CREATE TRIGGER                           Y  Y\r\nPIPBOY             C##JADM                CREATE USER                              N  Y\r\nPIPBOY             C##JADM                CREATE VIEW                              Y  Y\r\nPIPBOY             C##JADM                SET CONTAINER                            N  Y\r\nSPECIAL            C##JADM                ALTER USER                               N  Y\r\nSPECIAL            C##JADM                CREATE PROCEDURE                         Y  Y\r\nSPECIAL            C##JADM                CREATE SEQUENCE                          Y  Y\r\nSPECIAL            C##JADM                CREATE SESSION                           Y  Y\r\nSPECIAL            C##JADM                CREATE SYNONYM                           Y  Y\r\nSPECIAL            C##JADM                CREATE TABLE                             Y  Y\r\nSPECIAL            C##JADM                CREATE TRIGGER                           Y  Y\r\nSPECIAL            C##JADM                CREATE USER                              N  Y\r\nSPECIAL            C##JADM                CREATE VIEW                              Y  Y\r\nSPECIAL            C##JADM                SET CONTAINER                            N  Y\r\n<\/pre>\n<p>Now, still using common user sys, I&#8217;m going to switch to pipboy and grant two more privileges but only locally. It&#8217;s not possible to use other values than all or current in container clause.<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nalter session set container = pipboy;\r\ngrant create type, create materialized view\r\n   to c##jadm container = current;\r\nstart mt\/cprivilege121\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nInput grantee name: %jadm%\r\nPrivileges and roles granted to LIKE %jadm%\r\n\r\nContainer name     Grantee                Privilege                                AO C\r\n------------------ ---------------------- ---------------------------------------- -- -\r\nPIPBOY             C##JADM                ALTER USER                               N  Y\r\nPIPBOY             C##JADM                CREATE MATERIALIZED VIEW                 N  N\r\nPIPBOY             C##JADM                CREATE PROCEDURE                         Y  Y\r\nPIPBOY             C##JADM                CREATE SEQUENCE                          Y  Y\r\nPIPBOY             C##JADM                CREATE SESSION                           Y  Y\r\nPIPBOY             C##JADM                CREATE SYNONYM                           Y  Y\r\nPIPBOY             C##JADM                CREATE TABLE                             Y  Y\r\nPIPBOY             C##JADM                CREATE TRIGGER                           Y  Y\r\nPIPBOY             C##JADM                CREATE TYPE                              N  N\r\nPIPBOY             C##JADM                CREATE USER                              N  Y\r\nPIPBOY             C##JADM                CREATE VIEW                              Y  Y\r\nPIPBOY             C##JADM                SET CONTAINER                            N  Y\r\n<\/pre>\n<p>From PDB session cdb_sys_privs behave just like dba_sys_privs but it is restricted to local informations only. v$container view exists on PDB level too thus we can use joins between those views and still get proper result.<\/p>\n<p>In the listing we see create type and create materialized view privileges granted locally (common column with N value).<\/p>\n<p>It&#8217;s time to connect as c##jadm and use his privileges to create another local user. Grant him basic privileges and allow to start his work.<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nconnect c##jadm\/secret123@pipboy\r\ncreate user drlesko identified by drlesko;\r\ngrant create table, create view, create session\r\n   to drlesko;\r\nalter user drlesko quota 25m on vault13;\r\nconn \/ as sysdba\r\nstart mt\/cprivilege121\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nInput grantee name: %lesko%\r\nPrivileges and roles granted to LIKE %lesko%\r\n\r\nContainer name     Grantee                Privilege                                AO C\r\n------------------ ---------------------- ---------------------------------------- -- -\r\nPIPBOY             DRLESKO                CREATE SESSION                           N  N\r\nPIPBOY             DRLESKO                CREATE TABLE                             N  N\r\nPIPBOY             DRLESKO                CREATE VIEW                              N  N\r\n<\/pre>\n<p>I&#8217;ve used granted commonly privilege create user from c##jadm user to create drlesko. drlesko has been granted ability to create tables and views. In addition create session allows him to connect to the database (if he finally find out how to use sql*plus).<\/p>\n<p>To revoke granted privileges we need to use the same container clauses like we did when granting the privileges. First attempt to revoke create table commonly granted privilege from c##jadm:<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nrevoke create table from c##jadm;\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nORA-65092: system privilege granted with a different scope to 'C##JADM'\r\n<\/pre>\n<p>Scope is different &#8211; when you go back to the listing with privileges you can see column C (for common grant) in line with create table privilege. We need to change default container clause (which is set to current) and use all value:<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nrevoke create table from c##jadm container = all;\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nRevoke succeeded.\r\n<\/pre>\n<p>To revoke locally granted privilege we need to be in the same container where the grant command has been executed. It&#8217;s not possible from root container. Even with container = all we won&#8217;t succeed &#8211; we need to be more precise. Both commands presented below end up with the same ora error.<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nrevoke create type from c##jadm;\r\nrevoke create type from c##jadm container = all;\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nORA-01952: system privileges not granted to 'C##JADM'\r\n<\/pre>\n<p>Container clause is not necessary as the default value solves our situation here &#8211; I&#8217;m adding it to highlight value of this parameter.<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nalter session set container = pipboy;\r\nrevoke create type from c##jadm container = current;\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nSession altered.\r\nRevoke succeeded.\r\n<\/pre>\n<p>Just the same way like I&#8217;ve granted locally create table, session and view to drlesko you could do the same from any other local user, who has such privileges. PDBs inside behave just like any other standalone (or according to latest naming convention: non-CDB).<\/p>\n<p>It&#8217;s worth to mention about one situation. You grant commonly a privilege and then add the same one locally. On the list you&#8217;ll see locally and commonly granted privilege. Revoking common on local grant has no influence on the other one. For example:<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nalter session set container = pipboy;\r\ngrant create table to c##jadm;\r\nstart mt\/cprivilege121\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nContainer name     Grantee                  Privilege                                AO C\r\n------------------ ------------------------ ---------------------------------------- -- -\r\n(...)\r\nPIPBOY             C##JADM                  CREATE TABLE                             Y  Y\r\nPIPBOY             C##JADM                  CREATE TABLE                             N  N\r\n<\/pre>\n<p>Which privilege takes precedence?<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nconnect c##jadm\/secret123@pipboy\r\ncreate user arthurmaxson identified by secret123;\r\ngrant create table to arthurmaxson;\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nUser created.\r\nGrant succeeded.\r\n<\/pre>\n<p>I&#8217;ll revoke common grant with admin option and create one without this clause.<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nconnect \/ as sysdba\r\nrevoke create table from c##jadm container = all;\r\ngrant create table to c##jadm container = all;\r\nstart mt\/cprivilege121\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nContainer name     Grantee                  Privilege                                AO C\r\n------------------ ------------------------ ---------------------------------------- -- -\r\n(...)\r\nPIPBOY             C##JADM                  CREATE TABLE                             N  N\r\nPIPBOY             C##JADM                  CREATE TABLE                             N  Y\r\n<\/pre>\n<p>I&#8217;ll revoke previously granted privilege to arthurmaxson using system user and add admin option to local privilege for c##jadm user and try again grant this privilege.<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nconnect system\/manager@pipboy\r\nrevoke create table from arthurmaxson;\r\ngrant create table to c##jadm with admin option;\r\nconnect c##jadm\/secret123@pipboy\r\ngrant create table to arthurmaxson;\r\nstart mt\/cprivilege121\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\n(...)\r\nGrant succeeded.\r\n<\/pre>\n<p>Looks like common and local privileges works additive &#8211; only in one place admin option granted give the ability (on PDB level) to grant create table privilege.<\/p>\n<h2>Roles granted commonly and locally<\/h2>\n<p>To make our lives easier Oracle Database offers roles. With multitenant all gone wild and we&#8217;ve got new topic to redefine role usage. I&#8217;m going to start with new common role and one privilege inside &#8211; select any table (*which I&#8217;ll add later).<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nconnect \/ as sysdba\r\ncreate role c##reader container = all;\r\n<\/pre>\n<p>We don&#8217;t have to use container clause &#8211; as a default in root container it is automatically set to value all (which is different than for privilege command). Check status of this role with crole121.sql script.<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nstart mt\/crole121\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nKey for column names\r\nC - common role?\r\nAO - admin option granted?\r\nD - delegate option\r\nDR - default role\r\nOM - Oracle maintained\r\n\r\nAdd %% if needed for owner name. Search is case insensitive.\r\n\r\nInput role name: %reader%\r\nRoles with name LIKE %reader%\r\n\r\nContainer name   Role name            Pass. req. Authent. type C OM\r\n---------------- -------------------- ---------- ------------- - --\r\nCDB$ROOT         C##READER            NO         NONE          Y N\r\nMOLERAT_CLONE    C##READER            NO         NONE          Y N\r\nMOLERAT_CLONE37  C##READER            NO         NONE          Y N\r\nPIPBOY           C##READER            NO         NONE          Y N\r\nSPECIAL          C##READER            NO         NONE          Y N\r\n\r\nRoles with name LIKE %reader% granted to other users and roles\r\n\r\nContainer name   Grantee                  Granted role             AO D DR C\r\n---------------- ------------------------ ------------------------ -- - -- -\r\nCDB$ROOT         SYS                      C##READER                Y  N Y  Y\r\nMOLERAT_CLONE    SYS                      C##READER                Y  N Y  Y\r\nMOLERAT_CLONE37  SYS                      C##READER                Y  N Y  Y\r\nPIPBOY           SYS                      C##READER                Y  N Y  Y\r\nSPECIAL          SYS                      C##READER                Y  N Y  Y\r\n\r\nPrivileges granted to role LIKE %reader%\r\n\r\nno rows selected\r\n<\/pre>\n<p>Role exists in each container. Role is granted to sys user in each container.<\/p>\n<p>One of the rules that is mandatory is to use c## or C## prefix before role name to create a common one. Next restriction is related with use of role: you can grant common role to common or local user. I&#8217;ll grant c##reader to c##jadm user and give this user admin option (common to common grant). Then I&#8217;ll grant this role to machete local user in pipboy PDB with admin option (common to local user grant) and this user grant it to drlasko in pipboy PDB (local to local user grant).<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\ngrant c##reader to c##jadm with admin option container = all;\r\nconnect c##jadm\/secret123@pipboy\r\ngrant c##reader to machete with admin option;\r\nconnect machete\/dominic@pipboy\r\ngrant c##reader to drlesko;\r\nconnect \/ as sysdba\r\nstart mt\/crole121\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nKey for column names\r\nC - common role?\r\nAO - admin option granted?\r\nD - delegate option\r\nDR - default role\r\nOM - Oracle maintained\r\n\r\nAdd %% if needed for owner name. Search is case insensitive.\r\n\r\nInput role name: %reader%\r\nRoles with name LIKE %reader%\r\n\r\nContainer name   Role name            Pass. req. Authent. type C OM\r\n---------------- -------------------- ---------- ------------- - --\r\nCDB$ROOT         C##READER            NO         NONE          Y N\r\nMOLERAT_CLONE    C##READER            NO         NONE          Y N\r\nMOLERAT_CLONE37  C##READER            NO         NONE          Y N\r\nPIPBOY           C##READER            NO         NONE          Y N\r\nSPECIAL          C##READER            NO         NONE          Y N\r\n\r\nRoles with name LIKE %reader% granted to other users and roles\r\n\r\nContainer name   Grantee                  Granted role             AO D DR C\r\n---------------- ------------------------ ------------------------ -- - -- -\r\nCDB$ROOT         C##JADM                  C##READER                Y  N Y  Y\r\nCDB$ROOT         SYS                      C##READER                Y  N Y  Y\r\nMOLERAT_CLONE    C##JADM                  C##READER                Y  N Y  Y\r\nMOLERAT_CLONE    SYS                      C##READER                Y  N Y  Y\r\nMOLERAT_CLONE37  C##JADM                  C##READER                Y  N Y  Y\r\nMOLERAT_CLONE37  SYS                      C##READER                Y  N Y  Y\r\nPIPBOY           C##JADM                  C##READER                Y  N Y  Y\r\nPIPBOY           DRLESKO                  C##READER                N  N Y  N\r\nPIPBOY           MACHETE                  C##READER                Y  N Y  N\r\nPIPBOY           SYS                      C##READER                Y  N Y  Y\r\nSPECIAL          C##JADM                  C##READER                Y  N Y  Y\r\nSPECIAL          SYS                      C##READER                Y  N Y  Y\r\n\r\n12 rows selected.\r\n\r\nPrivileges granted to role LIKE %reader%\r\n\r\nno rows selected\r\n\r\n<\/pre>\n<p>Effect of those commands was aligned to the documentation &#8211; no surprises here. We&#8217;ve got local grants to machete with admin option and drlesko without admin option in pipboy PDB. Common grant to c##jadm with admin option. So far no privileges have been granted to our role. Last test require another common user to grant locally from local user to common one.<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\ncreate user c##vikia identified by secret123;\r\ngrant create session to c##vikia container = all;\r\nconnect machete\/dominic@pipboy\r\ngrant c##reader to c##vikia;\r\nconnect \/ as sysdba\r\nstart mt\/crole121\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nRoles with name LIKE %reader% granted to other users and roles\r\n\r\nContainer name   Grantee                  Granted role             AO D DR C\r\n---------------- ------------------------ ------------------------ -- - -- -\r\n[... removed part of listing]\r\nPIPBOY           C##VIKIA                 C##READER                N  N Y  N\r\n[... removed part of listing]\r\n<\/pre>\n<p>Common role behave similar to what we know from earlier versions. One more layer have been added &#8211; common layer but this does not change anything for local users. Yet another role with c## prefix. I&#8217;ll add privilege to this common role.<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\ngrant select any table to c##reader container = current;\r\nstart mt\/crole121\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\n[... removed part of listing]\r\nPrivileges granted to role LIKE %read%\r\n\r\nContainer name   Grantee                  Privilege                                AO C\r\n---------------- ------------------------ ---------------------------------------- -- -\r\nCDB$ROOT         C##READER                SELECT ANY TABLE                         N  N\r\n<\/pre>\n<p>I&#8217;ll add one more local grant from pipboy container.<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nalter session set container = pipboy;\r\ngrant select any table to c##reader container = current;\r\nalter session set container = cdb$root;\r\nstart mt\/crole121\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\n[... removed part of listing]\r\nPrivileges granted to role LIKE %read%\r\n\r\nContainer name   Grantee                  Privilege                                AO C\r\n---------------- ------------------------ ---------------------------------------- -- -\r\nCDB$ROOT         C##READER                SELECT ANY TABLE                         N  N\r\nPIPBOY           C##READER                SELECT ANY TABLE                         N  N\r\n<\/pre>\n<p>Next test &#8211; I&#8217;ll try to add common privilege to current local privileges.<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\ngrant select any table to c##reader with admin option container = all;\r\nstart mt\/crole121\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nPrivileges granted to role LIKE %read%\r\n\r\nContainer name   Grantee                  Privilege                                AO C\r\n---------------- ------------------------ ---------------------------------------- -- -\r\nCDB$ROOT         C##READER                SELECT ANY TABLE                         Y  Y\r\nCDB$ROOT         C##READER                SELECT ANY TABLE                         N  N\r\nMOLERAT_CLONE    C##READER                SELECT ANY TABLE                         Y  Y\r\nMOLERAT_CLONE37  C##READER                SELECT ANY TABLE                         Y  Y\r\nPIPBOY           C##READER                SELECT ANY TABLE                         Y  Y\r\nPIPBOY           C##READER                SELECT ANY TABLE                         N  N\r\nSPECIAL          C##READER                SELECT ANY TABLE                         Y  Y\r\n<\/pre>\n<p>We&#8217;ve got doubled entries for containers where commonly and locally select any table privilege has been granted. I&#8217;ve added admin option just to improve visibility of output.<\/p>\n<p>To revoke granted privilege I need to use the same containers which I&#8217;ve used previously.<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nalter session set container = pipboy;\r\nrevoke select any table from c##reader;\r\nalter session set container = cdb$root;\r\nstart mt\/crole121\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nPrivileges granted to role LIKE %reader%\r\n\r\nContainer name   Grantee                  Privilege                                AO C\r\n---------------- ------------------------ ---------------------------------------- -- -\r\nCDB$ROOT         C##READER                SELECT ANY TABLE                         N  N\r\nCDB$ROOT         C##READER                SELECT ANY TABLE                         Y  Y\r\nMOLERAT_CLONE    C##READER                SELECT ANY TABLE                         Y  Y\r\nMOLERAT_CLONE37  C##READER                SELECT ANY TABLE                         Y  Y\r\nPIPBOY           C##READER                SELECT ANY TABLE                         Y  Y\r\nSPECIAL          C##READER                SELECT ANY TABLE                         Y  Y\r\n<\/pre>\n<p>Privilege from pipboy PDB have been removed.<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nrevoke select any table from c##reader container = all;\r\nstart mt\/crole121\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nPrivileges granted to role LIKE %read%\r\n\r\nContainer name   Grantee                  Privilege                                AO C\r\n---------------- ------------------------ ---------------------------------------- -- -\r\nCDB$ROOT         C##READER                SELECT ANY TABLE                         N  N\r\n<\/pre>\n<p>Common role has lost common possibility to share select any table privilege with other users and roles. One more revoke to be done:<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nrevoke select any table from c##reader container = current;\r\nstart mt\/crole121\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nPrivileges granted to role LIKE %read%\r\n\r\nno rows selected\r\n<\/pre>\n<p>The last thing we can do now is to drop this common role.<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\ndrop role c##reader;\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nRole dropped.\r\n<\/pre>\n<p>Note, that when I was creating this role I used container = all clause (for roles in root container using common user it is the default, a bit different than with users or privileges). There is no way to use this clause with drop role command &#8211; it&#8217;s not within the syntax. You just have to remember that common DDLs can be executed only from root container. Otherwise, you&#8217;ll receive an error reminding you about this rule. One more test with creating a local role from root container:<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\ncreate role reader;\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nORA-65096: invalid common user or role name\r\n<\/pre>\n<p>&#8230;and another test&#8230;<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\ncreate role reader container = current;\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nORA-65049: creation of local user or role is not allowed in CDB$ROOT\r\n<\/pre>\n<p>This only confirms what we&#8217;ve seen earlier when I&#8217;ve tried to create local user in root container.<\/p>\n<p>Local roles are separated between PDBs and can be granted to common role and common roles can be granted to local roles. All commands below execute without an error:<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nconn \/ as sysdba\r\ncreate role c##reader;\r\nalter session set container=pipboy;\r\ncreate role newreader;\r\ngrant c##reader to newreader;\r\nrevoke c##reader from newreader;\r\ngrant newreader to c##reader;\r\nrevoke newreader from c##reader;\r\ndrop role newreader;\r\n<\/pre>\n<p>This concludes chapter related with create, grant, revoke and drop common role.<\/p>\n<h2>Accessing container data<\/h2>\n<p>Oracle added new clause in alter user related with container data &#8211; only to alter user, it&#8217;s not possible to create user and give him those privileges in one command. This feature provide user ability to access CDB related data. You can check all_tables and all_views  views to see if particular information is within container data scope.<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nselect container_data, con_id, count(0)\r\n  from cdb_views\r\n group by container_data, con_id\r\n order by container_data, con_id;\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nC     CON_ID   COUNT(0)\r\n- ---------- ----------\r\nN          1       3833\r\nN          3       3843\r\nN          4       3843\r\nN          5       3844\r\nN          6       3844\r\nY          1       2665\r\nY          3       2665\r\nY          4       2665\r\nY          5       2665\r\nY          6       2665\r\n<\/pre>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\ncol owner for a30 hea 'Owner'\r\ncol view_name for a30 hea 'View name'\r\ncol con_id for 999999 hea 'Con ID'\r\nselect owner, view_name, con_id\r\n  from cdb_views\r\n where container_data = 'Y'\r\n   and view_name in ('V_$SESSION','V_$PROCESS')\r\n order by view_name, con_id;\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nOwner                          View name                       Con ID\r\n------------------------------ ------------------------------ -------\r\nSYS                            V_$PROCESS                           1\r\nSYS                            V_$PROCESS                           3\r\nSYS                            V_$PROCESS                           4\r\nSYS                            V_$PROCESS                           5\r\nSYS                            V_$PROCESS                           6\r\nSYS                            V_$SESSION                           1\r\nSYS                            V_$SESSION                           3\r\nSYS                            V_$SESSION                           4\r\nSYS                            V_$SESSION                           5\r\nSYS                            V_$SESSION                           6\r\n<\/pre>\n<p>Notice, that in cdb_views we&#8217;ve got container_data column as varchar2(1) with values Y or N. In cdb_tables you can find the same column name but with other length: varchar2(3) and with values NO and probably YES &#8211; didn&#8217;t see that one coming. When you take a look on cdb_container_data view you can find default_attr and all_containers columns &#8211; first is char(1) and the another one varchar2(1) &#8211; both with values Y or N. I found even more inconsistency like those two in 12c release (for example, username column in v$pwfile_users or v$session_longops is varchar2(30) and in cdb_objects owner is varchar2(128) &#8211; just query cdb_tab_columns by username or owner and you&#8217;ll see what I&#8217;ve got on mind with columns inconsistency problem).<\/p>\n<p>Ok, back to container data &#8211; as a default common user has access to default set of container data objects. This means, root container and CDB structures but without PDBs information. Off course, you can&#8217;t select anything until at least local grant in root container.<\/p>\n<p>Altering user container data privileges on v$session in all containers gives access to all v$session data from containers 0 (CDB level), 1 (root level) and PDBs but it will require connection with root container. In the opposite, we can commonly grant select on v$session but this would require switching between PDBs to see local data &#8211; for example, connected sessions to pipboy PDB force c##jadm to switch to PDB pipboy to see them in v$session.<\/p>\n<p>I still have my c##jadm junior administrator. I&#8217;ll give him grant to select on v_$session (I&#8217;m using sys connection).<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\ngrant select on v_$session to c##jadm container = all;\r\nstart mt\/cobjectpriv121\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nKey for column names\r\nC - common privilege?\r\nG - grant option added?\r\nH - hierarchy?\r\n\r\nAdd %% if needed for grantee name. Search is case insensitive.\r\n\r\nInput grantee name: %jadm%\r\nPrivileges granted on objects to LIKE %jadm%\r\n\r\nContainer name  Grantee        Owner          Object name        Privilege    G H C Ob.type\r\n--------------- -------------- -------------- ------------------ ------------ - - - -------\r\nCDB$ROOT        C##JADM        SYS            V_$SESSION         SELECT       N N Y VIEW\r\nMOLERAT_CLONE   C##JADM        SYS            V_$SESSION         SELECT       N N Y VIEW\r\nMOLERAT_CLONE37 C##JADM        SYS            V_$SESSION         SELECT       N N Y VIEW\r\nPIPBOY          C##JADM        SYS            V_$SESSION         SELECT       N N Y VIEW\r\nSPECIAL         C##JADM        SYS            V_$SESSION         SELECT       N N Y VIEW\r\n<\/pre>\n<p>Right now I can select contents of v$session view from <b>within<\/b> each container. I&#8217;ll check number of sessions from root container.<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nconnect c##jadm\/secret123@tcdb\r\ncol username for a30 hea 'Username'\r\ncol program for a35 hea 'Program'\r\nselect con_id, username, program, count(0)\r\n  from v$session\r\n where type != 'BACKGROUND'\r\n group by con_id, username, program\r\n order by con_id, username, program;\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\n    CON_ID Username                       Program                               COUNT(0)\r\n---------- ------------------------------ ----------------------------------- ----------\r\n         1 C##JADM                        sqlplus@odone (TNS V1-V3)                    1\r\n<\/pre>\n<p>The same result of this query is returned from sys user in root container. I&#8217;ll create new putty session with connection to pipboy PDB as system user (if you want to know more about containers and connecting to them review articles about CDB and PDBs available on my site or check in Administrator&#8217;s Guide) and connect as c##jadm user again to check on v$session with current session.<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nconnect c##jadm\/secret123@tcdb\r\ncol username for a30 hea 'Username'\r\ncol program for a35 hea 'Program'\r\nselect con_id, username, program, count(0)\r\n  from v$session\r\n where type != 'BACKGROUND'\r\n group by con_id, username, program\r\n order by con_id, username, program;\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\n    CON_ID Username                       Program                               COUNT(0)\r\n---------- ------------------------------ ----------------------------------- ----------\r\n         1 C##JADM                        sqlplus@odone (TNS V1-V3)                    1\r\n<\/pre>\n<p>Result is just the same like earlier. We&#8217;ve got only local (root) access to v$session (just like described in docs as a default) because we didn&#8217;t alter container data yet. I&#8217;ll change it to see all containers and check again. Session as system user to pipboy still remains active.<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nconnect \/ as sysdba\r\nalter user c##jadm\r\n  set container_data = all container = current;\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nUser altered.\r\n<\/pre>\n<p>Don&#8217;t forget about container = current clause &#8211; without it you&#8217;ll receive an error presented below.<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nalter user c##jadm\r\n  set container_data = all;\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nORA-65048: error encountered when processing the current DDL statement in pluggable\r\ndatabase PIPBOY\r\nORA-65056: CONTAINER_DATA attribute is not used in a pluggable database.\r\n<\/pre>\n<p>There is a really nice description of this error and container_data column and clause usage (see cause and action section of error ORA-65056) &#8211; I think this description is better than alter user command and reference for dba_container_data view altogether from other docs.<\/p>\n<p>Ok, we&#8217;ve got all PDBs accessible as c##jadm &#8211; I&#8217;ll check again sessions.<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nconnect c##jadm\/secret123@tcdb\r\nselect con_id, username, program, count(0)\r\n  from v$session\r\n where type != 'BACKGROUND'\r\n group by con_id, username, program\r\n order by con_id, username, program;\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\n    CON_ID Username                       Program                               COUNT(0)\r\n---------- ------------------------------ ----------------------------------- ----------\r\n         1 C##JADM                        sqlplus@odone (TNS V1-V3)                    1\r\n         3 SYSTEM                         sqlplus@odone (TNS V1-V3)                    1\r\n<\/pre>\n<p>Now we can see system session. I&#8217;ll change this connection to special PDB which has different container id and execute the query again:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\n    CON_ID Username                       Program                               COUNT(0)\r\n---------- ------------------------------ ----------------------------------- ----------\r\n         1 C##JADM                        sqlplus@odone (TNS V1-V3)                    1\r\n         4 SYSTEM                         sqlplus@odone (TNS V1-V3)                    1\r\n<\/pre>\n<p>Notice, that we see this data in root container because we&#8217;ve altered container data privileges not because we&#8217;ve got commonly granted select on v$session.<\/p>\n<p>Now, I&#8217;ll cut available containers list only to pipboy (or I would like to&#8230;):<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nconnect \/ as sysdba\r\nalter user c##jadm\r\n  set container_data = (pipboy) container = current;\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nORA-65057: CONTAINER_DATA attribute must always include the current container\r\n<\/pre>\n<p>This means that you always have to add root container to the list when specifying a list of containers.<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nalter user c##jadm\r\n  set container_data = (cdb$root, pipboy) container = current;\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nUser altered.\r\n<\/pre>\n<p>To summarize so far: always use container = current and don&#8217;t forget about cdb$root in the list when altering user container_data options.<\/p>\n<p>I&#8217;ll check again session list from c##jadm user and then change system session and connect to pipboy again (I&#8217;m connected to special PDB right now).<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nconnect c##jadm\/secret123@tcdb\r\nselect con_id, username, program, count(0)\r\n  from v$session\r\n where type != 'BACKGROUND'\r\n group by con_id, username, program\r\n order by con_id, username, program;\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\n    CON_ID Username                       Program                               COUNT(0)\r\n---------- ------------------------------ ----------------------------------- ----------\r\n         1 C##JADM                        sqlplus@odone (TNS V1-V3)                    1\r\n<\/pre>\n<p>Only one session &#8211; just like configured. I&#8217;m changing system session to pipboy and executing query again.<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\n    CON_ID Username                       Program                               COUNT(0)\r\n---------- ------------------------------ ----------------------------------- ----------\r\n         1 C##JADM                        sqlplus@odone (TNS V1-V3)                    1\r\n         3 SYSTEM                         sqlplus@odone (TNS V1-V3)                    1\r\n<\/pre>\n<p>We can see new session on the list. All is working properly. As we&#8217;ve got select on v$session in each PDB I&#8217;ll try to change container and see from within if I can see session in special PDB. I&#8217;m changing system connection from pipboy to special PDB and adjusting my session container for c##jadm:<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nalter session set container = special;\r\nselect con_id, username, program, count(0)\r\n  from v$session\r\n where type != 'BACKGROUND'\r\n group by con_id, username, program\r\n order by con_id, username, program;\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\n    CON_ID Username                       Program                               COUNT(0)\r\n---------- ------------------------------ ----------------------------------- ----------\r\n         4 C##JADM                        sqlplus@odone (TNS V1-V3)                    1\r\n         4 SYSTEM                         sqlplus@odone (TNS V1-V3)                    1\r\n<\/pre>\n<p>From special PBD all is visible locally.<\/p>\n<p>I&#8217;ll add another privilege for c##jadm user and try to restrict access to only one of those views.<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nconnect \/ as sysdba\r\ngrant select on v_$process\r\n   to c##jadm container = all;\r\nstart mt\/cobjectpriv121\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nInput grantee name: %jadm%\r\nPrivileges granted on objects to LIKE %jadm%\r\n\r\nContainer name  Grantee        Owner          Object name        Privilege    G H C Ob.type\r\n--------------- -------------- -------------- ------------------ ------------ - - - -------\r\nCDB$ROOT        C##JADM        SYS            V_$PROCESS         SELECT       N N Y VIEW\r\nCDB$ROOT        C##JADM        SYS            V_$SESSION         SELECT       N N Y VIEW\r\nMOLERAT_CLONE   C##JADM        SYS            V_$PROCESS         SELECT       N N Y VIEW\r\nMOLERAT_CLONE   C##JADM        SYS            V_$SESSION         SELECT       N N Y VIEW\r\nMOLERAT_CLONE37 C##JADM        SYS            V_$PROCESS         SELECT       N N Y VIEW\r\nMOLERAT_CLONE37 C##JADM        SYS            V_$SESSION         SELECT       N N Y VIEW\r\nPIPBOY          C##JADM        SYS            V_$PROCESS         SELECT       N N Y VIEW\r\nPIPBOY          C##JADM        SYS            V_$SESSION         SELECT       N N Y VIEW\r\nSPECIAL         C##JADM        SYS            V_$PROCESS         SELECT       N N Y VIEW\r\nSPECIAL         C##JADM        SYS            V_$SESSION         SELECT       N N Y VIEW\r\n<\/pre>\n<p>And adjust container data privileges using alter user command.<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nalter user c##jadm\r\n  set container_data = all for v_$session container = current;\r\nstart mt\/cdata121\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nKey for column names\r\nD - default attribute\r\nAC - all containers\r\n\r\nAdd %% if needed for user name. Search is case insensitive.\r\n\r\nInput user name: %jadm%\r\nContainer data granted to user LIKE %jadm%\r\n\r\nContainer name   User name            D Object owner         Object name                  AC\r\n---------------- -------------------- - -------------------- ---------------------------- --\r\nCDB$ROOT         C##JADM              Y                                                   N\r\nPIPBOY           C##JADM              Y                                                   N\r\n                 C##JADM              N SYS                  V_$SESSION                   Y\r\n<\/pre>\n<p>With clause <b>for<\/b> we can chose specific object which contents user is going to see. We can see all sessions from root container according to granted access (all containers Y in AC column):<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nconnect c##jadm\/secret123@tcdb\r\nselect con_id, username, program, count(0)\r\n  from v$session\r\n where type != 'BACKGROUND'\r\n group by con_id, username, program\r\n order by con_id, username, program;\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\n    CON_ID User name            Program                               COUNT(0)\r\n---------- -------------------- ----------------------------------- ----------\r\n         1 C##JADM              sqlplus@odone (TNS V1-V3)                    1\r\n(...)\r\n         4 SYSTEM               sqlplus@odone (TNS V1-V3)                    1\r\n<\/pre>\n<p>But we&#8217;re going to see v$process view contents from root container only for root and pipboy PDB (con_id = 3):<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nselect con_id, username, program, count(0)\r\n  from v$process\r\n where background is null\r\n group by con_id, username, program\r\n order by con_id, username, program;\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\n    CON_ID User name            Program                               COUNT(0)\r\n---------- -------------------- ----------------------------------- ----------\r\n(...)\r\n         1 grid                 oracle@odone                                 1\r\n         3 grid                 oracle@odone                                 1\r\n<\/pre>\n<p>When I&#8217;ve terminated system connection to pipboy in second session and switched to special (con_id = 4) only from sys I could see this process. It isn&#8217;t visible for c##jadm.<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nselect con_id, username, program, count(0)\r\n  from v$process\r\n where background is null\r\n group by con_id, username, program\r\n order by con_id, username, program;\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\n    CON_ID User name            Program                               COUNT(0)\r\n---------- -------------------- ----------------------------------- ----------\r\n(...)\r\n         1 grid                 oracle@odone                                 1\r\n<\/pre>\n<p>Now it&#8217;s time to take back what we&#8217;ve given to c##jadm common user. Just to remind about current state of granted privileges on objects:<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nconnect \/ as sysdba\r\nstart mt\/cdata121\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nKey for column names\r\nD - default attribute\r\nAC - all containers\r\n\r\nAdd %% if needed for user name. Search is case insensitive.\r\n\r\nInput user name: %jadm%\r\nContainer data granted to user LIKE %jadm%\r\n\r\nContainer name   User name            D Object owner         Object name                  AC\r\n---------------- -------------------- - -------------------- ---------------------------- --\r\nCDB$ROOT         C##JADM              Y                                                   N\r\nPIPBOY           C##JADM              Y                                                   N\r\n                 C##JADM              N SYS                  V_$SESSION                   Y\r\n<\/pre>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nstart mt\/cobjectpriv121\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nKey for column names\r\nC - common privilege?\r\nG - grant option added?\r\nH - hierarchy?\r\n\r\nAdd %% if needed for grantee name. Search is case insensitive.\r\n\r\nInput grantee name: %jadm%\r\nPrivileges granted on objects to LIKE %jadm%\r\n\r\nContainer name  Grantee        Owner          Object name        Privilege    G H C Ob.type\r\n--------------- -------------- -------------- ------------------ ------------ - - - -------\r\nCDB$ROOT        C##JADM        SYS            V_$PROCESS         SELECT       N N Y VIEW\r\nCDB$ROOT        C##JADM        SYS            V_$SESSION         SELECT       N N Y VIEW\r\nMOLERAT_CLONE   C##JADM        SYS            V_$PROCESS         SELECT       N N Y VIEW\r\nMOLERAT_CLONE   C##JADM        SYS            V_$SESSION         SELECT       N N Y VIEW\r\nMOLERAT_CLONE37 C##JADM        SYS            V_$PROCESS         SELECT       N N Y VIEW\r\nMOLERAT_CLONE37 C##JADM        SYS            V_$SESSION         SELECT       N N Y VIEW\r\nPIPBOY          C##JADM        SYS            V_$PROCESS         SELECT       N N Y VIEW\r\nPIPBOY          C##JADM        SYS            V_$SESSION         SELECT       N N Y VIEW\r\nSPECIAL         C##JADM        SYS            V_$PROCESS         SELECT       N N Y VIEW\r\nSPECIAL         C##JADM        SYS            V_$SESSION         SELECT       N N Y VIEW\r\n<\/pre>\n<p>I&#8217;ll try to remove access to v$session from c##jadm. First, I&#8217;ll try to remove only one grant from special PDB.<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\n alter user c##jadm\r\nremove container_data = (special) for v_$session container = current;\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nORA-65062: CONTAINER_DATA attribute is set to ALL\r\n<\/pre>\n<p>Ok, I&#8217;ll try to remove with all value for container_data clause.<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\n alter user c##jadm\r\nremove container_data = all for v_$session container = current;\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nORA-00922: missing or invalid option\r\n<\/pre>\n<p>Ah, yes, there is no syntax available to remove with all value for container_data (see alter user command in SQL Language Reference).<\/p>\n<p>Maybe I&#8217;ll be able to reset this user access and remove this grant overwriting it with default.<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\n alter user c##jadm\r\n   set container_data = default for v_$session container = current;\r\nstart mt\/cdata121\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nInput user name: %jadm%\r\nContainer data granted to user LIKE %jadm%\r\n\r\nContainer name   User name            D Object owner         Object name                  AC\r\n---------------- -------------------- - -------------------- ---------------------------- --\r\nCDB$ROOT         C##JADM              Y                                                   N\r\nPIPBOY           C##JADM              Y                                                   N\r\n<\/pre>\n<p>Ok, I don&#8217;t know, why we have <b>remove<\/b> in this command available &#8211; maybe we can remove single container from scope of this user.<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\n alter user c##jadm\r\nremove container_data = (pipboy) container = current;\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nInput user name: %jadm%\r\nContainer data granted to user LIKE %jadm%\r\n\r\nContainer name   User name            D Object owner         Object name                  AC\r\n---------------- -------------------- - -------------------- ---------------------------- --\r\nCDB$ROOT         C##JADM              Y                                                   N\r\n<\/pre>\n<p>Probably this is it. Now, how to remove this one entry too?<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\n alter user c##jadm\r\nremove container_data = (cdb$root) container = current;\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nORA-65057: CONTAINER_DATA attribute must always include the current container\r\n<\/pre>\n<p>Maybe reset to default would help just like with object privilege.<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nalter user c##jadm\r\n  set container_data = default container = current;\r\nstart mt\/cdata121\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nInput user name: %jadm%\r\nContainer data granted to user LIKE %jadm%\r\n\r\nno rows selected\r\n<\/pre>\n<p>And cleaning up the c##jadm user from grants:<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nrevoke select on v_$process from c##jadm container = all;\r\nrevoke select on v_$session from c##jadm container = all;\r\n<\/pre>\n<p>Earlier I&#8217;ve used common grants with select on both views &#8211; just to underline once more that common grants (or local) on objects are separated from container data available via alter user command. I&#8217;ll add only local grant to select v$session view and all container data to c##jadm privileges list. A session as system user to pipboy PDB have been established in a separate window (container id for pipboy PDB is 3 and for special it is 4).<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nconnect \/ as sysdba\r\ngrant select on v_$session to c##jadm container = current;\r\nalter user c##jadm\r\n  set container_data = all for v_$session container = current;\r\nstart mt\/cdata121\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nInput user name: %jadm%\r\nContainer data granted to user LIKE %jadm%\r\n\r\nContainer name   User name            D Object owner         Object name                  AC\r\n---------------- -------------------- - -------------------- ---------------------------- --\r\n                 C##JADM              N SYS                  V_$SESSION                   Y\r\n<\/pre>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nstart mt\/cobjectpriv121\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nInput grantee name: %jadm%\r\nPrivileges granted on objects to LIKE %jadm%\r\n\r\nContainer name  Grantee        Owner          Object name        Privilege    G H C Ob.type\r\n--------------- -------------- -------------- ------------------ ------------ - - - -------\r\nCDB$ROOT        C##JADM        SYS            V_$SESSION         SELECT       N N N VIEW\r\n<\/pre>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nconnect c##jadm\/secret123@tcdb\r\ncol username for a30 hea 'Username'\r\ncol program for a35 hea 'Program'\r\nselect con_id, username, program, count(0)\r\n  from v$session\r\n where type != 'BACKGROUND'\r\n group by con_id, username, program\r\n order by con_id, username, program;\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\n Con ID Username                       Program                               COUNT(0)\r\n------- ------------------------------ ----------------------------------- ----------\r\n      1 C##JADM                        sqlplus@odone (TNS V1-V3)                    1\r\n      4 SYSTEM                         sqlplus@odone (TNS V1-V3)                    1\r\n<\/pre>\n<p>Switching system session from special to pipboy in additional window and querying again about the session list from main window.<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\ncol username for a30 hea 'Username'\r\ncol program for a35 hea 'Program'\r\nselect con_id, username, program, count(0)\r\n  from v$session\r\n where type != 'BACKGROUND'\r\n group by con_id, username, program\r\n order by con_id, username, program;\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\n Con ID Username                       Program                               COUNT(0)\r\n------- ------------------------------ ----------------------------------- ----------\r\n      1 C##JADM                        sqlplus@odone (TNS V1-V3)                    1\r\n(...)\r\n      3 SYSTEM                         sqlplus@odone (TNS V1-V3)                    1\r\n<\/pre>\n<p>Cleaning up again.<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nalter user c##jadm\r\n  set container_data = default for v_$session container = current;\r\nrevoke select on v_$session from c##jadm;\r\n<\/pre>\n<p>Finally, all privileges have been set to defaults. This means that c##jadm has standard access to container data: all root container views\/tables which are granted for him to see their contents.<\/p>\n<h2>Conclusion<\/h2>\n<p>Container database is a great way to improve <b>hardware<\/b> resource usage &#8211; there is no doubt about it. One instance versus many is always better when thinking about of memory or space for system metadata.<\/p>\n<p>Problems comes up when PDBs are far from being similar &#8211; different role names, different tablespaces, different security approach for applications that use those PDBs. You can see many simple commands that have failed (all according to implemented and documented features, off course, but not exactly convenient in use). Managing security is a heavy bargain when you need to manage common users across all PDBs and, what is terrifying, with one command drop user you can lose days of configuration adjusted for each PDB. Only restore of the root container will bring up this user (or SQL scripts which you prepare somewhere in a flat file away from the database &#8211; after all &#8211; expdp\/impdp does not cooperate with root container too well and we cannot extract common users scripts from PDB too, like presented above).<\/p>\n<p>Common users are impractical as schema owners &#8211; they should not have any objects at all &#8211; remap schema is not possible (or I need more suggestive hint from uncle google). Moreover, name usage in different parts of the database question sense of using them at all (# is just another special character and require special treatment).<\/p>\n<p>You need to &#8220;use a force&#8221; to find a common sense within this new way of managing users across containers. It&#8217;s very cumbersome in use, many commands differs in container clause default value (privileges vs roles and users with theirs common friends) &#8211; the default value is strongly related with your current session and context of use. After spending a week with intensive testing I&#8217;m still far from getting used to it or be proficient with this feature. I strongly disagree that one CDB administrator replace couple administrators from many databases and leverage costs related with the number of people &#8211; I feel just the opposite &#8211; you need one new specialist who will explain everyone the new idea, tutor current administrators, create common users (probably administrators) and maintain order within container data privileges.<\/p>\n<p>There is a hope that with second release all container clauses will be equalized, one default for all commands on root level and one default on PDB level. Improve container data and maybe extend to give access not only from root container but from PDB site too (to separate visibility of root sessions from many PDBs sessions). There are those columns length problem &#8211; this should be equalized too. A bit work and improve in documentation and this could be a great feature &#8211; unfortunately &#8211; before those tests and relying only on documentation I couldn&#8217;t get the idea behind the feature.<\/p>\n<p>Thanks for reading this topic up to the last word. This was quite a trip.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Oracle Database 12c &#8211; Multitenant &#8211; Common users and roles It&#8217;s time to use common users and roles. Introduction Starting point for this article is presented in a table below. Attribute Value Software Oracle Linux 6.5 (64 bit for x86) Oracle Database 12.1.0.2.0 (64 bit for Linux 6.5) Installation and configuration of this software is&hellip;<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[3],"tags":[],"_links":{"self":[{"href":"https:\/\/oradistrict.com\/index.php?rest_route=\/wp\/v2\/posts\/125"}],"collection":[{"href":"https:\/\/oradistrict.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/oradistrict.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/oradistrict.com\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/oradistrict.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=125"}],"version-history":[{"count":1,"href":"https:\/\/oradistrict.com\/index.php?rest_route=\/wp\/v2\/posts\/125\/revisions"}],"predecessor-version":[{"id":126,"href":"https:\/\/oradistrict.com\/index.php?rest_route=\/wp\/v2\/posts\/125\/revisions\/126"}],"wp:attachment":[{"href":"https:\/\/oradistrict.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=125"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/oradistrict.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=125"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/oradistrict.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=125"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}