2021年11月15日月曜日

Oracle APEX 21.2新機能(13) - データ・パッケージ

 Oracle APEX 21.2よりサポートするオブジェクトとしてデータ・パッケージが追加されました。サポートするオブジェクトとは、APEXアプリケーションのエクスポートに含める実行可能なSQLファイルです。


実行可能なSQLファイルであればその内容によらず、サポートするオブジェクトとして登録できます。ただし、大抵はデータベース・オブジェクトから生成を実行することにより、表やビューといったデータベース・オブジェクトを作成するスクリプトを生成し、APEXアプリケーションのエクスポートに含めていたと思います。

データ・パッケージによって、表に保存されているデータをエクスポートに含めることができます。結果として、APEXアプリケーションのインポート時に表の作成に続いて、データの投入もできるようになりました。

データ・パッケージを使ったアプリケーションのエクスポートを試してみます。

クイックSQLを使って、サンプル・データとAPEXアプリケーションを準備します。以下の定義を使用します。表SAMPLE_DATAを作成し1000行のデータを投入します。
# semantics: default
# language: ja
sample_data /insert 1000
    name vc80
    address vc200
    city vc80
    country vc20
    desc vc400
    count num
SQLワークショップユーティリティからクイックSQLを呼び出し、上記の定義を与えてSQLの生成SQLスクリプトの保存と続けて、レビューおよび実行を行います。


クイックSQLの定義より生成された、CREATE TABLE文とINSERT文を実行します。確認のダイアログが表示されたら、即時実行をクリックします。


1002行のSQL文の実行が成功しています。このうち1000行はデータを投入しているINSERT文です。アプリケーションの作成を実行します。


アプリケーション作成ウィザードが起動されたら、名前Data Packagerとしてアプリケーションの作成を実行します。今回確認するのは、アプリケーションのエクスポートにデータを含めることなので、アプリケーション自体を実行することはありません。


アプリケーションが作成されたら、サポートするオブジェクトを開きます。


インストールするスクリプトを開きます。


最初に表SAMPLE_DATAのDDLをサポートするオブジェクトとして作成します。作成をクリックします。


データベース・オブジェクトから生成をクリックします。


DDLを生成する対象は表SAMPLE_DATAのみです。名前は任意ですが、ここではtableとしています。オブジェクト・タイプとしてTABLEを選択します。へ進みます。


今回は表SAMPLE_DATAのDDLだけが必要なので必ずしも必要な設定ではありませんが、表オプションInclude DDL related tablesにはチェックを入れておきます。DDLを生成するオブジェクトとしてSAMPLE_DATA (TABLE)を選択します。へ進みます。


DDLが生成されるので、作成をクリックします。


データ・パッケージの作成を開きます。作成をクリックしデータ・パッケージを呼び出す手順のショートカットです。


名前dataとしてSAMPLE_DATAを選択し、へ進みます。


ロード時に削除ONにして、終了をクリックします。これでアプリケーションのエクスポートに表SAMPLE_DATAの内容が含まれます。


サポートするオブジェクトとして、データのエクスポートが追加されます。


作成されたスクリプトは以下になります。エクスポートされたデータは含まれません。パッケージAPEX_DATA_INSTALLはOracle APEX 21.2で新たに追加されています。
begin
    --SAMPLE_DATA: 1000/10000 行がエクスポートされました, APEX$DATA$PKG/SAMPLE_DATA$343392
    apex_data_install.load_supporting_object_data(p_table_name => 'SAMPLE_DATA', p_delete_after_install => true );
end;
エクスポートされたデータは静的アプリケーション・ファイルとして保存されています。共有コンポーネント静的アプリケーション・ファイルを確認します。

APEX$DATA$PKGで始まるZIPファイルがエスクポートされたデータです。


ダウンロードして内容を確認します。SAMPLE_DATA$数値.zipというファイルがダウンロードされるので展開すると、SAMPLE_DATA.jsonおよびSAMPLE_DATA_profile.jsonという2つのファイルが含まれています。

