本文介绍了 DBMS_CLOUD 包的基本用法。
自治数据库中引入了 DBMS_CLOUD 包,以提供一种与数据库中的对象存储进行交互的简单方法。它可用于版本 19c 和 21c 的本地安装。 它同样适用于 AWS S3 存储 buckets 或 Oracle Cloud Object Storage 存储 buckets。
先决条件
本文中的大多数示例都使用 DBMS_CLOUD 包的本地安装,但某些功能似乎只能在自治数据库上正常工作,过程中我将强调这些限制出现的地方。
DBMS_CLOUD 包默认存在于自治数据库中,它未安装在 Oracle 19c 或 21c 安装中,因此必须手动安装,此 MOS 说明中描述了安装。
可以参考下方的安装示例:
对于某些示例,我们需要一个对象存储 buckets。这可以是 Oracle Cloud Object Store 存储 buckets 或 AWS S3 存储 buckets。以下文章介绍了如何创建 Oracle Cloud Object Store 存储 buckets。
安装
我们创建一个测试用户,确保用户可以创建凭据,并授予其访问 DBMS_CLOUD 包的权限。
conn sys/SysPassword1@//localhost:1521/pdb1 as sysdba --drop user testuser1 cascade; create user testuser1 identified by testuser1 quota unlimited on users; grant connect, resource to testuser1; grant create credential to testuser1; grant execute on dbms_cloud to testuser1;
我们需要一个本地目录对象来与数据库文件服务器上的文件进行交互,授予 test 用户和 C##CLOUD$SERVICE 用户访问此目录的权限。
createorreplacedirectorytmp_files_diras'/tmp/files'; grantread, writeondirectorytmp_files_dirtotestuser1, C##CLOUD$SERVICE;
外部表功能需要访问名为 DATA_PUMP_DIR 的目录对象,因此在 PDB 中创建它并向测试用户授予读/写访问权限。
altersessionset"_oracle_script"=TRUE; createorreplacedirectorydata_pump_diras'/u01/app/oracle/admin/cdb1/dpdump/'; altersessionset"_oracle_script"=FALSE; grantread, writeondirectorydata_pump_dirtotestuser1;
连接到测试用户并创建下表:
conntestuser1/testuser1//localhost:1521/pdb1createtableemp ( empnonumber(4,0), enamevarchar2(10byte), jobvarchar2(9byte), mgrnumber(4,0), hiredatedate, salnumber(7,2), commnumber(7,2), deptnonumber(2,0), constraintpk_empprimarykey (empno) ); insertintoemp (empno,ename,job,mgr,hiredate,sal,comm,deptno) values (7369,'SMITH','CLERK',7902,to_date('17-DEC-80','DD-MON-RR'),800,null,20); insertintoemp (empno,ename,job,mgr,hiredate,sal,comm,deptno) values (7499,'ALLEN','SALESMAN',7698,to_date('20-FEB-81','DD-MON-RR'),1600,300,30); insertintoemp (empno,ename,job,mgr,hiredate,sal,comm,deptno) values (7521,'WARD','SALESMAN',7698,to_date('22-FEB-81','DD-MON-RR'),1250,500,30); insertintoemp (empno,ename,job,mgr,hiredate,sal,comm,deptno) values (7566,'JONES','MANAGER',7839,to_date('02-APR-81','DD-MON-RR'),2975,null,20); insertintoemp (empno,ename,job,mgr,hiredate,sal,comm,deptno) values (7654,'MARTIN','SALESMAN',7698,to_date('28-SEP-81','DD-MON-RR'),1250,1400,30); insertintoemp (empno,ename,job,mgr,hiredate,sal,comm,deptno) values (7698,'BLAKE','MANAGER',7839,to_date('01-MAY-81','DD-MON-RR'),2850,null,30); insertintoemp (empno,ename,job,mgr,hiredate,sal,comm,deptno) values (7782,'CLARK','MANAGER',7839,to_date('09-JUN-81','DD-MON-RR'),2450,null,10); insertintoemp (empno,ename,job,mgr,hiredate,sal,comm,deptno) values (7788,'SCOTT','ANALYST',7566,to_date('19-APR-87','DD-MON-RR'),3000,null,20); insertintoemp (empno,ename,job,mgr,hiredate,sal,comm,deptno) values (7839,'KING','PRESIDENT',null,to_date('17-NOV-81','DD-MON-RR'),5000,null,10); insertintoemp (empno,ename,job,mgr,hiredate,sal,comm,deptno) values (7844,'TURNER','SALESMAN',7698,to_date('08-SEP-81','DD-MON-RR'),1500,0,30); insertintoemp (empno,ename,job,mgr,hiredate,sal,comm,deptno) values (7876,'ADAMS','CLERK',7788,to_date('23-MAY-87','DD-MON-RR'),1100,null,20); insertintoemp (empno,ename,job,mgr,hiredate,sal,comm,deptno) values (7900,'JAMES','CLERK',7698,to_date('03-DEC-81','DD-MON-RR'),950,null,30); insertintoemp (empno,ename,job,mgr,hiredate,sal,comm,deptno) values (7902,'FORD','ANALYST',7566,to_date('03-DEC-81','DD-MON-RR'),3000,null,20); insertintoemp (empno,ename,job,mgr,hiredate,sal,comm,deptno) values (7934,'MILLER','CLERK',7782,to_date('23-JAN-82','DD-MON-RR'),1300,null,10); commit;
本文中所有 SQL 操作均由测试用户执行,除非特殊说明。
conntestuser1/testuser1//localhost:1521/pdb1
对象存储 URI
对于本文中的许多示例,我们使用对象存储 URI。对于 Oracle Cloud,URI 可以采用这些形式之一。
https://swiftobjectstorage.{region}.oraclecloud.com/v1/{namespace}/{bucket}/{objectname} https://objectstorage.{region}.oraclecloud.com/n/{namespace}/b/{bucket}/o/{objectname}
本文主要使用 swiftobjectstorage URI,但两者都有效。 在本文的其余部分,我们将使用 swiftobjectstorage URI。
AWS S3 和 Azure blob 存储 URI 通常如下所示:
AWSS3: https://s3-{region}.amazonaws.com/{bucket}/{objectname}AzureBlogStorage: https://{account}.blob.core.windows.net/{container}/{objectname}
对象存储凭证
DBMS_CLOUD 包包含来自 DBMS_CREDENTIAL 包的过程的副本。这两个包可以互换使用,因为它们做同样的事情。
使用 CREATE_CREDENTIAL 过程为您的对象存储创建凭证。对于 Oracle 对象存储桶,我们使用我们的 Oracle Cloud 电子邮件和我们生成的身份验证令牌。
begindbms_cloud.create_credential ( credential_name=>'obj_store_cred', username=>'me@example.com', password=>'{my-Auth-Token}' ) ; end; /
对于 AWS 存储 buckets,我们使用我们的 AWS 访问密钥和秘密访问密钥。
begindbms_cloud.create_credential ( credential_name=>'obj_store_cred', username=>'my AWS access key', password=>'my AWS secret access key' ); end; /
可以使用 USER_CREDENTIALS 视图显示有关凭证的信息。
columncredential_nameformata25columnusernameformata20selectcredential_name, username, enabledfromuser_credentialsorderbycredential_name; CREDENTIAL_NAMEUSERNAMEENABL--------------------------------------------------OBJ_STORE_CREDmeTRUESQL>
DISABLE_CREDENTIAL 和 ENABLE_CREDENTIAL 过程分别禁用和启用凭据。
begindbms_credential.disable_credential('obj_store_cred'); dbms_credential.enable_credential('obj_store_cred'); end;/
UPDATE_CREDENTIALS 过程允许我们编辑凭证的属性。
begindbms_credential.update_credential( credential_name=>'obj_store_cred', attribute=>'username', value=>'me@example.com'); dbms_credential.update_credential( credential_name=>'obj_store_cred', attribute=>'password', value=>'{my-Auth-Token}'); end; /
DROP_CREDENTIAL 过程删除命名凭据。
begindbms_cloud.drop_credential(credential_name=>'obj_store_cred'); end; /
以下示例需要有效凭据。
对象和文件
有几个例程可用于操作本地数据库文件系统上的文件和云对象存储中的对象。
mkdir -p /tmp/files echo "This is a test file" > /tmp/files/test1.txt
我们使用 PUT_OBJECT 过程将文件从目录对象位置传输到云对象存储。
begin dbms_cloud.put_object ( credential_name => 'obj_store_cred', object_uri => 'https://swiftobjectstorage.uk-london-1.oraclecloud.com/v1/my-namespace/ob-bucket/test1.txt', directory_name => 'tmp_files_dir', file_name => 'test1.txt'); end; /
PUT_OBJECT 过程有一个重载,用于将 BLOB 的内容传输到对象存储。
declare l_file blob; begin l_file := utl_raw.cast_to_raw('This is another test file'); dbms_cloud.put_object ( credential_name => 'obj_store_cred', object_uri => 'https://swiftobjectstorage.uk-london-1.oraclecloud.com/v1/my-namespace/ob-bucket/test2.txt', contents => l_file); end; /
LIST_OBJECTS 表函数列出对象存储 URI 指向的位置中的对象。
setlinesize150columnobject_nameformata12columnchecksumformata35columncreatedformata35columnlast_modifiedformata35select*fromdbms_cloud.list_objects( credential_name=>'obj_store_cred', location_uri=>'https://swiftobjectstorage.uk-london-1.oraclecloud.com/v1/my-namespace/ob-bucket'); OBJECT_NAMEBYTESCHECKSUMCREATEDLAST_MODIFIED-------------------------------------------------------------------------------------------------------------------------------test1.txt205dd39cab1c53c2c77cd352983f9641e111-SEP-2108.45.42.779000AM+00:00test2.txt25d0914057907f9d04dd9e68b1c1e180f011-SEP-2108.45.54.148000AM+00:00SQL>
我们使用 GET_METADATA 函数返回有关特定对象的信息。
selectdbms_cloud.get_metadata( credential_name=>'obj_store_cred', object_uri=>'https://swiftobjectstorage.uk-london-1.oraclecloud.com/v1/my-namespace/ob-bucket/test2.txt') asmetadatafromdual; METADATA--------------------------------------------------------------------------------{"Content-Length":25} SQL>
我们使用 GET_OBJECT 过程将对象从云对象存储传输到目录对象位置。
begindbms_cloud.get_object ( credential_name=>'obj_store_cred', object_uri=>'https://swiftobjectstorage.uk-london-1.oraclecloud.com/v1/my-namespace/ob-bucket/test2.txt', directory_name=>'tmp_files_dir', file_name=>'test2.txt'); end; /
有一个 GET_OBJECT 函数可以将对象从云对象存储传输到 BLOB。
declarel_fileblob; beginl_file :=dbms_cloud.get_object ( credential_name=>'obj_store_cred', object_uri=>'https://swiftobjectstorage.uk-london-1.oraclecloud.com/v1/my-namespace/ob-bucket/test2.txt'); end; /
DELETE_OBJECT 过程从云对象存储中删除对象。
begindbms_cloud.delete_object( credential_name=>'obj_store_cred', object_uri=>'https://swiftobjectstorage.uk-london-1.oraclecloud.com/v1/my-namespace/ob-bucket/test1.txt'); dbms_cloud.delete_object( credential_name=>'obj_store_cred', object_uri=>'https://swiftobjectstorage.uk-london-1.oraclecloud.com/v1/my-namespace/ob-bucket/test2.txt'); end; /
DELETE_FILE 过程从目录对象位置删除文件。
begindbms_cloud.delete_file( directory_name=>'tmp_files_dir', file_name=>'test1.txt'); dbms_cloud.delete_file( directory_name=>'tmp_files_dir', file_name=>'test2.txt'); end; /
LIST_FILES 表函数列出指定 Oracle 目录对象指向的位置中的文件。 文档说它只支持映射到 Oracle 文件系统 (OFS) 或数据库文件系统 (DBFS) 文件系统的目录对象,所以我们不能将它用于常规文件系统。 它确实在自治数据库上提供的位置工作。
select*fromdbms_cloud.list_files(directory_name=>'data_pump_dir');
外部表
CREATE_EXTERNAL_TABLE
我们使用以下内容创建一个名为“emp.dat”的文件并将其放入我们的对象存储中。 它是一个没有标题的管道分隔文件。
7369|"SMITH"|"CLERK"|7902|17-DEC-80|800||20 7499|"ALLEN"|"SALESMAN"|7698|20-FEB-81|1600|300|30 7521|"WARD"|"SALESMAN"|7698|22-FEB-81|1250|500|30 7566|"JONES"|"MANAGER"|7839|02-APR-81|2975||20 7654|"MARTIN"|"SALESMAN"|7698|28-SEP-81|1250|1400|30 7698|"BLAKE"|"MANAGER"|7839|01-MAY-81|2850||30 7782|"CLARK"|"MANAGER"|7839|09-JUN-81|2450||10 7788|"SCOTT"|"ANALYST"|7566|19-APR-87|3000||20 7839|"KING"|"PRESIDENT"||17-NOV-81|5000||10 7844|"TURNER"|"SALESMAN"|7698|08-SEP-81|1500|0|30 7876|"ADAMS"|"CLERK"|7788|23-MAY-87|1100||20 7900|"JAMES"|"CLERK"|7698|03-DEC-81|950||30 7902|"FORD"|"ANALYST"|7566|03-DEC-81|3000||20 7934|"MILLER"|"CLERK"|7782|23-JAN-82|1300||10
CREATE_EXTERNAL_TABLE 过程基于云对象存储中的文件创建名为 EMP_EXT 的外部表。
--drop table emp_ext; begin dbms_cloud.create_external_table( table_name => 'emp_ext', credential_name => 'obj_store_cred', file_uri_list => 'https://swiftobjectstorage.uk-london-1.oraclecloud.com/v1/my-namespace/ob-bucket/emp.dat', column_list => 'empno number(4), ename varchar2(10), job varchar2(9), mgr number(4), hiredate date, sal number(7,2), comm number(7,2), deptno number(2)', format => json_object('ignoremissingcolumns' value 'true', 'removequotes' value 'true') ); end; /
我们查询外部表,它从云对象存储中读取数据。
select*fromemp_ext; EMPNOENAMEJOBMGRHIREDATESALCOMMDEPTNO------------------------------------------------------------------------------7369SMITHCLERK790217-DEC-80800207499ALLENSALESMAN769820-FEB-811600300307521WARDSALESMAN769822-FEB-811250500307566JONESMANAGER783902-APR-812975207654MARTINSALESMAN769828-SEP-8112501400307698BLAKEMANAGER783901-MAY-812850307782CLARKMANAGER783909-JUN-812450107788SCOTTANALYST756619-APR-873000207839KINGPRESIDENT17-NOV-815000107844TURNERSALESMAN769808-SEP-8115000307876ADAMSCLERK778823-MAY-871100207900JAMESCLERK769803-DEC-81950307902FORDANALYST756603-DEC-813000207934MILLERCLERK778223-JAN-8213001014rowsselected. SQL>
FORMAT 参数允许我们调整加载过程以适应数据文件内容。 可以在此处找到格式选项的完整列表,以下示例适用于 CSV 文件。
我们使用以下内容创建一个名为“emp.csv”的文件并将其放入我们的对象存储中。 它是一个带有标题行的 CSV 文件。
"EMPNO","ENAME","JOB","MGR","HIREDATE","SAL","COMM","DEPTNO"7369,"SMITH","CLERK",7902,17-DEC-80,800,,207499,"ALLEN","SALESMAN",7698,20-FEB-81,1600,300,307521,"WARD","SALESMAN",7698,22-FEB-81,1250,500,307566,"JONES","MANAGER",7839,02-APR-81,2975,,207654,"MARTIN","SALESMAN",7698,28-SEP-81,1250,1400,307698,"BLAKE","MANAGER",7839,01-MAY-81,2850,,307782,"CLARK","MANAGER",7839,09-JUN-81,2450,,107788,"SCOTT","ANALYST",7566,19-APR-87,3000,,207839,"KING","PRESIDENT",,17-NOV-81,5000,,107844,"TURNER","SALESMAN",7698,08-SEP-81,1500,0,307876,"ADAMS","CLERK",7788,23-MAY-87,1100,,207900,"JAMES","CLERK",7698,03-DEC-81,950,,307902,"FORD","ANALYST",7566,03-DEC-81,3000,,207934,"MILLER","CLERK",7782,23-JAN-82,1300,,10
CREATE_EXTERNAL_TABLE 过程基于云对象存储中的文件创建名为 EMP_CSV_EXT 的外部表。
--droptableemp_csv_ext; begindbms_cloud.create_external_table( table_name=>'emp_csv_ext', credential_name=>'obj_store_cred', file_uri_list=>'https://swiftobjectstorage.uk-london-1.oraclecloud.com/v1/my-namespace/ob-bucket/emp.csv', column_list=>'empno number(4),ename varchar2(10),job varchar2(9),mgr number(4),hiredate date,sal number(7,2),comm number(7,2),deptno number(2)', format=>json_object('type'value'csv', 'skipheaders'value'1') ); end; /
我们查询外部表,它从云对象存储中读取数据。
select*fromemp_csv_ext; EMPNOENAMEJOBMGRHIREDATESALCOMMDEPTNO------------------------------------------------------------------------------7369SMITHCLERK790217-DEC-80800207499ALLENSALESMAN769820-FEB-811600300307521WARDSALESMAN769822-FEB-811250500307566JONESMANAGER783902-APR-812975207654MARTINSALESMAN769828-SEP-8112501400307698BLAKEMANAGER783901-MAY-812850307782CLARKMANAGER783909-JUN-812450107788SCOTTANALYST756619-APR-873000207839KINGPRESIDENT17-NOV-815000107844TURNERSALESMAN769808-SEP-8115000307876ADAMSCLERK778823-MAY-871100207900JAMESCLERK769803-DEC-81950307902FORDANALYST756603-DEC-813000207934MILLERCLERK778223-JAN-8213001014rowsselected. SQL>
VALIDATE_EXTERNAL_TABLE 过程允许我们检查外部表的有效性。
begindbms_cloud.validate_external_table('emp_csv_ext'); end; /
CREATE_EXTERNAL_PART_TABLE
set markup csv on quote on set trimspool on linesize 1000 feedback off pagesize 0 spool /tmp/files/gbr1.txt select 'GBR', object_id, owner, object_name from all_objects where object_id <= 2000 and rownum <= 1000; spool off spool /tmp/files/gbr2.txt select 'GBR', object_id, owner, object_name from all_objects where object_id BETWEEN 2000 AND 3999 and rownum <= 1000; spool off spool /tmp/files/ire1.txt select 'IRE', object_id, owner, object_name from all_objects where object_id <= 2000 and rownum <= 1000; spool off spool /tmp/files/ire2.txt select 'IRE', object_id, owner, object_name from all_objects where object_id BETWEEN 2000 AND 3999 and rownum <= 1000; spool off set markup csv off set trimspool on linesize 1000 feedback off pagesize 14
在上传文件之前,您可能需要稍微清理文件的开头和结尾。 将文件复制到对象存储:
begindbms_cloud.put_object ( credential_name=>'obj_store_cred', object_uri=>'https://swiftobjectstorage.uk-london-1.oraclecloud.com/v1/my-namespace/ob-bucket/gbr1.txt', directory_name=>'tmp_files_dir', file_name=>'gbr1.txt'); end; /begindbms_cloud.put_object ( credential_name=>'obj_store_cred', object_uri=>'https://swiftobjectstorage.uk-london-1.oraclecloud.com/v1/my-namespace/ob-bucket/gbr2.txt', directory_name=>'tmp_files_dir', file_name=>'gbr2.txt'); end; /begindbms_cloud.put_object ( credential_name=>'obj_store_cred', object_uri=>'https://swiftobjectstorage.uk-london-1.oraclecloud.com/v1/my-namespace/ob-bucket/ire1.txt', directory_name=>'tmp_files_dir', file_name=>'ire1.txt'); end; /begindbms_cloud.put_object ( credential_name=>'obj_store_cred', object_uri=>'https://swiftobjectstorage.uk-london-1.oraclecloud.com/v1/my-namespace/ob-bucket/ire2.txt', directory_name=>'tmp_files_dir', file_name=>'ire2.txt'); end; /
CREATE_EXTERNAL_PART_TABLE 过程基于云对象存储中的文件创建名为 COUNTRY_PART_TAB_EXT 的外部分区表。
--droptablecountry_part_tab_ext; begindbms_cloud.create_external_part_table( table_name=>'country_part_tab_ext', credential_name=>'obj_store_cred', format=>json_object('type'value'csv', 'skipheaders'value'1'), column_list=>'country_code varchar2(3),object_id number,owner varchar2(128),object_name varchar2(128)', partitioning_clause=>'partition by list (country_code) (partition part_gbr values (''GBR'') location (''https://swiftobjectstorage.uk-london-1.oraclecloud.com/v1/my-namespace/ob-bucket/gbr1.txt'',''https://swiftobjectstorage.uk-london-1.oraclecloud.com/v1/my-namespace/ob-bucket/gbr2.txt''),partition part_ire values (''IRE'') location (''https://swiftobjectstorage.uk-london-1.oraclecloud.com/v1/my-namespace/ob-bucket/ire1.txt'',''https://swiftobjectstorage.uk-london-1.oraclecloud.com/v1/my-namespace/ob-bucket/ire2.txt''))' ); end; /
我们查询外部表,它从云对象存储中读取数据。
selectcountry_code, count(*) asamountfromcountry_part_tab_extgroupbycountry_codeorderbycountry_code; COUAMOUNT-------------GBR2000IRE2000SQL>
VALIDATE_EXTERNAL_PART_TABLE 过程允许我们检查外部分区表的有效性。
begindbms_cloud.validate_external_part_table('country_part_tab_ext'); end; /
CREATE_HYBRID_PART_TABLE
CREATE_HYBRID_PART_TABLE 过程基于云对象存储中的文件创建一个名为 COUNTRY_HYBRID_PART_TAB_EXT 的外部混合分区表。
--drop table country_hybrid_part_tab_ext; begin dbms_cloud.create_hybrid_part_table( table_name => 'country_hybrid_part_tab_ext', credential_name => 'obj_store_cred', format => json_object('type' value 'csv', 'skipheaders' value '1'), column_list => 'country_code varchar2(3), object_id number, owner varchar2(128), object_name varchar2(128)', partitioning_clause => 'partition by list (country_code) ( partition part_gbr values (''GBR'') external location ( ''https://swiftobjectstorage.uk-london-1.oraclecloud.com/v1/my-namespace/ob-bucket/gbr1.txt'', ''https://swiftobjectstorage.uk-london-1.oraclecloud.com/v1/my-namespace/ob-bucket/gbr2.txt'' ), partition part_ire values (''IRE'') external location ( ''https://swiftobjectstorage.uk-london-1.oraclecloud.com/v1/my-namespace/ob-bucket/ire1.txt'', ''https://swiftobjectstorage.uk-london-1.oraclecloud.com/v1/my-namespace/ob-bucket/ire2.txt'' ), partition part_usa values (''USA'') )' ); end; /
我们在常规分区中插入一行。
insertintocountry_hybrid_part_tab_extvalues ('USA', 123, 'banana', 'banana'); commit;
我们查询外部表,它从云对象存储中读取数据。
selectcountry_code, count(*) asamountfromcountry_hybrid_part_tab_extgroupbycountry_codeorderbycountry_code; COUAMOUNT-------------GBR2000IRE2000USA1SQL>
VALIDATE_HYBRID_PART_TABLE 过程允许我们检查外部混合分区表的有效性。
begindbms_cloud.validate_hybrid_part_table('country_hybrid_part_tab_ext'); end; /
COPY_DATA
COPY_DATA 过程允许我们将数据从云对象存储复制到现有表中。
我们使用以下内容创建一个名为“emp.csv”的文件并将其放入我们的对象存储中。 它是一个带有标题行的 CSV 文件。
"EMPNO","ENAME","JOB","MGR","HIREDATE","SAL","COMM","DEPTNO" 7369,"SMITH","CLERK",7902,17-DEC-80,800,,20 7499,"ALLEN","SALESMAN",7698,20-FEB-81,1600,300,30 7521,"WARD","SALESMAN",7698,22-FEB-81,1250,500,30 7566,"JONES","MANAGER",7839,02-APR-81,2975,,20 7654,"MARTIN","SALESMAN",7698,28-SEP-81,1250,1400,30 7698,"BLAKE","MANAGER",7839,01-MAY-81,2850,,30 7782,"CLARK","MANAGER",7839,09-JUN-81,2450,,10 7788,"SCOTT","ANALYST",7566,19-APR-87,3000,,20 7839,"KING","PRESIDENT",,17-NOV-81,5000,,10 7844,"TURNER","SALESMAN",7698,08-SEP-81,1500,0,30 7876,"ADAMS","CLERK",7788,23-MAY-87,1100,,20 7900,"JAMES","CLERK",7698,03-DEC-81,950,,30 7902,"FORD","ANALYST",7566,03-DEC-81,3000,,20 7934,"MILLER","CLERK",7782,23-JAN-82,1300,,10
我们截断本地 EMP 表并使用 COPY_DATA 过程从云对象存储重新加载数据。
truncate table emp begin dbms_cloud.copy_data( table_name => 'emp', credential_name => 'obj_store_cred', file_uri_list => 'https://swiftobjectstorage.uk-london-1.oraclecloud.com/v1/my-namespace/ob-bucket/emp.csv', format => json_object('type' value 'csv', 'skipheaders' value '1') ); end; /
我们查询EMP表,可以看到数据已经加载完毕。
select*fromemp; EMPNOENAMEJOBMGRHIREDATESALCOMMDEPTNO------------------------------------------------------------------------------7369SMITHCLERK790217-DEC-80800207499ALLENSALESMAN769820-FEB-811600300307521WARDSALESMAN769822-FEB-811250500307566JONESMANAGER783902-APR-812975207654MARTINSALESMAN769828-SEP-8112501400307698BLAKEMANAGER783901-MAY-812850307782CLARKMANAGER783909-JUN-812450107788SCOTTANALYST756619-APR-873000207839KINGPRESIDENT17-NOV-815000107844TURNERSALESMAN769808-SEP-8115000307876ADAMSCLERK778823-MAY-871100207900JAMESCLERK769803-DEC-81950307902FORDANALYST756603-DEC-813000207934MILLERCLERK778223-JAN-8213001014rowsselected. SQL>
与外部表示例类似,FORMAT 参数允许我们定制加载过程以适应数据文件内容。
Export Data
EXPORT_DATA 过程获取查询生成的数据,并以请求的格式将其导出到云对象存储。 这似乎不适用于 DBMS_CLOUD 包的本地版本,但适用于自治数据库。
begin dbms_cloud.export_data ( credential_name => 'obj_store_cred', file_uri_list => 'https://swiftobjectstorage.uk-london-1.oraclecloud.com/v1/my-namespace/ob-bucket/emp.json', query => 'select * from emp', format => '{"type" : "JSON"}' ); end; / begin dbms_cloud.export_data ( credential_name => 'obj_store_cred', file_uri_list => 'https://swiftobjectstorage.uk-london-1.oraclecloud.com/v1/my-namespace/ob-bucket/emp.csv', query => 'select * from emp', format => '{"type" : "CSV"}' ); end; /
SODA Collections
Oracle 数据库可用作使用简单 Oracle 文档访问 (SODA) 的文档存储。 您可以在此处阅读有关 SODA 的信息。
我们创建一个名为“TestCollection1”的新集合。
set serveroutput on declare l_collection soda_collection_t; begin l_collection := dbms_soda.create_collection('TestCollection1'); if l_collection is not null then dbms_output.put_line('Collection ID : ' || l_collection.get_name()); else dbms_output.put_line('Collection does not exist.'); end if; end; / Collection ID : TestCollection1 PL/SQL procedure successfully completed. SQL>
使用以下内容创建一个名为“fruit.json”的文件并将其上传到您的云对象存储。
{"fruit": "banana"}
COPY_COLLECTION 过程将数据从我们的云对象存储加载到集合中。
begindbms_cloud.copy_collection( collection_name=>'TestCollection1', credential_name=>'obj_store_cred', file_uri_list=>'https://swiftobjectstorage.uk-london-1.oraclecloud.com/v1/my-namespace/ob-bucket/fruit.json', format=>json_object('unpackarrays'value'true') ); end; /
我们可以使用以下查询查看集合中的数据。
selectjson_documentfrom"TestCollection1"; JSON_DOCUMENT--------------------------------------------------------------------------------{"fruit":"banana"} SQL>
删除操作
SQL> desc user_load_operations Name Null? Type ----------------------------------------------------- -------- ------------------------------------ ID NOT NULL NUMBER TYPE NOT NULL VARCHAR2(128) SID NOT NULL NUMBER SERIAL# NOT NULL NUMBER START_TIME TIMESTAMP(6) WITH TIME ZONE UPDATE_TIME TIMESTAMP(6) WITH TIME ZONE STATUS VARCHAR2(9) OWNER_NAME VARCHAR2(128) TABLE_NAME VARCHAR2(128) PARTITION_NAME VARCHAR2(128) SUBPARTITION_NAME VARCHAR2(128) FILE_URI_LIST VARCHAR2(4000) ROWS_LOADED NUMBER LOGFILE_TABLE VARCHAR2(128) BADFILE_TABLE VARCHAR2(128) TEMPEXT_TABLE VARCHAR2(128) SQL>
我们使用 USER_LOAD_OPERATIONS 视图返回当前会话的操作。
columntypeformata10selectid, typefromuser_load_operationsorderby1; IDTYPE--------------------1COPY11COPYSQL>
DELETE_OPERATION 过程允许我们清除与特定操作相关的附加文件。
begindbms_cloud.delete_operation(1); end; /selectid, typefromuser_load_operationsorderby1; IDTYPE--------------------11COPYSQL>
DELETE_ALL_OPERATIONS 过程允许我们清理所有操作的附加文件,或者如果我们指定类型值,则清理特定类型操作的附加文件。
begindbms_cloud.delete_operation(1); end; /selectid, typefromuser_load_operationsorderby1; IDTYPE--------------------11COPYSQL>