tutorials.de Buch-Aktion 05/2012
ERLEDIGT
NEIN
ANTWORTEN
9
ZUGRIFFE
6624
EMPFEHLEN
  • An Twitter übertragen
  • An Facebook übertragen
AUF DIESES THEMA
ANTWORTEN
  1. #1
    forced forced ist offline Mitglied
    Registriert seit
    Nov 2007
    Beiträge
    24
    Hi

    Ich habe in meiner "Oracle-Tabelle" ein Spalte vom Typ Varchar2. Dies funktionierte bisher sehr gut, doch nun muss eine Datensatz eingefügt werden, welcher mehr als 4000 Zeichen in dieser Spalte benötigt.

    Also muss ich den Spaltentyp ändern. Meine Wahl ist nun CLOB. Mit "Alter table.." erhalte ich folgende Fehlermeldung "ORA-22858: invalid alteration of datatype".

    Laut Oracle soll ich die Spalte erst entfernen und anschließend neu anlegen.
    1. Gibt es da keine einfachere Vorgehensweise?
    2. Gibt es eine alternativ zu meinem Vorgehen? ( BEIM Datentyp "LONG" erhalte ich irgendeine "constrain" Meldung, mit der ich nichts anfangen kann .-( )

    Vielen Dank!
     

  2. #2
    Albiorix Albiorix ist offline Mitglied
    Registriert seit
    Jun 2008
    Beiträge
    15
    Hi,

    Oracle kann ab 10g auch VARCHAR2-Spalten bis zu einer Länge von 32767, also einfach mal versuchen, die Spalte entsprechend zu erweitern.

    Grundsätzlich gilt: Wenn man einen Spalteninhalt mit SELECT aufrufen bzw. entsprechend mit DML-Ops verändern will, ist VARCHAR2 immer noch die beste Wahl. (C)LOBs in den Oracle-DB lassen sich idR nur über DBMS_LOB modifizieren und das für jemanden, der das nicht ständig macht, etwas "unübersichtlich".

    Und was LONG betrifft: Lt. Oracle soll der Datentyp irgendwann mal "obsolet" sein. Allerdings höre ich die Aussage schon seit ca. 2000 immer mal wieder und in der 11g ist der Spalten-Typ immer noch drin

    Ich hoffe geholfen zu haben

    Sascha
     

  3. #3
    dbwizard dbwizard ist offline Mitglied Brokat
    Registriert seit
    May 2007
    Ort
    Zürich
    Beiträge
    285
    Zitat Zitat von Albiorix Beitrag anzeigen
    Hi,

    Oracle kann ab 10g auch VARCHAR2-Spalten bis zu einer Länge von 32767, also einfach mal versuchen, die Spalte entsprechend zu erweitern.

    Sascha
    - ? Wie kommst du darauf ?

    SQL*Plus: Release 10.2.0.1.0 - Production on Wed Jun 4 15:26:36 2008

    Copyright (c) 1982, 2005, Oracle. All rights reserved.


    Connected to:
    Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - 64bit Production
    With the Partitioning, OLAP and Data Mining options

    m_hoko@THLTST12>
    m_hoko@THLTST12> CREATE TABLE TESTVARCHAR (string VARCHAR2 (100))
    /

    Table created.

    m_hoko@THLTST12> ALTER TABLE TESTVARCHAR MODIFY (STRING VARCHAR2 (8000))
    /
    ALTER TABLE TESTVARCHAR MODIFY (STRING VARCHAR2 (8000))
    *
    ERROR at line 1:
    ORA-00910: specified length too long for its datatype


    m_hoko@THLTST12>


    - Du verwechselst das mit den PL/SQL Variablen

    Gruss
     

  4. #4
    Albiorix Albiorix ist offline Mitglied
    Registriert seit
    Jun 2008
    Beiträge
    15
    Zitat Zitat von dbwizard Beitrag anzeigen

    - Du verwechselst das mit den PL/SQL Variablen

    Gruss
    ok, Asche auf mein Haupt.

    Zum Thema LONG (Auszug aus der Oracle-Doku):
    Do not create tables with LONG columns. Use LOB columns (CLOB, NCLOB, BLOB) instead. LONG columns are supported only for backward compatibility.
    Dann bleibt eigentlich nur noch CLOB.
     

  5. #5
    forced forced ist offline Mitglied
    Registriert seit
    Nov 2007
    Beiträge
    24
    ok vielen Dank für die Hilfe.. Habs nun auf CLOB umgestellt (Tabelle gelöscht, neue erstellt, mit Daten befüllt) und nun protokolliert der Trigger keine Änderungen der CLOB-Spalte mehr. Das ist echt zum verzweifeln

    Nach einer Änderung in einer der CLOB Spalten ist in OLD:Spaltenname noch der alte Inhalt zu finden, in der New:spaltenname steht nichts drin.. Mit Varchar2 funktionierte es problemlos..

    Vielen Dank für die Hilfe!
     

  6. #6
    Avatar von Nico Graichen
    Nico Graichen Nico Graichen ist offline aka gemballa
    tutorials.de Moderator
    Registriert seit
    Dec 2003
    Ort
    Pulheim (NRW)
    Beiträge
    3.898
    Blog-Einträge
    34
    Das hättest du auch einfacher haben können, vorallem wenn schon Daten vorhanden waren.

    Neue Spalte in der Tabelle vom Typ CLOB anlegen --> Daten von der VARCHAR2-Spalte in die CLOB-Spalte kopieren --> VARCHAR2-Spalte löschen --> CLOB-Spalte umbenennen

    Bzgl des Trigger-Problems:
    http://www.stanford.edu/dept/itss/do...5/adfns_tr.htm
    vielleicht hilft das
    Geändert von Nico Graichen (06.06.08 um 13:25 Uhr)
     
    Grüße Nico
    ----------------------
    Xing
    ----------------------
    Zitat Zitat von Mark Twain (1835-1910)
    Es gibt drei Dinge, die eine Frau aus dem Nichts hervorzaubern kann: einen Hut, einen Salat und einen Ehekrach.
    Zitat Zitat von Mike Wilson - Biographie über Larry Ellison (CEO Oracle)
    The Difference Between God and Larry Ellison: God Doesn't Think He's Larry Ellison

  7. #7
    Albiorix Albiorix ist offline Mitglied
    Registriert seit
    Jun 2008
    Beiträge
    15
    hm, komisch, ich hab gerade versucht, das Problem nachzustellen, und bei mir Loggt der Trigger erfolgreich die Transaktionen mit.

    Zum Nachtesten:
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    
    CREATE TABLE test_tabelle
       (id NUMBER NOT NULL, 
        clob_marker CLOB, 
             CONSTRAINT test_tabelle_pk PRIMARY KEY (id)) ;
     
    CREATE OR REPLACE TRIGGER test_tabelle_br_iud BEFORE
       INSERT OR
       UPDATE OR
       DELETE ON 
     test_tabelle FOR EACH ROW
    DECLARE
      dml_ops VARCHAR2(3);
      
    BEGIN 
    IF inserting THEN
      IF :NEW.ID IS NULL THEN
        SELECT TEST_SEQ.nextval
          INTO :NEW.ID
          FROM dual;
      END IF;
    END IF;
     
    CASE
      WHEN inserting THEN
        dml_ops := 'INS';
      WHEN updating THEN
        dml_ops := 'UPD';
      WHEN deleting THEN
        dml_ops := 'DEL';
      ELSE
        dml_ops := 'UNK';
    END CASE;
     
    -- Protokoll Transaktion
    INSERT INTO test_tabelle_jn
      (jn_operation
      ,jn_datetime
      ,id
      ,clob_marker) 
    VALUES
      (dml_ops
      ,sysdate
      ,DECODE(dml_ops, 'DEL', :OLD.id, :NEW.id)
      ,DECODE(dml_ops, 'DEL', :OLD.clob_marker, :NEW.clob_marker));
    END;
    /
    ALTER TRIGGER test_tabelle_br_iud ENABLE;
     
    -- Logging-Tabelle (Journalisierung der aktuellen Transaktion
    CREATE TABLE test_tabelle_jn
       (jn_operation VARCHAR2(3 BYTE) NOT NULL, 
        jn_datetime DATE NOT NULL, 
        id NUMBER NOT NULL, 
        clob_marker CLOB
       );

    Ansonsten, man kann ein Lob nicht direkt in den PL/SQL-Funkionen anfassen. Dafür gibt es das Paket DBMS_LOB.
     

  8. #8
    forced forced ist offline Mitglied
    Registriert seit
    Nov 2007
    Beiträge
    24
    ok vielen Dank für die Hilfe.. der Trigger loggt nun meistens alles mit, ab und zu scheint der Zugriff auf die CLOB Spalte gestört zu sein..

    Dennoch ist das Trigger-Problem nicht beseitigt.

    Der Trigger soll änderungen an einer Tabelle protokolieren, aber nur die Änderungen, welche manuell durch Personen durchgeführt werden. Auf diese Tabelle greift aber auch eine Java Software zu, welche ebenfalls Änderungen durchführt, was aber nicht protokolliert werden soll..

    Nun habe ich mir überlegt, das die Software praktisch eine Variable setzt und diese später von dem Trigger abgefragt wird. Ist die Variable gleich der gesetzten der Javasoftware, so soll nicht mitgeloggt werden, andernfalls loggen.

    Code :
    1
    
    java.sql.CallableStatement cStmt = db.Oracle.conn.prepareCall("{ call dbms_application_info.set_client_info('JAVASOFWARE')}");

    im Trigger steht in dieser Variable aber nichts drin- Ich frage den Wert wie folgt ab:

    Code :
    1
    
    SELECT USERENV('CLIENT_INFO') INTO clientinfo FROM dual;

    Jemand eine Idee?
    Evtl. sollte ich mich hiermit auch ans Java-Forum wenden, aber ich weiß nicht auf welcher Seite das Problem vorliegt.

    Danke
     

  9. #9
    Albiorix Albiorix ist offline Mitglied
    Registriert seit
    Jun 2008
    Beiträge
    15
    Das Problem mit den CLOB ist folgender:

    Wenn das CLOB (idR) größer als 4k ist, feuert der Trigger, obwohl noch nciht alle Daten in der DB stehen. Das hat folgenden Hintergrund: ab 4K Größe werden die Date nicht mehr in der Zeile gespeichert. Oracle streamt die Daten im Hintergrund weiter, damit das Statement bei größeren Datenmengen nicht "hängen" bleibt. Das bedeutet aber auch, das das CLOB-Feld beim ersten Durchlauf auch erstmal nicht "voll" ist.
    Der Workaround wäre an der Stelle, die Daten erstmal in einem Temporären CLOB zwischenzupuffern und erst nach dem Stream zu speichern.

    Zu deiner 2. Frage:
    Innerhalb von PL/SQL-Blöcken, dazu zählen auch Trigger, brauchst du die dämliche "SELECT xxx FROM DUAL-Notation nicht, jedenfalls bei den meisten Zuweisungen nicht. Der dbms_application_info.set_client_info-Call ist nur für die Laufzeit einer Session gültig, d.h. Zwischen dem connect und dem disconnect. Wenn die Session beendet ist, also in der Anwendung mittendrin, ist der Wert natürlich auch weg.
    Du kannst das auch gerne prüfen, ob der Wert angekommen ist, er sollte in der Spalte CLIENT_INFO in dem Systemview V$SESSION stehen (wenn du die Berechtigung für den Zugriff auf die Ansicht hast).

    Ich würde dir empfehlen, wenn du keine dauerhafte Session in deiner Applikation abgebildet hast, folgendes zu tun

    Code :
    1
    2
    3
    4
    5
    
    connect zur DB
    dbms_application_info.set_client_info ...
    ==auszuführende Aktion==
      (hier zieht im Normalfall der Trigger)
    disconnect

    und wenn der Trigger zieht (d.h. zwischen connect und disconnect) im Trigger
    Code :
    1
    2
    3
    4
    5
    
    clientinfo := userenv('CLIENTINFO') -- kann auch in einer IF-Bedingung benutzt werden
     
    bzw. alternativ
     
    dbms_application_info.read_client_info(clientinfo);

    Ich hoffe das wars

    Sascha
     

  10. #10
    forced forced ist offline Mitglied
    Registriert seit
    Nov 2007
    Beiträge
    24
    Ich danke
     

Ähnliche Themen

  1. Frage bezüglich CLOB (Oracle)
    Von ush im Forum Relationale Datenbanksysteme
    Antworten: 1
    Letzter Beitrag: 08.09.10, 09:24
  2. Abfrage von CLOB Spalte aus einer Oracle DB
    Von Templorials im Forum PHP
    Antworten: 0
    Letzter Beitrag: 24.07.08, 11:44
  3. [Oracle] CLOB wird mal abgeschnitten und mal nicht
    Von Gray im Forum Relationale Datenbanksysteme
    Antworten: 1
    Letzter Beitrag: 16.01.08, 14:52
  4. Oracle: CLOB speichern klappt nicht
    Von Gray im Forum Relationale Datenbanksysteme
    Antworten: 0
    Letzter Beitrag: 23.11.07, 11:23
  5. Oracle CLOB Felder in Access
    Von NBOne im Forum Relationale Datenbanksysteme
    Antworten: 0
    Letzter Beitrag: 15.05.07, 16:07