Trigger als Sequence mit eigenem "Kriterium"?

Hallo,
ich weiss gerade nicht genau wie ich die Überschrift besser nennen sollte.
Ich versuche mal zu erklären was ich versuche zu erreichen. Eigentlich ganz einfach, nur werd ichs wohl wieder unheimlich umständlich erklären.

Ich brauche in einer Tabelle einen Trigger der wie eine Sequenz arbeitet.
Dieser Trigger soll vor dem Speichern ausgelöst werden, und mir einen Werte in dem neuen Datensatz eintragen. Dieser Werte ergibt sich aus der Anzahl der vorhandenen Datensätze + 1.

Beispiel: Ich habe zwei Tabellen. Kunde und Transaktionen. Der Kunde wird über kunde_id in der Transaktionen Tabelle referenziert. Sobald jetzt eine neue Transaktion angelegt wird, soll der Trigger mein “Zählfeld” auf “Anzahl der Transaktoinen dieses Kunden” + 1 setzen. Das Ganze soll, bzw. muss aber dann auch so sein, dass der nächste Datensatz die nächst höhere Nummer bekommt. Also dass wenn 3 Anfragen zur gleichen Zeit ankommen, darf keine dieser drei Anfragen den gleichen Wert des Inkrements erhalten. Prinzipiell so wie eine Sequenz es auf ein Feld macht, aber eben nicht einfach um eins hochzählen, sondern eben in Abhängigkeit der vorhandenen Datensätze.

Aufjedenfall steh ich da auf dem Schlauch wie ich das realisieren kann. Besonders das Sicherstellen dass nicht zwei Datensätze den gleichen Wert erhalten will mir gerade nicht so recht in den Kopf. Vielleicht gibts das ja auch schon von Haus aus, nur ich weis es mal wieder nicht. Wäre da für ein paar Hilfestellung oder Ideen immens dankbar. :slight_smile:

Gruß und Danke

Warum so umständlich? Du willst wissen, wieviel Transaktionen pro Kunde getätigt wurden. Entweder du zählst das starr in einer table und hast dann Probleme mit Mehrfachzugriff, Update und Delete von Datensätzen etc. oder machst einfach einen View:

test=# create table kunde (id serial primary key, name text);
NOTICE:  CREATE TABLE will create implicit sequence "kunde_id_seq" for serial column "kunde.id"
NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "kunde_pkey" for table "kunde"
CREATE TABLE
test=*# create table kunde_tx (kunde_id int references kunde(id), ts timestamp);
CREATE TABLE
test=# create view kunde_view as select a.id, a.name, count(b) from kunde a left join kunde_tx b on(a.id=b.kunde_id) group by id, name;
CREATE VIEW

-- einige inserts

test=# select * from kunde_view ;
 id | name | count
----+------+-------
  1 | ich  |     2
  2 | du   |     1
  3 | er   |     0
(3 rows)

test=*# select * from kunde_tx ;
 kunde_id |             ts
----------+----------------------------
        1 | 2007-07-17 15:44:06.156817
        1 | 2007-07-17 15:44:10.522831
        2 | 2007-07-17 15:44:15.178443



Beispiel: Ich habe zwei Tabellen. Kunde und Transaktionen. Der Kunde wird über kunde_id in der Transaktionen Tabelle referenziert. Sobald jetzt eine neue Transaktion angelegt wird, soll der Trigger mein “Zählfeld” auf “Anzahl der Transaktoinen dieses Kunden” + 1 setzen. Das Ganze soll, bzw. muss aber dann auch so sein, dass der nächste Datensatz die nächst höhere Nummer bekommt. Also dass wenn 3 Anfragen zur gleichen Zeit ankommen, darf keine dieser drei Anfragen den gleichen Wert des Inkrements erhalten. Prinzipiell so wie eine Sequenz es auf ein Feld macht, aber eben nicht einfach um eins hochzählen, sondern eben in Abhängigkeit der vorhandenen Datensätze.

Vermutlich wirst Du dann mit ‘select for update’ arbeiten müssen, um eine Sperre auf den Kundendatensatz zu machen.


Andreas

Warum so umständlich? Du willst wissen, wieviel Transaktionen pro Kunde getätigt wurden. Entweder du zählst das starr in einer table und hast dann Probleme mit Mehrfachzugriff, Update und Delete von Datensätzen etc. oder machst einfach einen View

Hast du wohl recht. Wohl wieder zu umständlich gedacht. Werde es jetzt wohl so machen dass ich aus meiner Anwendung (RAILS) einfach wie du sagst “starr” nach oben zähle. Falls es dann mal vorkommen sollte dass es nicht klappen sollte, fange ich die Exception ab und versuche es einfach solange mit einem neuen Wert bis es funktioniert. Mit Abbruchbedingung versteht sich. :wink: Sollte dann auf diesem Wege über einen unique index machbar sein. Wird denke ich sowieso in 1 von 10000 Fällen mal soweit kommen. Dann sollte das auch so in der Anwendung handlebar sein.

Dachte halt nur es gäbe sowas evtl. schon “fertig” in pgsql.

Wäre eigentlich ein anderer Weg pro Kunde eine Sequenz zu haben, und diese dann anzusprechen “machbar” oder wäre das eine Vergewaltigung der DB? Weil über ne Sequenz hat man das Problem mit der Doppelvergabe ja nicht soweit ich weiss. Da diese ja wirklich pro Anfrage generiert wird und dann als “burned” nicht mehr zur Verfügung steht. Nur mal so ein Gedanke am Rande.

Aufjedenfall Danke für die fixe Antwort. :slight_smile:

Trigger, bei der Einfügen eines neuen Kunden eine Sequence erstellt und ein Trigger, der bei jeder Aktion des Kunden diese via nextval() erhöht. Aber damit hättest Du vermutlich einen nicht unerheblichen Aufwand (bei vielen Kunden) für die Verwaltung (Katalogtabellen).

Andreas

Jep, der Overhead bzw. Aufwand würde aufjedenfall deutlich steigen. Da es sich aber um momentan kleine bzw. überschaubare Anzahlen handelt wäre das dann ja evtl. auch ein Weg. Aber wie gesagt, werds erstmal per “starrem” Hochzählen umsetzen. Sollte passen.

Gruß

Daniel