Dies scheint ein Fehler in Oracle zu sein, wenn CLOB
Datentypen werden als Werte verwendet, die an MERGE
übergeben werden -Anweisung ON
Klausel. Angenommen diese Datenbank:
CREATE TABLE t (
v INT,
s VARCHAR2(400 CHAR)
);
Wiedergabe mit eingebetteten Werten
Führen Sie nun die folgende Anweisung in einem beliebigen Oracle-Client aus, einschließlich SQL*Plus, SQL Developer oder von JDBC, wodurch das Problem sehr einfach reproduziert werden kann (ich verwende 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);
Das Beispiel ist albern, und der CLOB
war hier "zufällig" gebunden. Trotzdem sollte eine solche Aussage keine Zombie-Session in Oracle erzeugen, aber sie ist da. Ich führe die obige Anweisung dreimal in SQL*Plus aus und führe dann dies aus...
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%';
... Ich bekomme:
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
Beachten Sie, wie unterschiedlich das gemeldete Ereignis ist ("db file sequential read" ) aus dem ursprünglichen Ereignis ("SQL*Net-Nachricht vom Client"). ), die Bind-Variablen verwendete
Reproduktion unter Verwendung von Bindungswerten
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);
Die obige Anweisung, die in SQL*Plus ausgeführt wird, erzeugt ebenfalls den Fehler:
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
Keine Reproduktion in PL/SQL
Interessanterweise wird der Fehler in der folgenden PL/SQL-Anweisung vermieden:
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;
/
Ich bekomme:
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
Es sieht so aus, als ob die PL/SQL-Engine Clients vor diesem SQL-Engine-Bug schützt.