[OCI]日次バッチ等で必要なオブジェクト・ストレージ・バケットの作成をAutonomous Databaseにやらせてみた

# はじめに

Autonomous Databaseでは、Oracle Cloud Infrastructure SDK for PL/SQL（PL/SQL SDK）を使用して、Oracle Cloud Infrastructureのリソースを管理するためのPL/SQLコードを記述できます。

今回は、日次のバッチ処理でオブジェクト・ストレージ・バケットの作成が必要なケースを想定して、日付を名前に含むバケットをAutonomous Databaseに作成させ、そこにクエリの結果を出力するPL/SQLプロシージャを作成してみました。

なお、今回の検証ではバケットの作成およびアクセスにリソース・プリンシパルを使用しますので、Autonomous Databaseインスタンスを含む動的グループを作成し、オブジェクト・ストレージ・バケットへのアクセスを許可するポリシーを正しく設定した上で、 Autonomous Databaseのリソース・プリンシパルを有効にしておきます。

# 1. PL/SQLプロシージャの作成

今回は、実行するとDATA_YYYYMMDD（YYYYMMDD部分はプロシージャの実行日から生成）という名前のバケットを作成し、そこにv$parameerの検索結果をCSV形式で出力する、create_daily_bucketという名前のPL/SQLプロシージャを作成します。


プロシージャcreate_daily_bucketのDDLは以下のようになります。
なお、このプロシージャでは、Autonomous Databaseのリージョン、コンパートメントをv$pdbsビューから取得して、バケットをAutonomous Databaseと同じリージョン、同じコンパートメントに作成しています。

```sql:create_daily_bucket
CREATE OR REPLACE PROCEDURE create_daily_bucket
IS
    -- 変数の宣言
    resp_get_namespace   dbms_cloud_oci_obs_object_storage_get_namespace_response_t;
    resp_create_bucket   dbms_cloud_oci_obs_object_storage_create_bucket_response_t;
    create_bucket_detail dbms_cloud_oci_object_storage_create_bucket_details_t := dbms_cloud_oci_object_storage_create_bucket_details_t();
    adb_region           VARCHAR2(20);
    adb_compartment_ocid VARCHAR2(100);
    namespace            VARCHAR2(100);
    bucket_name          VARCHAR2(100);

BEGIN
    -- ADBが存在するリージョンとコンパートメントのOCIDを取得
    SELECT json_value(cloud_identity, '$.REGION'), LOWER(json_value(cloud_identity, '$.COMPARTMENT_OCID'))
	    INTO adb_region, adb_compartment_ocid FROM v$pdbs;

    -- オブジェクト・ストレージ・ネームスペースを取得
    resp_get_namespace := DBMS_CLOUD_OCI_OBS_OBJECT_STORAGE.GET_NAMESPACE(
                              region          => adb_region,
                              credential_name => 'OCI$RESOURCE_PRINCIPAL'
	                      );
    namespace := REPLACE(resp_get_namespace.response_body, '"', '');

    -- 日付からバケット名（DATA_YYYYMMDD）を生成
    SELECT 'DATA_'||TO_CHAR(sysdate, 'YYYYMMDD') INTO bucket_name FROM DUAL;

    -- バケット作成時のパラメータをセット
    create_bucket_detail.name           := bucket_name;
    create_bucket_detail.compartment_id := adb_compartment_ocid;

    -- バケットを作成
    resp_create_bucket := DBMS_CLOUD_OCI_OBS_OBJECT_STORAGE.CREATE_BUCKET(
                              region                => adb_region,
                              credential_name       => 'OCI$RESOURCE_PRINCIPAL',
                              namespace_name        => namespace,
                              create_bucket_details => create_bucket_detail
                          );

    DBMS_CLOUD.EXPORT_DATA(
        credential_name => 'OCI$RESOURCE_PRINCIPAL',
        file_uri_list   => 'https://objectstorage.'||adb_region||'.oraclecloud.com/n/'||namespace||'/b/'||bucket_name||'/o/'||'parameter.csv',
        format          => '{"type" : "csv"}',
        query           => 'SELECT * FROM v$parameter'
 );

END;
/
```
DDLを実行して、プロシージャcreate_daily_bucketを作成します。
```
SQL> CREATE OR REPLACE PROCEDURE create_daily_bucket
     IS
         resp_get_namespace   dbms_cloud_oci_obs_object_storage_get_namespace_response_t;
         resp_create_bucket   dbms_cloud_oci_obs_object_storage_create_bucket_response_t;
         create_bucket_detail dbms_cloud_oci_object_storage_create_bucket_details_t := dbms_cloud_oci_object_storage_create_bucket_details_t();
         adb_region           VARCHAR2(20);
         adb_compartment_ocid VARCHAR2(100);
         namespace            VARCHAR2(100);
         bucket_name          VARCHAR2(100);
     
     BEGIN
         -- ADBが存在するリージョンとコンパートメントのOCIDを取得
         SELECT json_value(cloud_identity, '$.REGION'), LOWER(json_value(cloud_identity, '$.COMPARTMENT_OCID'))
         INTO adb_region, adb_compartment_ocid FROM v$pdbs;
     
         -- オブジェクト・ストレージ・ネームスペースを取得
         resp_get_namespace := DBMS_CLOUD_OCI_OBS_OBJECT_STORAGE.GET_NAMESPACE(
                                   region          => adb_region,
                                   credential_name => 'OCI$RESOURCE_PRINCIPAL'
                           );
         namespace := REPLACE(resp_get_namespace.response_body, '"', '');
     
         -- 日付からバケット名（DATA_YYYYMMDD）を生成
         SELECT 'DATA_'||TO_CHAR(sysdate, 'YYYYMMDD') INTO bucket_name FROM DUAL;
     
         -- バケット作成時のパラメータをセット
         create_bucket_detail.name           := bucket_name;
         create_bucket_detail.compartment_id := adb_compartment_ocid;
     
         -- バケットを作成
         resp_create_bucket := DBMS_CLOUD_OCI_OBS_OBJECT_STORAGE.CREATE_BUCKET(
                                   region                => adb_region,
                                   credential_name       => 'OCI$RESOURCE_PRINCIPAL',
                                   namespace_name        => namespace,
                                   create_bucket_details => create_bucket_detail
                               );
     
         DBMS_CLOUD.EXPORT_DATA(
             credential_name => 'OCI$RESOURCE_PRINCIPAL',
             file_uri_list   => 'https://objectstorage.'||adb_region||'.oraclecloud.com/n/'||namespace||'/b/'||bucket_name||'/o/'||'parameter.csv',
             format          => '{"type" : "csv"}',
             query           => 'SELECT * FROM v$parameter'
      );
     
     END;
     /

Procedure CREATE_DAILY_BUCKET compiled

SQL> 
```
プロシージャcreate_daily_bucketが作成できました。

