Seite 1 von 1

Nummernkreise automatisiert. [erledigt]

Verfasst: Fr, 02. Jun 2023 11:16
von Manfred
ich habe eine Kundendatei, in der es ein Feld gibt für Kundennummern. Dieses Feld soll jedesmal um 1 hochgezählt werden bei einem Insert. Es muß aber unterschieden werden in verschiedene Kategorien. Ist es die Kundenart "A", dann bitte aus dem Nummernkreis die nächsthöhere nehmen, ist es die Kundenart "B", dann bitte aus dem anderen Nummerkreis die nächsthöhere Nummer nehmen. usw. natürlich darf keine Nummer doppelt vergeben werden. Wie könnte man sowas elegant lösen? Wenn es nur 1 Kreis wäre, wäre es ja mit einem autoincrement zu lösen, aber bei verschiedenen Nummernkreisen? Schön wäre es, wenn der ADS es auch verwalten würde, das bei Parallelerfassungen keine Nummer doppelt vergeben wird.

Re: Nummernkreise automatisiert.

Verfasst: Fr, 02. Jun 2023 12:18
von nightcrawler
Hier aus meinen Trainings der Code zur Erstellung eines Generators. Die Werte für die Nummernkreise werden in einer Tabelle verwaltet. Bei Abruf wird Transaktionssicher der Wert um eins erhöht.

Code: Alles auswählen

CREATE FUNCTION gen_id(cname cichar(255))
  RETURNS integer
BEGIN
  declare @numrows integer;
  declare @nextid integer;
  declare @rv integer;
  --create generator table if not exists
  if not exists(select * from system.tables where name like 'tb_generator') then
    create table tb_generator(id autoinc, name cichar(255), lastid integer, rv rowversion);
  endif;
  --check if there's already a generator for that name
  MERGE tb_generator ON name LIKE cname
    WHEN NOT MATCHED THEN INSERT(name,lastid) VALUES(cname,0);
    --now update that record until you got it (concurrency!)
    @numrows=0;
    while @numrows=0 do
      @rv=(select rv from tb_generator where name like cname);
      @nextid=(select lastid+1 from tb_generator where name like cname);
      try
        update tb_generator set lastid=@nextid where name like cname and rv=@rv;
        --if there's no update, another user already updated that record
        @numrows=(select ::stmt.UpdateCount from system.iota);
      catch all
        @numrows=0;
      end try;
    end while;
  return @nextid;
END;
Verwendung:

Code: Alles auswählen

SELECT gen_id('test') FROM SYSTEM.IOTA;
Das kannst Du entweder direkt verwenden (im Insert) oder in einem Trigger. Als Text gibst Du den Nummernkreis an.

Edit: Falls es Dir bekannt vorkommt. Du hast auch am ADS Workshop in Willingen am 4.5.2017 teilgenommen. Einfach nochmals das Script lesen;)

Re: Nummernkreise automatisiert.

Verfasst: Fr, 02. Jun 2023 12:42
von Manfred
auh man,
jetzt hast Du ordentlich Salz in die Wunde gestreut. Meine Erinnerung daran sind etwas dünn. Ich habe auch keine Ahnung, wo das Script sein könnte. Hast Du das noch irgendwo?

Re: Nummernkreise automatisiert.

Verfasst: Fr, 02. Jun 2023 12:44
von nightcrawler
ja.

Re: Nummernkreise automatisiert.

Verfasst: Fr, 02. Jun 2023 14:18
von Tom
Manfred war in Willingen auch NUR AM FEIERN. Dass er sich überhaupt noch daran erinnert, mal dort gewesen zu sein, grenzt an ein Wunder. 8) Ich hätte ihm das Script aus dem Kopf aufschreiben können. :wink:

Re: Nummernkreise automatisiert.

Verfasst: Fr, 02. Jun 2023 14:34
von Manfred
:shock:

Re: Nummernkreise automatisiert.

Verfasst: Fr, 02. Jun 2023 15:12
von Tom
Das war natürlich nur ein Witz.

Re: Nummernkreise automatisiert.

Verfasst: Fr, 02. Jun 2023 15:50
von Manfred
:lol:

Re: Nummernkreise automatisiert.

Verfasst: Do, 08. Jun 2023 11:44
von Manfred
nightcrawler hat geschrieben: Fr, 02. Jun 2023 12:18 Verwendung:

Code: Alles auswählen

SELECT gen_id('test') FROM SYSTEM.IOTA;
Das kannst Du entweder direkt verwenden (im Insert) oder in einem Trigger. Als Text gibst Du den Nummernkreis an.
Die Funktion habe ich angelegt. Es kommt auch was zurück. Aber was meinst Du mit "als Text". oder meinst Du damit den Wert 'test' ?
da habe ich folgendes gemacht

Code: Alles auswählen

SELECT gen_id('4000000') from system.iota
hier bekomme ich aber nur ab 1 hochgezählt jedesmal zurück.

Re: Nummernkreise automatisiert.

Verfasst: Do, 08. Jun 2023 13:58
von nightcrawler
Name des Generators

Re: Nummernkreise automatisiert. [erledigt]

Verfasst: Do, 08. Jun 2023 15:44
von Martin Altmann
Manfreds Problem: er möchte eine noch nicht vergebene Nummer - wobei der Generator beginnen soll bei 4.000.000 - also die nächste unbenutzte Nummer ab 4 Millionen liefern soll.
Nur damit ihr nicht wieder aneinander vorbei schreibt...

Viele Grüße
Martin

Re: Nummernkreise automatisiert. [erledigt]

Verfasst: Do, 08. Jun 2023 15:50
von Manfred
OK,
ich glaube ich habe es kapiert.

Re: Nummernkreise automatisiert. [erledigt]

Verfasst: Do, 08. Jun 2023 16:13
von Manfred
ich hatte den Zusammenhang überhaupt nicht erkannt. Es wird eine weitere Tabelle im DD angelegt, in der die Werte gespeichert werden. Die Function (könnte ja auch eine eigene im programm sein, ist aber dann nicht zählsicher) im DD wird aufgerufen und erzeugt dann immer wieder die benötigten Zahlen. Mir ist trotz mehrmaligen Schauen nicht aufgefallen, das eine neue Tabelle im DD erzeugt wurde. (in dem Falle tb_generator) ich nhabe sie einfach übersehen. Weil nicht erwartet. Jetzt ist alles klar. Die Werte werden einfach in die Tabelle eingetragen und dann macht die Function den Rest. War mal wieder zu einfach um es sofort zu erkennen..... menno.

Re: Nummernkreise automatisiert. [erledigt]

Verfasst: Do, 08. Jun 2023 17:21
von nightcrawler
Manfred hat geschrieben: Do, 08. Jun 2023 16:13 ich hatte den Zusammenhang überhaupt nicht erkannt. Es wird eine weitere Tabelle im DD angelegt, in der die Werte gespeichert werden.
wie in meinem ersten Post genannt:
Die Werte für die Nummernkreise werden in einer Tabelle verwaltet.

Re: Nummernkreise automatisiert. [erledigt]

Verfasst: Fr, 09. Jun 2023 6:35
von Manfred
Hatte ich total überlesen, bzw. nicht registriert. Ich hatte das Konzept zu dem Zeitpunkt überhaupt nicht verinnerlicht. :roll:
Meine Frage wäre aber noch, wie sicher ist das gegen doppelte Vergabe von Nummern? So ein Konzept hatte ich früher ohne ADS auch und da habe ich jedesmal die Nummerntabelle exklusiv geöffnet und somit verhindert, das Nummern doppelt vergeben werden konnten.

Re: Nummernkreise automatisiert. [erledigt]

Verfasst: Sa, 10. Jun 2023 12:08
von nightcrawler
100% sicher bei bei remote server, da rowversion abgefragt wird.

Re: Nummernkreise automatisiert. [erledigt]

Verfasst: Sa, 22. Jul 2023 8:46
von Manfred
und wo liegt hier der Denkfehler?

Code: Alles auswählen

UPDATE mandanten SET kundennummer=(SELECT gen_id('Schüler') from system.iota)
hier wird nicht bei jedem Satz hochgezählt nur beim ersten Mal. Wird das nicht bei jedem Satz erneut aufgerufen, oder nur 1x und dann für alle restlchen so übernommen?

Re: Nummernkreise automatisiert. [erledigt]

Verfasst: Sa, 22. Jul 2023 11:51
von nightcrawler
Hallo Manfred,
genauso ist es. Du legst einmal den Wert fest und änderst alle Datensätze auf genau diesen Wert.
Besser: Trigger erstellen und dann bei Nichtvorhandensein der Nummer, diese einfügen:

Code: Alles auswählen

CREATE TRIGGER upd_mandanten ON mandanten AFTER UPDATE
BEGIN
  UPDATE mandanten SET kundennummer=gen_id('Schüler') WHERE kundennummer IS NULL and ROWID=::stmt.TrigRowid;
END
Dan ein Update über alle Datensätze

Code: Alles auswählen

UPDATE mandanten SET kundennummer=kundennummer;

Re: Nummernkreise automatisiert. [erledigt]

Verfasst: Sa, 22. Jul 2023 12:08
von Manfred
Danke Joachim,
war mal wieder mein Denkfehler. Habe den Ablauf falsch erkannt. Select hat da nichts zu suchen.