![]() |
Datenbank: Firebird • Version: 1.5 • Zugriff über: IB-Controls
SELECT-Statement innerhalb eines Triggers
Hallo Leute.
Ich versuche gerade in meiner Rechnungsdaten-Tabelle doppelte eingaben eines Artikels zu vermeiden. Die Tabelle sieht quasi so aus:
SQL-Code:
Über folgenden Trigger habe ich versucht eine bereits bestehende Zeile aus der Rechnungsdaten-Tabelle zu löschen, falls versucht wird eine neue mit denselben Daten einzufügen:
create table Rechnungen(
RechnungsID Integer, KundenID Integer, Datum Date ); create table RechnungsDaten( RechnungsID Integer, AusleihID Integer );
SQL-Code:
Obiger Code funktioniert leider gar nicht. Außerdem kenn ich leider nicht alle Funktionen, die Firebird-SQL für Trigger zur Verfügung stellt (vlt. hat da ja jemand eine Online-Referenz zur Hand).
create trigger TRIG_test for rechnungsdaten
before insert as begin if ( (SELECT ausleihid FROM rechnungsdaten WHERE old.rechnungsid = new.rechnungsid AND old.ausleihid = new.ausleihid) > 0) then DELETE FROM rechnungsdaten WHERE ausleihid=new.ausleihid AND rechnungsid=new.rechnungsid; end; Nun meine Frage gibt es eine elegante Methode um die Eingabe mehrerer identischer Zeilen in der Tabell zu verhindern? Mit einem Trigger habe ich es versucht, da der UNIQUE-Schlüssel in der Tabellendefinition von "Rechnungsdaten" bisher rausgefallen ist, da mir die IB-Controls eine Exception auswerfen, anstelle es im stillen zu unterbinden. Außerdem möchte ich möglichst viel Code aus meiner Applikation in die Datenbank auslagern. |
Re: SELECT-Statement innerhalb eines Triggers
Ich würde nicht den vorhandenen Eintarg Löschen, sondern den neuen verhindern.
Du könntest auch einen zusammengesetzen Primärschlüssel verwenden, der beide Felder umfasst. |
Re: SELECT-Statement innerhalb eines Triggers
Mir ist gerade aufgefallen was ich eigentlich fürn murks ich da in dem Trigger fabriziert hab...
So gehts...
SQL-Code:
@mkinzler:
create trigger trig_test for rechnungsdaten
before insert as begin if ( EXISTS(SELECT * FROM rechnungsdaten WHERE rechnungsid = new.rechnungsID AND ausleihid = new.ausleihid) ) then DELETE FROM rechnungsdaten WHERE ausleihid = new.ausleihid rechnungsid = new.rechnungsid; end; Wie kann ich denn den neuen Eintrag verhindern? Und wie läuft das mit dem Schlüssel? |
Re: SELECT-Statement innerhalb eines Triggers
wenn der Primärschlüssel auch mehrern Feldern besteht, so muß die Kombination eindeutig sein und das Einfügen wird automatsch abgelehnt.
|
Re: SELECT-Statement innerhalb eines Triggers
Was ist das :
Zitat:
SQL-Code:
Den Rest hat mkinzler schon gesagt : im Prinzip wird Schadenswiedergutmachung versucht. So was lässt man aber besser von Anfang an nicht zu. Was soll aber nun gemacht werden, falls das Programm versucht, einen Datensatz einzutragen, der schon da ist ? Ich würde vorab mal sagen, daß ein Trigger der falsche Ansatz ist und das besser in einer SP aufgehoben wäre. Trigger sind gut für automatische Sachen, wie ID-Vergabe, Vorbesetzung oder automatische Änderung von Feldern. Ansonsten kann er das Programm aus den Angeln heben, denn er lauert im Hintergrund und schlägt ohne Warnung zu, sofern eine Bedingung erfüllt ist. Eine SP kann ich gesteuert aus dem eigenen Programm aus aufrufen.
create table Rechnungen(
ID Integer, RECHNNR integer, KundenID Integer, Datum Date ); create table RechnungsDaten( ID Integer, ID_Rechnungen integer, /* erhält Wert von der ID aus table Rechnungen */ AusleihID Integer ); |
Re: SELECT-Statement innerhalb eines Triggers
Hallo,
der einzige saubere Weg ist ein unique Index. Das Problem der Trigger ist, sioe laufen im Kontext der aktuellen Transaktion. Falls also "zeitgleich" zwei Datensätze eingetragen werden, sind die wieder doppelt drin. Das läßt sich zwar etwas über Transaktions-Modi steuern (readcommitted), aber warum erst rumärgern ? Was heisst "die IB-Controls zeigen eine Exception an". ?? Starte das Programm doch mal ohne die IDE. Heiko |
Re: SELECT-Statement innerhalb eines Triggers
Zitat:
Frage 2 : eine Transaktion läuft immer, sonst geht sowieso nichts. Der Trigger ändert daran nichts. Der Kontext kann commited werden und fertig oder eben Rollback. Einzige Ausnahme : Generatoren. Diese Tatsache fiel hier letztens noch unter den Tisch. 8) Frage 3 : zeitgleich ? Unter MGA ? :shock: Wie soll das gehen ? |
Alle Zeitangaben in WEZ +1. Es ist jetzt 10:30 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz