Oracle Database - Multi Row INSERT、バインド変数を使うと、リテラル値を使う場合では見える景色が変わるんだよね #1 - バグなのか現時点の仕様なのか? Tweet
Previously on Mac De Oracle
前回は、
帰ってきた! 標準はあるにはあるが癖の多いSQL #22 - Multi Row INSERT でした。
TVC(Table Value Constractor)の流れではあったのですが、通常やるとは思えないリテラルを使ったMulti row insertで大量の行を詰め込んでみました!
TVCはともかく、Multi row insertをリテラル値で、かつ、大量の行を詰め込むのはリーズナブルな方法ではないですよね。特にOracle Databaseでは。というあたりに気づければそれで良いと思います:)
PostgreSQL/MySQLは幾分マイルドなw 結果でしたが、Oracle Databaseは、らしい特徴がでていましたよね。
ハードパースコストがめちゃめちゃ高くて。
そういえば、
以前、
パースが重いぞーというネタをやってたことありましたが、取り上げたハードパースがキツくなるネタは、Oracle Databaseで索引のある列に対してIN句を使い大量の値をセットするネタでした。(これ意外と見かけます)
それ以外のケースだと、MySQLで結合する表が多くて考え過ぎてるケース。
どちらも実行計画を立てるためにオプティマイザが考え過ぎてしまう(得られる実行計画は良いのですが)ことでパース時間が異常に長くなる症状でしたよね!
悩ませ過ぎは及ばざるがごとし #3
悩ませ過ぎは及ばざるがごとし #4
悩ませ過ぎは及ばざるがごとし #7 - おまけ
悩ませ過ぎは及ばざるがごとし (MySQL 8.0.32編)
ただ、今回取り上げたOracle DatabaseのINSERT(Multi row insert)は、どちらかというとメモリリソース確保の影響が色濃い状況でした。(パース時の帯域イベントもほぼそれだけ)
リテラル値を使い、大量の行を詰め込んだ巨大なmulti row insert文を実行するのは考えものですよね。まじでw
前置きはそれぐらいにして、
前回、そんなことやる人いないでしょーっ、というノリで、リテラル値を使い巨大なMulti row insertを行いましたが、
通常なら、バインド変数使いますよね! 絶対!w
ということで、バインド変数を利用したMulti row insertの準備をしていた際に気づいたバグというか現時点の仕様というかなんというかw にハマった記録です! が今回のネタ。
(Oracle Database 23ai FREEのPL/SQLからの実行だと、現時点では、EXECUTE IMMEDIATEを利用してバインド変数化することぐらいしかできなそう!)
まじで?! という状況なので、細かい確認は次のリリース以降で再度試してみようかなと。
不具合?なのか現時点の仕様なのか、制限っぽいエラーについてのログは以下。
運良く見つけた、現状、唯一の逃げ道も最後に記載しています。
(PL/SQLだと以前から他の方法(Bulk Insert)もあるので困ることはないとは思いますが。。。)
前回作成した表を利用します。(SCOTTスキーマに作成)
create table meows_ins_tab
(
id integer not null primary key,
col1 varchar2(1000),
col2 varchar2(1000),
col3 varchar2(1000),
col4 varchar2(1000),
col5 varchar2(1000),
col6 varchar2(1000),
col7 varchar2(1000),
col8 varchar2(500)
);
前提 PL/SQLを利用しリテラル値のままのMulti row insert、バインド変数を利用したMulti row insertが対象です。(PL/SQLで利用する場合だけで発生していると思われるエラー。それ以外の言語ではどうかは未確認)
以下のような構文で、バインド変数を使ういたかったわけです。PL/SQLなので直接!
INSERT INTO mrows_ins_tab(id, col8) VALUES (...), (...) ...;
と書きたいところでしたが、
これが。。。。いろいろと引き当ててしまう原因になるとは。。。知る由もなかった。。。。
いろいろあります。。。よ! (^^ ;;;;;
バグ? or 現時点の仕様、または制限? その1
後で気づいたのですが、このエラーには2つの要素が絡んでいるようでした。
ひとつは、INSERTする表の列指定。もう一つは、バインド変数として利用しているVARRAY (可変サイズの配列)の二つ。(詳細は後続のエラーにて)
SQL文が無効ですというエラーに惑わされますが、エラー自体はORA-00600です。
SCOTT@localhost:1521/freepdb1> !cat bug1.sql
DECLARE
c11 NUMBER;
c12 NUMBER;
c81 VARCHAR2(500);
c82 VARCHAR2(500);
TYPE c1_type IS VARRAY(2) OF NUMBER;
TYPE c8_type IS VARRAY(2) OF VARCHAR2(500);
c1 c1_type := c1_type();
c8 c8_type := c8_type();
BEGIN
c1.extend(2);
c8.extend(2);
c1(1) := 1;
c1(2) := 2;
c8(1) := LPAD(TO_CHAR(c1(1)),373,'x');
c8(2) := LPAD(TO_CHAR(c1(2)),373,'x');
INSERT INTO mrows_ins_tab(id,col8) VALUES
(c1(1), c8(1))
, (c1(2), c8(2))
;
END;
/
SCOTT@localhost:1521/freepdb1> @bug1
c82 VARCHAR2(500);
*
行5でエラーが発生しました。:
ORA-00900: SQL文が無効です。
ORA-00600: 内部エラー・コード, 引数: [qcsTVCApplyqbc:nameres], [], [], [], [], [], [], [], [], [], [], [] ヘルプ:
https://docs.oracle.com/error-help/db/ora-00900/
.trcファイルにも同様のログあり
Incident 222887 created, dump file: /opt/oracle/diag/rdbms/free/FREE/incident/incdir_222887/FREE_ora_4633_i222887.trc
ORA-00600: 内部エラー・コード, 引数: [qcsTVCApplyqbc:nameres], [], [], [], [], [], [], [], [], [], [], []
上記無名PL/SQLブロックスクリプトを以下のように書き換えてみます。 違いはVARRAY配列を利用していないという1点です。
VARRAY配列の要素をmulti row insert文で直接使うことはできない(現状)ことがわかります!(まじかー!)
なお、このケースではINSERT文で表の列を指定しても指定しなくても影響はありません。(他のケースではこの表の列指定が影響する問題がありました。後述)
SCOTT@localhost:1521/freepdb1> !cat bug1_1.sql
DECLARE
c11 NUMBER;
c12 NUMBER;
c81 VARCHAR2(500);
c82 VARCHAR2(500);
BEGIN
c11 := 1;
c12 := 2;
c81 := LPAD(TO_CHAR(c11),373,'x');
c82 := LPAD(TO_CHAR(c12),373,'x');
INSERT INTO mrows_ins_tab(id,col8) VALUES
(c11, c81)
, (c12, c82)
;
END;
/
SCOTT@localhost:1521/freepdb1> @bug1_1
PL/SQLプロシージャが正常に完了しました。
さらに書き換えてみます。このテストケースでは、VARRAY配列の要素を使うことが原因でエラーになっているようです。
SCOTT@localhost:1521/freepdb1> !cat bug1_2.sql
DECLARE
c11 NUMBER;
c12 NUMBER;
c81 VARCHAR2(500);
c82 VARCHAR2(500);
BEGIN
c11 := 1;
c12 := 2;
c81 := LPAD(TO_CHAR(c11),373,'x');
c82 := LPAD(TO_CHAR(c12),373,'x');
INSERT INTO mrows_ins_tab(id, col1, col2, col3, col4, col5, col6, col7, col8) VALUES
(c11, null, null, null, null, null, null, null, c81)
, (c12, null, null, null, null, null, null, null, c82)
;
END;
/
SCOTT@localhost:1521/freepdb1> @bug1_2
PL/SQLプロシージャが正常に完了しました。
さらに書き換えて、表の列指定を行わない構文(このような構文はほとんどの現場では使えないと思いますが、。。。)でも正常に実行できています。ポイントは、VARRAY配列の要素を直接渡せない(現状)って部分だけです(ここまでのテストケースでは)。
なお、ここまでは表の所有者であるSCOTTユーザで接続して検証を行いました。
次のテストケースでは、SCOTT2ユーザで接続し、DB Link経由でSCOTTの表へMulti row insertするテストを行ってみます。。。そこでも色々おきます!
SCOTT@localhost:1521/freepdb1> !cat bug1_3.sql
DECLARE
c11 NUMBER;
c12 NUMBER;
c81 VARCHAR2(500);
c82 VARCHAR2(500);
BEGIN
c11 := 1;
c12 := 2;
c81 := LPAD(TO_CHAR(c11),373,'x');
c82 := LPAD(TO_CHAR(c12),373,'x');
INSERT INTO mrows_ins_tab VALUES
(c11, null, null, null, null, null, null, null, c81)
, (c12, null, null, null, null, null, null, null, c82)
;
END;
/
SCOTT@localhost:1521/freepdb1> @bug1_3
PL/SQLプロシージャが正常に完了しました。
バグ? or 現時点の仕様、または制限? その2 PL/SQLではローカルのデータベースへアクセスことになるため、通常はSQL*Netを経由するNetwork Round Tripは発生しません。
ただ、一般的なアプリケーションではアプリケーションサーバーとデータベースサーバー間では、SQL*Net経由でNetwork Round Tripが発生するほうが普通です。
そのような状況を想定してDB Linkを経由させることで、意図的にSQL*Net経由でNetwork Round Tripを発生させるテストケースも試したいなーと、準備していた時に気づいた、とうかハマったバグ?、または現時点の仕様、制限です。
まず、scott.emp表を単一インスタンではありますが、無理やりscott2ユーザーからdb link経由でリモート表としてMulti row insertする準備から。
権限は雑に許可しちゃってます(特にシステム権限あたり)
準備
SYSTEM@localhost:1521/freepdb1> create user scott2 identified by [password] default tablespace users temporary tablespace temp quota unlimited on users;
ユーザーが作成されました。
SYSTEM@localhost:1521/freepdb1> grant select any dictionary to scott2;
権限付与が成功しました。
SYSTEM@localhost:1521/freepdb1> grant drop any table to scott2;
権限付与が成功しました。
SYSTEM@localhost:1521/freepdb1> grant connect , resource , create database link to scott2;
権限付与が成功しました。
SCOTT@localhost:1521/freepdb1> grant select on scott.mrows_ins_tab to scott2;
権限付与が成功しました。
SCOTT@localhost:1521/freepdb1> grant insert on mrows_ins_tab to scott2;
権限付与が成功しました。
SCOTT@localhost:1521/freepdb1> grant delete on mrows_ins_tab to scott2;
権限付与が成功しました。
SCOTT@localhost:1521/freepdb1> grant update on mrows_ins_tab to scott2;
権限付与が成功しました。
[oracle@arm64-oraclelinux8u10 ~]$ sqlplus scott2@localhost:1521/freepdb1
SCOTT2@localhost:1521/freepdb1> create database link link2scott connect to scott identified by [password] using 'localhost:1521/freepdb1';
データベース・リンクが作成されました。
COTT2@localhost:1521/freepdb1> select * from mrows_ins_tab@link2scott;
レコードが選択されませんでした。
SCOTT2@localhost:1521/freepdb1> create synonym mrows_ins_tab for mrows_ins_tab@link2scott;
シノニムが作成されました。
SCOTT2@localhost:1521/freepdb1> select * from mrows_ins_tab;
レコードが選択されませんでした。
SCOTT2@localhost:1521/freepdb1> select table_name from user_tables;
レコードが選択されませんでした。
SCOTT2@localhost:1521/freepdb1> truncate table scott.mrows_ins_tab;
表が切り捨てられました。
scott2に接続して、その1と同じことを試してみます。(scott.mrows_ins_tabをDB Link経由でアクセスしている点が異なります)
以下は、ローカル表アクセスと同じ結果なので想定通りの結果です。
SCOTT2@localhost:1521/freepdb1> !cat bug1.sql
DECLARE
c11 NUMBER;
c12 NUMBER;
c81 VARCHAR2(500);
c82 VARCHAR2(500);
cTYPE c1_type IS VARRAY(2) OF NUMBER;
cTYPE c8_type IS VARRAY(2) OF VARCHAR2(500);
cc1 c1_type := c1_type();
cc8 c8_type := c8_type();
BEGIN
c1.extend(2);
c8.extend(2);
c1(1) := 1;
c1(2) := 2;
c8(1) := LPAD(TO_CHAR(c1(1)),373,'x');
c8(2) := LPAD(TO_CHAR(c1(2)),373,'x');
INSERT INTO mrows_ins_tab(id,col8) VALUES
(c1(1), c8(1))
, (c1(2), c8(2))
;
END;
/
SCOTT2@localhost:1521/freepdb1> @bug1
c82 VARCHAR2(500);
*
行5でエラーが発生しました。:
ORA-00900: SQL文が無効です。
ORA-00600: 内部エラー・コード, 引数: [qcsTVCApplyqbc:nameres], [], [], [], [], [], [], [], [], [], [], [] ヘルプ:
https://docs.oracle.com/error-help/db/ora-00900/
問題はローカル表へのMulti row insertでは正常に実行できた残りの3ケース。 以下のケース。ローカル表では正常に実行されましたが、VARRAY配列を利用した場合と異なる点は、ORA-07445 になっているということです。SIGSEGVなので、これはバグの類です。
SCOTT2@localhost:1521/freepdb1> !cat bug1_1.sql
DECLARE
c11 NUMBER;
c12 NUMBER;
c81 VARCHAR2(500);
c82 VARCHAR2(500);
BEGIN
c11 := 1;
c12 := 2;
c81 := LPAD(TO_CHAR(c11),373,'x');
c82 := LPAD(TO_CHAR(c12),373,'x');
INSERT INTO mrows_ins_tab(id,col8) VALUES
(c11, c81)
, (c12, c82)
;
END;
/
SCOTT2@localhost:1521/freepdb1> @bug1_1
c82 VARCHAR2(500);
*
行5でエラーが発生しました。:
OORA-03113: 通信チャネルでend-of-fileが検出されました プロセスID:
5150
セッションID: 17、シリアル番号: 17264 ヘルプ:
https://docs.oracle.com/error-help/db/ora-03113/
.trcファイルから本当の原因を確認してみると。。。。 ORA-07445!
Incident 222926 created, dump file: /opt/oracle/diag/rdbms/free/FREE/incident/incdir_222926/FREE_ora_5225_i222926.trc
OORA-07445: 例外が検出されました: コア・ダンプ [qcsorcqb()+784] [SIGSEGV] [ADDR:0x0] [PC:0xF0F3084] [Address not mapped to object] []
次のケースでは、また別の原因でエラーに? この文もローカル表では正常に実行できていましたよね?(前述)
SCOTT2@localhost:1521/freepdb1> !cat bug1_2.sql
DECLARE
c11 NUMBER;
c12 NUMBER;
c81 VARCHAR2(500);
c82 VARCHAR2(500);
BEGIN
c11 := 1;
c12 := 2;
c81 := LPAD(TO_CHAR(c11),373,'x');
c82 := LPAD(TO_CHAR(c12),373,'x');
INSERT INTO mrows_ins_tab(id, col1, col2, col3, col4, col5, col6, col7, col8) VALUES
(c11, null, null, null, null, null, null, null, c81)
, (c12, null, null, null, null, null, null, null, c82)
;
END;
/
SCOTT2@localhost:1521/freepdb1> @bug1_2
INSERT INTO mrows_ins_tab(id, col1, col2, col3, col4, col5, col6, col7, col8) VALUES
*
行11でエラーが発生しました。:
ORA-06550: 行11、列77:
PL/SQL: ORA-00904: "COL8": 無効な識別子です。
ORA-06550: 行11、列5:
PL/SQL: SQL Statement ignored
ヘルプ: https://docs.oracle.com/error-help/db/ora-06550/
.trcファイルから本当の原因を探ると。。でてました。また別のログが!!!!
これって、現時点では実装されてない? ってこと? だとすると現時点の仕様という制限だろうか。。
fsd_notify_cb: FsDirect not implemented
さて、最後に、留め! (違 以下のケースもローカル表へ実行した場合は正常に実行できていました(前述)
これ、おそらく、実装されてない感じですかね。
PL/SQLのエンジンがOracle Databaseのカーネルに組み込まれていなかったOracle 7の頃とか、この類の新規構文の実装時期がズレるって珍しくなかったのですが、久々にこのような状況を見てノスタルジーを感じる、セピア色www
これどうやって回避できんのかなぁ!?
SCOTT2@localhost:1521/freepdb1> !cat bug1_3.sql
DECLARE
c11 NUMBER;
c12 NUMBER;
c81 VARCHAR2(500);
c82 VARCHAR2(500);
BEGIN
c11 := 1;
c12 := 2;
c81 := LPAD(TO_CHAR(c11),373,'x');
c82 := LPAD(TO_CHAR(c12),373,'x');
INSERT INTO mrows_ins_tab VALUES
(c11, null, null, null, null, null, null, null, c81)
, (c12, null, null, null, null, null, null, null, c82)
;
END;
/
SCOTT2@localhost:1521/freepdb1> @bug1_3
DECLARE
*
行1でエラーが発生しました。:
ORA-00900: SQL文が無効です。
ORA-00600: 内部エラー・コード, 引数: [qctcopn_internal: null_colkcc], [0], [0], [0], [0], [0], [1], [0], [], [], [], [] ヘルプ:
https://docs.oracle.com/error-help/db/ora-00900/
.trcファイルでも同じ
Incident 222671 created, dump file: /opt/oracle/diag/rdbms/free/FREE/incident/incdir_222671/FREE_ora_5572_i222671.trc
ORA-00600: 内部エラー・コード, 引数: [qctcopn_internal: null_colkcc], [0], [0], [0], [0], [0], [1], [0], [], [], [], []
さて、ほんとうに試した事とから随分と遠くにきてしまった感じがしますが、、逃げ道を見つけましたw
対策をしばし考え中。。。。現状回避できる方法はあるのでは?。。。。わずかな期待。。。
PL/SQLには、他の方法として、 EXECUTE IMMEDIATEを使う方法はあるか。。。その分のオーバーヘッドは乗ってしまうわけだが。。。。
試してみる! (全テストケース NGとなったDB Link経由のケースで確認する。このケースで実行できればローカルでも動作するはずだ。。。。と)
EXECUTE IMMEDIATEでバイント変数を利用するためにUSING句を使ってみました。ためにし、VARRAY配列を使っています。また、表も列指定しています。ここでローカル表でのテストでも発生した
fsd_notify_cb: FsDirect not implementedがトレースファイルに記録されていました。!!! VARRAYはEXECUTE IMMEDIATEでMulti row insertする場合でもダメなのか??。
SCOTT2@localhost:1521/freepdb1> !cat bug1_4.sql
DECLARE
sql_text CLOB := EMPTY_CLOB();
TYPE c1_type IS VARRAY(2) OF NUMBER;
TYPE c8_type IS VARRAY(2) OF VARCHAR2(500);
c1 c1_type := c1_type();
c8 c8_type := c8_type();
BEGIN
c1.extend(2);
c8.extend(2);
c1(1) := 1;
c1(2) := 2;
c8(1) := LPAD(TO_CHAR(c1(1)),373,'x');
c8(2) := LPAD(TO_CHAR(c1(2)),373,'x');
sql_text := 'INSERT INTO mrows_ins_tab(id, col8) VALUES'
|| '(:c11, :c81)'
|| ', (:c12, :c82);';
EXECUTE IMMEDIATE sql_text
USING c1(1), c8(1), c1(2), c8(2);
END;
/
SCOTT2@localhost:1521/freepdb1> @bug1_4
DECLARE
*
行1でエラーが発生しました。:
ORA-00904: "COL8": 無効な識別子です。
ORA-06512: 行17
ヘルプ: https://docs.oracle.com/error-help/db/ora-00904/
.trcファイル
fsd_notify_cb: FsDirect not implemented
まずは、切り分けのために、VARRAY配列の使用をやめてみます。表の列指定だけは残してありますが、これでも同じエラーが発生します!!
SCOTT2@localhost:1521/freepdb1> !cat bug1_5.sql
DECLARE
sql_text CLOB := EMPTY_CLOB();
c11 NUMBER;
c12 NUMBER;
c81 VARCHAR2(500);
c82 VARCHAR2(500);
BEGIN
c11 := 1;
c12 := 2;
c81 := LPAD(TO_CHAR(c11),373,'x');
c82 := LPAD(TO_CHAR(c12),373,'x');
sql_text := 'INSERT INTO mrows_ins_tab(id, col8) VALUES'
|| '(:c11, :c81)'
|| ', (:c12, :c82);';
EXECUTE IMMEDIATE sql_text
USING c11, c81, c12, c82;
END;
/
SCOTT2@localhost:1521/freepdb1> @bug1_5
DECLARE
*
行1でエラーが発生しました。:
ORA-00904: "COL8": 無効な識別子です。
ORA-06512: 行15
ヘルプ: https://docs.oracle.com/error-help/db/ora-00904/
.trcファイル
fsd_notify_cb: FsDirect not implemented
気を取り直してw
USING句ではVARRAY配列を利用し、表の列指定だけを行わないようにしてみます。
おおおおおおお、やっと逃げ道発見! w 変数は配列でもOKなので、取り合えず、行数増やしてもプログラミングで捌ける:)
SCOTT2@localhost:1521/freepdb1> !cat bug1_6.sql
DECLARE
sql_text CLOB := EMPTY_CLOB();
TYPE c1_type IS VARRAY(2) OF NUMBER;
TYPE c8_type IS VARRAY(2) OF VARCHAR2(500);
c1 c1_type := c1_type();
c8 c8_type := c8_type();
BEGIN
c1.extend(2);
c8.extend(2);
c1(1) := 1;
c1(2) := 2;
c8(1) := LPAD(TO_CHAR(c1(1)),373,'x');
c8(2) := LPAD(TO_CHAR(c1(2)),373,'x');
sql_text := 'INSERT INTO mrows_ins_tab VALUES'
|| '(:c11, null, null, null, null, null, null, null, :c81)'
|| ', (:c12, null, null, null, null, null, null, null, :c82);';
EXECUTE IMMEDIATE sql_text
USING c1(1), c8(1), c1(2), c8(2);
END;
/
SCOTT2@localhost:1521/freepdb1> @bug1_6
PL/SQLプロシージャが正常に完了しました。
この方法でもいける!
ただ、配列使えるなら配列のほうが便利なので、一つ前の方式に決定 EXECUTE IMMEDIATEだと全部リテラルというケースも試せるからEXECUTE IMMEDIATEでのるある程度のオーバーヘッドは見えて良いのかも。
ただ、EXECUTE IMMEDIATEを利用しない場合のポテンシャルは確認できないのが、ちょっと残念。
SCOTT2@localhost:1521/freepdb1> !cat bug1_7.sql
DECLARE
c11 NUMBER;
c12 NUMBER;
c81 VARCHAR2(500);
c82 VARCHAR2(500);
sql_text CLOB := EMPTY_CLOB();
BEGIN
c11 := 1;
c12 := 2;
c81 := LPAD(TO_CHAR(c11),373,'x');
c82 := LPAD(TO_CHAR(c12),373,'x');
sql_text := 'INSERT INTO mrows_ins_tab VALUES'
|| '(:c11, null, null, null, null, null, null, null, :c81)'
|| ', (:c12, null, null, null, null, null, null, null, :c82);';
EXECUTE IMMEDIATE sql_text
USING c11, c81, c12, c82;
END;
/
SCOTT2@localhost:1521/freepdb1> @bug1_7
PL/SQLプロシージャが正常に完了しました。
いや、まじで、Multi row insert構文をPL/SQLで使おうとすると結構な壁というか問題残ってそうですね。
とはいえ、PL/SQLでやるなら FORALLのバルクインサートもあるわけで、困ることはないだろうなとも思われ(現状)
とはいえ、PL/SQLでやるならローカル表の場合なら、FORALLでバルクインサートでもよいのだろうけども、
リモート表だとFORALLは使えないのでまあ、DB Link使ってる環境では注意した方が良いよね。ローカルからにする方法にするとか。
そもそもエラーで挙動周りの差異を見切れてないのは心残りではあるけども、次回りリースのai新版以降のお楽しみということで.... :)
ほんとうに試したかったのとはちょっとちがうが、Multi row insert文、リテラル値じゃなくてバインド変数を使えば、メモリ消費は抑えられるよっていう、ネタ含めた次の話題は書けそうな気がしてきた。
以下の方式(EXECUTE IMMEDIATEを利用する方法を代替策にして)でバインド変数化とリテラル値を利用したMulti row insertのメモリ消費を見るネタへ続く。(予定w)
DECLARE
sql_text CLOB := EMPTY_CLOB();
TYPE c1_type IS VARRAY(2) OF NUMBER;
TYPE c8_type IS VARRAY(2) OF VARCHAR2(500);
c1 c1_type := c1_type();
c8 c8_type := c8_type();
BEGIN
c1.extend(2);
c8.extend(2);
c1(1) := 1;
c1(2) := 2;
c8(1) := LPAD(TO_CHAR(c1(1)),373,'x');
c8(2) := LPAD(TO_CHAR(c1(2)),373,'x');
sql_text := 'INSERT INTO mrows_ins_tab VALUES'
|| '(:c11, null, null, null, null, null, null, null, :c81)'
|| ', (:c12, null, null, null, null, null, null, null, :c82);';
EXECUTE IMMEDIATE sql_text
USING c1(1), c8(1), c1(2), c8(2);
END;
/
いや、まじでいろいろハマり過ぎだろ、ってぐらいハマったw
ではまた。
関連エントリ
・帰ってきた! 標準はあるにはあるが癖の多いSQL #20 - Table Value Constructer (TVC)
・帰ってきた! 標準はあるにはあるが癖の多いSQL #21 - Table Value Constructer(TVC)- ハードパース時間とメモリ消費量 / BONUS TRACK
・帰ってきた! 標準はあるにはあるが癖の多いSQL #22 - Multi Row INSERT



最近のコメント