Neuigkeiten:

Wenn ihr euch für eine gute Antwort bedanken möchtet, im entsprechenden Posting einfach den Knopf "sag Danke" drücken!

Mobiles Hauptmenü

Primärschlüssel

Begonnen von gsaccess, Februar 06, 2024, 22:02:53

⏪ vorheriges - nächstes ⏩

gsaccess

Eine Frage zum Primärschlüssel bei der Übernahme von Daten.
In der alten Auftrags_Tabelle gibt es einen Primärschlüssel AuftragsID als Autowert und die Auftrag_Nr als Double (wird aus Datum und Uhrzeit gebildet - dies wird unbedingt so gebraucht)
Bei der Übernahme in eine neue Auftrags_Tabelle muss ich wieder einen Primärschlüssel als Autowert und die AuftragsNr anlegen demit die Auftragsnummern richtig übernommen werden.
Oder gibt es hier eine bessere Lösung?
In den Auftragdetails wird dann mit der AuftragsID eine Beziehung erstellt. Damit kann in den Auftragdetails die Auftragnummer abgefragt werden.

Günther

ebs17

ZitatAuftrag_Nr als Double
Das birgt eine Gefährlichkeit, weil Double der Fließkommaproblematik unterliegt und Vergleiche auf Gleichheit schiefgehen könnten. Wenn schon Dezimalzahlen an dieser Stelle, dann Currency oder Decimal.
Mit freundlichem Glück Auf!

Eberhard

MzKlMu

Hallo,
wie sieht eigentlich eine solche Auftragsnummer als Double aus?
Und wie genau wird diese gebildet?
Gruß Klaus

markusxy

Zitat von: gsaccess am Februar 06, 2024, 22:02:53Bei der Übernahme in eine neue Auftrags_Tabelle muss ich wieder einen Primärschlüssel als Autowert und die AuftragsNr anlegen

Du kannst beide Schlüssel sowie allen anderen Daten mittels Einfüge-Abfrage anlegen.
Da gibt es nichts Besonderes zu berücksichtigen - außer natürlich die Beziehungen anzulegen.

gsaccess

ZitatAuftrag_Nr als Double
auf Dezimal kann ich umstellen. Soll dabei die Genauigkeit auf 18 belassen werden?
Zitatwie sieht eigentlich eine solche Auftragsnummer als Double aus?
Und wie genau wird diese gebildet?
der Code für die Bildung der Auftragsnummer:
Dim AuftragAlt As Double
Dim AuftragNeu As Double
'Die Auftragsnummer wird aus Datum und Uhrzeit ermittelt
AuftragNeu = (Format(Now, "yymmddhhnn"))
'Wenn noch keine Daten in tblAuftraege stehen
If IsNull(DMax("(Auftrag_Nr_h)", "t_auftraege")) Then
AuftragAlt = (Format(Now, "yymmddhhnn"))
Else
AuftragAlt = (DMax("(Auftrag_Nr_h)", "t_auftraege"))
End If
'Wenn in der gleichen Minute mehrere Aufträge angelegt werden wird die Auftragsnummer immer um 1 erhöht
If AuftragNeu <= AuftragAlt Then
Me.Auftrag_Nr_h = (AuftragAlt + 1)
Else
Me.Auftrag_Nr_h = AuftragNeu
End If
Dies soll ja auf Dezimalzahl umgestellt werden.

ZitatDu kannst beide Schlüssel sowie allen anderen Daten mittels Einfüge-Abfrage anlegen.
Da gibt es nichts Besonderes zu berücksichtigen - außer natürlich die Beziehungen anzulegen.
Das heißt, dass es auch in der neune Tabelle eine AuftragsID (Autowert =PK) und eine Auftragsnummer (Dezimalzahl) gibt.
Beziehung mit Auftragdetails über die AuftragID.


PhilS

Zitat von: gsaccess am Februar 07, 2024, 13:54:49der Code für die Bildung der Auftragsnummer:
Dim AuftragAlt As Double
Dim AuftragNeu As Double
'Die Auftragsnummer wird aus Datum und Uhrzeit ermittelt
AuftragNeu = (Format(Now, "yymmddhhnn"))

