Nummernkreis mit 0 auffüllen

Ronald Nickel

Legendäres Mitglied
Hallo

ich muss einen dynamischen Nummernkreis für Rechnungsnummern generieren. Dabei soll aber beispielsweise die zweistelllige Rechnungsnummer "23" eine 6-stellinge Zahl werden und mit vorangestellten nullen aufgefüllt werden "000023". Dieses Format soll natürlich beibehalten und nirgends weggestrichen werden. Gibt es in MySql eine Moglichkeit das Feld so zu formatieren das, es egal welche Zahl eingetragen wird, immer 6 Ziffern abgelegt werden?

Gruß Ronny
 
QUOTE (Ronald Nickel @ Mi 16.06.2010, 14:18)ich muss einen dynamischen Nummernkreis für Rechnungsnummern generieren. Dabei soll aber beispielsweise die zweistelllige Rechnungsnummer "23" eine 6-stellinge Zahl werden und mit vorangestellten nullen aufgefüllt werden "000023". Dieses Format soll natürlich beibehalten und nirgends weggestrichen werden. Gibt es in MySql eine Moglichkeit das Feld so zu formatieren das, es egal welche Zahl eingetragen wird, immer 6 Ziffern abgelegt werden?

Mir fallen aktuell zwei Möglichkeiten ein (zwar .NET, aber müßte analog auch in mySql / PHP gehen):

(1) Das Feld als nvarchar(6) definieren und beim Insert / Update die Nullen von links her auffüllen.

(2) Das Feld als Integer lassen. Bei der Ausgabe kann man (zumindest innerhalb von .NET) Excel-ähnliche Konstrukte verwenden:


CODE Dim i As Integer = 23
Console.WriteLine(i.ToString("000000"))


erzeugt die Ausgabe


CODE 000023


Das an allen Ausgabestellen konsistent eingesetzt löst das Problem.

Technisch stehen führende Nullen niemals in einem Integer-Feld drin.
 
QUOTE `rechnungsnummer` INT( 6 ) UNSIGNED ZEROFILL NOT NULL



Hier lassen sich wohl nur Nummern einfügen, dafür wird diese automatisch mit Nullen aufgefüllt. Also diesen Spagat von MS kannst Du da getrost vergessen. ;-)
 
QUOTE (Sascha Ahlers @ Mi 16.06.2010, 16:38)Also diesen Spagat von MS kannst Du da getrost vergessen. ;-)

Ich finde das keinen Spagat, sondern sehr sinnvoll.

Die Darstellung einer Nummer gehört für mich nicht in die Datenbank, sondern ins Frontend.

Und eine Formatierung


QUOTE DezimalzahlVariable.ToString("#,###,##0.00")


mit einem Wert 1234,56 wird dann für einen deutschen Leser als


QUOTE 1.234,56


für einen englischen Leser als


QUOTE 1,234.56


ausgegeben. Der Datentyp Integer umfaßt immer 4 Byte, eine Größendefinition int(6) gibt es m.W. nach im ANSI-Standard gar nicht.
 
QUOTE (Jürgen Auer @ Mi 16.06.2010, 14:32)Technisch stehen führende Nullen niemals in einem Integer-Feld drin.

*Klugscheißer-Modus an*
Gerade technisch stehen in einem Integer-Feld öfters führende Nullen drinne. Das hat die Binäre Speicherung so an sich
tongue.gif

*Klugscheißer-Modus aus*

Aber ich muss dir Recht geben, Formatierung gehört eindeutig ins Frontend und nicht in die Datenbank.
 
QUOTE (Flips @ Mi 16.06.2010, 20:08)Gerade technisch stehen in einem Integer-Feld öfters führende Nullen drinne. Das hat die Binäre Speicherung so an sich
tongue.gif


Stimmt!

Deshalb verstehe ich ja diesen Ausdruck int(6) auch nicht.

Denn zumindest bis jetzt bin ich davon ausgegangen, daß auch mySql Ganzzahlen binär abspeichert, so daß man mit einem Byte 0 - 255, mit zwei Byte 0 - 65535, mit vier Byte das erste Bit für das Vorzeichen und den Rest für die entsprechende Binärdarstellung abspeichern kann.


Beim MS-SqlServer gibt es inzwischen noch den Datentyp bigint mit acht Byte.

Daß int(6) die Zahlen als Ziffern im 10-er-System ablegt, kann ich mir eigentlich nicht vorstellen.
 
