===== Der Datentyp LONG und LONG RAW in der Oracle Datenbank ===== Als grundlegende Regel gilt, dass die "historischen" Binary Datentypen nicht mehr verwendet werden sollten. Mit RAW und LONG gibt es diverse Einschränkungen, vom Lesen der Daten bis zur hin zu Replikation. Statt Long oder RAW sollte die "modernen" Datentypen BLOB/CLOB etc. verwendet werden. Allerdings sind im Data Dictionary der Datenbank selber auch in 11g R2 immer noch LONG Datentypen im Einsatz. ==== Direkte Ausgabe der Wert in SQL*Plus ==== In SQL Plus können die Werte einfach ausgelesen werden, dazu zuvor aber mit "set long 32767" den SQL*Plus Buffer konfigurieren. Zum Beispiel um den den "Less Value" Wert auf einer Partition aus zu lesen: ----------------------------- -- Long values Vorbereitung ----------------------------- set long 32767 select p.partition_position , p.partition_name , p.HIGH_VALUE , s.bytes from dba_tab_partitions p , dba_segments s where p.table_owner like upper('&OWNER.') and p.table_name like upper('&TAB_NAME.') and p.table_name= s.SEGMENT_NAME (+) and p.partition_name= s.PARTITION_NAME (+) and p.table_owner = s.owner (+) order by p.partition_position / ==== Formatieren einer Long Spalte mit UTL_RAW ==== Leider steht keine interne Default Funktion wie to_char zur Verfügung einen Long Value direkt in char/varchar2 in SQL zu konvertieren. Im [[ http://docs.oracle.com/cd/B28359_01/appdev.111/b28419/u_raw.htm#BABJHEGF#i997085|UTL_RAW (siehe hier die Oracle Original Doku) ]] Package stehen aber für die Verarbeitung von Long Values in PL/SQL zwei Funktionen zur Verfügung, CAST_TO_VARCHAR2 und CAST_TO_RAW. ==== Einfachste Version einer Hilfsfunktion zum Auslesen von EBDIC bzw einer DEC Daten in long Row Spalten in einer SAP Tabelle === DEC = DEC MCS character = Digital Equipment Corporation Multinational Character Set -- Wie werden die Zeichen in Hex dargestellt: -- auf den Zeichensatz der SQL*Plus Session achten! sql>select dump(convert('Kostenübernahme','AL32UTF8','WE8ISO8859P15')) from dual; DUMP(CONVERT('KOSTENüBERNAHME','AL32UTF8','WE8ISO8859P15')) ---------------------------------------------------------------------------------- Typ=1 Len=18: 75,111,115,116,101,110,195,130,194,129,98,101,114,110,97,104,109,101 --EBDIC Zeichensatz 'WE8EBCDIC500' sql>select dump(convert('Kostenübernahme','AL32UTF8','WE8EBCDIC500')) from dual; DUMP(CONVERT('KOSTENüBERNAHME','WE8ISO8859P15','WE8EBCDIC500')) ----------------------------------------------------------------------------------------------------- Typ=1 Len=24: 46,63,195,139,195,136,195,129,62,66,97,195,130,195,129,195,138,62,47,195,135,95,195,129 -- das Ganze nun als RAW Wert sql>select utl_raw.cast_to_raw(CONVERT('Kostenübernahme','WE8ISO8859P15','WE8EBCDIC500')) from dual; UTL_RAW.CAST_TO_RAW(CONVERT('KOSTENüBERNAHME','WE8ISO8859P15','WE8EBCDIC500')) ------------------------------------------------------------------------------------------------------------------- 2E3FCBC8C13E4261C2C1CA3E2FC75FC1 -- Hier am Beispiel einer Test Tabelle: -- create table rawtest (id number, wert long raw); -- -- 1 Test mit hex Angabe des Strings insert into rawtest values ( 1 , hextoraw('2E3FCBC8C13E4261C2C1CA3E2FC75FC1')) / -- 2 Test mit EBDIC Text und Convert insert into rawtest values ( 2 , utl_raw.cast_to_raw(convert('Kostenübernahme','WE8ISO8859P15','WE8EBCDIC500')) ) / -- Funktion anlagen -- Tabelle mit dem PK auslesen und den Wert in eine Variable schreiben -- Wert dann je nach Bedarf konvertieren -- create or replace function readRawtoVarchar2(p_id number) return varchar2 as v_raw long raw; v_return varchar2(32000); begin select wert into v_raw from rawtest where id=p_id; v_return:=utl_raw.cast_to_varchar2(v_raw); -- je nach dem wie der Zeichensatz der Umgebung steht entsprechend umwandeln return convert(v_return,'WE8EBCDIC500','WE8ISO8859P15'); end; / -------------------------------------------------------------------------------------- -- Konkrete Umsetzung für die Tabelle T003T CREATE OR REPLACE FUNCTION readRawtoVarchar2T003T(p_key varchar2) RETURN varchar2 AS v_raw long raw; v_return varchar2(32000); BEGIN SELECT vardata INTO v_raw FROM atab WHERE tabname = 'T003T' and varkey = p_key; v_return:=substr(utl_raw.cast_to_varchar2(utl_raw.substr(v_raw,5)),1,99); -- je nachdem wie der Zeichensatz der Umgebung steht entsprechend umwandeln RETURN CONVERT(v_return,'WE8DEC','WE8ISO8859P15'); END; / -- -- --Auslesen select readRawtoVarchar2(id) as wert from rawtest where id=1; WERT ----------------- Kostenübernahme -- select readRawtoVarchar2(id) from rawtest where id=2; WERT ----------------- Kostenübernahme -- === Test mit LONG RAW === Hier ein Versuch mit Hilfe eines Ref Cursor das ganze flexible zu gestalten. Leider kann ein generischer Ref Cursor mit einer Long Spalte aber in SQL*Plus nicht erzeugt werden .-( . -- Test Table create table t (id number, value long raw); insert into t values (1,utl_raw.cast_to_raw('This is a message .-) ')); commit; -- Erster Versuch: SQL>select utl_raw.cast_to_varchar2(value) from t; select utl_raw.cast_to_varchar2(value) from t * ERROR at line 1: ORA-00997: illegal use of LONG datatype -- Hilfsfunktion definieren create or replace function read(p_cursor sys_refcursor) return varchar2 is v_long long raw; v_return varchar2(32000); v_id number; begin loop fetch p_cursor into v_id; exit when p_cursor%notfound; select value into v_long from t where id = v_id; v_return := utl_raw.cast_to_varchar2(v_long); --v_return:='-'; end loop; return v_return; end; -- Abfragen mit dem Erzeugen eines Cursor Objects in SQL*Plus select read(cursor(select id from t)) from dual; === Test mit LONG === Der reine LONG Datentyp ist etwas einfacher zu handhaben, in PL/SQL ist ein implizierter Cast nach Varchar2 möglich. --test Tabelle create table t (id number, value long); insert into t values (1,('This is a message .-) ')); commit; -- Test Hilfsfunktion für PL/SQL create or replace function read(p_cursor sys_refcursor) return varchar2 is v_return varchar2(32000); v_id number; begin loop fetch p_cursor into v_id; exit when p_cursor%notfound; -- Bei Long ist kein explizter Cast notwendig! select value into v_return from t where id = v_id; end loop; return v_return; end; / -- Abfragen mit dem Erzeugen eines Cursor Objects in SQL*Plus select read(cursor(select id from t)) from dual; === Tabelle mit einem Long Datentyp umkopieren === Mit PL/SQL kann dann auch die Migration einer Tabelle mit Long Spalten in eine CLOB Spalte erfolgen. --test Tabelle create table t2 (id number, value clob); set serveroutput on declare v_cursor sys_refcursor; v_value long; v_id number; v_count pls_integer := 0; begin open v_cursor for select id ,value from t; loop fetch v_cursor into v_id ,v_value; exit when v_cursor%notfound; insert into t2 (id ,value) values (v_id ,v_value); v_count := v_count + 1; -- commit every 1000 rows if mod(v_count, 1000) = 0 then commit; end if; end loop; close v_cursor; commit; dbms_output.put_line(rpad('-', 35, '-')); dbms_output.put_line('Info :: Insert Row Count :: ' || to_char(v_count)); dbms_output.put_line(rpad('-', 35, '-')); end; / ==== Java JDBC und LONG Datentypen ==== Links: * http://docs.oracle.com/cd/F49540_01/DOC/java.815/a64685/basic4.htm ---- ==== Nach BLOB konvertieren ==== Function **to_lob** verwenden: * https://docs.oracle.com/database/121/SQLRF/functions221.htm#SQLRF06134 ---- ==== Quellen ==== * http://docs.oracle.com/cd/B19306_01/server.102/b14200/expressions005.htm * http://docs.oracle.com/cd/B28359_01/appdev.111/b28419/u_raw.htm#i1003994