Kann ich eine Funktion für einen Standardwert in MySQL verwenden?

92

Ich möchte so etwas machen:


create table app_users
(
    app_user_id smallint(6) not null auto_increment primary key,
    api_key     char(36) not null default uuid()
);

Dies führt jedoch zu einem Fehler. Gibt es eine Möglichkeit, eine Funktion für einen Standardwert in MySQL aufzurufen?

Vielen Dank.

mmattax
quelle

Antworten:

127

Nein, das kannst du nicht.

Sie können jedoch leicht einen Auslöser dafür erstellen, z. B.:

CREATE TRIGGER before_insert_app_users
  VOR EINFÜGEN IN app_users 
  FÜR JEDE REIHE
  SET new.api_key = uuid ();
Harrison Fisk
quelle
2
@Siehe stackoverflow.com/questions/6280789/… zum Auffüllen von UUIDs in vorhandenen Zeilen.
Sam Barnum
2
Dies ist nicht ganz dasselbe wie ein DEFAULT-Wert. Wie würde man diese Antwort ändern, um den Schlüssel nur zu setzen, wenn der Wert NULL wäre?
ToolmakerSteve
1
Schade, dass es MySQL schon so lange gibt, aber Sie können keine Standard-UUID für eine Spalte ohne Trigger implementieren. Der Grund dafür liegt in der Technologie der 1980er Jahre, die anscheinend noch im MySQL- Basiscode vorhanden ist
RyanNerd
1
@RodolVelasco Die UUID-Funktion ist hochgradig kollisionssicher. Viel mehr als md5. Sobald Sie die UUID md5, haben Sie ein höheres Risiko für ID-Kollision
Cruncher
2
SET new.api_key = COALESCE(new.api_key, uuid())bestehende Werte zu erhalten.
Ryan
28

Ab MySQL v8.0.13 ist es möglich, einen Ausdruck als Standardwert für ein Feld zu verwenden:

Der in einer DEFAULT-Klausel angegebene Standardwert kann eine Literalkonstante oder ein Ausdruck sein. Schließen Sie mit einer Ausnahme die Standardwerte für Ausdrücke in Klammern ein, um sie von den Standardwerten für Literalkonstanten zu unterscheiden.

CREATE TABLE t1 (
  uuid_field     VARCHAR(32) DEFAULT (uuid()),
  binary_uuid    BINARY(16)  DEFAULT (UUID_TO_BIN(UUID()))
);
Schatten
quelle
1
Beachten Sie, dass gemäß den bereits verknüpften Dokumenten in Antwort: ... gespeicherte Funktionen und benutzerdefinierte Funktionen nicht zulässig sind . Das heißt, die einzigen Funktionen, die als Standardausdrücke verwendet werden können, sind integrierte Funktionen.
Ascherbar
1
Ab Mai 2020 sollte dies die richtige Antwort sein. Die anderen Antworten mit Triggern sind veraltet.
John Stock
19

Wie schon gesagt, kannst du nicht.

Wenn Sie dieses Verhalten simulieren möchten, können Sie einen Trigger folgendermaßen verwenden:

CREATE TRIGGER before_insert_app_users
BEFORE INSERT ON app_users
FOR EACH ROW
  IF new.uuid IS NULL
  THEN
    SET new.uuid = uuid();
  END IF;

Sie müssen noch vorhandene Zeilen wie folgt aktualisieren:

UPDATE app_users SET uuid = (SELECT uuid());
Pamput
quelle
8

Leider nein, MySQL 5 benötigt standardmäßig Konstanten. Das Problem wurde unter dem folgenden Link ausführlicher erörtert. Die einzige Antwort ist jedoch, null zuzulassen und einen Tabellenauslöser hinzuzufügen.

MySQL hat UUID erst kürzlich als Teil seines DB-Pakets akzeptiert und es ist nicht so funktionsreich, wie wir es gerne hätten.

http://www.phpbuilder.com/board/showthread.php?t=10349169

TravisO
quelle
1
Ich sollte hinzufügen, dass das Zulassen von NULL und das Verlassen auf Trigger möglicherweise funktioniert, aber die meisten Entwickler würden es als eine sehr hackige Lösung betrachten. Ich würde es nicht persönlich empfehlen, sondern jedem sein eigenes.
TravisO
6

Ich glaube du kannst nicht :

Der Standardwert muss eine Konstante sein. Es kann keine Funktion oder ein Ausdruck sein

Thibaut Barrère
quelle
Nicht wahr, Sie können getdate ()
amr osama
6
@amrosama - Nein, das kannst du nicht. getdate()ist nicht einmal eine MySQL-Funktion. Der Link in der Antwort erklärt die einzige Ausnahme: «Sie können CURRENT_TIMESTAMP als Standard für eine TIMESTAMP-Spalte angeben» .
Álvaro González
1
CURRENT_TIMESTAMP ist die einzige "Funktion", die als Standardwert verwendet werden kann. Alles andere muss (leider) eine Konstante sein.
Troy Morehouse
3
Technisch würde ich sagen, dass AUTO_INCREMENT auch als "Funktion" zum dynamischen Festlegen eines Standardwerts angesehen werden kann.
Rikaelus
1

Beachten Sie, dass die UUID()Rückgabe von MySQL CHAR(36)und das Speichern von UUIDs als Text (wie in den anderen Antworten gezeigt) offensichtlich ineffizient ist. Stattdessen sollte die Spalte sein BINARY(16), und Sie können sie UUID_TO_BIN()beim Einfügen von Daten und BIN_TO_UUID()beim Zurücklesen verwenden.

CREATE TABLE app_users
(
    app_user_id SMALLINT(6) NOT NULL AUTO_INCREMENT PRIMARY KEY,
    api_key     BINARY(16)
);

CREATE TRIGGER before_insert_app_users
BEFORE INSERT ON app_users
FOR EACH ROW
  IF new.api_key IS NULL
  THEN
    SET new.api_key = UUID_TO_BIN(UUID());
  END IF;

Da MySQL nicht wirklich weiß, dass es sich um eine UUID handelt, kann es schwierig sein, Probleme mit der als Binärdatei gespeicherten UUID zu beheben. In diesem Artikel wird erläutert, wie Sie eine generierte Spalte erstellen, die die UUID nach Bedarf in Text konvertiert, ohne Speicherplatz zu beanspruchen oder separate Binär- und Textversionen synchron zu halten: https://mysqlserverteam.com/storing-uuid-values-in -mysql-tables /

StephenS
quelle
0

Ich bin nicht sicher, ob die obigen Antworten für eine ältere Version gelten, aber ich habe irgendwo gesehen, dass Sie dies mit der Funktion unhex () tun können. Ich habe es versucht und es funktioniert. (Maria DB Version 10.2)

Du kannst tun

.... column_name binary(16) not null default unhex(replace(uuid(),'-',''))   

und es funktioniert. Um die UUID zu sehen, machen Sie einfach hex (Spaltenname).

ravindu1024
quelle
0

In MariaDB ab Version 10.2.1 können Sie. Siehe die Dokumentation .

CREATE TABLE test ( uuid BINARY(16) PRIMARY KEY DEFAULT unhex(replace(uuid(),'-','')) );
INSERT INTO test () VALUES ();
SELECT * FROM test;
ibotty
quelle