QUOTE (Jürgen Auer @ Mi 16.06.2010, 13:32)[...]
(1) Das Feld als nvarchar(6) definieren und beim Insert / Update die Nullen von links her auffüllen.
[...]

Ja, ein Nummernformat gehört eigentlich ins Frontend, doch in diesen besonderen Fall, würde ich sagen, ist es hier noch etwas anderes, als wenn ich einen Geldbetrag speicher, denn hier geht es um eine fortlaufende eindeutige Nummer. Auch speicher ich eine einfache Zahl nicht als String in eine DB. Das ist für mich ein Spagat. Wir können ja drüber diskutieren, ob und welches Format nun in der DB steht, irgendeins wird es auch bei Floats oder Dezimalzahlen in der Datenbank gespeichert, und ist damit auch ein vorgebendes Format was man hier ändert.



QUOTE [...]
nvarchar [ ( n | max ) ]

Unicode-Zeichendaten variabler Länge. n kann ein Wert zwischen 1 und 4.000 sein. max gibt an, dass die maximale Speichergröße 2^31-1 Bytes beträgt. Die Speichergröße in Bytes ist doppelt so groß wie die Anzahl eingegebener Zeichen + 2 Bytes. Die eingegebenen Daten können 0 Zeichen lang sein. Die ISO-Synonyme für nvarchar sind national char varying und national character varying.
[...]

http://technet.microsoft.com/de-de/library/ms186939.aspx


Dann lieber ein entsprechender Datentyp in der Datenbank, insbesondere da dieser bei 4 Byte bleibt. Und ist immer noch besser als eine Speichergröße von 2 Byte pro Zeichen + 2 Byte, womit man im 1 stelligen Bereich bei je 4 Byte sind, und im Zweistelligen schon bei 6 Byte (3 Zeichen - 8 Byte bis 6 Zeichen - 14 Byte), was definitiv unsinniger ist als ein Integer zu nehmen, der eine Stufe höher ist, und halt immer noch 4 Byte lang ist pro Datensatz, und nicht pro weiterer Stelle um 2 Byte anwächst.
Aber auch hier ist immer noch gegeben, die Nummer entsprechend zu formatieren, aber wenn es sich hier um eine UID handelt (in diesen Falle eine Rechnungsnummer), finde ich es auch nicht unbedingt abwegig diese mit führenden Nullen in die DB zu schreiben, damit hier die Zuordnung leichter ist.



Für andere Dinge, wie Du sie oben beschreibst kann immer noch number_format verwendet werden. Damit hast Du aber keine führende Nullen in Deinen Beträgen, macht hier aber auch kein Sinn, ist bei Deinen Beispiel mit den Preisbeträgen aber auch irgendwie nicht der Fall, würde auch nicht unbedingt funktionieren. So funktioniert das Auffüllen der Nullen bei MySQL nur bei einer vorzeichenlosen Ganzzahl, ergo unsigned zerofill



Für mich bleibt Dein Konstrukt von oben ein Spagat, da Du hier mit der Datenbank falsch umgehst. Da änderst Du absolut nichts mit schönreden dran.

Und damit wir gerade so schön dabei nochmal die Gebetsmühle: Man speichert Daten immer ins entsprechende Datenbankformat und nicht aus Bequemlichkeit in ein anderes Format, um dadurch ein Overhead an Speicherplatz zu verschwenden (Ja, ich hab da auch ein Fehler gemacht, das liegt aber an mangelnden Einsatz und des menschlichen Gehirn Dinge zu verdrängen).



Zu dem int(6), das heißt, nutze ein 4 Byte Ganzzahlen fällt mit der Maximallänge von 6 Zeichen, da kein Vorzeichen benötigt wird, wird 6 Zeichen verwenden. Ein Bigint wäre also überflüssig, ein smallint nicht ausreichen, da es nur 5 Zeichen ohne Vorzeichen hat. Mir fällt aber gerade auf, dass ein mediumint(3) auch reicht, dann wären wir bei 3 Bytes. Das unsigned im Befehlt sagt auch gleichzeitig, dass kein Vorzeichen benötigt wird, womit das erste Bit frei wird und der Werte Bereich sich verschiebt. Bei einen smallint auf 0-255 statt -128 bis 127 (mit 7 Bit lassen sich 128 Zahlen darstellen, mit 8 Bit 256 Zahlen, da wir mit der 0 beginnen halt von 0 bis 255).

