Hallo Tom,
ich fürchte, so einfach wird das nicht. das problem ist, dass
oracle es einem trigger nicht zulässt, auf die tabelle, auf
die gerade zugegriffen wird, lesend zuzugreifen.
Doch, doch, das Zauberwort nennt sich „Autonomous Transaction“
Jetzt bin ich aber enttäuscht: Das funktioniert doch gar nicht!
SQL\> create table mar\_tab (von date, bis date);
Table created.
SQL\> create or replace trigger mar\_trg before insert on mar\_tab for each row
2 DECLARE
3 PRAGMA AUTONOMOUS\_TRANSACTION;
4 ln\_anzahl number ;
5 begin
6 select count(\*)
7 into ln\_anzahl
8 from mar\_tab
9 where :new.von between von and bis
10 or :new.bis between von and bis ;
11 if ln\_anzahl \> 0 then
12 raise\_application\_error (-20001, 'Zeitraum überschneidet sich');
13 end if ;
14 end ;
15 /
Trigger created.
SQL\> insert into mar\_tab values (sysdate-10, sysdate-5);
1 row created.
Jetzt machen wir ein zweites SQL*Plus auf und schreiben dort:
SQL\> insert into mar\_tab values (sysdate-7, sysdate-2);
1 row created.
SQL\> commit;
Commit complete.
Wieder zurück im ersten Fenster:
SQL\> commit;
Commit complete.
SQL\> select \* from mar\_tab;
VON BIS
---------- ----------
11.05.2007 16.05.2007
14.05.2007 19.05.2007
Und jetzt?
(keine ahnung, ob das oben prinzipiell kompilieren würde -
habe gerade kein oracle zur verfügung…)
geht mir genauso
Tut es, löst aber leider das Problem nicht. Dir fehlt der „Lock table“ (der einem übrigens auch ohne autonomous_transaction nicht erspart bleibt).
autonomous_transaction kann hier aber noch mehr:
SQL\> delete from mar\_tab;
2 rows deleted.
SQL\> commit;
Commit complete.
SQL\> insert into mar\_tab values (sysdate - 5, sysdate);
1 row created.
SQL\> insert into mar\_tab values (sysdate - 3, sysdate - 1);
1 row created.
SQL\> insert into mar\_tab values (sysdate - 2, sysdate - 2);
1 row created.
SQL\> commit;
Commit complete.
SQL\> select \* from mar\_tab;
VON BIS
--------- ---------
16-MAY-07 21-MAY-07
19-MAY-07 19-MAY-07
18-MAY-07 20-MAY-07
Sieht gar nicht gut aus…
Allerdings: Diese autonomen Transaktionen in Tabellen-Triggern
habe ich persönlich noch nie angewandt - ein bisserl heikel
ist es halt schon, den sobald mehrere Records eingefügt
werden, ist der Zustand der Tabelle gar nicht mehr mal so
eindeutig definierbar …
Doch, eindeutig definierbar schon. Das Problem ist, dass mit Triggern referentielle zwischen bzw. logische Integrität innerhalb von Tabellen nur abbildbar ist, wenn da mindestens ein „Lock Table“ drinsteht - zumindest solange es keine ON COMMIT Trigger gibt. Dafür waren Trigger natürlich auch nie gedacht.
So, jetzt habe ich zwar deine Lösung niedergemacht, aber mir selbst fällt natürlich ausser dem Lock auch nichts vernünftiges ein. Allerdings müsste sich da bei http://asktom.oracle.com was finden, ist ja kein Problem, das völlig aus der Welt ist. Mir schwebt da natürlich wieder was mit Function based indices im Kopf herum, ich kann es nur nicht dingfest machen *g*
Liebe Grüße,
Martin