DBMS_CLOUD 包

简介: 自治数据库中引入了 DBMS_CLOUD 包,以提供一种与数据库中的对象存储进行交互的简单方法。它可用于版本 19c 和 21c 的本地安装。 它同样适用于 AWS S3 存储 buckets 或 Oracle Cloud Object Storage 存储 buckets。

本文介绍了 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_CREDme@example.comTRUESQL>


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


使用以下查询创建四个 CSV 文件:


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>


删除操作


许多 DBMS_CLOUD 操作会产生额外的文件(日志文件、坏文件、临时文件等)。 一旦操作完成,这些需要清理。 上面显示的几个过程具有返回操作 ID 值的重载,该值可与 DELETE_OPERATION 过程一起使用以清理额外的文件。 或者,可以使用 USER_LOAD_OPERATIONS 视图显示当前会话的操作。


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>


相关实践学习
通义万相文本绘图与人像美化
本解决方案展示了如何利用自研的通义万相AIGC技术在Web服务中实现先进的图像生成。
相关文章
|
Android开发
解决 Android Studio 日志乱码
解决 Android Studio 日志乱码
2298 0
解决 Android Studio 日志乱码
|
6月前
|
监控 前端开发
滴滴抢单辅助脚本,T3出行曹操阳光高德网约车,autojs版本下载
完整的订单监控系统,包含配置管理、订单解析、条件判断、自动抢单等功能模块。系统会持
不封号的滴滴抢单神器, 滴滴抢单加速器最新版下载,autojs脚本插件
autoJS实现网约车抢单的基本框架,包含了应用启动、订单检测、条件判断和接单操作等功能模块。
|
弹性计算 关系型数据库 数据库
PostgreSQL 数据库实例只读锁定(readonly) - 硬锁定,软锁定,解锁
标签 PostgreSQL , 只读 , 锁定 , readonly , recovery.conf , 恢复模式 , pg_is_in_revoery , default_transaction_read_only 背景 在一些场景中,可能要将数据库设置为只读模式。 例如, 1、云数据库,当使用的容量超过了购买的限制时。切换到只读(锁定)模式,确保用户不会用超。 2、业务上需要对
7655 0
|
存储 程序员 数据处理
【软件设计师】程序猿需掌握的技能——数据流图
【软件设计师】程序猿需掌握的技能——数据流图
|
网络安全
错误集--NFS报错clnt_create: RPC: Port mapper failure - Unable to receive: errno 113 (No route to host)
错误集--NFS报错clnt_create: RPC: Port mapper failure - Unable to receive: errno 113 (No route to host)
2117 0
错误集--NFS报错clnt_create: RPC: Port mapper failure - Unable to receive: errno 113 (No route to host)
|
图形学
【unity实战】3D水系统,游泳,潜水,钓鱼功能实现
【unity实战】3D水系统,游泳,潜水,钓鱼功能实现
625 0
|
SQL otter Oracle
otter
otter
969 2
|
开发框架 Java 开发者
Spring Boot接收参数的多种方式
【4月更文挑战第20天】
1282 0
|
SQL Oracle 关系型数据库
Oracle rman备份保留策略,归档删除策略及delete命令的使用
oracle rman备份保留策略、归档策略的使用及对delete命令的影响
2596 0

热门文章

最新文章