prev up next

Trigger

Die allgemeinste Konsistenzsicherung geschieht durch einen Trigger. Dies ist eine benutzerdefinierte Prozedur, die automatisch bei Erfüllung einer bestimmten Bedingung vom DBMS gestartet wird. Hilfreich sind zwei vom System gefüllte Tabellen DELETED und INSERTED, in der solche Zeilen gespeichert sind, auf die sich das beabsichtigte Löschen bzw. Einfügen beziehen. In diesem Zusammenhang ist die Operation UPDATE als hintereinander ausgeführte Kombination von Löschen und Einfügen zu sehen.

Listing 8.2 zeigt einen AFTER-UPDATE-Trigger für die Tabelle Professoren, der nach jedem Update aufgerufen wird und im Falle einer Degradierung diese wieder rückgängig macht.

Listing 8.2: Trigger zur Korrektur einer Degradierung
create trigger korrigieredegradierung -- definiere einen Trigger
on Professoren after update           -- nach update von Professoren
as                               
if update(Rang)                       -- falls Rang veraendert wurde
begin
  update professoren                  -- aendere Professoren erneut
  set    rang = d.rang                -- setze Rang auf alten Rang
  from   professoren p, deleted d     -- mit Hilfe der Tabelle deleted
  where  p.persnr = d.persnr          -- bei uebereinstimmender PersNr
  and    p.rang < d.rang              -- falls neuer Rang < alter Rang
end	

Listing 8.3 zeigt die Lösung für dasselbe Problem durch einen INSTEAD-OF-UPDATE-Trigger, der statt des Update durchgeführt wird. Durch Vergleich der Einträge in den Systemtabellen DELETED und INSERTED kann die beabsichtigte Beförderung für solche Professoren durchgeführt werden, die zuvor noch keine Rangangabe aufwiesen oder eine kleinere Rangangabe hatten.

Listing 8.3: Trigger zur Verhinderung einer Degradierung
create trigger verhinderedegradierung  -- definiere einen Trigger
on Professoren instead of update       -- statt eines updates
as
  update professoren                   -- aendere nun Professoren doch
  set    rang = i.rang                 -- setze auf eingefuegten Rang
  from   deleted d, inserted i         -- unter Verwendung von d und i
  where  professoren.persnr = d.persnr -- bei passender Personalnummer
  and    d.persnr = i.persnr           -- bei passender Personalnummer
  and    (d.rang=null                  -- falls vorher kein Rang vorhanden
         or d.rang < i.rang)           -- oder alter Rang < neuer Rang
	

Listing 8.4 zeigt einen AFTER-INSERT-Trigger, der immer nach dem Einfügen eines Tupels in die Tabelle hoeren einen Professor sucht, der jetzt mehr als 10 Hörer hat und ihn dann nach C4 befördert.

Listing 8.4: Trigger zum Auslösen einer Beförderung
create trigger befoerderung        -- definiere den Trigger befoerderung
on hoeren after insert, update     -- nach insert oder update bei hoeren
as 
update professoren set rang='C4'   -- befoerdere Professor nach C4
where persnr in                    -- falls seine Personalnummer in
  (select persnr                   -- der Menge der Personalnummern liegt
   from   professoren p,           -- die mehr als 10 Hoerer haben
          vorlesungen v, 
          hoeren h
   where  p.persnr = v.gelesenvon 
   and    v.vorlnr = h.vorlnr
   group by p.persnr
   having count(*) > 10)
	

Listings 8.5 und 8.6 zeigen die Verwendung eines INSTEAD-OF-INSERT-Triggers im Zusammenhang mit Sichten, in die nur unter sehr eingeschränkten Bedingungen eingefügt werden kann. Auf der Tabelle Person sei eine Sicht Geburtstagsliste gegeben. In dieser Sicht wird das momentane Lebensalter in Jahren anhand der Systemzeit und des gespeicherten Geburtsdatums errechnet. Natürlich ist diese Sicht nicht update-fähig bei Einfügen eines Namens mit Lebensalter. Durch den Trigger geburtstag läßt sich das Einfügen trotzdem erreichen, da nach Umrechnung des Alters in ein Geburtsdatum ein Tupel in die Tabelle Person eingefügt werden kann.

Listing 8.5: Nichtupdatefähige Sicht
create view Geburtstagsliste                       -- lege Sicht an
as                                                 -- bestehend aus
select Name,                                       -- Name
       datediff(year,gebdatum,getdate()) as Jahre  -- Lebensalter
from Person                                        -- von Tabelle Person	

Listing 8.6: Trigger zum Einfügen eines errechneten Geburtsdatums
create trigger Geburtstag                     -- lege Trigger an bzgl.
on Geburtstagsliste                           -- Geburtstagsliste
instead of insert                             -- statt einzufuegen
as
insert into Person (name,gebdatum)            -- fuege in Person ein
select i.name,                                -- eingefuegter Name
       dateadd(year, -i.jahre, getdate())     -- errechnetes Geburtsjahr
from inserted i                               -- aus Tabelle inserted                               
	

Das Schlüsselwort drop entfernt einen Trigger: drop trigger Geburtstag


prev up next