# 2. プロシージャの実行
execコマンドでcreate_daily_bucketを実行してみます。
```
SQL> exec create_daily_bucket

PL/SQL procedure successfully completed.

SQL>
```
問題なく実行できました。

DBMS_CLOUD.LIST_OBJECTSファンクションを使用して、バケットの作成、データのエクスポートが正しく行われているかを確認してみます。

```
SQL> SELECT object_name, bytes, created
     FROM DBMS_CLOUD.LIST_OBJECTS(
              credential_name       => 'OCI$RESOURCE_PRINCIPAL',
              location_uri          => 'https://objectstorage.ap-tokyo-1.oraclecloud.com/n/************/b/DATA_20231225/o'
          );

OBJECT_NAME                                  BYTES CREATED                                
_________________________________________ ________ ______________________________________ 
parameter_1_20231225T025034126155Z.csv       33687 25-DEC-23 02.50.34.534000000 AM GMT    

SQL> 
```
名前にプロシージャの実行日を含むバケットが作成され、その中に指定したプレフィックスを持つCSVが作成されていることが確認できました。

OCIコンソールからも確認してみます。
![スクリーンショット 2023-12-25 12.29.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/2bbddc27-c669-6e3d-0c2a-15491138f21a.png)
名前にプロシージャの実行日を含むバケットが作成されたことが確認できました。

バケットの内容を確認してみます。
![スクリーンショット 2023-12-25 12.29.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/a201f691-6f54-aafb-170c-c2f28d3d552e.png)
指定したプレフィックスを持つCSVが作成されていることが確認できました。

# 参考情報
・[DBMS_CLOUD_OCI_OBS_OBJECT_STORAGE.CREATE_BUCKET Function](https://docs.oracle.com/en-us/iaas/pl-sql-sdk/doc/dbms_cloud_oci_obs_object_storage.html#ADSDK-GUID-D0138FFF-99B7-464B-86F4-B2D33E2F3DBB)
・[DBMS_CLOUD_OCI_OBS_OBJECT_STORAGE.GET_NAMESPACE Function](https://docs.oracle.com/en-us/iaas/pl-sql-sdk/doc/dbms_cloud_oci_obs_object_storage.html#ADSDK-GUID-A0E4BE0C-F248-4362-BCEF-8A2A68229A6D)
・[DBMS_CLOUD_OCI_OBS_OBJECT_STORAGE_GET_NAMESPACE_RESPONSE_T Type](https://docs.oracle.com/en-us/iaas/pl-sql-sdk/doc/dbms_cloud_oci_obs_object_storage_t.html#ADSDK-GUID-16D3FB9D-5C6A-44BF-9087-683F561D379F)
・[DBMS_CLOUD_OCI_OBS_OBJECT_STORAGE_CREATE_BUCKET_RESPONSE_T Type](https://docs.oracle.com/en-us/iaas/pl-sql-sdk/doc/dbms_cloud_oci_obs_object_storage_t.html#ADSDK-GUID-7FC0AB4D-AD98-4854-87BB-1AF1930966C4)
・[DBMS_CLOUD_OCI_OBJECT_STORAGE_CREATE_BUCKET_DETAILS_T Type](https://docs.oracle.com/en-us/iaas/pl-sql-sdk/doc/object_storage_t.html#ADSDK-GUID-CE2C0F58-4DEE-4374-A972-4897D8D76032)
・[DBMS_CLOUD.EXPORT_DATA Procedure](https://docs.oracle.com/en/cloud/paas/autonomous-database/serverless/adbsb/dbms-cloud-subprograms.html#GUID-F8A70BE2-6060-48A7-9667-0A6B39198071)
・[DBMS_CLOUD.LIST_OBJECTS Function](https://docs.oracle.com/en/cloud/paas/autonomous-database/serverless/adbsb/dbms-cloud-subprograms.html#GUID-52801F96-8280-4FE0-8782-E194F4360E6F)