PL / SQLプロシージャからCLOBを返すときにDBMS_LOBを使用する必要がありますか?
-
06-07-2019 - |
質問
XMLをCLOBパラメータとして返すPL / SQLプロシージャを作成したいと思います。私はこれをしたいだけです(簡単なテストでうまくいきます):
create or replace procedure p_xml_test_1(
p_xml out nocopy clob
) is
begin
p_xml := '<?xml version="1.0" encoding="utf8" ?>' ||
'<test><something>some value</something></test>';
end p_xml_test_1;
しかし、基本的にこれを行う他のソースコードにはアクセスできます:
create or replace procedure p_xml_test_2(
p_xml out nocopy clob
) is
lv_xml clob;
begin
dbms_lob.createtemporary(
lob_loc => p_xml,
cache => true
);
lv_xml := '<?xml version="1.0" encoding="utf8" ?>' ||
'<test><something>some value</something></test>';
dbms_lob.writeappend(
lob_loc => p_xml,
amount => length(lv_xml),
buffer => lv_xml
);
end p_xml_test_2;
最初の方法が今後問題を引き起こすかどうか疑問に思っています。そのようにするのは大丈夫ですか? 2番目の方法には、もしあれば利点は何ですか?ありがとう!
解決
ループで何度も実行して、両方のメソッドのパフォーマンスを測定する必要があると思います。パフォーマンスが唯一の違いだと思います。 xmlブロックは短いですが、大きなxmlブロックを連結すると、||を使用するよりもdbms_low.writeappendと連結する方が高速です。
(少なくともOracle 9ではそうでしたが、Oracle 10ではパフォーマンスの差は小さいと思います。)
他のヒント
次の手順を実行して、実行時間を比較しました:
バージョン1
create or replace procedure p_xml_test_1(
p_xml out nocopy clob
) is
lv_i number;
begin
for lv_i in 1 .. 999999 loop
p_xml := p_xml || 'a';
end loop;
end p_xml_test_1;
バージョン2
create or replace procedure p_xml_test_2(
p_xml out nocopy clob
) is
lv_xml clob;
lv_i number;
begin
dbms_lob.createtemporary(
lob_loc => p_xml,
cache => true
);
for lv_i in 1 .. 999999 loop
lv_xml := 'a';
dbms_lob.writeappend(
lob_loc => p_xml,
amount => length(lv_xml),
buffer => lv_xml
);
end loop;
end p_xml_test_2;
違いは無視できます。どちらも一貫して約0.2秒で到着します。
手順を10000ではなく999999にループするように変更すると、バージョン1のパフォーマンスがいくらか低下し始めます(バージョン2の場合は32秒に対して約39秒)。
2番目のものを使用する理由はわかりません。
lv_xmlがCLOBではなくVARCHAR2の場合、非常に正当な理由がわかります(文字列リテラルの最大長とCLOBの最大長)。
回答ありがとうございます。以下にリストしたサイトで読んだ内容に基づいて、dbms_lob.writeappendを使用することが実際に良いことであると仮定します。そうでない場合は、VARCHAR2を使用することもあります(場合によっては十分な大きさではありません)。
&quot; l_clob&quot;というCLOB変数があり、&quot; l_clob:= l_clob || l_some_string_to_concatenate;&quot ;、連結を行う前に方程式の右側のl_clob値をVARCHAR2に変換し、無効な結果またはエラーが発生する可能性があります。
言及していないもう1つのオプションがあります。Oracleの組み込みXML機能を使用する(データベースバージョンが9i以上であると仮定した場合)。たとえば、クエリからXMLドキュメントを生成することは、 DBMS_XMLGEN.getXML()
または DBMS_XMLGEN.getXMLType()
を使用した切り取りです。