AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Datenbanken Letzte vergebene Nummer speichern
Thema durchsuchen
Ansicht
Themen-Optionen

Letzte vergebene Nummer speichern

Ein Thema von BlueStarHH · begonnen am 3. Aug 2022 · letzter Beitrag vom 7. Aug 2022
Antwort Antwort
Seite 1 von 4  1 23     Letzte »    
BlueStarHH

Registriert seit: 28. Mär 2005
Ort: Hamburg
849 Beiträge
 
Delphi 11 Alexandria
 
#1

Letzte vergebene Nummer speichern

  Alt 3. Aug 2022, 21:38
Datenbank: Firebird • Version: 3.x • Zugriff über: IBDAC
Hallo,

ich erzeuge mit einer StoredProcedure eine Art eindeutige ID. Die StoredProcedure kann natürlich von mehreren Benutzern aufgerufen werden. Ich möchte nun immer nur die zuletzt erzeugte ID in einer Tabelle speichern. Es ist keine simple Zahl. Wenn man eine Liste der IDs hat, kann man keine Reihenfolge und damit auch nicht die letzt ID erkennen.

Wenn es Delphi-Code wäre, würde ich die ID-Erzeugung mit einer CriticalSection schützen und dort einfach vor dem Verlassen der CriticalSection die ID in die Tabelle schreiben.

Doch wie mache ich das in einer Firebird StoredProcedure? Dort gibt es meines Wissens nach keine CriticalSections oder doch?
  Mit Zitat antworten Zitat
Papaschlumpf73
Online

Registriert seit: 3. Mär 2014
Ort: Berlin
436 Beiträge
 
Delphi 12 Athens
 
#2

AW: Letzte vergebene Nummer speichern

  Alt 3. Aug 2022, 21:59
Die StoredProcedure könnte "deine" ID in einer Tabelle anfügen. Diese Tabelle hat neben dieser ID-Spalte noch eine normale ID-Spalte, in der ein Integer hochgezählt wird. Die Zeile mit dem höchsten "normalen" ID-Wert enthält dann jeweils deine zuletzt erzeugte "eigene" ID. Alternativ könnte die Tabelle auch ein TimeStamp-Feld enthalten. Alle Datensätze mit einer kleineren ID oder einem kleineren TimeStamp könnten dann immer gelöscht werden, so dass nur der zuletzt erzeugte Datensatz übrig bleibt.
  Mit Zitat antworten Zitat
BlueStarHH

Registriert seit: 28. Mär 2005
Ort: Hamburg
849 Beiträge
 
Delphi 11 Alexandria
 
#3

AW: Letzte vergebene Nummer speichern

  Alt 3. Aug 2022, 22:06
Die StoredProcedure könnte "deine" ID in einer Tabelle anfügen. Diese Tabelle hat neben dieser ID-Spalte noch eine normale ID-Spalte, in der ein Integer hochgezählt wird. Die Zeile mit dem höchsten "normalen" ID-Wert enthält dann jeweils deine zuletzt erzeugte "eigene" ID. Alternativ könnte die Tabelle auch ein TimeStamp-Feld enthalten. Alle Datensätze mit einer kleineren ID oder einem kleineren TimeStamp könnten dann immer gelöscht werden, so dass nur der zuletzt erzeugte Datensatz übrig bleibt.
Beides funktioniert im Mehrbenutzerzugriff nicht. Dazu müsste es in der StoredProcedure eine CriticalSection geben. Denn sonst:
Benutzer A hat als erster die ID erzeugt, aber die StoredProcedure noch nicht verlassen. Bei Benutzer B, der nach Benutzer A die StoredProcedure startet ist sie schon durchlaufen und würde dann die ID von B als letzte ID eintragen. Danach würde die ID von A eingetragen werden.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.071 Beiträge
 
Delphi 12 Athens
 
#4

AW: Letzte vergebene Nummer speichern

  Alt 3. Aug 2022, 22:09
Zitat:
Dort gibt es meines Wissens nach keine CriticalSections oder doch?
Eigentlich doch.

Wenn du in eine Tabelle/Feld rein schreibst, dann wird dieser Record/Tabelle/Speicherseite gesperrt und kein Anderer kann reinschreiben.
Er kommt erst ebdgültig dazu, wenn die aktuelle Schreibaktion/Query beendet ist.

Du kannst also den Wert einfach reinschreiben und, wenn gewünscht, den zuletzt aktuellen Wert auch auslesen, ohne das zwischendrin ein Anderer schreiben kann.




Aber wie Vorgänger bereits sagte,
das Erstellen/Generieren kann glechzeitig passieren und dann kommt es drauf an, wer zuerst zum Speichern kommt ... dort könnte sich die Erstellungsreihenfolge umdrehen und dann der Erste zuletzt speichern.

Besser ist es, wenn du auf einen Generator des DBMS zugreifst.

Oder eben wie von Papaschlumpf73 genannt : nicht "die ID speichern", sondern ALLE und dann in der Tabelle ein Feld mit Generator (SERIAL) als Reihenfolge.



In manchen DBMS kann man Funktionen einer externen DLL oder Scriptes registrieren.
Da drin kannst du dann auch mit einer CriticalSection o.Ä. arbeiten.
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PoSex im Delphi viel seltener praktiziert.

Geändert von himitsu ( 3. Aug 2022 um 22:14 Uhr)
  Mit Zitat antworten Zitat
Papaschlumpf73
Online

Registriert seit: 3. Mär 2014
Ort: Berlin
436 Beiträge
 
Delphi 12 Athens
 
#5

AW: Letzte vergebene Nummer speichern

  Alt 3. Aug 2022, 22:12
Kannst du noch mal präzisieren, was du mit "zuletzt erzeugte ID" meinst? Die ID, die tatsächlich zuletzt erzeugt wurde, oder diejenige, deren Erzeugung zuletzt gestartet wurde?
  Mit Zitat antworten Zitat
Benutzerbild von MyRealName
MyRealName

Registriert seit: 19. Okt 2003
Ort: Heilbronn
675 Beiträge
 
Delphi 10.4 Sydney
 
#6

AW: Letzte vergebene Nummer speichern

  Alt 4. Aug 2022, 10:28
Warum nicht einfach einen Generator nutzen ? Der läuft ausserhalb von Transaktionen
  Mit Zitat antworten Zitat
BlueStarHH

Registriert seit: 28. Mär 2005
Ort: Hamburg
849 Beiträge
 
Delphi 11 Alexandria
 
#7

AW: Letzte vergebene Nummer speichern

  Alt 5. Aug 2022, 13:18
Warum nicht einfach einen Generator nutzen ? Der läuft ausserhalb von Transaktionen
Weil der Generator einfach eine Zahl erzeugt, kann ich ihn nicht nutzen. Ich brauche aber eine spezielle ID. Eine Art Seriennummer für einen Gegenstand.
  Mit Zitat antworten Zitat
BlueStarHH

Registriert seit: 28. Mär 2005
Ort: Hamburg
849 Beiträge
 
Delphi 11 Alexandria
 
#8

AW: Letzte vergebene Nummer speichern

  Alt 5. Aug 2022, 13:19
Kannst du noch mal präzisieren, was du mit "zuletzt erzeugte ID" meinst? Die ID, die tatsächlich zuletzt erzeugt wurde, oder diejenige, deren Erzeugung zuletzt gestartet wurde?
Danke für die Frage. Ich musste das selbst nochmal drüber nachdenken. Also ich versuche es nochmal deutlicher zu machen:

Die StoredProcedure, die die ID erzeugt sieht ungefähr so aus:

Code:
procedure GetNextID
  a := ErzeugePrefix;
 
  if Bedingung then
    b := gen_id(MeinGenerator, 1);
  else
    b := '';

  c := ErzeugeSuffix;

  result := a+b+c;
end;

Eine Reihenfolge von IDs wäre z.B.

XM07-001-Z
XM07-002-A
XM07-003-X
XM07-U
XM07-A
XM08-001-X
XM08-002-B
XM09-001-B
A444-5

Wenn dort keine fortlaufende Nummer enthalten ist, lässt sich nachträglich nur anhand der ID keine Reihenfolge mehr erkennen.

Der Generator wird nur unter einer bestimmten Bedingung genutzt, um in der Mitte der ID eine fortlaufende Nummer einzufügen. Im Mehrbenutzerzugriff brauche ich als letzte ID dann die ID, die den größten Generatorwert hat. Dafür darf auch keine Rolle spielen, welcher StoredProcedure-Aufruf zuerst aufgerufen worden ist oder durchgelaufen ist.
  Mit Zitat antworten Zitat
BlueStarHH

Registriert seit: 28. Mär 2005
Ort: Hamburg
849 Beiträge
 
Delphi 11 Alexandria
 
#9

AW: Letzte vergebene Nummer speichern

  Alt 5. Aug 2022, 13:24
Besser ist es, wenn du auf einen Generator des DBMS zugreifst.
Wie genau hilft das in meinem Fall?

Oder eben wie von Papaschlumpf73 genannt : nicht "die ID speichern", sondern ALLE und dann in der Tabelle ein Feld mit Generator (SERIAL) als Reihenfolge.
Hier wird dann die Reigefolge dadurch falsch festgelegt, wer zuerst in die Tabelle schreibt. Das muss nicht zwingend die Reihenfolge sein, in der die IDs erzeugt wurde.

In manchen DBMS kann man Funktionen einer externen DLL oder Scriptes registrieren.
Da drin kannst du dann auch mit einer CriticalSection o.Ä. arbeiten.
Ich komme wohl um eine CriticalSection nicht herum. Weiß jemand wie ich das mit einer DLL in Firebird lösen kann?

Geändert von BlueStarHH ( 5. Aug 2022 um 13:35 Uhr)
  Mit Zitat antworten Zitat
Delphi.Narium

Registriert seit: 27. Nov 2017
2.490 Beiträge
 
Delphi 7 Professional
 
#10

AW: Letzte vergebene Nummer speichern

  Alt 5. Aug 2022, 14:16
Du kannst einen Generator nutzen:

Dazu benötigst Du eine weitere Tabelle in der Form:
SQL-Code:
create Table LastID
(
  GeneratorID Integer not null,
  DeineID Integer not null -- oder welcher Type das auch immer sein mag.
);
Dazu einen Generator: CREATE GENERATOR GEN_LastID;

Und noch einen Trigger:
SQL-Code:
CREATE TRIGGER TR_LastID_BIU FOR LastID ACTIVE
BEFORE INSERT OR UPDATE POSITION 0
AS
BEGIN
  if ((NEW.GeneratorID is NULL)) then NEW.GeneratorID = Gen_ID(GEN_LastID, 1);
END^
Wenn Du eine neue ID erstellt hast, schreibst Du diese per Insert insert into LastID (DeineID) values (DerWertDerID); in diese Tabelle.

Willst Du nun die letzte Deiner IDs ermitteln, bekommst Du die per select first 1 DeineID from LastID order by GeneratorID desc;

Eventuell noch 'nen absteigenden Index auf die GeneratorID und regelmäßig nicht mehr benötigte Sätze aus der Tabelle LastID entfernen. Dazu könntest Du der Tabelle LastID ggfls. noch 'ne TimeStamp-Spalte gönnen und im Trigger diese mit CURRENT_TIMESTAMP befüllen, dann wird das Entfernen alter Sätze einfacher und Du kannst sogar nachvollziehen, in welcher Reihenfolge Deine IDs erstellt wurden.

Wäre das eventuell 'nen Versuch wert?
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 4  1 23     Letzte »    


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 13:48 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