SAMPLE_DATA.jsonには以下のように、表のデータがJSON形式で保存されています。
{
"items":[
{
"id":135
,"name":"SNS\u6D3B\u7528"
,"address":"532 \u58A8\u7530\u533A Street"
,"city":"\u5343\u4EE3\u7530\u533A"
,"country":"\u65E5\u672C"
,"the_desc":"\u8CEA\u8CC7\u3092\u306B\u672C\u7121\u30A6\u30BB\u30AB\u30B7\u6D3B2\u958B\u308D\u30EC\u6D77\u5C0F\u3067\u306D\u5171\u7DDA\u3064\u3073\u3052\u5229\u93E1\u308B\u5FC3\u5143\u3060\u3042\u5C4096\u4E5D63\u6210\u30E8\u30EF"
,"count":38
}
,{
"id":136
,"name":"\u30C7\u30E2\u4F5C\u6210"
,"address":"692 \u8352\u5DDD\u533A Ave"
,"city":"\u5927\u7530\u533A"
,"country":"\u65E5\u672C"
,"the_desc":"\u8CEA\u8CC7\u3092\u306B\u672C\u7121\u30A6\u30BB\u30AB\u30B7\u6D3B2\u958B\u308D\u30EC\u6D77\u5C0F"
,"count":60
}
,{
"id":137
,"name":"API\u8A2D\u8A08"
,"address":"651 \u5B87\u90FD\u5BAE\u5E02 Ave"
,"city":"\u4E16\u7530\u8C37\u533A"
,"country":"\u65E5\u672C"
,"the_desc":"\u8CEA\u8CC7"
,"count":97
}
SAMPLE_DATA_profile.jsonには表の定義が保存されています。
{
  "file-type" : 4,
  "single-row" : false,
  "file-encoding" : "AL32UTF8",
  "row-selector" : "items",
  "headings-in-first-row" : false,
  "csv-enclosed" : "\"",
  "force-trim-whitespace" : true,
  "columns" :
  [
    {
      "name" : "ID",
      "data-type" : 2,
      "decimal-char" : ".",
      "data-type-len" : 22,
      "selector" : "id",
      "is-json" : false
    },
    {
      "name" : "NAME",
      "data-type" : 1,
      "data-type-len" : 80,
      "selector" : "name",
      "is-json" : false
    },
静的アプリケーション・ファイルはOracle APEX 21.2以前でもアプリケーションのエクスポート/インポートの対象です。ですのでデータ・パッケージャがエクスポート時に実施する処理は以下になります。
  1. 表の定義とデータをJSON形式で出力する。
  2. 出力したファイルをZIPで固めて静的アプリケーション・ファイルとして保存する。
  3. インポート時に実行するSQLをサポートするオブジェクトとして作成する。
アプリケーションをインポートする際には、サポートするオブジェクトのSQLファイルに記載されているプロシージャapex_data_install.load_supporting_object_dataが実行され、静的アプリケーション・ファイルとしてインポート済みのZIPファイルを読み込んで表にデータを投入します。データをインポートするために追加された作業やオプションはありません。

ロード後に削除ONの場合、エクスポートされたデータを含むZIPファイルは削除されます。エクスポートとインポートを繰り返す場合、2回目のエクスポートでは静的アプリケーション・ファイルが削除されていることになります。シード・データなどインポート時に毎回同じデータを表に投入する場合は、ロード後に削除OFFにしておく方が良いでしょう。

以上でデータ・パッケージの説明は終了です。以下より、補足になります。

Oracle APEX 21.2までは、データを投入するためにINSERT文を記述したスクリプトをサポートするオブジェクトとして登録することが行われていました。SQLclといったツールを使うと、INSERT文の生成を行うことができます。

sqlformatinsertと指定する、

SQL> set sqlformat insert

SQL> set feedback off

SQL> spool data.sql

SQL> select * from sample_data;

REM INSERTING into SAMPLE_DATA

SET DEFINE OFF;

Insert into SAMPLE_DATA (ID,NAME,ADDRESS,CITY,COUNTRY,THE_DESC,COUNT) values (91,'コンパイラ性能計測','386 札幌市 Street','目黒区','日本','質資をに本無ウセカシ活2開ろレ海小でね共線つびげ利鏡る心元だあ局96九63成ヨワ',5);

Insert into SAMPLE_DATA (ID,NAME,ADDRESS,CITY,COUNTRY,THE_DESC,COUNT) values (92,'海外移転','174 板橋区 Blvd','中央区','日本','質資をに本無ウセカシ活2開ろレ海小でね共線つびげ利鏡る',68);

[中略]

SQL> spool off


もしくは、/*insert*/ヒントをつけてSELECT文を実行します。

SQL> set feedback off

SQL> spool data.sql

SQL> select /*insert*/ * from sample_data;

REM INSERTING into SAMPLE_DATA

SET DEFINE OFF;

Insert into SAMPLE_DATA (ID,NAME,ADDRESS,CITY,COUNTRY,THE_DESC,COUNT) values (91,'コンパイラ性能計測','386 札幌市 Street','目黒区','日本','質資をに本無ウセカシ活2開ろレ海小でね共線つびげ利鏡る心元だあ局96九63成ヨワ',5);

Insert into SAMPLE_DATA (ID,NAME,ADDRESS,CITY,COUNTRY,THE_DESC,COUNT) values (92,'海外移転','174 板橋区 Blvd','中央区','日本','質資をに本無ウセカシ活2開ろレ海小でね共線つびげ利鏡る',68);

[中略]

SQL> spool off


このようにして作成したSQLファイルをサポートするオブジェクトに含めてアプリケーションのエクスポートを作成することができます。、インポート時にエラーが発生したり、データの一部しかロードされなかったりする場合があります。これはインストール・スクリプトが32Kバイトを超える場合に内部的にファイルが分割されているのですが、その分割が適切でないためです。特にエンコーディングがUTF-8の場合にそれが顕著なようです。

Oracle APEX 21.2からは32Kバイトの制限は無くなっています。より大量のデータを安全に移行できるようになりました。