Access-o-Mania

Access-Forum (Deutsch/German) => Tabelle/Abfrage => Thema gestartet von: gsaccess am Februar 06, 2024, 22:02:53

Titel: Primärschlüssel
Beitrag von: gsaccess am Februar 06, 2024, 22:02:53
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
Titel: Re: Primärschlüssel
Beitrag von: ebs17 am Februar 06, 2024, 23:27:44
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.
Titel: Re: Primärschlüssel
Beitrag von: MzKlMu am Februar 07, 2024, 01:46:17
Hallo,
wie sieht eigentlich eine solche Auftragsnummer als Double aus?
Und wie genau wird diese gebildet?
Titel: Re: Primärschlüssel
Beitrag von: markusxy am Februar 07, 2024, 08:06:35
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.
Titel: Re: Primärschlüssel
Beitrag von: gsaccess am Februar 07, 2024, 13:54:49
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.

Titel: Re: Primärschlüssel
Beitrag von: PhilS am Februar 07, 2024, 14:14:00
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.
Titel: Re: Primärschlüssel
Beitrag von: MzKlMu am Februar 07, 2024, 14:30:17
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.
Titel: Re: Primärschlüssel
Beitrag von: PhilS am Februar 07, 2024, 15:08:19
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.
Titel: Re: Primärschlüssel
Beitrag von: gsaccess am Februar 07, 2024, 22:30:12
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.

Titel: Re: Primärschlüssel
Beitrag von: PhilS am Februar 08, 2024, 17:07:19
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.
Titel: Re: Primärschlüssel
Beitrag von: ebs17 am Februar 08, 2024, 18:06:51
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.
Titel: Re: Primärschlüssel
Beitrag von: gsaccess am Februar 08, 2024, 19:06:17
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.
Titel: Re: Primärschlüssel
Beitrag von: markusxy am Februar 09, 2024, 10:20:03
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?
Titel: Re: Primärschlüssel
Beitrag von: ebs17 am Februar 09, 2024, 11:12:29
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.
Titel: Re: Primärschlüssel
Beitrag von: gsaccess am Februar 09, 2024, 13:38:11
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
Titel: Re: Primärschlüssel
Beitrag von: gsaccess am Februar 11, 2024, 20:21:36
Was halten die Fachleute von einem Primärschlüssel der wie folgt erstellt wird:
AuftragID= (Format(Now, "yymmddhhnnss"))Datentyp könnte wie oben diskutuiert Dezimal, Double oder String sein.
Autowert funktioniert nicht, da bei einem Autowert die alten Daten nicht übernommen werden können.

Vielleicht komme ich so weiter.

Über eine Antwort bei der Bedenken oder Nogoes auch begründet werden, würde ich mich freuen.

Günther
Titel: Re: Primärschlüssel
Beitrag von: Beaker s.a. am Februar 12, 2024, 16:32:42
Hallo Günther,
ZitatWas halten die Fachleute von einem Primärschlüssel der wie folgt erstellt wird:
Nicht viel würde ich denken. Bleibe bei einem Autowert für die AuftragsID. Deine AuftragsNr
kannst du ja trotzdem in dem Format erzeugen. Die Beziehungen laufen ja alle über die ID,
wenn ich mich nicht verguckt habe.
Um die Beziehungen mit der neuen Tabelle = neuer AutoWert wie vorher wieder herzustellen
würde ich dieser eine Spalte gönnen für die alte ID. Über diese kannst du dann in einer
Abfrage die Detailtabellen verknüpfen und den FK aktualisieren.

gruss ekkehard
Titel: Re: Primärschlüssel
Beitrag von: gsaccess am Februar 14, 2024, 07:40:52
Vielen Dank für deine ausführliche Antwort.
In der alten Tabelle wurden die Detailtabellen mit der Auftrag_nr verknüpft.
Bei der Übernahme der Daten wäre dies auch einfacher.
Ich werde aber beide Varianten versuchen.

Günther
Titel: Re: Primärschlüssel
Beitrag von: Beaker s.a. am Februar 15, 2024, 16:30:41
Hallo Günther,
ZitatIn der alten Tabelle wurden die Detailtabellen mit der Auftrag_nr verknüpft.
Wenn es damit keine Probleme gegeben hat, kannst du diese Beziehung
ja für die Aktualisierung der Detailtabellen verwenden.
Diese bekommen ein neues Feld für den FK "AuftragID_F" (LongInteger)
in das du dann die neue ID überträgst. Anschliessend kannst das alte
Feld (Auftrag_nr) löschen, - die Nummer steht ja schon in der Haupt-
tabelle.

gruss ekkehard