BEGIN EXECUTE IMMEDIATE 'DROP TABLE alkis_beziehungen_insert CASCADE CONSTRAINTS'; EXCEPTION WHEN OTHERS THEN NULL; END; / CREATE TABLE alkis_beziehungen_insert( ogr_fid integer NOT NULL, beziehung_von character(16), beziehungsart varchar2(2047), beziehung_zu character(16), CONSTRAINT ALKIS_BZI PRIMARY KEY (ogr_fid) ); -- Beziehungssätze aufräumen CREATE OR REPLACE TRIGGER alkis_beziehung_ins AFTER INSERT ON "ALKIS_BEZIEHUNGEN" REFERENCING NEW AS NEW FOR EACH ROW BEGIN -- avoid table mutation INSERT INTO alkis_beziehungen_insert(ogr_fid,beziehung_von,beziehungsart,beziehung_zu) VALUES ( :NEW.ogr_fid, :NEW.beziehung_von, :NEW.beziehungsart, :NEW.beziehung_zu ); END alkis_beziehung_inserted; / -- show errors trigger alkis_beziehung_ins; CREATE OR REPLACE TRIGGER alkis_beziehungen_a_ins AFTER INSERT ON alkis_beziehungen BEGIN FOR a IN (SELECT * FROM alkis_beziehungen_insert) LOOP DELETE FROM alkis_beziehungen b WHERE a.ogr_fid:NEW.replacedBy THEN -- Beginnt-Datum aus Timestamp beginnt := substr(:NEW.featureid, 17, 4) || '-' || substr(:NEW.featureid, 21, 2) || '-' || substr(:NEW.featureid, 23, 2) || 'T' || substr(:NEW.featureid, 26, 2) || ':' || substr(:NEW.featureid, 28, 2) || ':' || substr(:NEW.featureid, 30, 2) || 'Z' ; END IF; ELSIF length(:NEW.featureid)=16 THEN alt_id := :NEW.featureid; ELSE raise_application_error(-20100, :NEW.featureid || ': Länge 16 oder 32 statt ' || length(:NEW.featureid) || ' erwartet.'); END IF; IF beginnt IS NULL THEN -- Beginnt-Datum des ältesten Eintrag, der nicht untergegangen ist -- => der Satz dessen 'endet' gesetzt werden muß EXECUTE IMMEDIATE 'SELECT min(beginnt) FROM ' || :NEW.typename || ' WHERE gml_id=''' || alt_id || '''' || ' AND endet IS NULL' INTO beginnt; END IF; IF beginnt IS NULL THEN IF :NEW.context = 'delete' OR :NEW.safetoignore = 'true' THEN dbms_output.put_line('Kein Beginndatum fuer Objekt ' || alt_id || ' gefunden.'); :NEW.ignored := 'true'; RETURN; ELSE raise_application_error(-20100, 'Kein Beginndatum fuer Objekt ' || alt_id || ' gefunden.'); END IF; END IF; IF :NEW.context='delete' THEN SELECT to_char(sysdate, 'YYYY-MM-DD"T"HH24:MI:SS"Z"') INTO endete FROM dual; ELSIF :NEW.context='replace' THEN :NEW.safetoignore := lower(:NEW.safetoignore); IF :NEW.safetoignore IS NULL THEN raise_application_error(-20100, :NEW.featureid || ': safeToIgnore nicht gesetzt.'); ELSIF :NEW.safetoignore<>'true' AND :NEW.safetoignore<>'false' THEN raise_application_error(-20100, :NEW.featureid || ': safeToIgnore ''' || :NEW.safetoignore || ''' ungültig (''true'' oder ''false'' erwartet).'); END IF; IF length(:NEW.replacedBy)=32 THEN -- Beginnt-Datum aus Timestamp neu_id := substr(:NEW.replacedBy, 1, 16); IF :NEW.featureid<>:NEW.replacedBy THEN endete := substr(:NEW.replacedBy, 17, 4) || '-' || substr(:NEW.replacedBy, 21, 2) || '-' || substr(:NEW.replacedBy, 23, 2) || 'T' || substr(:NEW.replacedBy, 26, 2) || ':' || substr(:NEW.replacedBy, 28, 2) || ':' || substr(:NEW.replacedBy, 30, 2) || 'Z' ; END IF; ELSIF length(:NEW.replacedBy)=16 THEN neu_id := :NEW.replacedBy; ELSIF length(:NEW.replacedBy)<>16 THEN raise_application_error(-20100, :NEW.replacedBy || ': Länge 16 oder 32 statt ' || length(:NEW.replacedBy) || ' erwartet.'); END IF; IF endete IS NULL THEN -- Beginnt-Datum des neuesten Eintrag, der nicht untergegangen ist -- => Enddatum für vorherigen Satz EXECUTE IMMEDIATE 'SELECT max(beginnt) FROM ' || :NEW.typename || ' WHERE gml_id=''' || neu_id || '''' || ' AND beginnt>''' || beginnt || '''' || ' AND endet IS NULL' INTO endete; END IF; IF alt_id<>neu_id THEN dbms_output.put_line('Objekt ' || alt_id || ' wird durch Objekt ' || neu_id || ' ersetzt.'); END IF; IF endete IS NULL THEN dbms_output.put_line('Kein Beginndatum fuer Objekt ' || neu_id || '.'); END IF; IF endete IS NULL OR beginnt=endete THEN raise_application_error(-20100, 'Objekt ' || alt_id || ' wird durch Objekt ' || neu_id || ' ersetzt (leere Lebensdauer?).'); END IF; ELSE raise_application_error(-20100, :NEW.featureid || ': Ungültiger Kontext ' || :NEW.context || '''delete'' oder ''replace'' erwartet).'); END IF; s := 'UPDATE ' || :NEW.typename || ' SET endet=''' || endete || '''' || ' WHERE gml_id=''' || alt_id || '''' || ' AND beginnt=''' || beginnt || '''' || ' AND endet IS NULL'; EXECUTE IMMEDIATE s; n := SQL%ROWCOUNT; IF n<>1 THEN dbms_output.put_line( 'SQL: ' || s); IF :NEW.context = 'delete' OR :NEW.safetoignore = 'true' THEN dbms_output.put_line( :NEW.featureid || ': Untergangsdatum von ' || n || ' Objekten statt nur einem auf ' || endete || ' gesetzt - ignoriert' ); :NEW.ignored := 'true'; RETURN; ELSIF n=0 THEN EXECUTE IMMEDIATE 'SELECT endet FROM ' || :NEW.typename || ' WHERE gml_id=''' || alt_id || '''' || ' AND beginnt=''' || beginnt || '''' INTO endete; IF NOT endete IS NULL THEN dbms_output.put_line( :NEW.featureid || ': Objekt bereits ' || endete || ' untergegangen - ignoriert' ); ELSE dbms_output.put_line( :NEW.featureid || ': Objekt nicht gefunden - ignoriert' ); END IF; :NEW.ignored := 'true'; RETURN; ELSE raise_application_error(-20100, :NEW.featureid || ': Untergangsdatum von ' || n || ' Objekten statt nur einem auf ' || endete || ' gesetzt - Abbruch' ); END IF; END IF; :NEW.ignored := 'false'; END delete_feature_trigger; / -- show errors trigger delete_feature_trigger;