CLOB
の場合、これはOracleのバグのようです。 データ型は、MERGE
に渡される値として使用されます ステートメントのON
句。このデータベースを想定します:
CREATE TABLE t (
v INT,
s VARCHAR2(400 CHAR)
);
インライン値を使用した複製
ここで、SQL * Plus、SQL Developer、またはJDBCを含む任意のOracleクライアントで次のステートメントを実行します。これにより、問題を非常に簡単に再現できます(Oracle 11g XE 11.2.0.2.0を使用しています)。
MERGE INTO t
USING (
SELECT
1 v,
CAST('abc' AS CLOB) s
FROM DUAL
) s
ON (t.s = s.s) -- Using a CLOB here causes the bug.
WHEN MATCHED THEN UPDATE SET
t.v = s.v
WHEN NOT MATCHED THEN INSERT (v, s)
VALUES (s.v, s.s);
例はばかげており、CLOB
ここでは「事故」に縛られていました。それにもかかわらず、そのようなステートメントはOracleでゾンビセッションを作成するべきではありませんが、それはそこにあります。上記のステートメントをSQL*Plusで3回実行してから、これを実行しています...
SELECT
s.sid,
s.serial#,
s.sql_id,
s.event,
s.blocking_session,
q.sql_text
FROM v$session s
JOIN v$sql q
ON s.sql_id = q.sql_id
WHERE s.username = 'TEST'
AND UPPER(TRIM(q.sql_text)) LIKE 'MERGE%';
...取得:
sid serial# sql_id event blocking_session
9 3 82a2k4sqzy1jq cursor: pin S wait on X 92
49 89 82a2k4sqzy1jq cursor: pin S wait on X 92
92 13 82a2k4sqzy1jq db file sequential read
報告されたイベントがどのように異なるかに注意してください("dbファイルの順次読み取り" )元のイベントから(「クライアントからのSQL*Netメッセージ」 )、バインド変数を使用していました
バインド値を使用した複製
var v_s varchar2(50)
exec :v_s := 'abc'
MERGE INTO t
USING (
SELECT
1 v,
CAST(:v_s AS CLOB) s
FROM DUAL
) s
ON (t.s = s.s) -- Using a CLOB here causes the bug.
WHEN MATCHED THEN UPDATE SET
t.v = s.v
WHEN NOT MATCHED THEN INSERT (v, s)
VALUES (s.v, s.s);
上記のステートメントをSQL*Plusで実行すると、バグも発生します。
sid serial# sql_id event blocking_session
8 1 4w9zuxrumumgj SQL*Net message from client
90 7 4w9zuxrumumgj cursor: pin S wait on X 8
94 21 4w9zuxrumumgj cursor: pin S wait on X 8
PL/SQLでの複製なし
興味深いことに、このバグは次のPL/SQL文で回避されています。
DECLARE
v_s CLOB := 'abc';
BEGIN
MERGE INTO t
USING (
SELECT
1 v,
CAST(v_s AS CLOB) s
FROM DUAL
) s
ON (t.s = s.s) -- Using a CLOB here causes the bug.
WHEN MATCHED THEN UPDATE SET
t.v = s.v
WHEN NOT MATCHED THEN INSERT (v, s)
VALUES (s.v, s.s);
END;
/
取得しています:
CAST(v_s AS CLOB) s
*
ERROR at line 8:
ORA-06550: line 8, column 11:
PL/SQL: ORA-00932: inconsistent datatypes: expected - got CLOB
ORA-06550: line 4, column 7:
PL/SQL: SQL Statement ignored
PL/SQLエンジンがこのSQLエンジンのバグからクライアントを保護しているように見えます。