2009-11-25 2 views
27

Wie bekomme ich die Größe in Bytes einer CLOB Spalte in Oracle?Wie erhalten Sie die Größe einer CLOB-Spalte in Oracle in Bytes?

LENGTH() und DBMS_LOB.getLength() beide Rückgabe Anzahl der Zeichen in der CLOB verwendet, aber ich muss wissen, wie viele Bytes verwendet werden (ich habe mit Multibyte-Zeichensatz).

+0

Warum beschäftigen Sie sich mit der Größe in Bytes des CLOB? – Thanatos

+1

Nicht das OP, aber in meinem Fall habe ich CLOBS über eine DB-Verbindung abgerufen und musste sie in 4000-Byte-Chunks schneiden, und ich wollte wissen, wie viele Chunks ich für meine Daten brauchte. –

+0

Das ist verrückt, ich möchte chinesischen Clob in varchar2 und nicht tun, weil ich die Größe nicht bestimmen kann – Toolkit

Antwort

13

Nach einigem Denken i mit dieser Lösung kam:

LENGTHB(TO_CHAR(SUBSTR(<CLOB-Column>,1,4000))) 

SUBSTR gibt nur die ersten 4000 Zeichen (max Stringgröße)

TO_CHAR wandelt CLOB-VARCHAR2

LENGTHB kehrt die Länge in Bytes, die von der Zeichenfolge verwendet werden.

+14

Aber das funktioniert nur, wenn Ihr CLOB klein ist. –

+1

Sie könnten 'LENGTHB (TO_CHAR (DBMS_LOB.SUBSTR (, 3000,1))) + NVL (LENGTHB (TO_CHAR (DBMS_LOB.SUBSTR (, 3000,3001)))), 0)' - dies funktioniert bis zu 6000 Bytes könnte aber unbegrenzt verlängert werden. Wenn Sie mit Multi-Byte-Zeichensätzen arbeiten, müssen Sie die Zeichenkette auf weniger als 4000 Zeichen aufteilen, sonst wird der Zeichenfolgenpuffer für ORA-06501 zu klein. Beachten Sie auch, dass DBMS_LOB.SUBSTR die Reihenfolge der Betrags- und Offset-Parameter invertiert. –

+0

Siehe auch http://stackoverflow.com/questions/10331912/performance-of-substr-on-clob – gavenkoa

-2

Es funktioniert nur bis 4000 Byte, was, wenn der clob größer als 4000 Byte ist dann verwenden wir diese

declare 
v_clob_size clob; 

begin 

     v_clob_size:= (DBMS_LOB.getlength(v_clob))/1024/1024; 
     DBMS_OUTPUT.put_line('CLOB Size ' || v_clob_size); 
end; 

oder

select (DBMS_LOB.getlength(your_column_name))/1024/1024 from your_table 
+0

Aber liefert DMBS_LOG.getlength (...) nicht die Anzahl der Zeichen und nicht die Anzahl der Bytes? –

+0

er sagte bereits, dass DBMS_LOB.getlength für seine Bedürfnisse ungeeignet war ... – Reimius

10

ich meinen Kommentar als Antwort, weil es das Hinzufügen löst das ursprüngliche Problem für einen größeren Bereich von Fällen als die akzeptierte Antwort. Hinweis: Sie müssen immer noch die maximale Länge und den ungefähren Anteil der Multibyte-Zeichen kennen, die Ihre Daten enthalten.

Wenn Sie einen CLOB größer als 4000 Byte haben, müssen Sie DBMS_LOB.SUBSTR anstelle von SUBSTR verwenden. Beachten Sie, dass die Menge und Offset Parameter in DBMS_LOB.SUBSTR umgekehrt sind.

Als nächstes müssen Sie möglicherweise weniger eine Menge an String als 4000, da diese Parameter die Anzahl der Zeichen sind, und wenn Sie Multi-Byte-Zeichen haben dann 4000 Zeichen mehr als 4000 Bytes lang sein, und Sie erhalten ORA-06502: PL/SQL: numeric or value error: character string buffer too small, weil das Teilstringergebnis in ein VARCHAR2 passen muss, das ein Limit von 4000 Byte hat. Wie viele Zeichen Sie abrufen können, hängt von der durchschnittlichen Anzahl der Bytes pro Zeichen in Ihren Daten ab.

So ist meine Antwort:

LENGTHB(TO_CHAR(DBMS_LOB.SUBSTR(<CLOB-Column>,3000,1))) 
+NVL(LENGTHB(TO_CHAR(DBM‌​S_LOB.SUBSTR(<CLOB-Column>,3000,3001))),0) 
+NVL(LENGTHB(TO_CHAR(DBM‌​S_LOB.SUBSTR(<CLOB-Column>,6000,6001))),0) 
+... 

wo man so viele Stücke hinzufügen, wie Sie Ihre längste CLOB- abdecken müssen, und stellen Sie die Blockgröße nach durchschnittlichen Bytes pro Zeichen Ihrer Daten.

+0

Siehe Antwort von TobiK für die gleiche Technik, die als Schleife ausgedrückt wird, so dass Sie nicht überprüfen müssen, ob Sie genug Teile hinzugefügt haben, um Ihren größten CLOB abzudecken . –

+0

Also diese Lösung beruht auf Hoffnung und Vermutung, ORA-06502 Fehler zu vermeiden? Sicherlich gibt es eine robuste Möglichkeit, einen CLOB in VARCHAR2-große Teile aufzuteilen! – PhilHibbs

+0

@PhilHibbs Es ist genug für meinen Zweck, weil ich nur mit Französisch zu tun habe und Annahmen über den Anteil der Multibyte-Zeichen machen kann. Aber ich stimme zu, dass es nicht zufriedenstellend ist und ich würde mich freuen, eine bessere Antwort zu sehen. –

4

versuchen diese für CLOB Größen größer als VARCHAR2:

Wir haben die CLOB in Teilen „VARCHAR2 kompatibel“ Größen spalten, LENGTHB durch jeden Teil der CLOB Daten laufen, und alle Ergebnisse zusammenfassen.

declare 
    my_sum int; 
begin 
    for x in (select COLUMN, ceil(DBMS_LOB.getlength(COLUMN)/2000) steps from TABLE) 
    loop 
     my_sum := 0; 
     for y in 1 .. x.steps 
     loop 
      my_sum := my_sum + lengthb(dbms_lob.substr(x.COLUMN, 2000, (y-1)*2000+1)); 
      -- some additional output 
      dbms_output.put_line('step:' || y); 
      dbms_output.put_line('char length:' || DBMS_LOB.getlength(dbms_lob.substr(x.COLUMN, 2000 , (y-1)*2000+1))); 
      dbms_output.put_line('byte length:' || lengthb(dbms_lob.substr(x.COLUMN, 2000, (y-1)*2000+1))); 
      continue; 
     end loop; 
     dbms_output.put_line('char summary:' || DBMS_LOB.getlength(x.COLUMN)); 
     dbms_output.put_line('byte summary:' || my_sum); 
     continue; 
    end loop; 
end; 
/
+0

Dies ist besser als meine Antwort, wenn Sie die Anforderung benötigen, in Zukunft ohne * a priori * der maximal möglichen CLOB-Größe ausführbar zu sein. Ich würde es in diesem Fall jedoch als eine Funktion schreiben. –

3

NVL (Länge (clob_col_name), 0) funktioniert für mich.

+0

Nein, 'length 'gibt die Länge in * Zeichen *, nicht Bytes, zurück. –

1

Überprüfen Sie den LOB-Segmentnamen von dba_lobs anhand des Tabellennamens.

select TABLE_NAME,OWNER,COLUMN_NAME,SEGMENT_NAME from dba_lobs where TABLE_NAME='<<TABLE NAME>>'; 

Verwenden Sie jetzt den Segmentnamen, um die in dba_segments verwendeten Bytes zu finden.

select s.segment_name, s.partition_name, bytes/1048576 "Size (MB)" 
from dba_segments s, dba_lobs l 
where s.segment_name = l.segment_name 
and s.owner = '<<OWNER>> ' order by s.segment_name, s.partition_name; 
0

Die einfache Lösung ist, CLOB in BLOB zu werfen und dann Länge von BLOB anzufordern!

Das Problem ist, dass Oracle keine Funktion haben, die CLOB zu BLOB werfen, aber wir können einfach eine Funktion definieren, das zu tun,

create or replace 
FUNCTION clob2blob (p_in clob) RETURN blob IS 
    v_blob  blob; 
    v_desc_offset PLS_INTEGER := 1; 
    v_src_offset PLS_INTEGER := 1; 
    v_lang  PLS_INTEGER := 0; 
    v_warning  PLS_INTEGER := 0; 
BEGIN 
    dbms_lob.createtemporary(v_blob,TRUE); 
    dbms_lob.converttoblob 
     (v_blob 
     , p_in 
     , dbms_lob.getlength(p_in) 
     , v_desc_offset 
     , v_src_offset 
     , dbms_lob.default_csid 
     , v_lang, v_warning 
     ); 
    RETURN v_blob; 
END; 

Der SQL-Befehl Nummer zu erhalten verwenden Bytes

ist
SELECT length(clob2blob(fieldname)) as nr_bytes 

oder

SELECT dbms_lob.getlength(clob2blob(fieldname)) as nr_bytes 

ich das auf Oracle 10g getestet haben ohne Unico mit de (UTF-8). Aber ich denke, dass diese Lösung richtig sein muss Verwendung von Unicode (UTF-8) Oracle-Instanz :-)

ich dank Nashev machen will, das eine Lösung zu konvertieren clob How convert CLOB to BLOB in Oracle? zu Blob und zu diesem Beitrag in Deutsch geschrieben geschrieben hat (Der Code ist in PL/SQL) 13ter.info.blog, die zusätzlich eine Funktion zum Konvertieren von Blob in Clob geben!

Kann jemand die 2 Befehle in Unicode (UTF-8) CLOB testen, also bin ich sicher, dass dies mit Unicode funktioniert?