[Informatonen und eine Frage] Trigger und so

Kampfgummibaerlie

Datenbank-Guru
Beiträge
728
Ich verlinke hier auf ein anderes Forum, weil ich glaube, auch dieses nur zwecks Informationsaustausch gut ist, und weniger zwecks kommerziellen Nutzen ;) (Und ich werde hier bleiben :D)

[Erledigt] trigger - wert von einer Tabelle in eine andere eintragen. - php.de

Ich zitiere hier ein schnell abgeschlossener Code von unserem "Mr. Elephant" (Akretschmer)


Hier ein relativ einfacher Trigger, welcher aber seinen Zweck erfüllt (Von Akretschmer geschrieben) ;)

Code:
test=# create table t1 (id int, val int);
CREATE TABLE
test=*# create table t2 (id int, val int);
CREATE TABLE
test=*# create or replace function t1_2_t2() returns trigger as $$begin insert into t2 values(new.id, new.val); return new; end;$$language plpgsql;
CREATE FUNCTION
test=*# create trigger trg1 after insert on t1 for each row execute procedure t1_2_t2();
CREATE TRIGGER
test=*# insert into t1 values (1,10);
INSERT 0 1
test=*# select * from t2;
id | val
----+-----
1 | 10
(1 row)

Musste am Anfang nachdenken, was es bringen würde, einen Trigger zu machen, dann werte in eine Tabelle einfügen, und die Tabelle abzurufen, von daher:
Es sind 2 verschiedene Tabellen ;) (Man fügt in t1 ein, und es werden die Werte (in diesem Fall 1:1) in de t2 ein)

Und zum Schluss kommt meine Frage:
Habe ich mir beinahe schon selbst beantwortet, aber zur Sicherheit frage ich auch noch nach:
Ist es möglich, wenn ich nur die ID ändere, dass sich >alle< (x) andere Werte so verändern, dass sie den Werten in der anderen Tabelle entsprechen? Oder ist das automatisch so?

Ich kenne folgenden Code, welchen ich nutze:

Code:
ALTER TABLE vermietungen ADD CONSTRAINT Maschinen_Synchen FOREIGN KEY (maschinen_id) REFERENCES maschinen (maschinen_id) ON UPDATE CASCADE ON DELETE RESTRICT;

Werde gleich mal probieren, und hier (15 Minuten kann man editieren, das sollte sich ausgehen) das Resultat meiner Versuche reineditieren, oder im nächsten Post schreiben ;)

Denke ich, funktioniert, weil in dem oben stehendem Trigger von Akretschmer ist ja "nur" ein insert-trigger, sprich on update tut der nix ^^
 
Werbung:
Ich hätte bezüglich der Trigger-Geschichte eine Frage:

Ich würde gerne regeln, dass sich eine eingetragene Mietung "automatisch" löscht, sobald der Kunde nach 15 Minuten nach der eigentlichen Miete nicht eintrifft. (Damit ein und dieselbe Maschine spätestens dann wo anders vermietet werden kann)

Kann man einen Trigger irgendwie alle 5 Minuten automatisch zünden? Ich glaube, Google hat die Antwort, aber ich stelle die Frage hier, damt sich, falls eine Antwort gefunden wird, auch andere die Information raussuchen könnten ;)

LG: der Baer :X

EDIT: Muss wohl immer before new insert sowas zünden ;)
 
Zuletzt bearbeitet:
Man kann bei UPDATE und DELETE über den Foreign Key die Änderungen weiter reichen, ich denke mal das hast du erfolgreich getestet? Der Trigger kopiert Daten, die sind natürlich von der Kaskade nicht betroffen, man kann natürlich hier auch wieder einen Trigger ON DELETE schreiben der auch das nachführt.

Trigger in Intervallen feuern geht meines Wissens nach auch bei PG nicht. Natürlich kann man einen Task anlegen der SQL Code ausführt, das sollte auch bei PG gehen. Ich mache das unter Windows mit MSSQL...
 
Meine Überlegung, die ich zurzeit habe, wäre ein Trigger, welcher ausgelöst werden würde, before inisert on ... und prüft, ob die maschine, die gemietet werden will, seit mehr als 15 Minuten frei ist (sprich der vorherige Kunde damit abgeschlossen hat).

Daweil gehe ich einen umständlicheren Weg, indem ich einfach den Query Abfrage, und als Parameter die gewollte ID angebe, wo der Kunde eben nicht kommt. Habe sie noch nie gebraucht, habe aber jede Menge spaß am Ganzen ;)

Ich weiß, du kennst dich bei Postgres nicht wirklich aus, da die Anwendung fehlt, denke ich, aber was wäre deine Idee, wie ich einen entsprechenden Trigger einbauen könnte, der before insert prüft, ob der andere bereits über 15 Minuten zu spät ist?
Ich glaube, da müsste ich extra eine Function bauen, die als Parameter eben die Maschinen_ID hat, die gemietet werden will, und schaut, ob die "Verspätung" bereits über 15 Minuten her ist.

Sitze, wie ach so oft, am Tatort ;) (Heute sollen 2 Leute kommen (stehen bereits in der Datenbank))

Wäre sehr dankbar für hilfreiche Ideen, und ich google dann, obs eure Lösungsmöglichkeit auch unter Postgres gäbe ;)

Soweit funkt es (glaube ich) auch ersteinmal, brauche nurnoch eine Function dafür:
Code:
select v_maschinen_id from vermietungen where lower(mietzeit) > now()::timestamp+'0.25 Hour' AND date(lower(mietzeit)) = current_date limit 1
 
Zuletzt bearbeitet:
Ich würde die Datensätze gar nicht löschen sondern beim Select oder über eine View alles ausblenden was die gewünschte Zeit überschritten hat.

Der Datensatz kann sicherlich irgendwann sinnvoll bereinigt werden aber vielleicht will man ja auch nach 16 Minuten noch nachvollziehen können ob es ihn gab oder nicht.
 
also ein Trigger, der die Mietung "beendet" (habe eine Funktion, die die Mietung beendet, indem sie der Range-Spalte den Upper-Wert gibt, und ab diesem Zeitpunkt die Mietung beendet ist.

nur, wieviel Minuten sollte man tollerieren, dass ein Kunde kommt, bevor man jemand anders zu der Maschine lassen würde?
anbei, glaube ich, wäre ich jetzt wieder am Punkt, dass ich alle X Minuten die Function ausführen möchte, was jedoch offenbar nicht möglich ist.

Aber ja, ich könnte einfach die Function zünden, before insert, und er damit die Miete "beendet" und die neue eben einträgt, weil die alte "beendet" ist, weil zuviel Zeit um ist.

Hätte mir nie gedacht, dass es so hart kompliziert werden kann, aber ja, meinte meine Schwester eh ^^

Narf, ist aber quasi blöd, weil dann die Leute ja "nur" 15 Minuten mieten könnten, was ich aber nicht wirklich möchte.
Mir wäre jetzt eingefallen, eine Function setzen (habe eh schon eine, die das lower(range) auf den momentanen Zeitpunkt setzt, welches aber noch dazu ein Boolean-Feld auf "True" setzt, und so weter.
 
Zuletzt bearbeitet:
Also das eine hat mit dem anderen nicht viel zu tun.

Problem A:
Du hast eine "Funktion" (nicht im Sinne von Function) in deiner Datenbank bei der ein Datensatz seine Gültigkeit verliert. Das ist ja nichts ungewöhnliches, der Datensatz darf dann nicht mehr angezeigt oder verwendet werden oder was auch immer. Jetzt liegt es vielleicht nahe immer und immer wieder eine Prozedur zu starten die dafür sorgt das die Daten irgendwie ausgesondert werden aber das ist natürlich in jedem Fall nicht sehr elegant. Es verursacht jedes mal Rechenaufwand, Schreibaufwand, und es wird nie ideal funktionieren. Daher ist es auch gut das eine DB einem so eine Lösung gar nicht erst aufdrängt. Du kannst das Problem gut mit einer View lösen...

Problem B:
Du gehst davon aus das du den Datensatz löschen musst um das Mietobjekt frei zu geben. Das kann man natürlich auch ganz anders gestalten, in dem man z.B. eine Liste mit "freien" Mietobjekten generiert bei der Mietungen die nicht statt gefunden haben entsprechend mit angezeigt werden.

Liste_verfügbarer_Objekte:
Objekt A | frei
Objekt B | gebucht am 01.01.2017, überfällig seit 16 Minuten
Jetzt kann man Objekt B neu verleihen, warum nicht. Es ist alles eine Frage der Gestaltung der Aplikation und, wenn man Constraints hat die Überschneidungen verhindern sollen, eine Frage der Anpassung eben solcher.

Ich verstehe auch nicht ganz deinen Drang alles per Funktion zu lösen, tuts nicht auch eine View?
 
Wie könnte ich das per View lösen? ginge natürlich auch ^^
Ich habe versucht mittels einer Function diese zu selecten, bisher nicht wirklich glücklich :(

Ich will sogar (!) die Maschinen mit den Dates of Timestamps joinen, und schauen, dass jede Maschine zu ein jedem Datum nur einmal vermietet werden kann. (Also, probiere ich gerade ^^)
 
Pseudo Code
Code:
CREATE VIEW tolle_view AS SELECT m.* FROM maschinen m WHERE NOT EXISTS ( SELECT 1 FROM vermietungen v WHERE m.id = v.maschinen_id AND getdate() BETWEEN v.von AND v.bis AND v.wurde_ausgegeben = 1 )
Ich gucke zu welcher Maschine es laufende Vermietungen gibt und setze voraus das eine Ausgabe statt gefunden hat. Das ist jetzt aber nur so dahin gewurschtelt, es gibt 100 Wege das schön darzustellen. Kommt drauf an welche Infos man haben will.
 
except denke ich ist hier der Schlüssel ;)

Code:
select maschinen_id from maschinen
except
select v_maschinen_id from vermietungen

ich habe 7 Maschinen in der Tabelle Maschinen, und habe, nur mal auf die schnelle, nur Maschine 1 vermietet, das Resultat ist hier 2, 3, 4, 5, 6 und 7

EDIT 1:

Hier auch die Function dazu:
Code:
create function freie_maschine (x integer) returns integer as 'select maschinen_id from maschinen except select v_maschinen_id from vermietungen' Language sql

Bin ich am richtigen Weg einer Datenbank-Erstellung? Ich habe im März angefangen, hier zu regergieren, war auch vorher nicht zwangshaft der SQL-Profi schlechthin, und finde, dass es gut läuft ;)

EDIT 2:

warum ich in diesem Fall nur einen Integer returne? Weil ich ehrlich gesagt vor hätte, dass ich das Ganze mit einer anderen Function verknüpfe ;)
 
Zuletzt bearbeitet:
Werbung:
sodala, hatte kurz das Problem, dass er Null inserted hat, aber gelöst, habe einfach die entsprechende Spalte NOT NULL gesetzt ;)

Ich denke, ich muss jetzt noch eine Funktion bauen, die 2 Parameter hat, 1 Timestamp und eben die maschinen_id......

Ich habe endlich wieder richtig Spaß am Ganzen :D
es ist so verdammt einfach, und ich humpel 4 extra Runden herum ^^

EDIT: 4 sind nur eine Annahme :X
 
Zuletzt bearbeitet:
Zurück
Oben