2016-07-19 26 views
2

Hier ist meine Ahnung ... Ich bin auf Orakel 11g. Viel gesucht, aber nichts gefunden.ORA-01461 (mit> 4k varchar2) Fehler Nur in Merge-Anweisung. Einfügen oder Aktualisieren funktioniert gut

Ich muss DML-Operationen ausführen, die Daten> 4k Zeichen enthalten können.

Wenn ich eine SQL-Block verwenden, befindet sich direkt im Orakel, wie die nächste, funktioniert alles einwandfrei

declare 
    txtV varchar2(32000); 
BEGIN 
    txtV:= 'MORE THAN 4k CHARS, here only few for readability' ; 
    Update FD_FILTERDEF 
    set SQLFILTER = txtV 
    where id='blabla'; 
END; 

ABER !!! wenn ich Merge-Anweisung verwenden, gibt es mir ORA-01461

declare 
    txtV varchar2(32000); 
BEGIN 
    txtV:= '' ; 
    MERGE INTO FD_FILTERDEF A 
     USING (select txtV C0 
        from dual) ST 
      ON (A.CODE = 'bla bla') 
    WHEN MATCHED THEN 
    Update set A.SQLFILTER = st.C0 
    WHEN NOT MATCHED THEN 
    insert (CODE ,SQLFILTER) 
     values ('bla bla' , ST.C0 ); 
END; 

Fehler Wenn einige Hinweis geschätzt :) dieses

+1

Bitte zeigen Sie Ihre Tabellendefinition – OldProgrammer

+1

Was ist die Art von 'fd_filterdef.sqlfilter'? Ein 'Clob' vielleicht? – user272735

+0

FD_FILTERDEF.SQLFILTER ist ein CLOB Spalte – Sabbe

Antwort

1

wäre die Verwendung haben:

create table fd_filterdef 
(code varchar2(10) primary key 
, sqlfilter clob); 

declare 
    txtv varchar2(32000); 
begin 
    txtv := rpad('select statement, really really long', 5000, ' etc'); 

    merge into fd_filterdef a 
    using (select 'bla bla' as code from dual) st 
    on (a.code = st.code) 
    when matched then 
     update set a.sqlfilter = txtv 
    when not matched then 
     insert (code, sqlfilter) 
     values (st.code,txtv); 
end; 
/

select code, length(sqlfilter) from fd_filterdef; 

CODE  LENGTH(SQLFILTER) 
---------- ----------------- 
bla bla     5000 

von Dual-Auswahl Ihrer langen Variable implizit wirft es zu einem SQL varchar2, das vor 12c nur bis zu 4000 Bytes hält.

1

Sie können nicht wählen varchar2 mehr als 4k https://docs.oracle.com/cd/B28359_01/server.111/b28320/limits001.htm

Code sehen

select txtV C0 from dual 

aber in Oracle 12c können Sie https://docs.oracle.com/database/121/SQLRF/sql_elements001.htm#SQLRF30020

+0

Das ist nicht ganz wahr ist ... wenn ich verwende 'Variable 'Text von mehr als 4k Zeichen';' und dann 'wählen Variable aus dual' i haben keine Probleme, also ist die Auswahl einer Variablen von mehr als 4k natürlich erlaubt. Das Problem ist nicht in Select-Anweisung, sondern in Merge One. – Sabbe

+0

zeigen Sie Ihre Auswahl in pl/SQL-Anweisung –

+0

@Sabbe, wenn ich versuche, "v1 in v2 aus Dual wählen", wo 'v1 ist> 4k, bekomme ich' ORA-01460: nicht implementiert oder unvernünftige Konvertierung angefordert '(in 11g bei am wenigsten). –

0

@William großer Hinweis, dies Sie Werke geschrieben.

Aber ich bin ziemlich sicher, dass ich eine Syntax sehr ähnlich getestet haben, in denen der einzige Unterschied in der select-Anweisung war, Die eine Ihnen zur Verfügung gestellten Werke gut ... das folgende den Fehler auslösen:

declare 
    txtV varchar2(32000); 
BEGIN 
    txtV:= '5000 chars ....'; 
    MERGE INTO FD_FILTERDEF A 
     USING (select 'not used' Code from dual) ST 
      ON (A.CODE = 'TESTCODE') 
    WHEN MATCHED THEN 
    Update set A.SQLFILTER = txtV --<<<< LOOK HERE I USE DIRECTLY THE VARIABLE DELCARED, NOT THE ONE FROM SELECT STMT 
    WHEN NOT MATCHED THEN 
    insert (CODE ,SQLFILTER) 
     values (st.code , txtV ); 
END; 
+0

Welchen Fehler bekommen Sie? Ich erhalte nur eine PK-Verletzung, weil das Ändern der Join-Bedingung es versucht, eine neue Zeile mit demselben Code hinzuzufügen. –

+0

PK Verstoß !? ... Warum? Merge sollte niemals einen PK-Verletzungsfehler geben (wenn reales pk in "ON" -Bedingung verwendet wird. Der Fehler, den ich mit meiner ersten (nicht funktionierenden) Version bekomme, ist 'ORA-01461: kann einen LONG-Wert nur zum Einfügen in eine LONG-Spalte binden ' – Sabbe

+0

Das obige Codebeispiel gibt eine PK-Verletzung, weil' a.code' nicht mit dem Literal 'TESTCODE' übereinstimmt, daher wird die Klausel' wenn nicht übereinstimmend dann insert' verwendet. Zwei Ausführungen versuchen, dieselbe Zeile einzufügen In meinem Beispiel habe ich ein PK auf 'code' definiert. Ich bin mir nicht sicher, was es zeigen soll. –

0

@William ... ok, vielleicht habe ich ein wenig Verwirrung beim Schreiben der Skripte gemacht. Ich war über den "PK-Fehler" überrascht, weil ich das Skript wie folgt gemacht habe. Ich beabsichtigte, die "select" -Anweisung überhaupt nicht zu verwenden, indem ich den Code innerhalb von insert und update (wie folgt) übergebe, weil ich die Abfrage programmatisch erstelle und Werte durch Platzhalter ersetze. Auf diese Weise gibt es kein PK Fehler überhaupt. In Ihren Beispielen wurde natürlich in insert der Code aus der Abfrage verwendet, aber in update wurde der Wert "TESTCODE" verwendet ... also wurde nach einem Code gesucht (und aktualisiert), aber ein anderer eingefügt: P Entschuldigung für meinen Fehler :)

declare 
    txtV varchar2(32000); 
BEGIN 
    txtV:= '5000 chars ....'; 
    MERGE INTO FD_FILTERDEF A 
     USING (select 'not used' Code from dual) ST 
      ON (A.CODE = 'TESTCODE') 
    WHEN MATCHED THEN 
    Update set A.SQLFILTER = txtV --<<<< LOOK HERE I USE DIRECTLY THE VARIABLE DELCARED, NOT THE ONE FROM SELECT STMT 
    WHEN NOT MATCHED THEN 
    insert (CODE ,SQLFILTER) 
     values ('TESTCODE' , txtV ); 
END;