|
|
Datenbanken Online Lexikon
|
| Datenbanken | Mutating-Table-Problem,Loesung |
Lösung des Mutating-Table-ProblemsUnterseite von Mutating-Table-ProblemGrundproblem beim Mutating-Table-Problem, wie es bei Oracle auftritt, ist, dass im Aktionsteil eines zeilenorientierten Triggers (ROW Trigger) mittels Anfragen oder INSERT-, UPDATE-, DELETE-Anweisung auf die Tabelle zugegriffen wird, für die der Trigger definiert ist. Wie die Aufgabenstellung des Beispiels zeigt, ist das eine durchaus naheliegendes Problem, das schnell mal auftreten kann. Der Versuch, die Aufgabenstellung mit einem ROW-Trigger zu lösen, hat den Vorteil, man verfügt in den Transitionsvariablen über die Informationen, welche Datensätze betroffen sind von der feuernden Manipulation. Der Versuch, die Aufgabenstellung mit einem STATEMENT-Trigger (befehlsorientierter Trigger) zu lösen funktioniert insofern, als die gewünschte Aktion im STATEMENT-Trigger ohne Laufzeitproblem ausführbar ist. Nur hat der STATEMENT-Trigger genau den Nachteil, in seinem Aktionsteil gibt es keine Transitionsvariablen mit den Informationen über die manipulierten Datensätze und muss mit für alle gespeicherten Datensätze die Aktion durchführen, was je nach Größe des Datenbestands äußerst ineffizient sein kann und entsprechend viel Zeit beansprucht. Grundidee einer Lösung mit Oracle-Triggern:
Für das "irgendwo" bieten sich zwei Lösungen an:
Lösung des Mutating-Table-Problems in vier Schritten mit Oracle-Konzepten:
Beispiel:Jede Abteilung verfügt über ein Gehaltsbudget (Spalte budget). Die Summe der Gehälter aller Mitarbeiter (Spalte gehalt) einer Abteilung darf dieses Budget nicht überschreiten. Das zweite Mutating-Table-Problem-Beispiel läßt sich nun wie folgt ohne dieses Laufzeitproblem lösen: -- 1. öffentliche Package-Variablen
CREATE OR REPLACE PACKAGE gehaltsbudget_pck AS
TYPE abtnr_tabletyp IS TABLE OF mitarbeiter.abtnr%TYPE NOT NULL
INDEX BY BINARY_INTEGER;
v_abtnr_tabelle abtnr_tabletyp;
v_zaehler BINARY_INTEGER DEFAULT 1;
END gehaltsbudget_pck;
-- 2. BEFORE STATEMENT zum Initialisieren
CREATE OR REPLACE TRIGGER init_gehaltsbudget_pck_trg
BEFORE INSERT OR UPDATE OF gehalt, abtnr ON mitarbeiter
BEGIN
gehaltsbudget_pck.v_zaehler := 1;
END;
-- 3. AFTER ROW für das Zwischenspeichern in den öffentlichen Package-Variablen
CREATE OR REPLACE TRIGGER gehaltsbudget_aiur_trg
AFTER INSERT OR UPDATE OF gehalt, abtnr ON mitarbeiter
FOR EACH ROW
BEGIN
gehaltsbudget_pck.v_abtnr_tabelle(gehaltsbudget_pck.v_zaehler) := :NEW.abtnr;
gehaltsbudget_pck.v_zaehler := gehaltsbudget_pck.v_zaehler + 1;
END;
-- 4. AFTER STATEMENT für die eigentlichen Aktionen, hier Tests
CREATE OR REPLACE TRIGGER gehaltsbudget_aius_trg
AFTER INSERT OR UPDATE OF gehalt, abtnr ON mitarbeiter
DECLARE
v_summe NUMBER(20);
v_budget abteilung.budget%TYPE;
BEGIN
FOR i IN 1..gehaltsbudget_pck.zaehler-1 LOOP
SELECT SUM(gehalt) INTO v_summe
FROM mitarbeiter
WHERE abtnr = gehaltsbudget_pck.abtnr_tabelle(i);
SELECT budget INTO v_budget
FROM abteilung
WHERE abtnr = gehaltsbudget_pck.abtnr_tabelle(i);
IF v_summe > v_budget THEN
RAISE_APPLICATION_ERROR(-20003,'Summe der Gehälter übersteigt das Abteilungsbudget: '
|| gehaltsbudget_pck.abtnr_tabelle(i));
END IF;
END LOOP;
END;
-- 5. AFTER ROW-Trigger auf Abteilung, weil auch eine Verringerung des Budgets ein feuerndes Ereignis ist
-- Dieser Trigger der Vollständigkeit der Lösung wegen, mit dem Mutating-Table-Problem hat er nichts zu tun
CREATE OR REPLACE TRIGGER gehaltsbudget_abt_trg
AFTER UPDATE OF budget, abtnr ON abteilung
FOR EACH ROW
WHEN (NEW.budget < OLD.budget)
DECLARE
v_summe number(20);
BEGIN
SELECT SUM(gehalt) INTO v_summe
FROM mitarbeiter
WHERE abtnr = :NEW.abtnr;
IF v_summe > :NEW.budget THEN
RAISE_APPLICATION_ERROR(-20003,'Summe der Gehälter übersteigt das Abteilungsbudget');
END IF;
END;
Kategorie: Aktive Datenbanken, Oracle-PL-SQL, SQL, M |
| XHTML und CSS dieser Seite validieren. | Letzte Aktualisierung am 23.08.2010, um 14:44:02 | Bearbeiten Versionen Druckansicht Aktuelle Änderungen |
|
Powered by PmWiki |
||