Für alle die vor dem Problem stehen, dass sie eine global eindeutige ID benötigen will ich euch nachfolgend meine Lösung präsentieren.
Natürlich gibt es das MySQL Feature autoincrement, allerdings liefert es nur eindeutige IDs innerhalb einer Tabelle. Wer aber eine ID benötigt die über mehrere Tabellen eindeutig ist kommt mit auoincrement nicht weiter. Grundsätzlich müssen wir also eine aus PostgreSQL oder Oracle bekannte Sequence simuliern, da MySQL nichts gleichwertiges anbietet.
Nun könnte man sich ja einfach eine neue Tabelle erstellen und sich einfach nur die letzte ID merken. Also einfach nur alten Wert erfragen, hochzählen und den neuen Wert wieder speichern.
ABER was passiert wenn zwei Clients zur gleichen Zeit den alten Wert auslesen? Kurz gesagt: wir haben
zweimal die gleiche ID.
Also müssen wir noch sicherstellen, dass das nicht passieren kann:
DROP TABLE IF EXISTS seqs; DROP FUNCTION IF EXISTS nextval; DROP FUNCTION IF EXISTS curval; DROP PROCEDURE IF EXISTS seq_reset; CREATE TABLE seqs ( seq_name VARCHAR(30), start INT, increment INT, curval INT, flag CHAR(1) ); INSERT INTO seqs VALUES('smkid',1,1,1,'A'); DELIMITER | CREATE FUNCTION `nextval`(v_seq_name varchar(30)) RETURNS INT DETERMINISTIC SQL SECURITY DEFINER COMMENT '' BEGIN DECLARE v_flag CHAR(1); DECLARE v_nextval INT; SET v_flag='N'; WHILE (v_flag='N') DO SELECT flag into v_flag FROM seqs WHERE seq_name=v_seq_name; END WHILE; UPDATE seqs SET flag='N' WHERE seq_name=v_seq_name; SELECT curval + increment INTO v_nextval FROM seqs WHERE seq_name=v_seq_name; UPDATE seqs SET flag='A',curval=v_nextval WHERE seq_name=v_seq_name; RETURN v_nextval; END | CREATE FUNCTION `curval`(v_seq_name varchar(30)) RETURNS INT DETERMINISTIC SQL SECURITY DEFINER COMMENT '' BEGIN DECLARE v_curval INT; SELECT curval INTO v_curval FROM seqs WHERE seq_name=v_seq_name; return v_curval; END | CREATE PROCEDURE `seq_reset`(v_seq_name varchar(30)) DETERMINISTIC SQL SECURITY DEFINER COMMENT '' BEGIN UPDATE seqs SET curval=start,flag='A' WHERE seq_name=v_seq_name; END; | DELIMITER ;
Nachdem Ihr den Code auf eurer Datenbank ausgeführt habt könnt Ihr nun mit:
SELECT curval('smkid')
den akutellen Wert der Sequenz ‘smkid’ abfragen
SELECT nextval('smkid')
den nächsten Wert der Sequenz ‘smkid’ abfragen
CALL seq_reset('smkid')
die Sequenz ‘smkid’ auf Ihren Startwert zurücksetzen.
Falls Ihr eine weitere unabhängige Sequenz benötigt könnt Ihr diese wie folgt anlegen:
INSERT INTO seqs VALUES('MeineSequenz',1,1,1,'A');