Will Kunde A an Kunde B Geld überweisen, so sind 2 Buchungen nötig. Schlecht wäre es, wenn es zwischen den beiden Buchungen zu einem Stromausfall käme. Dafür verwenden wir also eine Transaktion, um diese beiden Buchungen in einer Einheit durchzuführen.
Wir schreiben einfach eine Funktion in der Sprache SQL. Alles innerhalb einer Funktion ist automatisch auch innerhalb einer Transaktion.
001 -- 002 -- Funktion, um automatisiert eine Buchung zu erstellen 003 -- 004 005 CREATE OR REPLACE FUNCTION transfer(von INT, nach INT, NUMERIC(10,2), TEXT varchar) RETURNS bool AS ' 006 -- Abbuchung bei Kunde 1 auslösen 007 INSERT INTO buchungen (kontonr, ts, typ, wert, text) VALUES ($1, NOW(), ''A'', $3, $4); 008 -- den Betrag bei Kunde 2 auf das Konto buchen 009 INSERT INTO buchungen (kontonr, ts, typ, wert, text) VALUES ($2, NOW(), ''Z'', $3, $4); 010 -- einen Rückgabewert für OK liefern 011 SELECT true; 012 ' LANGUAGE sql; 013 014 015 -- Tests 016 017 -- theoretisch haben wir kein Geld auf der Bank, da bisher kein Kunde 018 -- Geld erhalten hat. Jedoch haben einige Kunden einen Dispo erhalten 019 -- und können somit ihr Konto belasten 020 SELECT transfer ( (SELECT kontonr::INTEGER FROM kunden WHERE kundenname='Kunde 1'), 021 (SELECT kontonr::INTEGER FROM kunden WHERE kundenname='Kunde 2'), 022 100.00, 023 'Überweisung Nr. 1, Kunde 1 an Kunde 2'); 024 025 -- Kontoübersicht anschauen 026 SELECT * FROM saldeninfo( (SELECT kontonr::INTEGER FROM kunden WHERE kundenname='Kunde 1') ); 027 SELECT * FROM saldeninfo( (SELECT kontonr::INTEGER FROM kunden WHERE kundenname='Kunde 2') ); 028 029 -- Geld zurückschicken 030 SELECT transfer ( (SELECT kontonr::INTEGER FROM kunden WHERE kundenname='Kunde 2'), 031 (SELECT kontonr::INTEGER FROM kunden WHERE kundenname='Kunde 1'), 032 100.00, 033 'Überweisung Nr. 2, Kunde 2 an Kunde 1'); 034 035 -- Kontoübersicht anschauen 036 SELECT * FROM saldeninfo( (SELECT kontonr::INTEGER FROM kunden WHERE kundenname='Kunde 1') ); 037 SELECT * FROM saldeninfo( (SELECT kontonr::INTEGER FROM kunden WHERE kundenname='Kunde 2') ); 038 039 -- das Finanzamt sieht nur die Buchungen 040 SELECT * FROM view_buchungen; 041 042 -- versuchen wir, einmal den Dispo zu überziehen 043 SELECT transfer ( (SELECT kontonr::INTEGER FROM kunden WHERE kundenname='Kunde 5'), 044 (SELECT kontonr::INTEGER FROM kunden WHERE kundenname='Kunde 4'), 045 300.00, 046 'Überweisung Nr. 3, Kunde 5 an Kunde 4'); 047 SELECT * FROM saldeninfo( (SELECT kontonr::INTEGER FROM kunden WHERE kundenname='Kunde 5') ); 048 SELECT * FROM saldeninfo( (SELECT kontonr::INTEGER FROM kunden WHERE kundenname='Kunde 4') );Download transfer.sql
Was passiert, wenn wir erst bei B das Geld einzahlen, und dann erst bei A abziehen, und bei A kommt es zu einer Überziehung des Kontos? Nun, probieren wir es aus!