Benutzer-Werkzeuge

Webseiten-Werkzeuge


prog:orcle_datatype_long

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 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

Nach BLOB konvertieren

Quellen

Cookies helfen bei der Bereitstellung von Inhalten. Durch die Nutzung dieser Seiten erklären Sie sich damit einverstanden, dass Cookies auf Ihrem Rechner gespeichert werden. Weitere Information
"Autor: Gunther Pipperr"
prog/orcle_datatype_long.txt · Zuletzt geändert: 2016/10/24 12:53 von Gunther Pippèrr