Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   FB: Unique Index auf Datum und Uhrzeit (https://www.delphipraxis.net/195085-fb-unique-index-auf-datum-und-uhrzeit.html)

hoika 31. Jan 2018 13:52

Datenbank: FB • Version: 2.01 • Zugriff über: egal

FB: Unique Index auf Datum und Uhrzeit
 
Hallo,
gegeben ist folgende Tabelle:

Id Integer
PersonalId Integer
Datum Date
Uhrzeit Date

So wie es oben schon steht, suche ich eine Möglichkeit, zu verhindern,
dass zur gleichen PersonalId ein Eintrag mit gleicher PersonalId, Datum und Uhrzeit erzeugt wird.
Da Date ja intern Float ist (?), steht für mich die Frage, ob dass über

Unique Index Test on (PersonalId, Datum und Uhrzeit)

funktionieren kann?

jobo 31. Jan 2018 14:04

AW: FB: Unique Index auf Datum und Uhrzeit
 
In Oracle kann Date Type auch Uhrzeiten enthalten.
Wenn das bei FB genauso ist, wäre es fast Glücksache, dass es per Primary Key Constraint über diese Spalte funktioniert.

Wenn die Tabelle nicht bereits tief in Bearbeitung ist und FB auch die Uhrzeit in Date Spalten speichern kann, dann würde ich dazu tendieren, die beiden Spalten zusammenzulegen, also die Spalte Uhrzeit wegzuwerfen.

Trotzdem ist natürlich die Uhrzeit in dem Format auch mit einer gewissen Genauigkeit im hundertstel Bereich gespeichert, was ggF. zu den von Dir befürchteten Effekten führt.

Man kann das aber runden / truncaten, z.B. auf Minuten oder halt so exakt, wie du es brauchst. Dann hast Du im Rahmen der Genauigkeit einen Unique Key (Primary)

dataspider 31. Jan 2018 14:53

AW: FB: Unique Index auf Datum und Uhrzeit
 
Sicher funktioniert das.
Die Frage ist nur, ob Einträge mit 1 Sekunde Abweichungen tatsächlich akzeptiert werden sollen oder nicht.
Wenn nicht, dann sollte man das eher über einen Trigger lösen und die erlaubte Abweichung berücksichtigen.

Frank

Delphi.Narium 31. Jan 2018 15:18

AW: FB: Unique Index auf Datum und Uhrzeit
 
Hilft die Seite weiter? Firebird - Data Types for Dates and Times

In Dialect 3 enthält der Datentyp Date nur das Datum ohne Uhrzeit, der Datentyp Time ist ausschließlich für die Uhrzeit.

Wenn dem wirklich so ist, stellt sich für mich erstmal die Frage: Was ist bei Deiner Tabelle tatsächlich in den Spalten Datum und Uhrzeit enthalten.

hoika 31. Jan 2018 15:55

AW: FB: Unique Index auf Datum und Uhrzeit
 
Hallo,
mir geht es hier in der Tat nur darum,
ob ein Unique Index auf ein Date-Feld wirklich sauber Dopplungen erkennt.

Delphi.Narium 31. Jan 2018 16:21

AW: FB: Unique Index auf Datum und Uhrzeit
 
ja

Ein Index auf eindeutige Werte kann einen Wert nur einmal enthalten, der Datentyp (die Datentypen bei mehreren Spalten im Index) ist dabei egal.

hoika 31. Jan 2018 17:39

AW: FB: Unique Index auf Datum und Uhrzeit
 
Hallo,
nein du hast die letzte Frage nicht verstanden
Unique Index auf ein Date-Feld

Mir geht es um den Datentyp Date, der intern eine Fließkomma-Zahl ist.

Ich bin jetzt am Überlegen, ob ich nicht das Datum als Integer speichere,
und damit den Vorkommawert des TDateTimes reinpacke.

Ich habe eine Dialect1-DB.
Im Feld Datum wird das Datum, und im Feld Zeit die Uhrzeit gespeichert.
Der jeweils andere Teil (Date-Datentyp in Dialect1 kann Datum und Uhrzeit speichern) bleibt frei,
also 30.12.1899 für die Zeit und 00:00 für das Datum.

Zusammenspeichern will ich das nicht, weil ich sonst nicht nach einem Datum direkt suchen kann,
sondern immer nur per Extract, also ohne Index.

Vielleicht speichere ich sogar beides, das Datum als Date und zusätzlich als Integer,
so gesehen ist das eine clevere Idee ;)

Delphi.Narium 31. Jan 2018 18:17

AW: FB: Unique Index auf Datum und Uhrzeit
 
Deine Frage hab' ich schon korrekt verstanden, fraglich ist halt nur, ob ein eindeutiger Index auf ein Datefeld bei 'nem Float-Inhalt, noch genau genug ist (da er ja nicht so zwingend "überpräzise" ist).

Die Trennung von Datum und Uhrzeit halte ich erstmal für i. O.

Datum ist halt Trunc(TDateTime) und die Uhrzeit ist TDateTime - Trunc(TDateTime).

Jenachdem, wie genau Du die Nachkommastellen (die Uhrzeit) haben möchtest, könntest Du dann sowas machen:

Uhrzeit := Trunc((TDateTime - Trunc(TDateTime)) * 10000)

Ob 10000 ausreicht, zuviel oder zuwenig ist, kommt auf Deine Belange an.

Damit hättest Du dann auch die Uhrzeit als Integer.

Eine Sekunde ist als Float = 1,1574074074074074074074074074074e-5, würde also bei obiger Rechnung abgerundet werden.

hoika 31. Jan 2018 22:10

AW: FB: Unique Index auf Datum und Uhrzeit
 
Hallo,
ah so, von der Seite gehst Du ran.
Also eigentlich dem Date als Fließkomma-Zahl prinzipiell misstrauen und alles auf Integer aufbauen.

Sekunden kann ich schon mal ausschließen, bleibt also Minutenzahl also:
1440 Minuten pro Tag übrig
60 min pro 1 h * 24 (24h pro Tag), also 60*24

Oh Mann, muss man wirklich so einen Murks wegen einem Unique Index auf Date machen ??? *wunder*

Delphi.Narium 31. Jan 2018 23:01

AW: FB: Unique Index auf Datum und Uhrzeit
 
Delphi-Quellcode:
Uhrzeit := Trunc((TDateTime - Trunc(TDatetime)) / (1 / 1440))


Mal aufgebröselt:

Delphi-Quellcode:
Datum := Trunc(TDateTime)

Delphi-Quellcode:
TagesAnteil := TDateTime - Datum

Delphi-Quellcode:
EineMinute := 1 / 1440

Delphi-Quellcode:
Uhrzeit := Trunc(TagesAnteil / EineMinute)


Datum würde hier dann die Anzahl der Tage (seit 30.12.1899) als Integer enthalten und Uhrzeit den Tagesanteil in Minuten als Integer.

Hoffentlich hab' ich jetzt keine zu großen Denkfehler gemacht.

p80286 31. Jan 2018 23:16

AW: FB: Unique Index auf Datum und Uhrzeit
 
Zitat:

Zitat von hoika (Beitrag 1392823)
Oh Mann, muss man wirklich so einen Murks wegen einem Unique Index auf Date machen ??? *wunder*

Kommt darauf an welcher zeitlicher Abstand minimal zwischen zwei Einträgen liegen kann. Wenn die Auflösung des Datentyps kleiner als der minimale Abstand der Einträge ist, solltest Du keine Probleme haben.

Gruß
K-H

Delphi.Narium 31. Jan 2018 23:32

AW: FB: Unique Index auf Datum und Uhrzeit
 
Wenn die kleinste Auflösung Minuten sein soll, dann kann ich bei 'nem Floatwert innerhalb einer Minute noch ein paar tausend Floatwerte bekommen, die innerhalb dieser Minute liegen. Mein Index bleibt aber weiterhin eindeutig.

Wenn ich die Uhrzeit als Float habe, aber die Eindeutigkeit auf maximal einem Satz pro Minute liegen soll, komme ich nicht ohne Rechnerei (Datenmanipulation, Umrechnung ...) aus.

hoika 31. Jan 2018 23:53

AW: FB: Unique Index auf Datum und Uhrzeit
 
Hallo,
kommt so im etwa hin.

TigerLilly 1. Feb 2018 06:51

AW: FB: Unique Index auf Datum und Uhrzeit
 
Du hast diesen Aspekt zwar nicht angesprochen, aber als Anregung:
1) Ein unique-Index, zu dem es in der Wirklich keine unique-Eigenschaft gibt, ist ein Design Flaw.
2) Ein unique-Index auf ein Datum/Zeit Attribut verbirgt meistens ein Designproblem.

jobo 1. Feb 2018 07:29

AW: FB: Unique Index auf Datum und Uhrzeit
 
Noch 2 Anmerkungen:
Ein Date Field mit Date und Time Anteil kann man auch unter Verwendung des Index auf Date abfragen indem man <between :gewünschtesDate and :gewünschtesDate+1 verwendet (Der Parameter darf natürlich dann keinen Timeanteil enthalten), analog mit >< Operatoren.
Gibt es den Bedarf auch reine Time Werte derart abzufragen, sieht es allerdings nicht so gut aus.
Ob es dann für das Time Abfrage Problem Anwendungsfälle gibt, sei mal dahin gestellt.

Neben den rechnerischen Verfahren für exakte DateTime Werte von Delphi.Narium kann man auch Textkonvertierung mit Cast nutzen oder mit AddDate (.. Intervall) arbeiten.

Diese Möglichkeiten bestehen hoffentlich auch im alten Dialekt.

hoika 1. Feb 2018 08:45

AW: FB: Unique Index auf Datum und Uhrzeit
 
Hallo,
Zitat:

TigerLilly
Es geht hier nicht ausschließlich um Datum/Uhrzeit,
sondern das sind zusätzliche Felder, die zusammen mit einem anderen Integer-Feld einen eindeutigen Wert erzeugen sollen.

Zitat:

Textkonvertierung mit Cast
Und damit entfällt das Suchen per Index. Das genau will ich nicht.
Das mit dem Between oder >= <= ist schon klar.

DeddyH 1. Feb 2018 08:56

AW: FB: Unique Index auf Datum und Uhrzeit
 
Und wenn man einfach ein neues Feld mit dem "abgeschnittenen" Datum anlegt, das per Trigger befüllt/aktualisiert wird? Das könnte dann VARCHAR oder INT sein, den Index legt man dann auf dieses Feld, so wie man das früher z.B. für einen case-insensitiven UNIQUE-Index auf VARCHAR-Felder machen musste.

hoika 1. Feb 2018 09:02

AW: FB: Unique Index auf Datum und Uhrzeit
 
Hallo,
ich mag keine Trigger ;)
Nö, ich mach das jetzt mit den Extra-Feldern als String.
Ich bin ja der der die Dateneingabe schreibt, und ändern soll sich das auch nicht lassen.

jobo 1. Feb 2018 09:22

AW: FB: Unique Index auf Datum und Uhrzeit
 
Zitat:

Zitat von hoika (Beitrag 1392855)
Zitat:

Textkonvertierung mit Cast
Und damit entfällt das Suchen per Index. Das genau will ich nicht.

Da hab ich mich nicht verständlich ausgedrückt. Ich meinte die Befüllung der Werte.
Ob die per Mathematik zugeschnitten werden (wenn sie eh als Zahl reinkommen) oder mit Textfunktionen (wenn sie bspw. aus einem Textedit stammen oder einer Komponenten, die auch Stringausgabe liefert), sie landen in der gewünschten Genauigkeit in der Spalte und sind in diesem Range dann eindeutig und bieten das Datenmaterial für einen Unique/Primary Constraint (ob jetzt mit oder ohne andere Spalten)

Das Problem der Un-/Wirksamkeit des Index gilt erst bei der Abfrage, wenn dort bspw. auf der Spalte gecastet wird oder mit anderen Funktionen rumgesäbelt wird.
Erlaubt und sinnvoll ist die Anwendung von Funktionen natürlich wieder auf Parameter Seite.
(Indexwirksamkeit hat natürlich gar nichts mit dem Unique Constraint zu tun, sollte aber immer berücksichtigt werden.)

hoika 1. Feb 2018 09:42

AW: FB: Unique Index auf Datum und Uhrzeit
 
Hallo,
ok.

Zitat:

Das Problem der Un-/Wirksamkeit des Index gilt erst bei der Abfrage,
Nein, die Wirksamkeit beginnt bei mir beim Insert.
Dass ich da auch was abfragen kann, ist mir erst mal nebensächlich.
Ich will verhindern, dass im Mehrnutzerbetrieb aus Versehen ein doppelter Datensatz erzeugt wird.
Im Programm prüfe ich das natürlich vorher selbst, aber sicher ist sicher.

jobo 1. Feb 2018 09:59

AW: FB: Unique Index auf Datum und Uhrzeit
 
Zitat:

Zitat von hoika (Beitrag 1392868)

Zitat:

Das Problem der Un-/Wirksamkeit des Index gilt erst bei der Abfrage,
Nein, die Wirksamkeit beginnt bei mir beim Insert.

Ich will verhindern, dass im Mehrnutzerbetrieb aus Versehen ein doppelter Datensatz erzeugt wird.
Im Programm prüfe ich das natürlich vorher selbst, aber sicher ist sicher.

Ich glaube Du vermischt da etwas, was nichts miteinander zu tun hat.
Wie auch immer der Wert beim Insert in die Spalte kommt, geradewegs, mit Funktion verdreht, gekürzt, was auch immer. Der Index wirkt und wird im Falle eines Primary Key Constraint vom Server genutzt um den Primary Key Constraint zu überprüfen.

Die Genauigkeit des Wertes, der eingefügt wird in Kombination mit vorhandenen Werten entscheidet lediglich über das Ergebnis der Primary Key Konstraint Prüfung. Je größer die Genauigkeit, desto unwahrscheinlicher eine Verletzung des Constraints. Je geringer die Genauigkeit, desto wahrscheinlicher die Verletzung (Was natürlich gewollt sein kann, eben ab dem Punkt, auf den man die Genauigkeit justiert)

Startest Du dagegen eine Abfrage und benutzt bspw. Funktionen auf der Spalte, wirkt der Index nicht mehr (im Sinne einer Beschleunigung des Zugriffs)

Ja und nur zur Klarheit in der Diskussion:
Index != Key != Primar Key != Primary Key Konstraint
Bedeutet, das Löschen aller Indizes in der DB ändert nichts an der Eindeutigkeitslogik in Deinem DB Modell, es wird nur alles ziemlich langsam. (Und man müsste sich keine Gedanken mehr über die Wirksamkeit von Indizes in Abfragen machen)

hoika 1. Feb 2018 10:30

AW: FB: Unique Index auf Datum und Uhrzeit
 
Hallo,
Einspruch Eurer Ehren ;)

Zitat:

das Löschen aller Indizes in der DB ändert nichts an der Eindeutigkeitslogik in Deinem DB Modell
Unter Firebird wird die Eindeutigkeit mit Hilfe eines Unique-Index sichergestellt.
Lösche ich den Unique-Index ist auch das Unique-Constraint weg, zumindestens unser FB.
Genauer gesagt, gibt es gar kein Unique-Constraint ohne Unique Index, oder irre ich mich da?

Und genau die Frage der Wahrscheinlichkeit eines "ungenauen" Unique-Index ist ja für mich die Frage.
Speichere Ich eine Uhrzeit, die sich um das 1/1000-tel einer Minute zu einem bestehenden Datensatz unterscheidet, wäre das "doof".
Deshalb speichere ich jetzt Datum und Uhrzeit zusätzlich als String, dessen Format von mir definiert wird,
und genau diese String-Felder neutze ich u.a. für den Unique Index.

jobo 1. Feb 2018 13:34

AW: FB: Unique Index auf Datum und Uhrzeit
 
Zitat:

Zitat von hoika (Beitrag 1392874)
Hallo,
Einspruch Eurer Ehren ;)

Einspruch abgelehnt! ;)

es ging mir erstmal um klare Begriffe. Index versus Constraint, ...
Die Technik: Moderne Datenbanken bieten normalerweise alle (Halb)Automatiken, die einen Index anlegen, sobald ein (Primary)Key-Constraint definiert wird und dann auch umgekehrt, wenn ein Constraint gelöscht wird, wird der Index gelöscht usw usf. Der Index eine ist eine Hilfsdatenstruktur zur Beschleunigung von Abfragen**, der Constraint eine logische Regel.
Darüber hinaus kann man natürlich Indizes selbst definieren (ohne Zusammenhang mit einem Schlüsselkonstraint)

Du möchtest einen Primary Key Constraint über mehrere Felder inkl Date, Time Spalte.
Das soll Eindeutigkeit garantieren, dazu sind diese Konstrukte da, kein Thema. Wird auch funktionieren.
Date / Time haben den "kleinen Randeffekt" mit der Genauigkeit, die musst/kannst Du nach Bedarf justieren (durch Beschneiden der Werte).

Die Problematik mit der Wirksamkeit eines Index zur Beschleunigung hat damit nur am Rande etwas zu tun. Eben bei einer Abfrage, niemals bei einem Insert*.
Wirken tut und wirken soll beim Insert dagegen die Eindeutigkeitsregel, der Primary Key Constraint. Die Überprüfung eines neue Wertes oder Wertegruppe wird beschleunigt durch einen ebenfalls existierenden-weil meist automatisch angelegten- Unique Index, der die vom Server automatisch durchgeführte Suche nach einem bereits vorhandenen, identischen Wert beschleunigt. Auch hier stören keine Casts oder was auch immer.

*die negative Beschleunigung eines zu aktualisierenden Index bei Insert mal außen vor gelassen
** indirekt werden so auch Inserts beschleunigt- durch beschleunigte Abfragen auf Duplikate

Meinetwegen können noch weitere Zeugenaussagen gemacht werden. Ich vertage mich.

hoika 1. Feb 2018 16:24

AW: FB: Unique Index auf Datum und Uhrzeit
 
Hallo,
Waffenstillstand ;)

Aber schön geschrieben und stimmt sogar.

Setzen: 1+

jobo 2. Feb 2018 04:59

AW: FB: Unique Index auf Datum und Uhrzeit
 
Es waren Waffen im Spiel?
;)

p80286 2. Feb 2018 07:30

AW: FB: Unique Index auf Datum und Uhrzeit
 
Hätten sein können!
Als Hoika schrieb Insert fiel mir eine Passage in irgendeinem Datenbankhandbuch ein "Wenn Du einen Unique Index nutzt und eine Doublette eingefügt wird, gibt es eine Fehlermeldung" und jetzt kann man fröhlich darüber streiten ob ein Unique Index das richtige ist um Doubletten zu vermeiden.....

Gruß
K-H

alex517 2. Feb 2018 09:16

AW: FB: Unique Index auf Datum und Uhrzeit
 
Zitat:

Zitat von p80286 (Beitrag 1392956)
Hätten sein können!
Als Hoika schrieb Insert fiel mir eine Passage in irgendeinem Datenbankhandbuch ein "Wenn Du einen Unique Index nutzt und eine Doublette eingefügt wird, gibt es eine Fehlermeldung" und jetzt kann man fröhlich darüber streiten ob ein Unique Index das richtige ist um Doubletten zu vermeiden.....

Gruß
K-H

Ich möchte mich nicht streiten, auch nicht fröhlich:-D aber,
das Einfügen von Doubletten sollte bereits vorher vermieden werden.
Mit dem unique constraint wird jedoch die Integrität der Datenbank sichergestellt,
damit es mit Sicherheit keine Doubletten gibt.

hoika 2. Feb 2018 10:28

AW: FB: Unique Index auf Datum und Uhrzeit
 
Hallo,
Zitat:

Unique Index das richtige ist um Doubletten
Wie weiter oben schon schön erklärt wurde, ist es nicht Index, sondern das Unique Constraint,
was die Doubletten verhindert, und somit die Integrität der Datenbank sichert.
Der Unique Index wird von Firebird zusätzlich angelegt, um schneller nach einem eventuell vorhandenen Wert zu suchen.

Wie soll ich denn sonst verhindern, dass Doubletten in die Datenbank kommen.
Soll etwas ausschließlich das Programm das prüfen?
Was ist, wenn quasi gleichzeitig 2 gleiche Einträge angelegt werden,
oder es einen Bug im Programm gibt?

Als letzte Instanz muss ich der DB sagen können, dass ich da keine Doubletten gibt.

jobo 2. Feb 2018 13:07

AW: FB: Unique Index auf Datum und Uhrzeit
 
Zitat:

Zitat von hoika (Beitrag 1392977)
ist es nicht Index, sondern das Unique Constraint,
was die Doubletten verhindert, und somit die Integrität der Datenbank sichert.
Der Unique Index wird von Firebird zusätzlich angelegt, um schneller nach einem eventuell vorhandenen Wert zu suchen.

Wie soll ich denn sonst verhindern, dass Doubletten in die Datenbank kommen.
Soll etwas ausschließlich das Programm das prüfen?
Was ist, wenn quasi gleichzeitig 2 gleiche Einträge angelegt werden,
oder es einen Bug im Programm gibt?

Als letzte Instanz muss ich der DB sagen können, dass ich da keine Doubletten gibt.

Das sehe ich auch so. Der Unique constraint ist die letzte Instanz, die im Fehlerfall zuschlägt.
Konzeptionell kann man das natürlich ganz verschieden einsetzen.
Bspw. Zufallszahlen als ID eintragen und immer wenn es sie schon gibt, knallt es halt.
Oder es dem User überlassen, so lange eingeben, bis es nicht knallt.
Oder die gängige Variante, eine Sequenz. Knallt selten.
Oder UUID usw.

Vor dem Insert manuell auf Eindeutigkeit zu prüfen macht m.E. keinen Sinn. Das macht die DB mit dem Unique Constraint sowieso. Also doppelte Arbeit und die eine Hälfte vielleicht auch noch vergeblich, weil nach der manuellen Prüfung ja schon Zeit wäre, wo sich der Datenstand verändert. (außer..egal)

Also sinnvoll ist eine ID Quelle, die auf natürliche Weise Eindeutigkeit garantiert oder halt zu 99,xy %. Und da schließt sich der Kreis, denn man könnte bspw. Datum / Uhrzeit nehmen. Soetwas muss natürlich mit der Entstehungsfreuenz der Datensätze dann abgestimmt sein.


"Beschießt" man das System bewusst mit nicht eindeutigen Werten, kann man sich zwar auf den Constraint verlassen, aber verpulvert natürlich ohne Not sehr viel Ressourcen. Wer's mag..
Ich glaube nicht, dass das im Sinne eines Höhentrainings unter Sauerstoffmangel später zu einer Leistungssteigerung des Systems führt, wenn es wieder normal genutzt wird. Training ist für KI Systeme, nicht für Fehlerbehandlungsroutinen.

hoika 2. Feb 2018 16:12

AW: FB: Unique Index auf Datum und Uhrzeit
 
Hallo,
Zitat:

Vor dem Insert manuell auf Eindeutigkeit zu prüfen macht m.E. keinen Sinn
Doch macht es, weil man dann eine schöne Meldung bringen kann ala "Datensatz bereits vorhanden".
Aus der DB-Exception herauszufinden, warum der Datensatz nicht angelegt werden konnte, ist schwerer.

Delphi.Narium 2. Feb 2018 16:55

AW: FB: Unique Index auf Datum und Uhrzeit
 
Ja, aber im Mehrbenutzerbetrieb dürfte das Unterfangen, Dubletten hauptsächlich per Programmcode zu ermitteln, eher schwierig werden, auf jeden Fall keinesfalls verlässlich.

In 'ner DB-Exception steht gewöhnlich drin, was passiert ist, Schlüsselverletzung ...

Wenn ich also einen Datensatz speichere und dann als Exception einen Constraintverletzung bekomme oder eine Verletzung eines eindeutigen Schlüssels, weiß ich schon, dass es sich um eben diese handelt. Und im Zusammenhang mit der Fachlichkeit, bei der der Fehler auftritt, sollte ich damit durchaus in der Lage sein, dem Anwender eine aussagefähige Meldung zu geben bzw. im Programm entsprechend zu reagieren.

Wenn man im Programm vor dem Speichern auf eventuell mögliche Schlüsselverletzungen prüft, so kann man dann zwar auch schon reagieren, muss aber beim Speichern trotzdem nochmal mit dem Auftreten einer entsprechenden DB-Exception rechnen und die dann auch vernünftig und aussagefähig für den Anwender handhaben.

An einer vernünftigen Verarbeitung von Datenbankfehlern kommt man also nicht vorbei. Die vorherige Prüfung ausserhalb der Datenbank ist also höchstens ein "Nice To Have", dass den Programmierer beruhigt, aber keinesfalls ein sicherer Umgang zur Vermeidung von Dubletten.

Die ausschließliche oder überwiegende Prüfung von Schlüsselverletzungen im Programm kann man (meiner Meinung nach) nur dann ernstlich in betrachtziehen, wenn absolut sichergestellt ist, dass eine Datenbank nur von einem Programm und einem Nutzer zeitgleich genutzt wird, also ein exklusiver Zugriff auf die Datenbank vorliegt.

jobo 3. Feb 2018 06:27

AW: FB: Unique Index auf Datum und Uhrzeit
 
Zitat:

Zitat von hoika (Beitrag 1393009)
Hallo,
Zitat:

Vor dem Insert manuell auf Eindeutigkeit zu prüfen macht m.E. keinen Sinn
Doch macht es, weil man dann eine schöne Meldung bringen kann ala "Datensatz bereits vorhanden".
Aus der DB-Exception herauszufinden, warum der Datensatz nicht angelegt werden konnte, ist schwerer.

Also es gibt nur wenige Meldungen, die so eindeutig sind wie eine Primärschlüsselverletzung- Fehlermeldungen bestehen ja originär aus einer Nummer, die man in der Exception abfangen kann. Die Natur des Fehlers "Primärschlüsselverletzung" bedeutet prinzipbedingt, dass auch keine weiteren Fehler aus der Anweisung folgen.
Es besteht also gar nicht die Möglichkeit, dass das System andere Fehler liefert, falsche Fremdschlüssel oder was auch immer bemeckert, weil es soweit gar nicht kommt.

Und es gilt auch was Delphi.Narium schreibt, in einem Mehrbenutzersystem ist eine manuelle Duplikat-Prüfung Glückssache. Außer:
- manuelle Prüfung und tatsächliches Insert werden in einer Transaktion durchgeführt
- die fachliche Datenlage erlaubt gar keine Duplikate (dann brauche ich aber auch keine Prüfung)

Im Zusammenhang mit der Thematik Date/Time Value als Teil des Primärschlüssels kommt hinzu, das die Fachlichkeit unscharf wird und sich die Frage stellt, was dieses Konstrukt eigentlich regulieren soll. Eine Art Floodlimit, ..?

Wenn 2 Sachbearbeiter in einem Büro einen Stapel von Bauanträgen eintippen, kann nichts passieren.
Wenn 2 Verkäufer am Telefon eines Verkaufssenders die letzten 3 Superdampfbügeleisen verkaufen, sieht es allerdings anders aus.

himitsu 3. Feb 2018 07:38

AW: FB: Unique Index auf Datum und Uhrzeit
 
Zitat:

Zitat von jobo (Beitrag 1392701)
In Oracle kann Date Type auch Uhrzeiten enthalten.

Das wäre auch besser, denn sein Uhrzeit-Feld ist ja auch als DATE und nicht als TIME deklariert. :stupid:

Jupp, also theoretisch würde der Index ja funktionieren. (aber wie bereits genannt wurde, gibt es das Hindernis mit den ungenauen Werten)
SQL-Code:
CREATE UNIQUE INDEX DeineTabelle_id_datetime ON DeineTabelle (PersonalId, Datum, Uhrzeit)


Aber zur Sicherheit kannst du deine Zeit-Werte auch im Index umrechnen/casten, zusammenfassen und vor allem auf ein gewünschtes Maß "runden".
z.B. beim Datum die eventuelle Uhrzeit entfernen und die Uhrzeit auf Sekunden runden. (Trunc/Extract)
SQL-Code:
CREATE UNIQUE INDEX DeineTabelle_id_datetime ON DeineTabelle COMPUTED BY (PersonalId, CAST(Datum AS DATE), CAST(Uhrzeit AS TIME)); -- Cast geht wohl nicht, wenn DATE = DATETIME
CREATE UNIQUE INDEX DeineTabelle_id_datetime ON DeineTabelle COMPUTED BY (PersonalId, Trunc(Datum) + (Uhrzeit - Trunc(Uhrzeit)));
CREATE UNIQUE INDEX DeineTabelle_id_datetime ON DeineTabelle COMPUTED BY (PersonalId, DateAdd(Trunc(Datum), Uhrzeit));
...
Einen Cast/Round um Uhrzeit auf Sekunden zu runden oder ein
Delphi-Quellcode:
Cast(Extract(Uhrzeit, SecondOfDay) AS INTEGER)
gibt es wohl nicht?

Zitat:

Aus der DB-Exception herauszufinden, warum der Datensatz nicht angelegt werden konnte, ist schwerer.
Gut, man könnte auch über einen BeforeInsert-Trigger alles "nochmals" prüfen und eine bessere Fehlermeldung ausgeben.
Genauso kann man aber dem UniqueIndex auch einen sprechenden Namen geben, da er doch in der Fehlermeldung genannt wird.
Man könnte sich auch in die Error-Events der Connection/Querykomponente hängen und da den Triggernamen übersetzen, bzw. die Fehlermeldung um etwas Verständlicheres ergänzen.

IBExpert 3. Feb 2018 07:47

AW: FB: Unique Index auf Datum und Uhrzeit
 
was man wissen sollte:

Primärschlüssel und Unique Constraints werden von Firebird auch ohne commit auf Eindeutigkeit geprüft.

Kann man relativ einfach verstehen wenn man mit IBExpert oder isql 2 Instanzen öffnet und auf einer
Tabelle mit PK oder unique constraint in beiden Sitzungen einen identischen Insert macht, ohne den
zu committen.

Ablauf Beispiel auf einer leeren Tabelle mit PK auf der ID Spalte
create table tab(id bigint not null primary key);

1. Client 1: Select * from Tab where id=1;
2. Client 1: Select ausführen starten automatisch eine Transaktion für diese connection
3. Client 1: Weil die Tabelle beim Start leer war kommt kein Ergebnis

4. Client 2: Select * from Tab where id=1
5. Client 2: Select ausführen starten automatisch eine Transaktion für diese connection
6. Client 2: Weil die Tabelle beim Start und immer noch leer ist kommt kein Ergebnis

7. Client 1: insert into tab(id) values (1);
8. Client 1: Befehl wird fehlerfrei ausgeführt, aber Transaktion ist noch aktiv.
9. Client 1: Select * from Tab where id=1;
10.Client 1: In dieser Session sieht Client 1 den selbst erzeugten Datensatz auch wenn noch kein commit erfolgt ist

11. Client 2: Select * from Tab where id=1;
12. Client 2: Obwohl in der Tabelle schon ein Datensatz von Client 1 enthalten ist, sieht client 2 den nicht, weil der noch nicht committed ist (Stichwort MGA Multigenerations Architektur)
13. Client 2: Da kein Datensatz sichtbar ist versucht Client 2 den anzulegen
14. Client 2: insert into tab(id) values (1);
15. Client 2: Befehl wird sofort mit Fehler beendet, weil schon eine PK Verletzung vorliegt, auch wenn der konkurrierende Datensatz noch nicht committed ist.

Technisch wird der PK Wert schon in den Unique Indexbaum eingetragen, auch ohne commit. Wenn da schon einer ist, knallt es bei Unique.

Genau für solche Zwecke wurden die Sequenzen/Generatoren entworfen. Über den serverseitig serialisierten Aufruf der Funktion GEN_ID() wird Erhöhen, zurückschreiben und Ergebnis anzeigen unabhängig von Transaktionen netzwerksicher implementiert.

Zurück zur Ausgangsfrage Timestamp als Unique: CURRENT_TIMESTAMP unterstützt maximal Millisekunden. Also sind maximal 1000 unterschiedliche Werte pro Sekunde möglich. Die Auflösung der Zeitfunktionen unter Windows ist aber wesentlich geringer, man liest im Schnitt von 15ms und das entspricht auch meiner Erfahrung. Wer Spaß dran hat kann ggf eigene Datentypen nutzen und eine nanosekunden genaue Zeit über assembler funktionen abfragen (geht ggf auch als udf), löst aber das Problem nicht, weil auch da kein Unique garantiert werde kann.

Einen Zeitstempel als Unique anzunehmen ist bei langsam eintrudelnden Daten von nur einer Quelle durchaus denkbar, aber im Netzwerkbetrieb und bei schneller Datenerzeugung der falsche Weg (nicht nur unter Firebird)

p80286 3. Feb 2018 09:09

AW: FB: Unique Index auf Datum und Uhrzeit
 
In einigen vorigen Beiträgen wurde auf den Primärschlüssel hingewiesen. Der ist in diesem Zusammenhang irrelevant.
Zitat:

gegeben ist folgende Tabelle:

Id Integer
PersonalId Integer
Datum Date
Uhrzeit Date

So wie es oben schon steht, suche ich eine Möglichkeit, zu verhindern,
dass zur gleichen PersonalId ein Eintrag mit gleicher PersonalId, Datum und Uhrzeit erzeugt wird
Es könnte also sein, daß Datensätze generiert werden (von wem auch immer), in denen PersonalID,Datum,Uhrzeit gleich sind. Diese Doubletten dürfen nicht gespeichert werden.
Also sollte die Auflösung der Uhrzeit so groß sein, daß doppelte Werte nicht möglich sind. Ist das nicht möglich, sollte eine Hilfskonstruktion wie z.B. ein Index-Feld (integer) für gleiche Datensätze verwendet werden. Oder aber es wäre zu Überlegen ob Uhrzeit überhaupt das richtige Unterscheidungskriterium wäre.

Gruß
K-H

jobo 3. Feb 2018 09:35

AW: FB: Unique Index auf Datum und Uhrzeit
 
Zitat:

Zitat von p80286 (Beitrag 1393025)
In einigen vorigen Beiträgen wurde auf den Primärschlüssel hingewiesen. Der ist in diesem Zusammenhang irrelevant.
Zitat:

gegeben ist folgende Tabelle:

Id Integer
PersonalId Integer
Datum Date
Uhrzeit Date

So wie es oben schon steht, suche ich eine Möglichkeit, zu verhindern,
dass zur gleichen PersonalId ein Eintrag mit gleicher PersonalId, Datum und Uhrzeit erzeugt wird
Es könnte also sein, daß Datensätze generiert werden (von wem auch immer), in denen PersonalID,Datum,Uhrzeit gleich sind. Diese Doubletten dürfen nicht gespeichert werden.
Also sollte die Auflösung der Uhrzeit so groß sein, daß doppelte Werte nicht möglich sind. Ist das nicht möglich, sollte eine Hilfskonstruktion wie z.B. ein Index-Feld (integer) für gleiche Datensätze verwendet werden. Oder aber es wäre zu Überlegen ob Uhrzeit überhaupt das richtige Unterscheidungskriterium wäre.



Der Primärschlüssel wird ja diskutiert, ob er geeignet ist das Ziel zu erreichen. Aber Deine Ausführungen streifen m.E. wie einige andere Beiträge einen Knackpunkt, der vielleicht bei der Auflösung hilft.
Der exakte, gewünschte Nutzen von Datum/Uhrzeit als sagen wir mal "Hilfsmittel" zur Eindeutigkeit ist eigentlich gar nicht klar:

Soll maximale Auflösung erreicht werden?
Oder soll im Gegenteil eine Beschränkung stattfinden?

Im ersten Fall komme ich selbst durch Kombination mit den anderen Schlüsselfeldern irgendwo an eine Grenze. Datum/Uhrzeit/Sekunden/Millisekungen* sind bei dem Datentyp beschränkt.
Im 2. Fall kann ich durch Beschneiden der Uhrzeit definieren, wie viel Datensätze es denn sein dürfen. Eine Kürzung des gespeicherten Wertes z.B. auf Sekunden würde ergeben, dass nicht mehr als 60 Werte pro Minute (in Kombination mit den anderen Schlüsselfeldern) gespeichert werden können.


Alle Zeitangaben in WEZ +1. Es ist jetzt 00:47 Uhr.

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