[...]
Dies soll ja auf Dezimalzahl umgestellt werden.
Warum Dezimalzahl?
Der obige Ausdruck ergibt einen String. Behandle ihn dann doch einfach entsprechend.
Du könntest in den Tabellen auch Large Number verwenden, wenn du eine ausreichend aktuelle Access Version hast. Da das aber in VBA recht unhandlich ist, würde ich eher bei dem String bleiben.
Neue Videoserie: Windows API in VBA

Klassische CommandBars visuell bearbeiten: Access DevTools CommandBar Editor

MzKlMu

Hallo,
ich würde Währung (Currency) als Datentyp verwenden, der Ausdruck Format(Now, "yymmddhhnn") ergibt Text der durch die Deklaration als Double (bzw. als Currency) als Zahl angelegt wird. Das wird aber eine Ganzzahl,
Daher dürfte Fließkommaproblematik hier keine Rolle spielen. Double köntte man daher mMn auch lassen.

Und wieso hier dann noch + 1 addiert wird, ist auch eigenartig, wenn wie gesagt die Auftragsnummer immer mit Datum und Zeit gebildet wird.

@phil
Er addiert aber da noch + 1 dazu (warum ist mir unklar) wodurch ein String auch wieder als Zahl behandelt werden müsste.
Gruß Klaus

PhilS

Zitat von: MzKlMu am Februar 07, 2024, 14:30:17Und wieso hier dann noch + 1 addiert wird, ist auch eigenartig, wenn wie gesagt die Auftragsnummer immer mit Datum und Zeit gebildet wird.
Das +1 dient dazu, die Auftragsnummer um 1 zu erhöhen, falls zufällig in derselben Minute von einem anderen Benutzer auch ein Auftrag erstellt wurde. - Damit ist natürlich die ach so zwingende Notwendigkeit die Auftragsnummer aus Datum/Uhrzeit zu bilden etwas ad Absurdum geführt.

@gsaccess, mir scheint es zunehmend so, als würdest du dir selbst mit scheinbar unumstößlichen, aber dann doch eher schwammigen, Anforderungen das Leben schwerer machen, als nötig.
Neue Videoserie: Windows API in VBA

Klassische CommandBars visuell bearbeiten: Access DevTools CommandBar Editor

gsaccess

Zitat@gsaccess, mir scheint es zunehmend so, als würdest du dir selbst mit scheinbar unumstößlichen, aber dann doch eher schwammigen, Anforderungen das Leben schwerer machen, als nötig.
Du hast grundsätzlich recht. Ich habe aber keinen anderen Weg gefunden, wie ich die Fehlermeldung, wenn mehrere Aufträge in der gleichne Minute angelegt werden, vermeiden kann. Zusätzlich die Sekunden mit aufzunehmen würde die Länge der Auftragsnummer unnötig verlängern. Zudem kommt es selten vor, dass Aufträge in der gleichen Minute angelegt werden. Die genaue Minutenzuordnung (oder +1) ist sekundär. Der Auftrag ist fast genau der Minute der Anlage zuzuordnen. Ev. könnte ich ja auch die Sekunden aufnehmen, Würde aber das Problem nur auf die Sekunden verschieben.

Zitatich würde Währung (Currency) als Datentyp verwenden, der Ausdruck Format(Now, "yymmddhhnn") ergibt Text der durch die Deklaration als Double (bzw. als Currency) als Zahl angelegt wird. Das wird aber eine Ganzzahl,
Daher dürfte Fließkommaproblematik hier keine Rolle spielen. Double köntte man daher mMn auch lassen.
Mir ist derzeit nicht klar welche Vor- Nachteile Currency, String bzw. Double in diesem Zusammenhang hat.


PhilS

Zitat von: gsaccess am Februar 07, 2024, 22:30:12Mir ist derzeit nicht klar welche Vor- Nachteile Currency, String bzw. Double in diesem Zusammenhang hat.
Fließkommazahlen, zu denen Double gehört, sind per Definition keine exakten Zahlen, sondern nur Näherungswerte. Auch wenn ich bei deinem konkreten Anwendungsbeispiel keine echtes Problem erwarten würde, ist dieser Datentyp 'aus Prinzip' für einen Primärschlüssel ungeeignet.