http://dev.mysql.com/doc/refman/5.1/de/numeric-types.html

Und MySQL ist nicht 100% ANSI-konform, aber das soll afaik MS SQL auch nicht sein.
http://troels.arvin.dk/db/rdbms/



@Ronald:
Ein mediumint(6) reicht auch, sind dann nur 3 Byte Speicherbedarf und macht das macht schon etwas aus, selbst wenn es max. 1 Million Rechnungen sein können, den Typ hatte ich nicht mehr direkt im Kopf, hab länger nicht mehr intensiv mit MySQL gearbeitet.

1.000.000 Byte = 976,56 KB
 
Also ...

Ich würde niemals ein nvarchar(6) verwenden, das war eine Hilfskonstruktion, weil ich mySql nicht großartig kenne, damit auch int(6) nicht kapiere.

Ich würde das als int mit automatischer Erhöhung machen, dann ist das von alleine eindeutig. Und die führenden Nullen gehen über die Ausgabe.


QUOTE (Sascha Ahlers @ Do 17.06.2010, 10:58)Für andere Dinge, wie Du sie oben beschreibst kann immer noch number_format verwendet werden. Damit hast Du aber keine führende Nullen in Deinen Beträgen


Innerhalb der MS-Welt habe ich mit der obigen Technik die führenden Nullen. Wenn number_format das nicht leistet ... Problem von PHP oder mySql (keine Ahnung, wo die Funktion hingehört).


QUOTE (Sascha Ahlers @ Do 17.06.2010, 10:58)Für mich bleibt Dein Konstrukt von oben ein Spagat, da Du hier mit der Datenbank falsch umgehst. Da änderst Du absolut nichts mit schönreden dran.


Ich würde das so nicht verwenden.


QUOTE (Sascha Ahlers @ Do 17.06.2010, 10:58)Man speichert Daten immer ins entsprechende Datenbankformat und nicht aus Bequemlichkeit in ein anderes Format, um dadurch ein Overhead an Speicherplatz zu verschwenden


Ist meine Aussage - Ganzzahlen als Integer speichern, die Darstellung übers Frontend abwickeln.
 
QUOTE (Jürgen Auer @ Do 17.06.2010, 13:54)[...]
Ich würde niemals ein nvarchar(6) verwenden, das war eine Hilfskonstruktion, weil ich mySql nicht großartig kenne, damit auch int(6) nicht kapiere.
[...]

Das mag ja sein, aber wenn Probleme mit Deinen Tools löst, solltest Du Sie zumindestens richtig verwenden. Der nächste versucht es auf MySQL zu übertragen und nutzt ein varchar(6)-Feld für eine Ganzzahl. Dadurch entsteht unhaltbares Falschwissen. Solche üblen Workarounds sollten daher nicht angeboten werden.
Da andere auch verstehen können, was Du da an Programmcode schreibst, ist Dir wohl nun auch klar, was ich das als Spagat bezeiche, ich habe nie angemägelt, dass die Formatierung über die Programmiersprache geschehen sollte. Aber bei einer eindeutigen ID, empfinde ich diese Art der Verwendung nicht schlimm. Mein Codeausschnitt dient auch nur zur Hervorhebung, welche Option mitgegeben wird.




QUOTE [...]
Innerhalb der MS-Welt habe ich mit der obigen Technik die führenden Nullen. Wenn number_format das nicht leistet ... Problem von PHP oder mySql (keine Ahnung, wo die Funktion hingehört).
[...]

Moment oben verwendest Du 2 verschiedene Methoden der Formatierung, einmal für den Geldbetrag, einmal zum Auffüllen von Nullen, in PHP gibt es natürlich Funktionen die so was ähnliches erfüllen, ich will aber nicht den Eindruck erwecken, dass number_format dies ist, welche als Beispiel für den Geldbetrag angeführt wurde. Für Problem 1 wäre das str_pad.

CODE echo str_pad($number, 6, '0', STR_PAD_LEFT);




Trotz allen finde ich bei einer UID das auffüllen der Nullen über die Datenbank nicht schlimm, sondern teilweise sogar für sinnvoll, dies vereinfacht die Wiedererkennung, wenn man in der Datenbank etwas suchen muss. Auch kann die Rechungsid trotzdem jederzeit anders formatiert werden, wenn es bliebt.

 
Zurück
Oben