Sie können alles tun, was Sie für SQL-Trigger benötigen. Das folgende SQL fügt einen Trigger für tablename.table_id
hinzu, um die UUID des Primärschlüssels beim Einfügen automatisch zu erstellen, und speichert die neu erstellte ID anschließend zum späteren Abruf in einer SQL-Variablen:
Als Bonus fügt es die UUID in binärer Form in ein binäres (16) Feld ein, um Speicherplatz zu sparen und die Abfragegeschwindigkeit erheblich zu erhöhen.
edit: Der Trigger sollte nach einem vorhandenen Spaltenwert suchen, bevor er seine eigene UUID einfügt, um die Fähigkeit zu simulieren, Werte für Tabellenprimärschlüssel in MySQL zu liefern - ohne dass irgendwelche übergebenen Werte immer von überschrieben werden der Auslöser. Das Beispiel wurde aktualisiert, um ASCII() = 0
zu verwenden, um nach dem Vorhandensein des Primärschlüsselwerts im INSERT zu suchen, der leere Zeichenfolgenwerte für ein Binärfeld erkennt.
edit 2: nach einem Kommentar Hier wurde mir seither darauf hingewiesen, dass die Verwendung von BEFORE INSERT
die Variable @last_uuid
selbst dann setzt, wenn das Einfügen der Zeile fehlschlägt. Ich habe meine Antwort aktualisiert, um AFTER INSERT
zu verwenden - während ich dies unter den allgemeinen Umständen als völlig akzeptabel empfinde, könnte es Probleme bei der Zeilenreplikation unter geclusterten oder replizierten Datenbanken geben. Wenn jemand weiß, würde ich auch gerne!
Um die Einfüge-ID der neuen Zeile wieder zu lesen, führen Sie einfach SELECT @last_uuid
.
Beim Abfragen und Lesen solcher Binärwerte sind die MySQL-Funktionen HEX()
und UNHEX()
sehr hilfreich, ebenso wie das Schreiben Ihrer Abfragewerte in Hex-Notation (mit vorangestelltem 0x
). Der php-side-Code für Ihre ursprüngliche Antwort würde bei diesem Typ von Trigger, der auf Tabelle1 angewendet wird, lauten:
Als Reaktion auf @inas Kommentar :
Eine UUID ist keine Zeichenfolge, auch wenn MySQL sie als solche darstellt. Es sind binäre Daten in ihrer rohen Form, und diese Bindestriche sind nur die freundliche Art, sie von MySQL für Sie darzustellen.
Der effizienteste Speicher für eine UUID ist, sie als UNHEX(REPLACE(UUID(),'-',''))
zu erstellen - dadurch wird diese Formatierung entfernt und in binäre Daten zurückkonvertiert. Diese Funktionen werden die ursprüngliche Einfügung verlangsamen, aber alle folgenden Vergleiche, die Sie für diesen Schlüssel oder diese Spalte durchführen, werden in einem 16-Byte-Binärfeld viel schneller sein als eine 36-Zeichen-Zeichenfolge.
Zum einen müssen Zeichendaten analysiert und lokalisiert werden. Alle Zeichenfolgen, die in die Abfrage-Engine eingehen, werden im Allgemeinen automatisch mit dem Zeichensatz der Datenbank verglichen, und einige APIs (wordpress kommt mir in den Sinn) lassen sogar CONVERT()
für alle Zeichenfolgendaten vor der Abfrage laufen. Binärdaten haben diesen Overhead nicht. Für den anderen reserviert Ihr char(36)
tatsächlich 36 Zeichen , was bedeutet, dass (wenn Ihre Datenbank UTF-8 ist) jedes Zeichen so lang sein kann wie 3 oder 4 Byte , abhängig von der verwendeten MySQL-Version. Ein char(36)
kann also irgendwo zwischen 36 Bytes (wenn es vollständig aus ASCII-Zeichen besteht) bis 144 reichen, wenn es vollständig aus UTF8-Zeichen höherer Ordnung besteht. Dies ist viel größer als die 16 Bytes, die wir für unser Binärfeld reserviert haben.
Jede Logik, die für diese Daten ausgeführt wird, kann mit UNHEX()
durchgeführt werden, wird jedoch besser durch einfaches Entkommen von Daten in Abfragen als hex mit dem Präfix 0x
erreicht. Dies ist genauso schnell wie das Lesen einer Zeichenfolge, wird im laufenden Betrieb in binäre konvertiert und direkt der fraglichen Abfrage oder Zelle zugewiesen. Sehr schnell.
Das Auslesen von Daten ist etwas langsamer - Sie müssen HEX()
für alle aus einer Abfrage gelesenen Binärdaten aufrufen, um sie in ein nützliches Format zu bringen, wenn Ihre Client-API nicht gut mit binären Daten zurechtkommt binary strings === null
und bricht sie, wenn manipuliert, ohne zuerst bin2hex()
, base64_encode()
oder ähnliches aufzurufen - aber dieser Overhead ist ungefähr so minimal wie die Zeichenkollation und, was noch wichtiger ist, wird nur für die tatsächlichen Zellen SELECT
ed aufgerufen , nicht alle Zellen, die an den internen Berechnungen eines Abfrageergebnisses beteiligt sind.
Natürlich sind all diese kleinen Geschwindigkeitssteigerungen sehr minimal und andere Bereiche führen zu kleinen Verringerungen - aber wenn Sie sie addieren, kommt% up_co_de% immer noch an die Spitze, und wenn Sie Anwendungsfälle und die allgemeinen 'liest & gt; schreibt 'Prinzip es scheint wirklich.
... und deshalb ist binary
besser als binary(16)
.
Abhängig davon, wie die uuid () -Funktion implementiert wird, ist dies eine sehr schlechte Programmierpraxis. Wenn Sie dies mit aktiviertem binärem Logging (dh in einem Cluster) versuchen, wird die Einfügung meisten wahrscheinlich scheitern . Ivans Vorschlag sieht so aus, als ob er das unmittelbare Problem lösen könnte - aber ich dachte, das würde nur den Wert ergeben, der für ein Auto-Inkrement-Feld generiert wurde - tatsächlich ist das was das Handbuch sagt .
Was ist auch der Vorteil einer Uuid ()? Es ist rechenintensiv zu generieren, erfordert viel Speicherplatz, erhöht die Kosten für die Abfrage der Daten und ist nicht kryptographisch sicher. Verwenden Sie stattdessen einen Sequenzgenerator oder Autoincrement.
Unabhängig davon, ob Sie einen Sequenzgenerator oder eine UUID verwenden, müssen Sie diesen Wert als einzigen eindeutigen Schlüssel in der Datenbank verwenden. Dann müssen Sie den Wert zuerst zuweisen, in phpland zurücklesen und den Wert als einbetten / binden ein Literal für die nachfolgende Einfügeabfrage.