Strings sind einfach Zeichenfolgen und somit generell erstmal gut als Primärschlüssel geeignet. Bei der Programmierung in VBA und SQL muss man beachten, dass String-Werte immer in Begrenzer (" oder ') einschließen muss, um Ihren Anfang und Ende deutlich zu machen.

Festkommazahlen (Currency und Decimal) stellen eine wirkliche Zahl dar. Das bedeutet, sie benötigen weniger Speicherplatz als ein String gleicher Länge und man muss nicht mit Begrenzern arbeiten. Führende Nullen werden daher allerdings auch nicht gespeichert, was in deinem Fall relevant wäre falls du noch alte Aufträge aus 2009 und früher in deiner Anwendung hast.
Neue Videoserie: Windows API in VBA

Klassische CommandBars visuell bearbeiten: Access DevTools CommandBar Editor

ebs17

Zitatmehrere Aufträge in der gleichen Minute anlegen
Als ID dafür einen Timestamp verwenden und dann über die Länge klagen ...?

Ein simpler AUTOwert wäre da übersichtlicher, oder eine eigenerzeugte Zahl (Long!) per DMax+1.
Den Timestamp zur Anlage des Auftrages würde man doch sowieso parallel in einem Date-Feld ablegen, um direkt Auswertungen darüber vornehmen zu können.

Oben bist Du doch nur auf Double gekommen, weil Dein gekürzter Zeitstempel 10 Ziffern umfasst, Long als sinnvoller Datentyp aber nur einen Wertebereich bis etwa 2,18 Mrd. hat und damit in der Aufnahme irgendwo im Jahr 2021 endet. Also wie gesagt: Ganz anders machen.
Mit freundlichem Glück Auf!

Eberhard

gsaccess

ZitatAls ID dafür einen Timestamp verwenden und dann über die Länge klagen ...?
Ich verwende einen Autowert AuftragNrID.
Zusätzlich einen Zeitstempel für die Auftragnummer um die alten Daten in der neuen DB mitzuführen.
Nur ein Autowert funktioniert meiner Meinung nach nicht, da ich die Datensätze aus der alten Tabelle übernehmen muss und diese wie oben beschrieben gespeichert sind. Ich könnte den bisherigen Double durch einen anderen Feldtyp ersetzen. (zB 
Die alten Auftragsnummern sind in der alten Datenbank die Basis für die verknüften Tabellen.
Dies ändere ich nun, indem ich den Autowert AuftragNrID als Basis für die verknüften Tabellen verwende.
Die Alten Auftragsnummern muss ich in der neuen Datenbank mitführen, weil die Auftagszettel... auch so ausgedruckt und abgelegt wurden.
Die Auftragsnummer wird mitgeführt, der Primärschlüssel für die in Beziehung stehenden Tabellen ist der Autowert AuftragNrID. (Siehe Beziehungsfenster.)

ZitatMir ist derzeit nicht klar welche Vor- Nachteile Currency, String bzw. Double in diesem Zusammenhang hat.
Danke für die ausführlichen Erklärungen.

markusxy

Zitat von: gsaccess am Februar 08, 2024, 19:06:17Nur ein Autowert funktioniert meiner Meinung nach nicht

Warum bist du wohl der Einzige mit dieser Meinung?

ebs17

Irritierend ist schon, dass es in Deinem beziehungsbild Auftrag_Nr und AuftragNr als solche nicht gibt und man also raten und interpretieren müsste.
Präzision im Beschreiben und in der Sache ist etwas anderes.
Mit freundlichem Glück Auf!

Eberhard

gsaccess

Ich komme hier nochmals auf die am Beginn gestellte Frage zurück:
ZitatIn der alten Auftrags_Tabelle gibt es einen Primärschlüssel AuftragsID als Autowert und die Auftrag_Nr als Double (wird aus Datum und Uhrzeit gebildet - dies wird unbedingt so gebraucht)
Bei der Übernahme in eine neue Auftrags_Tabelle muss ich wieder einen Primärschlüssel als Autowert und die AuftragsNr anlegen demit die Auftragsnummern richtig übernommen werden.
Oder gibt es hier eine bessere Lösung?

Hier noch das Beziehungsbild der alten und neuen Datenbank. Die Auftrag_Nr_h (double) soll in die neue Datenbank importiert werden und muss dabei den alten Wert beibehalten. Wie funktioniert das nur mit einem Autowert?

Günther