Announcement

Collapse
No announcement yet.

VIEW UND TRIGGER

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • VIEW UND TRIGGER

    Hi !

    Ich habe vollgendes Konstrukt und anscheinend ein Verständnis-Problem, wie sich das mit TRIGGERN und VIEWS verhält.

    Meine Tabelle TBTEXT enthält drei Spalten: ID (PK), TYP, TEXT. Die Spalte TYP bestimmt, was die Spalte TEXT enthält – zb. Namen von Personen oder
    Namen von Orten. Ein BEFORE-INSERT-TRIGGER für die Tabelle setzt über einen GENERATOR die ID. Ein VIEW gibt die Sicht auf alle Reihen, in denen
    mit TYP=0 die Namen von Personen stehen, ein zweiter mit Typ=1 zeigt die Namen von Orten. Der jeweilige BEFORE-INSERT-TRIEGGER der VIEWS soll für
    die korrekte Eingabe sorgen:

    <PRE>
    <B>TABELLE TBTEXT:</B>
    CREATE GENERATOR GEN_TBTEXT_ID;
    CREATE TABLE TBTEXT
    (
    ID INTEGER NOT NULL,
    TYP SMALLINT NOT NULL,
    TEXT VARCHAR( 50) NOT NULL
    );
    ALTER TABLE TBTEXT ADD CONSTRAINT PK_TBTEXT PRIMARY KEY (ID);

    CREATE TRIGGER TRBI_TBTEXT FOR TBTEXT ACTIVE BEFORE INSERT POSITION 0 AS
    BEGIN
    IF (NEW.ID IS NULL) THEN NEW.ID = GEN_ID(GEN_TBTEXT_ID, 1);
    END

    <PRE>
    <B>VIEW für die PERSONEN-NAMEN:</B>
    CREATE VIEW VW_PNAMEN(PERSON) AS SELECT a.TEXT FROM TBTEXT a WHERE a.TYP = 0;

    CREATE TRIGGER TRBI_VW_PNAMEN FOR VW_PNAMEN ACTIVE BEFORE INSERT POSITION 0 AS
    BEGIN
    INSERT INTO TBTEXT(TYP, TEXT) VALUES (0, NEW.PERSON);
    END

    <PRE>
    <B>VIEW für die ORT-NAMEN:</B>
    CREATE VIEW VW_ONAMEN(ORT) AS SELECT a.TEXT FROM TBTEXT a WHERE a.TYP = 1;

    CREATE TRIGGER TRBI_VW_ONAMEN FOR VW_ONAMEN ACTIVE BEFORE INSERT POSITION 0 AS
    BEGIN
    INSERT INTO TBTEXT(TYP, TEXT) VALUES (1, NEW.ORT);
    END
    </PRE>

    Um dem Konstrukt einen weiteren Sinn zu geben, stelle man sich vor, zur Laufzeit noch nicht zu wissen was für Informationen gespeichert werden
    sollen. Durch die Wahl weiterer Typen plus jeweiliger VIEWS/TRIGGER kann die Tabelle TBTEXT zur Speicherung beliebig vieler Listen dienen.

    <BR><B>
    Das Resultat der Eingabe über einen der VIEWS ergibt immer die Fehlermeldung: Spalte TYP darf nicht NULL sein ...
    <BR></B>
    Was muß geändert werden, damit das Konstrukt funktioniert ? Was mag mein Verständnis-Problem sein ?
    <BR>

    Ein Workaround mutet etwas seltsam an:
    <PRE>
    <B>VIEW für die PERSONEN-NAMEN:</B>
    CREATE VIEW VW_PNAMEN(PERSON) AS
    SELECT a.TEXT FROM TBTEXT a JOIN TBTEXT B WHERE a.ID = b.ID AND a.TYP = 0;
    </PRE>

    Warum verhält sich INTERBASE in diesem Fall anders ???

  • #2
    Der Code in den Before-Insert Triggers auf die beiden Views ersetzen die auslösende Insert-Operation nicht, sondern ergänzen sie nur.

    Ein Insert in eine View hat zunächst bewirkt einen Insert in die unterliegende Tabelle, aus der die View Daten liest.
    Die beiden Triggers auf die zwei Views definieren weitere Insert-Operationen, die _zusätzlich_ und nicht ersatzweise ausgeführt werden.

    Gruss
    Karsten Strobe

    Comment


    • #3
      Wenn ich das richtig verstehe, muß ich also für einen VIEW, den ich auch zur Daten-Eingabe nutzen möchte, sämtliche durch den DATA DEFINITION GUIDE angegebenen Vorraussetzungen erfüllen, also u.a., daß der Primary Key in den VIEW aufgenommen werden muß und Spalten die nicht im View referenziert werden NULL-Einträge zulassen müssen !?

      Der DDG schreibt u.a. auch, daß Updateble Views nur auf einer Tabelle basieren dürfen, VIEWs die mehrere Tabellen 'JOINEN' seien automatisch readonly ??

      Will ich also den INSERT in die Basis-Tabelle über die Trigger ermöglichen, muß der VIEW Readonly sein, was er in dem WORK-AROUND durch den JOIN ja ist - so ein Readonly-VIEW aber keinen INSERT ausführt, warum feuern dann trotzdem die TRIGGER ?

      Könntest du vielleicht noch etwas mehr ins Detail gehen. Wenn sich das Dunkel auch ein wenig lichtet, so liegt die zugrunde liegende Logik noch auserhalb meines Verständisses.

      Tobia

      Comment


      • #4
        Hallo Tobias,

        ja, es ist sinnvoll, den PK in einen View aufzunehmen, wenn man darüber editieren will.

        Ein read/only View ist kein Workaround für das Problem, denn ein Insert in so einen View ist erst gar nicht möglich, also wird der Trigger mit dem Insert nie aufgerufen.

        Desweiteren liegst richtig: Nicht im View aufgeführte Felder müssen zwecks der Insert-fähigkeit nicht not-null sein oder eine Default-Klausel aufweisen.

        Dein ursprüngliches Problem kannst Du wahrscheinlich am einfachsten lösen, indem Du das Feld TYP in die Views mit aufnimmst und im Trigger nicht insert aufrufst sondern einfach die Anweisung "NEW.TYP = x" o.ä. programmierst.

        Gruss
        K

        Comment

        Working...
        X