Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi SELECT-Statement innerhalb eines Triggers (https://www.delphipraxis.net/78084-select-statement-innerhalb-eines-triggers.html)

EnORItZ 28. Sep 2006 19:42

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:
create table Rechnungen(
   RechnungsID   Integer,
   KundenID   Integer,
   Datum      Date
);

create table RechnungsDaten(
   RechnungsID   Integer,
   AusleihID   Integer
);
Ü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:
SQL-Code:
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;
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).

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.

mkinzler 28. Sep 2006 19:45

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.

EnORItZ 28. Sep 2006 19:53

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:
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;
@mkinzler:
Wie kann ich denn den neuen Eintrag verhindern?
Und wie läuft das mit dem Schlüssel?

mkinzler 28. Sep 2006 19:55

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.

Hansa 29. Sep 2006 01:28

Re: SELECT-Statement innerhalb eines Triggers
 
Was ist das :

Zitat:

Zitat von EnORItZ
Hallo Leute.

Ich versuche gerade in meiner Rechnungsdaten-Tabelle doppelte eingaben eines Artikels zu vermeiden.

Die Tabelle sieht quasi so aus:
SQL-Code:
create table Rechnungen(
   RechnungsID   Integer,
   KundenID   Integer,
   Datum      Date
);

create table RechnungsDaten(
   RechnungsID   Integer,
   AusleihID   Integer
);

Ist RechnungsID quasi die ID des Datensatzes der Table ? Hängen die Tabellen voneinander ab ? Falls ja : wo ist dann der Verweis von einer Tabelle auf die andere ? Gehe doch systematischer vor : vergeb zunächst mal eine ID, egal für welche Tabelle. Hängt die Tabelle von einer anderenn ab, dann kriegt die eben noch eine die für den Verweis zuständig ist. Glaskugel meint so etwas :

SQL-Code:
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
);
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.

hoika 29. Sep 2006 15:05

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

Hansa 29. Sep 2006 18:38

Re: SELECT-Statement innerhalb eines Triggers
 
Zitat:

Zitat von hoika
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.

Frage 1 : was nützt ein unique Index ? Meine Frage vorher zielt auf das ab : kann man den überhaupt so zusammenbauen ? Wo ist die Referenz ? Ist der so überhaupt unique zu machen ?

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 00:18 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz