Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Wie eindeutige Rechnungsnummer in DB erstellen und speichern? (https://www.delphipraxis.net/191066-wie-eindeutige-rechnungsnummer-db-erstellen-und-speichern.html)

DCoderHH 5. Dez 2016 09:24

Datenbank: Firebird • Version: 2.5 • Zugriff über: DevArt IBDAC

Wie eindeutige Rechnungsnummer in DB erstellen und speichern?
 
In unser Inhouse-Kunden-DB hatten wir bisher die Rechnungsnummer als Interger-Feld (Primärschlüssel), fortlaufend von 1 bis 2 erzeugt über einen Generator.

Nun soll eine Tochterfirma von uns auch die Software nutzen. Diese vergibt die Rechnungsnummer aber nach dem Schema YYYY-MM-N. Y=Aktuelles Jahr, M=Aktueller Monat, N=Fortlaufende Nummer von 1 bis n im aktuellen Monat.

Wie kann ich solche Rechnungsnummern eindeutig erzeugen? (Löcher sind in beiden Fällen erlaubt. Nur fortlaufend soll es sein.) Anmerkung: Die Datenbestände beider Firmen sind vollständig getrennt und werden nicht vermischt. Es gibt also immer die eine Art der Rechnungsnummer oder die andere Art. Nie beide gleichzeitig.

Wie sollen die Rechnungsnummern am jetzt am Besten gespeichert werden? Ein VarChar-Feld, dass dann für uns eine numerische Kundennumer enthält und für die Tocherfirma das Format YYYY-MM-N? Das ganze dann immer noch als Primärschlüssel? Ein Kollege meinte, das macht man nicht (hat aber keine Begründung). Er würde zusätzlich zur VarChar-Kundennummer noch ein ID-Feld (Integer) einführen, das nur programmintern als Primärschlüssel genutzt wird und andere Tabellen darüber verknüpft werden. Sollte man das machen? Vor-/Nachteile davon?

sh17 5. Dez 2016 09:30

AW: Wie eindeutige Rechnungsnummer in DB erstellen und speichern?
 
Ich würde eine Spalte ID für den Primärschlüssel und die zweite Spalte für die Rechnungsnummer mit Index drüber machen.

sakura 5. Dez 2016 09:41

AW: Wie eindeutige Rechnungsnummer in DB erstellen und speichern?
 
Erste Gegenfrage:

Werden Rechnungen für einen Monat X eventuell erstellt, wenn ein für den folgenden Monat bereits Rechnungen in der Datenbank existieren?

...:cat:...

FrankJ28 5. Dez 2016 09:53

AW: Wie eindeutige Rechnungsnummer in DB erstellen und speichern?
 
Hallo,
was ist denn das für eine Branche? Werden denn da die Monate betriebswirtschaftlich "abgeschlossen"? Sonst hättet ihr Probleme mit dem lückenlosen Rechnungsnummernkreis innerhalb des Wirtschaftsjahres. Wenn ihr die Monate buchhalterisch abschließen würdet, dann wäre das doch der richtige Zeitpunkt den Nummernkreis entsprechend neu starten zu lassen.
Ciao
Frank

jobo 5. Dez 2016 10:38

AW: Wie eindeutige Rechnungsnummer in DB erstellen und speichern?
 
Eine Rechnungsnummer ist eine fachliche Anforderung, deshalb würde man keinen PK dafür einsetzen. Wie Du an dem Problem "Tochterfirma" mit anderer Handhabung der Rechnungsnummer sehen kannst, ist ein PK eine sehr eingeschränkt nutzbare Implementierungsform für dieses Problem.
Wenn es eine einheitliche Software ist, die mit diesen beiden verschiedenen Anforderungen umgehen muss würde ich es so machen:
- Ein neues, autarkes Feld für die Implementierung der Rechnungsnr ala Tochterfirma.
- Dafür einen Mechnismus implementieren, der es per Angabe einer Formatmaske erlaubt, die Rechnungsnummer nach Bedarf auszusteuern
- Und damit eine (zunächst) 2-gleisige Lösung schaffen
- Um- /Erstellung aller Reports, Ausdrucke, Templates für die Tochter auf Basis des neuen Verfahrens (Das dürfte im Wesentlichen die Verwendung des neuen Feldes sein)

- Dann die bestehende Lösung (altes/jetziges Verfahren) so adaptieren, dass sie in einer neuen Version auch in der Lage ist, das neue Feld zu nutzen, inkl. der bereits angepassten Reports usw.

- Die 2gleisigkeit ist m.E. eine sinnvolle Sicherheitsmaßnahme für Dich, damit Dir mittendrin nichts im Bestandssystem um die Ohren fliegt.

Zukünftig können dann neue, geänderte Rechnungsnummerverfahren unproblematisch angepasst werden.

p80286 5. Dez 2016 11:17

AW: Wie eindeutige Rechnungsnummer in DB erstellen und speichern?
 
Zitat:

Zitat von DCoderHH (Beitrag 1355340)
Wie sollen die Rechnungsnummern am jetzt am Besten gespeichert werden? Ein VarChar-Feld, dass dann für uns eine numerische Kundennumer enthält...

Einwurf am Rande, auch wenn Eure Rechnungsnummer aus Ziffern besteht, ist sie nicht Numerisch sprich eine Zahl, mit der man Rechnen kann.
Da es immer noch viele Schwergewichter gibt, die hemmungslos mit diesen und anderen Nummern rechnen, der Hinweis: "Nicht alles was wie eine Zahl aussieht, ist auch eine Zahl"

Gruß
K-H

mm1256 5. Dez 2016 14:43

AW: Wie eindeutige Rechnungsnummer in DB erstellen und speichern?
 
Zitat:

Zitat von p80286 (Beitrag 1355360)
...die hemmungslos mit diesen und anderen Nummern rechnen, der Hinweis: "Nicht alles was wie eine Zahl aussieht, ist auch eine Zahl"

In diesem Fall würde ich aber eine Zahl bevorzugen, einen Integer im Format YYYMMnnn wobei nnn dann die fortlaufende Nummer im Monat wäre. Wie man den Integer dann formatiert ausgibt, bleibt Ermessenssache. So nebenbei wird das dann auch noch kompatibel mit manchen Fibus die nur rein numerische Belegnummern verarbeiten können.

p80286 5. Dez 2016 15:04

AW: Wie eindeutige Rechnungsnummer in DB erstellen und speichern?
 
Ich hab da so meine Bedenken!
die Generierung der Nummer YYYYMMnnn aus einer Zahl, kein Problem, aber danach ist sie ein string aus 9Ziffern, wobei hat nnn führende Nullen?
In meiner Praxis habe ich des Öfteren mit Personalnummern zu tun, 6Stellig nur Ziffern. Access hat es schon einmal fertig gebracht, daraus Datumsdaten zu machen. Standard ist es die führende 0 zu streichen und selbst die Berechnung der Prüfziffer erfolgt ja nicht von einem numerischen wert sondern vom numerischen Wert einzelner Ziffern bzw. Ziffernkombinationen.

Gruß
K-H

jobo 5. Dez 2016 15:58

AW: Wie eindeutige Rechnungsnummer in DB erstellen und speichern?
 
Ich würde einen String nehmen, dann ist mir alles andere egal (außer die maximale Länge, die für eine unbeschwerte Zukunft doch noch irgendwie bestimmt/"geraten" werden müsste). Damit hätte ich dann mit einer beliebigen Formatmaske pro Mandant / Konfiguration dann alle Freiheiten.

nahpets 5. Dez 2016 16:17

AW: Wie eindeutige Rechnungsnummer in DB erstellen und speichern?
 
Also sagen wir mal so:

Prinzipiell kann man das mit der Nummer so ala ((Jahreszahl * 100) + Monat) * 1000 machen.

Das klappt soweit auch ganz gut.

Per wie auch immer gearteter Datenbanklogik kann mein eine Sequenz zum Monatsbeginn auf eben diesen Wert setzen.

Und richtig gut wird das Ganze dann, wenn irgend so ein "bekloppter Kunde" dafür sorgt, dass er in einem Monat mal die 999 plus 1. Rechnung verursacht.

Dann sind wir in dem Nummernkreis wunderbar z. B. bei

2017 * 100 wird zu 201700 plus Monat (Januar) ist dann 201701.
Das mal 1000 ergibt 201701000.
plus 999 ergibt 201701999 (für die 999. Rechnung)
plus 1 wird zu 201702000 (für die 1000. Rechnung)
plus noch eins wird dann 201702001 (für die 1001. Rechnung)

Und am 1. Februar setzen wir dann die Sequenz auf 201702000.

Und die erste Rechnung im Februar macht uns dann eine "wunderbare" Rechnungsdublette.

Delphitechnisch könnte man das z. B. ungefähr so umsetzen:
Delphi-Quellcode:
var
  i : Integer;
  Rechnungsnummer : String;
begin
  for i := 0 to 1001 do begin
    Rechnungsnummer := Format('%.4d-%.2d-%.3d',[YearOf(Now),MonthOf(Now),i]);
  end;
end.
Pech, wenn man in der Datenbank dann nur 11 Zeichen für die so formatierte Rechnungsnummer reserviert hat.

Und nein, die 1000. Rechnung in einem Monat können wir für immer und alle Zeiten ganz ganz ganz absolut sicher ausschließen.

Nene, sprechende Schlüssel sind ein Graus ;-)
Irgendwann gehen sie schief und alle rätseln: Wie konnte sowas nur passieren :evil:

Ok, genug geblödelt.

Meiner Meinung nach sollte man hier für das Tochterunternehmen einfach mal folgende Regel einführen:

Ok, Ihr könnt ab 1.1.2017 mit unserer Software arbeiten, wir werden euch das alles einrichten. Die erste Rechnung die Ihr im Jahr 2017 erstellt, bekommt die Nr. 1. Jede weitere Rechnung bekommt eine um 1 höhere Rechnungsnummer.

Punkt.

Die Leute werden sich sehr schnell daran gewöhnen, dass die Rechnungsnummer eine Nummer ist.

Praktische Erfahrung: Am Häufigsten bestehen die Leute auf irgendwelche Formalismen beim Erstellen von Nummern ..., die in der Praxis am Wenigsten damit in Berührung kommen.

Wenn's denn sein muss: Formal (also optisch) erstellt Ihr die Rechnungsnummer weiterhin mit JJJJ-MM-n.
Aber die n beginnt nicht mehr jeden Monat bei 1, sondern wird für alle Zeiten jeweils um 1 weitergezählt.

Teilt jetzt ein Kunde bei 'ner Nachfrage seine Rechnungsnummer mit, weiß man immernoch, aus welchem Jahr und Monat sie ist, aber halt nicht mehr, die wievielte es aus dem Monat ist. Für irgendwelche praktischen Abläufe dürfte diese "Information" eh irrelevant sein.

p80286 5. Dez 2016 16:29

AW: Wie eindeutige Rechnungsnummer in DB erstellen und speichern?
 
langsam aber sicher[OT]
Wir bekommen jetzt eine DB bei der die Aktennummern nach dem Schema YYYYMMDDnnn aufgebaut sind, angeblich geht es nicht anders, und der Hersteller ist seit einigen Jahren im Geschäft.

Was soll man rauchen um das zu ertragen?
:drunken:
[/OT]

jobo 5. Dez 2016 16:41

AW: Wie eindeutige Rechnungsnummer in DB erstellen und speichern?
 
Ja, meinetwegen, ist ein wenig schwarz gemalt, aber wie auch immer.
Diese Anforderungen ergeben sich ja nicht primär daraus, dass der verantwortliche Buchhalter Nummerologe ist. Oft sind es eher Sachzwänge aus irgendwelcher Legacy Software, was weis ich. Die Anforderung hat der TE gesetzt oder das Tochterunternehmen, ...
Ich würde an der Stelle keine Sachzwänge durch einen Datentyp in Kauf nehmen, geschweige durch Regularien, die sich aus der Verwendung Nutzung einer DB Funktion ergeben, die nicht dafür gedacht ist, ein Primärschlüssel und die DB Hilfskonstrukkte dazu sind halt was anderes als eine Rechnungsnummer.
Speicherplatz kostet auch nicht mehr so viel, dass man hier mit Bits rechnen muss.

Ob oder welche Arbeitsabläufe (Aktensortierung) hinter solchen Dingen stecken, kann man aus der Ferne auch nicht sagen.

Und eine 20 stellige Rechnungsnummer ist doch irgendwie auch .. beeindruckend.. oder nicht ;)

Ghostwalker 5. Dez 2016 18:09

AW: Wie eindeutige Rechnungsnummer in DB erstellen und speichern?
 
Ich persönlich würde wie folgt verfahren:

- Primarykey abtrennen....der hat nix mit ner Rechnungsnummer zu tun
- Einheitliches Format für Rechnungsnummer generieren:

z.B.
Mit dem Datum der Rechnung
Der Kundennummer
und ggf. einer lfd. Nummer


Das ganze als Varchar mit Index in die DB klatschen feddich.

Wenn ggf. die Anforderung besteht, das der Aufbau der Rechnungsnummer nicht ersichtlich sein soll,
kann man noch drüber nachdenken den o.g. String durch eine Hash-Routine zu jagen und den Hash als Rechnungsnummer zu nutzen. Damit wäre die Eindeutigkeit auch gesichert.

DCoderHH 5. Dez 2016 18:29

AW: Wie eindeutige Rechnungsnummer in DB erstellen und speichern?
 
OK, ihr hab micht überzeugt. Ich werde 2 Felder nutzen: Ein ID-Feld als Primärschlüssel und die Rechnungsnummer im VarChar-Feld. Nun ist noch offen:

Wie erzeuge ich die Rechnungsnummer nach dem Schema YYYY-MM-NNNNNN? Y=Aktuelles Jahr, M=Aktueller Monat, N=Fortlaufende Nummer von 1 bis n im aktuellen Monat?

nahpets hat in Post #10 schon Code dazu genannt. Der sieht aber nicht so aus, als ob man dem mit einer DB im Multiuser-Zugriff nutzen könnte... Wer hat da eine gute Idee? Danke!

nahpets 5. Dez 2016 18:45

AW: Wie eindeutige Rechnungsnummer in DB erstellen und speichern?
 
Naja, statt i nimmst Du in dem Teil hier
Delphi-Quellcode:
Rechnungsnummer := Format('%.4d-%.2d-%.3d',[YearOf(Now),MonthOf(Now),i]);
'ne Datenbanksequenz.

Ggfls. könnte diesen Job aber auch ein Datenbanktrigger übernehmen?

