2017-11-23 2 views
0

Ich habe eine Tabelle namens "Project" in meiner Datenbank und eine Tabelle namens "Milestone". Der Primärschlüssel von "Project" ist eine Spalte namens ProjectID. Die Beziehung "Meilenstein" hat einen Primärschlüssel mit der Bezeichnung "Nummer" und einen Fremdschlüssel, der sich auf das Projekt bezieht, zu dem er gehört.OracleSQL: Auto Increment abhängig von einer anderen Spalte (schwache Entity-Modellierung)

Wenn ich einen neuen Eintrag in "Milestone" einfüge möchte ich, dass der Primärschlüssel "Number" automatisch erhöht wird, aber in Bezug auf das Projekt gehört der neue Meilenstein. Die Idee ist im Grunde folgende:

 Milestone 
ProjectID | Number 
    69    1 
    69    2 
    69    3 
    420   1 
    420   2 
    666   1 
    420   3 

Ist es möglich, dies in OracleSQL mit einem Trigger zu erkennen, wenn die Werte innerhalb der „Milestone“ Tabelle einfügen?

Antwort

0

Zunächst einmal ist die Benennung einer Spalte NUMBER in Oracle eine unglaublich schlechte Idee, da dies der Name des numerischen Basistyps ist. Ich nehme an, Sie werden schlau sein und stattdessen PROJECT_LINE anrufen.

Sie können einen Compound-Trigger verwenden, um dies zu erreichen. Im BEFORE STATEMENT Triggerpunkt erfassen Sie die maximale PROJEKTLINIE für alle Projekte (weil Sie im Abschnitt VOR DER ERKLÄRUNG nicht wissen welche Projekt Sie betrachten), dann im BEFORE EACH ROW Triggerpunkt den maximalen Wert zuweisen + 1 an die neue PROJECT_LINE, und die Linie des Projekts max Werte aktualisieren:

CREATE OR REPLACE TRIGGER MILESTONE_TRG 
    FOR INSERT ON MILESTONE 
COMPOUND TRIGGER 
    TYPE NUMBER_MAP IS TABLE OF NUMBER 
    INDEX BY PLS_INTEGER; 
    tblMAX_PROJECT_LINE NUMBER_MAP; -- store max PROJECT_LINE, indexed by PROJECT_ID 

    BEFORE STATEMENT IS 
    BEGIN 
    tblMAX_PROJECT_LINE := NUMBER_MAP(); 

    FOR aRow IN (SELECT PROJECT_ID, 
         MAX(PROJECT_LINE) AS MAX_PROJECT_LINE 
        FROM MILESTONE 
        GROUP BY PROJECT_LINE) 
    LOOP 
     tblMAX_PROJECT_LINE(aRow.PROJECT_ID) := aRow.MAX_PROJECT_LINE; 
    END LOOP; 
    END BEFORE STATEMENT; 

    BEFORE EACH ROW IS 
    BEGIN 
    :NEW.PROJECT_LINE := tblMAX_PROJECT_LINE(:NEW.PROJECT_ID) + 1; 
    tblMAX_PROJECT_LINE(:NEW.PROJECT_ID) := tblMAX_PROJECT_LINE(:NEW.PROJECT_ID) + 1; 
    END AFTER EACH ROW; 
END MILESTONE_TRG; 

ich werde nicht für die Effizienz, dies zu tun bürgen. Außerdem können mehrere gleichzeitige INSERTs kollidieren. Sie müssen eine PRIMARY KEY- oder UNIQUE-Einschränkung auf (PROJECT_ID, PROJECT_LINE) setzen, die Ausnahme für die Schlüsselverletzung abfangen, die bei Ihrer INSERT-Anweisung auftreten kann, und die INSERT-Operation wiederholen.

Viel Glück.

+0

Vielen Dank für Ihren freundlichen Kommentar und eine sehr gute Klarstellung. In Bezug auf die Spalte "Nummer" habe ich zum Glück für mich die Spalte "Nummer" genannt, obwohl ich nicht das englische Wort dafür verwendet habe, sondern eine andere Sprache. Der Code, den Sie mir gezeigt haben, funktioniert jedoch nicht vollständig. Wenn ich versuche, einen neuen Milestone-Eintrag einzufügen, erhalte ich den Fehler "Trigger ist ungültig und erneute Validierung fehlgeschlagen". – Infecto

+0

Wie bei allem Code in StackOverflow müssen Sie möglicherweise ein wenig Debugging durchführen, um es in Ihrer Situation zum Laufen zu bringen. Anscheinend gibt es einen Fehler im Code für deinen Auslöser. Um herauszufinden, was der Fehler ist, können Sie Folgendes ausführen: 'SELECT * FROM ALL_ERRORS WHERE OWNER = 'Besitzer auslösen' UND NAME = 'Name des Triggers' ORDER BY SEQUENCE ', wobei' 'Triggername' 'durch den Namen Ihres Triggers ersetzt wird und "Trigger Owner" mit dem Schema, in dem der Trigger erstellt wurde. Viel Glück. –

Verwandte Themen