Anzeige:
Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 15 von 16

Thema: [PostgesSQL] Sequenzen

  1. #1
    Registrierter Benutzer
    Registriert seit
    21.07.2000
    Ort
    Österreich
    Beiträge
    189

    [PostgesSQL] Sequenzen

    ich arbeite zu zeit an einer datenbank zur rechnungsverwaltung.

    ich habe eine tabelle in der alle rechnungen gespeichert werden. jede rechnung ist eindeutig durch eine rechnungsnummer die mit hilfe einer sequenz automatisch erhöht wird.
    dann hab ich noch eine 2. tabelle in der die einzelen sätze der rechnung drinnen sind. nun hab ich die möglichkeit jeden satzt durch eine "satznummer" mit hilfe einer sequenz eindeutig zu machen. das problem dabei ist dass diese satznummern dann sehr schnell wachsen (da nicht bei jeder rechnung von null begonnen wird).
    die lösung die ich bevorzugen würde wäre die einzelen sätze durch kombination der rechnungsnumm und der satznummer eindeutig zu machen. also dass ein z.b. eine rechnungsnummer 1234 habe und zu der die sätze 0, 1, 2, 3, ... und dann die rechnungsnummer 1235 wieder mit den sätzen 0, 1, 2, 3, ...
    gibt es da eine möglichkeit diese satznummer automatisch von postgresql erhöhen zu lassen. also ich sage ich will einen satz in die rechnung 1234 einfügen, und die DB weist dann automatisch die nächst höhere satznummer zu?

    ich hoffe das war jetzt nicht zu verwirrend ...

  2. #2
    Registrierter Benutzer
    Registriert seit
    02.08.2001
    Beiträge
    57
    Moin,

    ist ein Versuch, aber funktioniert es nicht, wenn du sowohl die Rechnungsnummer, als auch die Satznummer als Primärschlüssel deklarierst?

    Sonst mach es per Hand (Programm)

  3. #3
    Registrierter Benutzer
    Registriert seit
    21.07.2000
    Ort
    Österreich
    Beiträge
    189
    ja, dass müsste ich in meinem 2. (bevorzugten) fall ja sowieso machen. aber das behebt ja nicht das problem mit dem zählen.

  4. #4
    Registrierter Benutzer Avatar von elrond
    Registriert seit
    04.10.2001
    Ort
    potsdam
    Beiträge
    881
    wenn du keine eindeutige ID aus einer sequenz willst, würde ich manuell hochzählen:

    select max(satznummer)+1 as insertsatznr from rechnungssatz where rechnungsnr="12345"

    damit kannst du einen PK über Rechnungsnummer+Satznummer erzeugen und hast den gewünschten Zustand...
    "Um die Welt zu ruinieren, genügt es, wenn jeder seine Pflicht tut." (Winston Churchill)

  5. #5
    Registrierter Benutzer
    Registriert seit
    02.08.2001
    Beiträge
    57
    wenn du keine eindeutige ID aus einer sequenz willst, würde ich manuell hochzählen:
    Du meinst, ein zusätzliches Feld (Typ Sequenz), das jeden Datensatz eindeutig macht?
    Der Art
    tabelle_rechnungssatz = ({neuesFeld, rechnungsnr., satznr.}, {neuesFeld}) ?
    Primärschlüssel: neuesFeld

    Ist IMHO überflüssig, da die Kombination rechnungsnr.+satznr. schon eindeutig ist. Ich (jeder so wie er/sie/es will) würde das manuelle Zählen machen. Um nicht jedes mal nach max() fragen zu müssen (Performance) 'n Zähler im Programm halten, der das macht...

    MfG

  6. #6
    Registrierter Benutzer Avatar von elrond
    Registriert seit
    04.10.2001
    Ort
    potsdam
    Beiträge
    881
    ich weiß ja nicht, wieviele tausend Rechnungsätze Du in der Minute schreiben willst... Ich habe mit dieser Konstruktion noch nie Performanceprobleme gehabt, trotz der max() abfrage. Da die rechnungsnummer ein teil des PK ist, sollte das selbst bei großen Datenmengen keine Probleme bereiten.

    -allerdings habe ich mit postgresql noch nicht gearbeitet, so daß ich nichts über die Performance des DBMS sagen kann--
    "Um die Welt zu ruinieren, genügt es, wenn jeder seine Pflicht tut." (Winston Churchill)

  7. #7
    Registrierter Benutzer
    Registriert seit
    22.06.1999
    Beiträge
    677
    Das Problem mit dem "select max(feld)+1" ist nicht Performance sondern, dass das Ergebnis nicht eindeutig ist, wenn diese Abfrage mehrere Leute gleichzeitig machen.

    Wenn Du aber weisst, dass dieselbe Rechnung nur von einem Benutzer gleichzeitig bearbeitet werden kann, dann sehe ich in dem Verfahren kein Problem.

    Ansonsten hilft Dir eine Sequence nicht weiter, aber vielleicht ein vorheriges Sperren des Hauptrechnungssatzes mit SELECT FOR UPDATE.

  8. #8
    Registrierter Benutzer Avatar von elrond
    Registriert seit
    04.10.2001
    Ort
    potsdam
    Beiträge
    881
    Das Problem mit dem "select max(feld)+1" ist nicht Performance sondern, dass das Ergebnis nicht eindeutig ist, wenn diese Abfrage mehrere Leute gleichzeitig machen.
    Da hast du natürlich recht. Um die Eindeutigkeit der Wertes sicherzustellen, ist es notwendig konkurierende Zugriffe zu verhindern.

    Ansonsten hilft Dir eine Sequence nicht weiter,....
    Theoretisch ist es möglich für jede Rechnungsnummer eine eigene Sequenz zu erzeugen. Ich weiß wie gesagt nicht wie das bei pg läuft mit den Sequenzes...

    Afaik kann ich in einer Oracle-DB einfach eine Sqz. mit beliebigem Namen erzeugen und dann abfragen. Ob das beliebig viele werden können, und wie Oracle das verwaltet weiß ich allerdings nicht..
    Geändert von elrond (05-09-2003 um 12:21 Uhr)
    "Um die Welt zu ruinieren, genügt es, wenn jeder seine Pflicht tut." (Winston Churchill)

  9. #9
    Registrierter Benutzer
    Registriert seit
    02.08.2001
    Beiträge
    57
    Original geschrieben von elrond
    ich weiß ja nicht, wieviele tausend Rechnungsätze Du in der Minute schreiben willst... Ich habe mit dieser Konstruktion noch nie Performanceprobleme gehabt, trotz der max() abfrage.
    Ich glaube auch nicht, daß max() langsam wird. Aber mein Programm müßte für 1 Update/ Insert 2 Anfragen machen, das dauert mir (bei meinem Problem) zu lange.

  10. #10
    Registrierter Benutzer
    Registriert seit
    21.07.2000
    Ort
    Österreich
    Beiträge
    189
    Original geschrieben von Christoph
    Das Problem mit dem "select max(feld)+1" ist nicht Performance sondern, dass das Ergebnis nicht eindeutig ist, wenn diese Abfrage mehrere Leute gleichzeitig machen.
    also das sind meine ersten erfahrungen mit datenbanken darum frag ich sicherheitshalb nochmals nach:

    wenn ich vor der abfrage "select max(feld)+1" eine transaction starte und nach dem einfügen des neuen datensatzes commite sollte das ja kein problem sein, und es sollte jeder seinen eindeutigen satz bekommen!?.

  11. #11
    Registrierter Benutzer
    Registriert seit
    22.06.1999
    Beiträge
    677
    Original geschrieben von Alex_K
    wenn ich vor der abfrage "select max(feld)+1" eine transaction starte und nach dem einfügen des neuen datensatzes commite sollte das ja kein problem sein, und es sollte jeder seinen eindeutigen satz bekommen!?.
    Nein! Denn konkurrierende SELECTS werden von verschiedenen Transaktionen ungehindert zugelassen. Wenn Du das verhindern willst, musst Du SELECT FOR UPDATE verwenden (am besten auf den übergeordneten Rechnungssatz. Das zweite SELECT FOR UPDATE wird dann blockieren, bzw. im Fall von einem Deadlock (Postgres erkennt die glaube ich automatisch) mit einem Fehler ("Deadlock detected") zurückgewiesen (Deshalb: Fehlercode immer abfragen!).

  12. #12
    Registrierter Benutzer
    Registriert seit
    21.07.2000
    Ort
    Österreich
    Beiträge
    189
    gut, dann hab ich nochmals eine frage zu "select for update":

    da in meinem PostgreSQL buch und in meinem SQL buch nichts über den select for update befehl zu finden ist habe ich die online doku zu postgesql miteibezogen. in der steht "The lock is held until the transaction commits or rolls back." heißt dass nun wenn ich ein select for update mache wird auch automatisch eine transaktion gestarte? oder muss ich select for update anfragen immer in transaktionen packen?
    Geändert von Alex_K (10-09-2003 um 08:43 Uhr)

  13. #13
    Registrierter Benutzer
    Registriert seit
    22.06.1999
    Beiträge
    677
    Original geschrieben von Alex_K
    Heißt dass nun wenn ich ein select for update mache wird auch automatisch eine transaktion gestarte? oder muss ich select for update anfragen immer in transaktionen packen?
    Laut SQL2-Standard beginnt ein SELECT automatisch eine Transaktion, die bis zum nächsten COMMIT/ROLLBACK dauert.

    Außer Oracle hält sich aber meines Wissens keine Datenbank an diese Vorgabe, so dass Du bei PostgreSQL die Transaktion zuvor mit BEGIN starten musst.

  14. #14
    Registrierter Benutzer
    Registriert seit
    21.07.2000
    Ort
    Österreich
    Beiträge
    189
    ich hab das mit dem select for update mal versucht, und bin auf folgendes problem gestoßen:

    wenn ich jetzt das programm starte, und einen neuen satz einfüge mache ich ein select for update auf alle sätze einer bestimmten rechungsnummer. ich wollte erst dann das commit/rollback machen nachdem der benutzer den datensatz fertig eingegeben hat.
    wenn nun aber ein 2. bentzer auf diese datensätze zugreifen will gibt die datenbank keine rückmeldung in der richtung dass die datzensätze gesperrt sind, sondern sie reagiert einfach nicht bis das select for update von 1. benutzer ein commit/rollback erhalten hat. was nun zu folge hat dass beim 2. bentzer das programm einige zeit hängt, oder er ein timeout bekommt.

    nun meine frage: gibt es eine möglichkeit dass zu umgehen (möglicherweise ein konfigurationsproblem der DB)?

  15. #15
    Registrierter Benutzer
    Registriert seit
    21.07.2000
    Ort
    Österreich
    Beiträge
    189
    hast sich erledigt, ich habs nun anderes gelöst (erst alle eingaben machen, dann erst sperren und einfügen, somit sind die reihen immer nur für minimale zeiten gesperrt).

Lesezeichen

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •