Hallo alle,
ich möchte Datensätze aus meiner
FB-Datenbank exportieren und diese auf diesem oder anderen Rechnern wieder importieren. Dabei sollen die Daten eine auf diesem Globus oder besser im Universum
eindeutige "unverwechselbare" ID erhalten.
Ich habe jetzt dafür eine sheinbar praktikable Lösung gefunden und will bei Euch einmal nachfragen, was Ihr davon haltet...
In meinem Projekt geht es u.a. um Mannschaften und Spieler. Jede Mannschaft soll eine eindeutige ID erhalten und jeder Spieler natürlich auch.
Die Mannschaften mit den Spielern sollen (incl. ID) exportiert, verteilt und wieder irgendwo importiert werden können (dazu folgt später mal ein eigener Thread mit meinen Fragen zum Import/Export)).
Mein Lösungsansatz zu einer globalen ID (GID):
Es werden 2 Zeitstempel verwaltet und ein Generatorwert.
Zeitstempel 1 wird als MAINGID in einer Tabelle der Datenbank abgelegt, die nur einen Datensatz enthält.
Zeitstempel 2 ist in allen Tabellen als Feld GID enthalten, die über eine eindeutige ID verfügen müssen.
Der GIDGenerator ist ein normaler Generator.
MainGID und GID sind vom Typ D_GID.
Domain D_GID entspricht VARCHAR(50).
Für die Abfrage eines Zeitstempels wird folgende Prozedur benutzt:
Delphi-Quellcode:
ALTER PROCEDURE GET_GID_STAMP
RETURNS (
GID VARCHAR(40))
AS
declare variable S varchar(40);
begin
s = cast(current_timestamp as varchar(40));
gid = substring(s from 1 for 4) ||
substring(s from 6 for 2) ||
substring(s from 9 for 2) ||
substring(s from 12 for 2) ||
substring(s from 15 for 2) ||
substring(s from 18 for 2) ||
substring(s from 21 for 4);
suspend;
end^
Das Ergebnis sieht so aus: "200907311859118060"
MAINGID wird bei before_insert gesetzt sowie bei jedem Programmstart durch einen Prozeduraufruf innerhalb MainForm.OnCreate().
-> In MainGID steht also grundsätzlich die Programmstartzeit.
Die GID´s der einzelnen Tabellen werden später aus der MAINGID und der dann aktuellen Zeit zusammengesetzt, zusätzlich noch mit einem Generatorwert ergänzt und jeweils durch before_insert-Trigger zugewiesen:
Delphi-Quellcode:
ALTER PROCEDURE GET_GID
RETURNS (
GID D_GID)
AS
declare variable GID1 D_GID;
declare variable GID2 D_GID;
declare variable GID3 varchar(10);
begin
select gid from tournamentevent
into :gid1;
if (gid1 is null) then
begin
execute procedure setmaingid;
select gid from tournamentevent
into :gid1;
end
execute procedure get_gid_stamp
returning_values(gid2);
gid3 = cast(gen_id(gen_gid,1) as varchar(10));
gid = gid1 || gid2 || gid3;
suspend;
end^
Das Ergebnis sieht dann etwa so aus: "2009073118591180602009073119122234752"
Ich halte das für eine ID, die zumindest auf der Erde einmalig sein dürfte. Es müssten 2 Nutzer das Programm auf die 1000stel Sekunde gleichzeitig starten und auch einen Datensatz genau zum gleichen Zeitpunkt einfügen und bis dahin genau gleich viele Generator-Erhöhungen durchgeführt haben, damit eine gleiche ID vergeben wird.
Den Nachteil, dass die ID sehr lang ist, kann ich verschmerzen. Die Anzahl der betreffenden Datensätze hält sich bei mir in Grenzen. So bleibt aber auch bei einem späteren Datenaustausch jeder "Datensatz" eindeutig identifizierbar.
Evtl. könnte man überlegen, ob man den zweiten Zeitstempel auf einen "Unterschied zum ersten Zeitstempel" kürzt, aber ich denke, die paar Byte lohnen den Aufwand nicht.
Was haltet Ihr von der Lösung?
Gibt es bessere?
Das ist für mich noch etwas Neuland.
Eine Grundsätzliche Frage noch:
Damit die o.g. Lösung mit den Substrings funktioniert muss der TimeStamp-CAST immer im gleichen Format erfolgen. Offenbar macht dies
FB unabhängig von den Ländereinstellungen immer gleich...
Kann ich aber evtl. auch ein Cast in einer bestimmten Form erzwingen (z.B. "YYYYMMDDHHNNSSTTTT")?
Stahli