2016-06-09 11 views
0

brauchen Ihre HilfeKreuztabellen Datenvalidierung

Ich habe 2 verbundene Einheiten: Bibliothek Leser (Abonnent) und Buch Probleme. Reader kann für einen gewissen Zeitraum in Tagen gesperrt werden, da brechen Bibliothek Regeln:

DB logical scheme

Ich brauche Scheck hinzufügen, so dass Leser, der Sperrzeitraum ist noch nicht beendet, konnte kein Buch in einem nehmen Bibliothek (mit anderen Worten, Issue.Taken> Subscriber.Lock_Date + Subscriber.Lock_Period)

Bitte helfen, wie kann ich das tun?

Antwort

1

ich mit MTO darüber einig, dass eine solche Validierungen von Anwendungscode verarbeitet werden (über eine gespeicherte Prozedur). Wenn Sie jedoch darauf bestehen, diese Validierung über die Datenbank durchzuführen, ist der folgende Trigger hilfreich. Auch hier empfehle ich diese Lösung nicht, und der beste Weg wäre, sie mit Anwendungslogik zu behandeln.

CREATE OR REPLACE TRIGGER trg_val_lock_dt 
BEFORE INSERT ON issue 
FOR EACH ROW 
DECLARE 
    v_is_valid CHAR(1); 
BEGIN 

    v_is_valid := 'Y'; 

    SELECT 'N' INTO v_is_valid 
    FROM subscriber s 
    WHERE :NEW.subscr_id = s.subscr_id 
    AND :NEW.taken BETWEEN s.lock_date AND (s.lock_date + lock_period); 

    RAISE_APPLICATION_ERROR(-20001,'The subscriber is locked'); 

EXCEPTION 
    WHEN NO_DATA_FOUND THEN 
     NULL; 
END; 

Der obige Trigger wird vor jedem Einsatz Feuer in der Ausgabe Tabelle. Es wird geprüft, ob das eingegebene Datum zwischen dem Sperrdatum und dem Sperrdatum + Sperrzeitraum liegt (was das Sperrenddatum wäre). Wenn ein solcher Datensatz gefunden wird, wird der folgende Fehler ausgegeben und die Zeile wird nicht eingefügt.

ORA-20001: The subscriber is locked 
ORA-06512: at "RETAIL_1.TRG_VAL_LOCK_DT", line 12 

Wenn die Bedingung nicht erfüllt ist, dann wird die keine Daten gefunden Ausnahme ausgelöst werden, wenn der Auslöser nichts tun wird, und die Zeile eingefügt wird.

+0

Es funktioniert gut für das Einfügen einer neuen Zeile in Tabelle, aber wenn ich versuche, Buch (oder ein anderes Update) zurückzugeben, bekomme ich ORA-04091 Tabelle mutiert Fehler. Kann ich diesen Fehler umgehen oder ist das eine Begrenzung des Triggers? – JGDger

+0

Aber der Auslöser sollte nur auf Einsatz auslösen. Feuert es auf Update ab? –

+0

Ja, Fehler wirft auf Update und ich verstehe nicht warum – JGDger

3

Dies sollte wirklich in der Geschäftslogik und nicht auf der Tabellenebene behandelt werden.

aber man könnte es tun, eine materialisierte Ansicht mit:

CREATE TABLE subscriber (
    id   INT PRIMARY KEY, 
    lock_date DATE, 
    lock_period INTERVAL DAY(5) TO SECOND 
); 

CREATE TABLE issue (
    id  INT PRIMARY KEY, 
    subscr_id INT NOT NULL REFERENCES subscriber(id), 
    book_id INT, 
    taken  DATE, 
    returned DATE 
); 

CREATE MATERIALIZED VIEW LOG ON subscriber 
    WITH SEQUENCE, ROWID(id, lock_date, lock_period) 
    INCLUDING NEW VALUES; 

CREATE MATERIALIZED VIEW LOG ON issue 
    WITH SEQUENCE, ROWID(subscr_id, taken) 
    INCLUDING NEW VALUES; 

CREATE MATERIALIZED VIEW subscriber_issue_MV 
    BUILD IMMEDIATE 
    REFRESH FAST ON COMMIT 
    AS SELECT s.id, 
      s.lock_date, 
      s.lock_period, 
      i.taken 
     FROM subscriber s 
      INNER JOIN 
      issue i 
      ON (i.subscr_id = s.id); 

ALTER TABLE subscriber_issue_MV ADD CONSTRAINT subscriber_issue__mv__chk 
    CHECK ( lock_date IS NULL 
     OR lock_period IS NULL 
     OR NOT taken BETWEEN lock_date AND lock_date + lock_period); 
+0

Es wurde versucht, aber beim Erstellen der materialisierten Ansicht trat ein Fehler auf: ORA 00439 - Feature nicht aktiviert: Erweiterte Replikation. Bedeutet das, dass ich aus irgendeinem Grund keine materialisierte Ansicht erstellen kann? – JGDger

+0

Sie können, aber Sie können nicht die Protokolle oder 'FAST REFRESH ON COMMIT' verwenden ... was bedeutet, dass es funktionieren könnte, aber Sie müssten die materialisierte Ansicht durch eine andere Methode aktualisiert werden - was es unpraktisch machen würde. – MT0

+0

Wie ich schon in der ersten Zeile gesagt habe - Lösung auf Tabellenebene ist möglich, aber nicht die beste Lösung. Eine bessere Lösung wäre, dass Bücher nur über eine Prozedur (oder die Geschäftslogik der mittleren Ebene, die Sie für den Zugriff auf Oracle verwenden) herausgenommen werden und dann die gesamte Geschäftslogik der Überprüfung des Benutzers nicht eingeschlossen wird. – MT0