DCoderHH 5. Dez 2016 18:55

AW: Wie eindeutige Rechnungsnummer in DB erstellen und speichern?
 
Zitat:

Zitat von nahpets (Beitrag 1355427)
Naja, statt i nimmst Du in dem Teil hier
Delphi-Quellcode:
Rechnungsnummer := Format('%.4d-%.2d-%.3d',[YearOf(Now),MonthOf(Now),i]);
'ne Datenbanksequenz.

Ggfls. könnte diesen Job aber auch ein Datenbanktrigger übernehmen?

Datenbanksequenz = Generator in Firebird? Und wie setze ich den dann jeden Monat wieder auf 1? Und zwar so, dass er nur genau ein mal pro Monat auf 1 gesetzt wird?

jobo 5. Dez 2016 19:03

AW: Wie eindeutige Rechnungsnummer in DB erstellen und speichern?
 
Code:
insert into mytable
values (1,                                                                       -- id
        'rn#_'||CAST(Extract(year FROM cast('NOW' as date))*10000 +
                     Extract(month FROM cast('NOW' as date))*100 +
                     Extract(day  FROM cast('NOW' as date)) AS VARCHAR(8))||
        LPAD (gen_id(gen_rn,1), 6, '0'),                                         -- rechnungsnummer
        cast('Now' as date));                                                    -- date
und reset

Code:
set generator gen_rn to 0;

DCoderHH 5. Dez 2016 19:24

AW: Wie eindeutige Rechnungsnummer in DB erstellen und speichern?
 
Zitat:

Zitat von jobo (Beitrag 1355430)
und reset

Code:
set generator gen_rn to 0;

Und wann und wie rufst Du das auf und zwar so dass es genau ein mal pro Monat ausgeführt wird?

jobo 5. Dez 2016 19:40

AW: Wie eindeutige Rechnungsnummer in DB erstellen und speichern?
 
naja, einmal im Monat :)
Mitternacht, am letzten Tag des Monats.

Ok, also ernst:
Eine lazy Variante wäre, das auf dem Server durch einen (Cron)Job durchführen zu lassen.
Dabei besteht leider die Gefahr, dass der Job fehlschlägt, das müsste man absichern.

Ich würde es wohl eher so machen, den gesamten Ausdruck, der die Nummer generiert, als Funktion abzurufen. Darin wird die Datumsgrenze geprüft und der Reset gemacht.
Dabei besteht leider das Problem, den Wechsel festzustellen, dafür eignet sich wohl am besten eine Hilfstabelle mit einer Zeile, die sich das Datum bei jedem Aufruf zum Vergleichen merkt.

Im übrigen muss man sich vielleicht noch überlegen, was das Rechnungsdatum wird. Tag der Erstellung, Tag des Versandes, ..
Je nach dem würde die Rechnungsnummer dann unterschiedlich generiert.

rokli 6. Dez 2016 07:22

AW: Wie eindeutige Rechnungsnummer in DB erstellen und speichern?
 
Moin,

es gibt auch die Möglichkeit, eine Tabelle anzulegen, in der die Nummern verwaltet werden z. B.:

SQL-Code:
CREATE TABLE [dbo].[Nummernkreise](
   [IdNo] [int] IDENTITY(1,1) NOT NULL,
   [Mandant] [tinyint] NULL,
   [BelegArt] [char](10) NULL,
   [BelegNr] [int] NULL,
   [BelegPrefix] [char](20) NULL,
 CONSTRAINT [PK_Nummernkreise] PRIMARY KEY CLUSTERED
(
   [IdNo] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

Und der Inhalt sieht dann so aus:
Code:
IdNo   Mandant   BelegArt   BelegNr   BelegPrefix
1   1   RE          123   2016-12             
2   1   LS          17   2016-12             
3   2   RE          17   KDNR              
4   1   AB          500   2016-16

Dann hast Du für alle möglichen Belegarten einen Speicher, in dem Du hochzählen kannst, in dem Du Startwerte setzen kannst etc.; und natürlich sind weitere Felder in der Tabelle denkbar, wie Monat und / oder Jahr, wenn das nötig wäre.

Gruß

rokli 6. Dez 2016 07:25

AW: Wie eindeutige Rechnungsnummer in DB erstellen und speichern?
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hier noch mal die Ansicht der Daten in der DB als Bild; das ist da oben nicht wirklich gut zu erkennen!

Und alles natürlich in TSQL ... :wink:

jobo 6. Dez 2016 08:05

AW: Wie eindeutige Rechnungsnummer in DB erstellen und speichern?
 
Ich habe hier mal einen Versuch gemacht mit einer autarken SP ohne separates Reset des Generators. Da ich wenig Praxis mit FB habe, bitte gut testen. Vielleicht schaut ja auch einer der FB Kenner hier mal drüber.

SQL-Code:
-- create daily cyclic sequence number / expression

-- table storing last used date
-- drop table rndatebuffer;
create table rndatebuffer (
  isRestricted char(1) Default 'X' unique,         --force one record only
  lastDate date not null ,
  constraint forceOneRow check (restricted='X'));  --force one record only
 
-- insert into rndatebuffer (lastdate) values(CURRENT_DATE-1);
-- select * from rndatebuffer;

-- sequence
CREATE GENERATOR gen_rn;
SET GENERATOR gen_rn TO 0;


--drop procedure getrn;
--procedure to fetch new "number"
SET TERM ^ ;
CREATE Procedure GetRN RETURNS (prn varchar(20)) as
  declare aDif integer;
BEGIN

  select CURRENT_DATE-lastdate from rndatebuffer into :aDif;          -- detect date border
  if (aDif is null) then                                              -- init
  begin
    insert into rndatebuffer (lastdate) values(CURRENT_DATE);
    execute statement 'set generator gen_rn to 0';
  end

  If (aDif <> 0) then                                                 -- date border reached
  begin
    update rndatebuffer set lastdate=CURRENT_DATE;                    -- reset date buffer
    execute statement 'set generator gen_rn to 0';                    -- reset generator
  end

  for
    select                                                            -- build Rechnungsnummer
      CAST(Extract(year FROM cast('NOW' as date))*10000 +
      Extract(month FROM cast('NOW' as date))*100 +
      Extract(day FROM cast('NOW' as date)) AS VARCHAR(8))||
      LPAD (gen_id(gen_rn,1), 6, '0')
    from RDB$DATABASE into :prn
  do begin
    suspend;
  end
END
^

SET TERM ; ^

P.S.: der Aufruf wäre dann einfach
Code:
select * from GetRN;

DCoderHH 6. Dez 2016 08:19

AW: Wie eindeutige Rechnungsnummer in DB erstellen und speichern?
 
@jobo: Deine StoredProcedure GetRN aus Post #22 eignet sich auch für Multiuser-Zugriff? Was ist wenn 2 Clients die StoredProcedure gleichzeitig aufrufen? Ist das berücksichtigt?

DCoderHH 6. Dez 2016 08:22

AW: Wie eindeutige Rechnungsnummer in DB erstellen und speichern?
 
Zitat:

Zitat von rokli (Beitrag 1355438)
es gibt auch die Möglichkeit, eine Tabelle anzulegen, in der die Nummern verwaltet werden

Wie würde man die Tabelle in einer Multiuser-Umgebung abfragen und setzen so dass es keine doppelten Nummern gibt? Ein einfaches select und update würde ja nicht funktionieren...

mkinzler 6. Dez 2016 08:35

AW: Wie eindeutige Rechnungsnummer in DB erstellen und speichern?
 
Zitat:

Zitat von DCoderHH (Beitrag 1355442)
@jobo: Deine StoredProcedure GetRN aus Post #22 eignet sich auch für Multiuser-Zugriff? Was ist wenn 2 Clients die StoredProcedure gleichzeitig aufrufen? Ist das berücksichtigt?

Ja, dafür sorgt die Semaphoren-Funktion gen_id()

mkinzler 6. Dez 2016 08:36

AW: Wie eindeutige Rechnungsnummer in DB erstellen und speichern?
 
Zitat:

Zitat von DCoderHH (Beitrag 1355443)
Zitat:

Zitat von rokli (Beitrag 1355438)
es gibt auch die Möglichkeit, eine Tabelle anzulegen, in der die Nummern verwaltet werden

Wie würde man die Tabelle in einer Multiuser-Umgebung abfragen und setzen so dass es keine doppelten Nummern gibt? Ein einfaches select und update würde ja nicht funktionieren...

Man könnte ein select for update verwenden.

Lemmy 6. Dez 2016 08:45

AW: Wie eindeutige Rechnungsnummer in DB erstellen und speichern?
 
Zitat:

Zitat von mkinzler (Beitrag 1355445)
Zitat:

Zitat von DCoderHH (Beitrag 1355442)
@jobo: Deine StoredProcedure GetRN aus Post #22 eignet sich auch für Multiuser-Zugriff? Was ist wenn 2 Clients die StoredProcedure gleichzeitig aufrufen? Ist das berücksichtigt?

Ja, dafür sorgt die Semaphoren-Funktion gen_id()

-gelöscht-

Ich würde das anders umsetzen und wenn möglich einen "Buchungsschluss" laufen lassen, der den Zugriff auf die DB blockiert und der dann letztlich den Rechnungsnummerngenerator initialisiert. Aber ganz sicher nicht in der SP in der neue Rechnungsnummern generiert werden

p80286 6. Dez 2016 08:55

AW: Wie eindeutige Rechnungsnummer in DB erstellen und speichern?
 
Ich möchte nochmal anmerken, daß diese datumsabhängige Generierung nur für einen geografisch begrenzten Raum durchführbar ist. Egal ob LocalTime oder eine zentrale Zeit (Greenich) irgendwann ist eine Datumsgrenze erreicht, die mit einem "Datumsgefühl" kollidiert. Alleine in den USA gibt es eine Zeitdifferenz von 3 Stunden, Die Westküste hat einen Abstand von 9 Stunden zu Deutschland, wenn dort die erste Rechnung generiert wird, ist bei uns die letzte im System. Aber für solche Szenarien wurde die Datenbank nicht entworfen, und das Jahr 2000 war in weiter Zukunft.

Gruß
K-H

jobo 6. Dez 2016 09:16

AW: Wie eindeutige Rechnungsnummer in DB erstellen und speichern?
 
Zitat:

Zitat von mkinzler (Beitrag 1355446)
Zitat:

Zitat von DCoderHH (Beitrag 1355443)
Zitat:

Zitat von rokli (Beitrag 1355438)
es gibt auch die Möglichkeit, eine Tabelle anzulegen, in der die Nummern verwaltet werden

Wie würde man die Tabelle in einer Multiuser-Umgebung abfragen und setzen so dass es keine doppelten Nummern gibt? Ein einfaches select und update würde ja nicht funktionieren...

Man könnte ein select for update verwenden.

Nach meinem Verständnis läuft das automatisch in einer Transaktion ab und würde keine Probleme bereiten. Dafür ist ja der Generator und Transaktionsicherheit da.

Notfalls mal ausprobieren und ein paar Consolen öffnen die in einer Loop Werte anfordern. Dazwischen manuel das Datum zurücksetzen. Dabei sollte nur eine einzige Sitzung einen Sequenzreset "erleben" und natürlich alle Sitzungen in Summe eindeutige Nummern liefern.

@Datumsgrenzen: Die sind natürlich international unterschiedlich. Das ist aber kein technisches Problem, sondern muss per Konvention vereinabrt werden, welche Datumsgrenze gewählt werden soll.

Ich selbst habe bei meinem Vorschlag eigentlich ein anderes Problem. Nämlich das Sequenzreset selbst. Ich bin mir nicht ganz sicher, wie das zu werten ist, aber es scheint als DML Befehl zu laufen und ich kenne es von anderen Systemen so, dass DML implizit commited. Das wäre aus meiner Sicht nicht wünschenswert.

Ghostwalker 6. Dez 2016 09:29

AW: Wie eindeutige Rechnungsnummer in DB erstellen und speichern?
 
Zitat:

Zitat von p80286 (Beitrag 1355448)
Ich möchte nochmal anmerken, daß diese datumsabhängige Generierung nur für einen geografisch begrenzten Raum durchführbar ist. Egal ob LocalTime oder eine zentrale Zeit (Greenich) irgendwann ist eine Datumsgrenze erreicht, die mit einem "Datumsgefühl" kollidiert. Alleine in den USA gibt es eine Zeitdifferenz von 3 Stunden, Die Westküste hat einen Abstand von 9 Stunden zu Deutschland, wenn dort die erste Rechnung generiert wird, ist bei uns die letzte im System. Aber für solche Szenarien wurde die Datenbank nicht entworfen, und das Jahr 2000 war in weiter Zukunft.

Gruß
K-H

Da hast du definitiv recht. Aber das Problem hast du generel mit Datumswerten, egal ob das nun in der
Rechnungsnummer oder sonstwo in der DB ist. Deshalb sollte man sich hier (Programmintern) auf eine Art einigen (i.d.R. GMT).

himitsu 6. Dez 2016 10:02

AW: Wie eindeutige Rechnungsnummer in DB erstellen und speichern?
 
MultiUser: Man nehme einen Generator (wie bei den AutoInc-Feldern) für den numerischen Anteil.
Und dann baut man sich 'ne DB-Funktion, die einen neuen AutoInc-Wert generieren lässt und dann YYYY, MM, DD mit AutoInc zusammensetzt und als VARCHAR rausgibt.
Diese Funktion könnte man z.B. auch als DEFAULT an ein Feld hängen und von der DB füllen lassen.

Wir haben bei uns 'ne Tabelle und paar Funktionen, wo mehrere solcher "Masken" definiert werden können, auch kundenabhängig, die man dann an irgendwelche Felder hängen kann oder im Programm abfragt.
Teilweise ist dann noch 'ne Lückenprüfung mit drin, welche abgefragte, aber dann doch nicht verwendete Werte findet und erneut nutzen kann.
Bei uns werden diese Werte, sowie die anderen DEFAULT-Werte, meistens nicht erst beim Post von der DB eingetragen, sondern schon von der Query-Komponente im OnAfterInster geladen, damit der User Diese bereits im Grid/den Edits sehen kann, bevor er speichert.

jobo 6. Dez 2016 10:22

AW: Wie eindeutige Rechnungsnummer in DB erstellen und speichern?
 
@himitsu
Genau das habe ich ja gemacht und es wird angezweifelt, dass es mutliuser fähig ist.

himitsu 6. Dez 2016 10:38

AW: Wie eindeutige Rechnungsnummer in DB erstellen und speichern?
 
Man muß halt die Generatoren/Sequenzen verwenden, diese sind quasi threadsave und werden auch nicht von Transaktionen beeinflusst.

Wenn man diese Zähler in eigenen Tabellenfeldern speichert ... nja, kommt dann halt drauf an, wie das DBMS mit gleichzeitigen Abfragen/Updates umgeht, die auf die selben Felder zugreifen.
SQL-Code:
UPDATE meinezählertabele SET zähler = zähler + 1 WHERE name = :name RETURNING zähler

jobo 6. Dez 2016 10:39

AW: Wie eindeutige Rechnungsnummer in DB erstellen und speichern?
 
Mach ich auch, zusätzlich aber noch ein Update auf eine Merkertabelle für den Datumswechsel.

rokli 6. Dez 2016 13:57

AW: Wie eindeutige Rechnungsnummer in DB erstellen und speichern?
 
Hallo DCoderHH,

Zitat:

Zitat von DCoderHH (Beitrag 1355443)
Zitat:

Zitat von rokli (Beitrag 1355438)
es gibt auch die Möglichkeit, eine Tabelle anzulegen, in der die Nummern verwaltet werden

Wie würde man die Tabelle in einer Multiuser-Umgebung abfragen und setzen so dass es keine doppelten Nummern gibt? Ein einfaches select und update würde ja nicht funktionieren...

Auch ein Status-Feld wäre möglich, z. b.:
User 10 setz Status = 10 => kein anderer darf eine Nummer generieren
User 10 generiert seine neue Nummer und trägt sie ein
User 10 setze Status = 0 => jemand anderes kann eine Nummer ziehen

jobo 6. Dez 2016 14:07

AW: Wie eindeutige Rechnungsnummer in DB erstellen und speichern?
 
Eine solche logische Sperre würde doch nichts an dem Multiuser Problem ändern (das es m.E. gar nicht gibt), sondern es nur verschieben.
Gäbe es das Multiuser-Zugriffs-Problem, würde es beim Statusupdate genauso auftreten, also nur bei einem anderen Updatebefehl.

nahpets 6. Dez 2016 14:34

AW: Wie eindeutige Rechnungsnummer in DB erstellen und speichern?
 
Sagen wir mal so, 'ne Sequenz wird aufgerufen und gibt 'nen Wert zurück.

Multi-User hin oder her, die Datenbank kann die Sequenz nur einmal gleichzeitig aufrufen. Egal wieviele User unterwegs sind, sie müssen dann eben warten, bis die Datenbank die Sequenz aufruft, den Wert liefert und entsprechend hochzählt.

Die Sequenzen / Generatoren sind ja gerade dafür da, im Multiuserbetrieb sicherzustellen, dass eine Nummer nur genau einmal geliefert wird, egal wieviele User da in welchem, von der Länge her gegen 0 tendierenten, Zeitraum abfragen. Im Gegensatz zur Verwaltung mit Statuswerten ... in welchen Tabellen auch immer, soll hier ja das Multiuserproblem behoben werden.
Sollte es bei Sequenzen und / oder Generatoren aber trotzdem mal ein Problem geben, weil die Dinger einen Wert mehrfach geliefert haben, würde ich die Datenbank (wegen schlechter Implementierung / Fehlerhaftigkeit) wechseln.

Ich persönlich halte es für unsinnig, kontraproduktiv und absolut überflüssige Fehlerquellen generierend, wenn ich einen eindeutigen Wert benötige und diesen per Sequenz / Generator erhalten kann, nach einer anderen Lösungsmöglichkeit zu suchen. Meiner Meinung nach ist das einfach nur Quatsch.

Hab' da noch was gefunden:

Wat is 'ne Sequenz:
Zitat:

Zitat von IBM
Eine Sequenz ist ein Datenbankobjekt, das die automatische Generierung von Werten wie zum Beispiel Schecknummern ermöglicht. Sequenzen eignen sich ideal für die Aufgabe der Generierung eindeutiger Schlüsselwerte. Anwendungen können Sequenzen verwenden, um mögliche Probleme in Bezug auf den gemeinsamen Zugriff und die Leistung infolge von Spaltenwerten zu vermeiden, die für die Protokollierung von numerischen Werten verwendet werden. Der Vorteil von Sequenzen im Vergleich zu außerhalb der Datenbank erstellten numerischen Werten besteht darin, dass der Datenbankserver die generierten numerischen Werte protokollieren kann. Durch einen Systemabsturz mit anschließendem Wiederanlauf werden keine doppelten Zahlenwerte generiert.

siehe: http://www.ibm.com/support/knowledge.../c0023175.html

jobo 6. Dez 2016 15:49

AW: Wie eindeutige Rechnungsnummer in DB erstellen und speichern?
 
Zitat:

Zitat von nahpets (Beitrag 1355493)
Sagen wir mal so, 'ne Sequenz wird aufgerufen und gibt 'nen Wert zurück.
..

Das sehe ich im Prinzip alles haargenauso.
Ohne Not muss man nicht rumzaubern mit solchen Nummern.
Eine Sequenz ist eine Sequenz.
Transaktionssicherheit ist Transkationsicherheit.
Ein DB, die das nicht kann, sollte man nicht nutzen.

Die Sequenz wird also immer(!) fortlaufende Nummern produzieren, auch im Multiuserbetrieb. Das sollte vollkommen klar sein.
Und der Reset mit dem drangeflickten Datum, da bin ich der Meinung, dass es genauso geht, aber das sehen die Leute hier teilweise offenbar kritisch- auch wenn noch niemand gesagt hat warum.

Letztlich ist es Sache des TE, das abzuwägen und ggF. zu testen.

Vielleicht hätte ich nicht sagen sollen, dass ich mir nicht sicher bin, ob das Vorgehen wasserdicht ist für fb.

Am Ende ist es ja so- ich traue mich kaum, es zu sagen:
Falls der Mechnismus selbst fehlschlagen würde (das wäre entgegen meiner Implementierung nicht einmal pro Tag ab Mitternacht, sondern einmal im Monat ab Mitternacht laut Anforderung) würde eine doppelte Rechnungsnummer immernoch durch einen Unique Constraint abgewiesen. Es werden also keine falschen Daten gespeichert. Auch dafür sind moderne DB gemacht.

p80286 6. Dez 2016 21:50

AW: Wie eindeutige Rechnungsnummer in DB erstellen und speichern?
 
Was vielleicht für Irritationen sorgt, ist, daß es Sequenzer gibt, die z.B 10 Nummern auf Vorrat erzeugen, und unter widrigen Umständen ist dieser Vorrat dann verloren.
Das ist aber letztlich egal, da es darum geht eine eindeutige Nummer zu erzeugen.

Gruß
k-H

nahpets 6. Dez 2016 22:57

AW: Wie eindeutige Rechnungsnummer in DB erstellen und speichern?
 
Wir hatten mal in 'nem Projekt bei den Sequenzen ein "Schrittweite" von 128.

Man holte sich also von der Sequenz einen Wert und konnte dann diesen, plus die nächsten 127 fortlaufenden Werte, "verbraten".

Wenn das nicht reicht, holte man sich den nächsten 128 Wertebereich.

Und wenn man sie nicht alle brauchte, dann gab's halt Lücken, ja und? Ist (zumindest) bei technischen Schlüsseln vollkommen wurscht.

Und gibt es irgendeine zwingende Erfordernis, dass Rechnungsnummern zwingend lückenlos aufsteigend nummeriert sein müssen?

Ob große Unternehmen, die täglich hunderte oder tausende von Rechnungen erstellen, wirklich darauf achten, dass die Nummer garantiert lückenlos vergeben wurde.

Es kann nun mal bei der Erstellung einer Rechnung passieren, dass der Vorgang abgebrochen werden muss. Dann ist diese Rechnungsnummer halt vergeben, obwohl diese Rechnung letztlich nie erstellt wurde.

Die "zwingende Lückenlosigkeit der Rechnungsnummer" ist nur was zur Befriedigung des persönlichen Ergeizes des vor dem Rechnersitzenden oder irgendeines "Verwaltungstieres", aber für den Kunden oder die weiter interne Verarbeitung vollkommen Irrelevantes.

Habe heute eine Rechnung mit der Nummer 21750094056 bekommen. Mir ist es doch sowas von wurscht, ob es die Nummern 21750094055 und 21750094057 gibt oder nicht. Und für den Rechnungsersteller dürfte das auch absolut egal sein, die Buchhaltung will nur irgendwann wissen, ob für jede erstellte Rechnung irgendwann (möglichst vor dem letztmöglichen Zahlungstermin) ein Geldeingang zu verbuchen ist.
Aber niemand wird die Rechnungen nach lückenlos aufsteigender Rechnungsnummer ablegen und irgendein Problem dabei bekommen, wenn da mal 'ne Nummer fehlt.

Meiner Meinung nach werden hier oft "fachliche Anforderungen" gestellt, die für die tatsächliche Verarbeitung völlig überflüssig sind. Man könnte für die Rechnungsnummer auch einfach die Millisekunden seit dem 1.1.1970 nehmen, man darf nur nicht auf die Idee kommen, die Uhr zurück zu stellen. Die Verarbeitung der Rechnungen im weiteren Geschäftsablauf dürfte dadurch in keiner Weise nachteilig beeinflusst werden.

Mit Anforderungen wie: "Die Rechnungsnummer muss aus Jahr, Monat und einer fortlaufenden Nummer bestehen." sorgen bei der Implementierung eigentlich nur für Probleme, ohne dass im eigentlichen Arbeitsablauf dadurch ein wesentlicher Nutzen entsteht.


Alle Zeitangaben in WEZ +1. Es ist jetzt 18:20 Uhr.
Seite 1 von 2  1 2      

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