همانطور که می دانید، در محیط Multitenant ، هpdbها از هم مجزا هستند و به اطلاعات همدیگر دسترسی ندارند با این حال، برای برقراری ارتباط بین pdbها، می توان از dblink استفاده کرد.
روشن است که در محیط Root container هم می توان با کمک dblink از جداول مختلف حاضر در pdbها، گزارش تهیه کرد.
از اوراکل 12.1.0.2، گزارش گیری در محیط Root container، به شیوه دیگری هم قابل انجام است! استفاده از عبارت CONTAINERS(در دستور select) قابلیت تهیه گزارش را بدون استفاده از db-link و بدون اتصال به pdbهای مختلف، فراهم خواهد کرد و با کمک این عبارت می توان محتویات جدول در pdbهای مختلف را به صورت ادغام شده مشاهده کرد.
شرط لازم برای استفاده از عبارت CONTAINERS، داشتن جداول(و یا ویوهایی) با نام و ترجیحا ساختار یکسان در pdbهای مختلف می باشد که در ادامه این متن، به شیوه استفاده از آن خواهیم پرداخت.
در سناریوی زیر، قصد داریم از جداول کاربر عمومی c##usef، که در pdbهای مختلف وجود دارند، گزارشی را تهیه کنیم.
### کاربر عمومی با نام c##usef را در root container ایجاد می کنیم و دسترسی dba را به آن اهدا می کنیم:
SQL> create user c##usef identified by a;
User created.
SQL> grant dba to c##usef CONTAINER=all;
Grant succeeded.
جدولی با نام mytbl را برای این کاربر(c##usef) در سه سطح CDB، PDB1 و PDB2 ایجاد می کنیم همچنین در pdb1 و pdb2 اطلاعاتی را در این جدول درج می کنیم:
SQL> sho con_name
CON_NAME
——————————
CDB$ROOT
SQL> create table c##usef.mytbl(name varchar2(14),last_name varchar2(14),pdb_name varchar2(9));
Table created.
SQL> conn c##usef/a@pdb1
Connected.
SQL> create table c##usef.mytbl(name varchar2(14),last_name varchar2(14),pdb_name varchar2(9));
Table created.
SQL> insert into c##usef.mytbl values(‘HADI’,’ALAVI’,’PDB1′);
1 row created.
SQL> commit;
Commit complete.
SQL> conn c##usef/a@pdb2
Connected.
SQL> create table c##usef.mytbl(name varchar2(14),last_name varchar2(14),pdb_name varchar2(9));
Table created.
SQL> insert into c##usef.mytbl values(‘VAHID’,’USEFZADEH’,’PDB2′);
1 row created.
SQL> commit;
Commit complete.
برای مشاهده اطلاعات جدول mytbl در هر کدام از این pdbها، می توانیم از عبارت CONTAINERS استفاده کنیم(در محیط ROOT container):
SQL> sho con_name
CON_NAME
——————————
CDB$ROOT
SQL> select * from containers(c##usef.mytbl);
NAME LAST_NAME PDB_NAME CON_ID
————– ————– ——— ———-
HADI ALAVI PDB1 3
VAHID USEFZADEH PDB2 6
همانطور که می بینید، ستون جدیدی با نام con_id هم در خروجی دیده می شود که شماره هر کدام از containerها را مشخص می کند.
نکته:برای مشاهده شماره هر کدام از این pdbها، می توان از دستور زیر استفاده کرد:
SQL> show pdbs
CON_ID CON_NAME OPEN MODE RESTRICTED
———- —————————— ———- ———-
2 PDB$SEED READ ONLY NO
3 PDB1 READ WRITE NO
6 PDB2 READ WRITE NO
با دستور زیر، می توان تنها اطلاعات این جدول را در container شماره سه(که pdb1 نام دارد) مشاهده کرد:
SQL> select * from containers(c##usef.mytbl) where con_id in (3);
NAME LAST_NAME PDB_NAME CON_ID
————– ————– ——— ———-
HADI ALAVI PDB1 3
همچنین با دستور زیر، اطلاعات این جدول را در pdb1 و pdb2 مشاهده خواهیم کرد:
SQL> select * from containers(c##usef.mytbl) where con_id in (3,6);
NAME LAST_NAME PDB_NAME CON_ID
————– ————– ——— ———-
HADI ALAVI PDB1 3
VAHID USEFZADEH PDB2 6
اجرای این دستور در هر کدام از pdbها، سبب خواهد شد تا اطلاعات جدول mytbl در آن pdb نمایش داده شود:
SQL> conn c##usef/a@pdb2
Connected.
SQL> select * from containers(c##usef.mytbl) where con_id in (3,6);
NAME LAST_NAME PDB_NAME CON_ID
————– ————– ——— ———-
VAHID USEFZADEH PDB2 6
شیوه گزارش گیری از جداولی که مالک آن یک کاربر عمومی است، در این قسمت بیان شد! حال اگر بخواهیم به اطلاعاتی که مالک ان یک کاربر محلی است، دسترسی داشته باشیم، به ناچار باید به سراغ ایجاد view در محیط کاربر عمومی برویم. ادامه متن را بخوانید.
###جدولی با نام local_tbl را در محیط pdb1 و pdb2 ایجاد می کنیم که در هر دو این pdbها، usef که یک کاربر محلی است، نقش مالک را ایفا می کند:
SQL> alter session set container=pdb1;
Session altered.
SQL> create user usef identified by a;
User created.
SQL> grant dba to usef;
Grant succeeded.
SQL> create table usef.local_tbl(id number primary key,name varchar2(14),last_name varchar2(14),pdb_name varchar2(9));
Table created.
SQL> insert into usef.local_tbl values(1,’REZA’,’NASIRI’,’PDB1′);
1 row created.
SQL> commit;
Commit complete.
SQL> alter session set container=pdb2;
Session altered.
SQL> create user usef identified by a;
User created.
SQL> grant dba to usef;
Grant succeeded.
SQL> create table usef.local_tbl(id number primary key,name varchar2(14),last_name varchar2(14),pdb_name varchar2(9));
Table created.
SQL> insert into usef.local_tbl values(1,’ALI’,’NADERI’,’PDB2′);
1 row created.
SQL> commit;
Commit complete.
برای دسترسی به اطلاعات هر کدام از این جداول در root container، باید viewای را در یکی از کاربران عمومی ایجاد کرد و در Root container هم جدولی هم نام یا آن ویو ایجاد شود:
SQL> create table c##usef.v_local_table(id number primary key,name varchar2(14),last_name varchar2(14),pdb_name varchar2(9));
Table created.
SQL> alter session set container=pdb1;
Session altered.
SQL> grant select on usef.local_tbl to c##usef;
Grant succeeded.
SQL> create or replace view c##usef.v_local_table as select * from usef.local_tbl;
View created.
SQL> alter session set container=pdb2;
Session altered.
SQL> grant select on usef.local_tbl to c##usef;
Grant succeeded.
SQL> create or replace view c##usef.v_local_table as select * from usef.local_tbl;
View created.
با ایجاد view، می توان از Root container به محتویات این جداول دسترسی داشت:
SQL> sho con_name
CON_NAME
——————————
CDB$ROOT
SQL> select * from containers(c##usef.v_local_table);
ID NAME LAST_NAME PDB_NAME CON_ID
———- ————– ————– ——— ———-
1 REZA NASIRI PDB1 3
1 ALI NADERI PDB2 6