Puis-je utiliser une fonction pour une valeur par défaut dans MySql?


93

Je veux faire quelque chose comme ça:


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

Cependant, cela entraîne une erreur, existe-t-il un moyen d'appeler une fonction pour une valeur par défaut dans mysql?

Merci.

Réponses:


129

Non, tu ne peux pas.

Cependant, vous pouvez facilement créer un déclencheur pour ce faire, tel que:

CREATE TRIGGER before_insert_app_users
  AVANT D'INSÉRER SUR app_users 
  POUR CHAQUE RANG
  SET new.api_key = uuid ();

2
@ Voir stackoverflow.com/questions/6280789/… pour renseigner les UUID dans les lignes existantes.
Sam Barnum

2
Ce n'est pas tout à fait la même chose que d'avoir une valeur DEFAULT. Comment changerait-on cette réponse pour ne définir la clé que si la valeur était NULL?
ToolmakerSteve

1
Triste que MySQL existe depuis aussi longtemps, mais vous ne pouvez pas implémenter un UUID par défaut pour une colonne sans déclencheur. La raison en est intégrée dans la technologie des années 1980 qui existe apparemment toujours dans le code de base MySQL (recherchez "nous ne pouvons pas avoir de belles choses"): percona.com/blog/2013/04/08/…
RyanNerd

1
@RodolVelasco la fonction uuid est conçue pour être hautement résistante aux collisions. Bien plus que md5. Dès que vous md5 le uuid, vous avez un risque plus élevé de collision d'identité
Cruncher

2
SET new.api_key = COALESCE(new.api_key, uuid())pour préserver les valeurs existantes.
Ryan

30

Depuis mysql v8.0.13, il est possible d'utiliser une expression comme valeur par défaut pour un champ:

La valeur par défaut spécifiée dans une clause DEFAULT peut être une constante littérale ou une expression. À une exception près, placez les valeurs par défaut de l'expression entre parenthèses pour les distinguer des valeurs par défaut des constantes littérales.

CREATE TABLE t1 (
  uuid_field     VARCHAR(32) DEFAULT (uuid()),
  binary_uuid    BINARY(16)  DEFAULT (UUID_TO_BIN(UUID()))
);

1
Notez que selon les documents déjà liés dans la réponse: ... les fonctions stockées et les fonctions définies par l'utilisateur ne sont pas autorisées . Par exemple, les seules fonctions qui peuvent être utilisées comme expressions par défaut sont des fonctions intégrées.
asherbar

2
À partir de mai 2020, cela devrait être la bonne réponse. Les autres réponses utilisant des déclencheurs sont obsolètes.
John Stock

20

Comme déjà indiqué, vous ne pouvez pas.

Si vous souhaitez simuler ce comportement, vous pouvez utiliser un déclencheur de cette manière:

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;

Vous devez toujours mettre à jour les lignes déjà existantes, comme ceci:

UPDATE app_users SET uuid = (SELECT uuid());

8

Malheureusement non, MySQL 5 nécessite des constantes par défaut. La question a été discutée plus en détail dans le lien ci-dessous. Mais la seule réponse est d'autoriser null et d'ajouter un déclencheur de table.

MySQL n'a accepté que récemment l'UUID dans son package DB, et ce n'est pas aussi riche en fonctionnalités que nous le souhaiterions.

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


1
Je dois ajouter qu'autoriser NULL et s'appuyer sur des déclencheurs peut fonctionner, mais la plupart des développeurs le considéreraient comme une solution très hack-y. Je ne le recommanderais pas personnellement mais à chacun le sien.
TravisO

6

Je crois que vous ne pouvez pas :

la valeur par défaut doit être une constante; ça ne peut pas être une fonction ou une expression


Ce n'est pas vrai, vous pouvez utiliser getdate ()
amr osama

6
@amrosama - Non, vous ne pouvez pas. getdate()n'est même pas une fonction MySQL. Le lien dans la réponse explique la seule exception: «vous pouvez spécifier CURRENT_TIMESTAMP comme valeur par défaut pour une colonne TIMESTAMP» .
Álvaro González

1
CURRENT_TIMESTAMP est la seule "fonction" qui peut être utilisée comme valeur par défaut. Tout le reste doit être une constante (malheureusement).
Troy Morehouse

3
Techniquement, je dirais que AUTO_INCREMENT peut également être vu comme une "fonction" pour définir dynamiquement une valeur par défaut.
Rikaelus

1

Notez que les UUID()retours de MySQL CHAR(36)et le stockage des UUID sous forme de texte (comme indiqué dans les autres réponses) est évidemment inefficace. Au lieu de cela, la colonne doit être BINARY(16), et vous pouvez l'utiliser UUID_TO_BIN()lors de l'insertion de données et BIN_TO_UUID()lors de la lecture.

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;

Notez que comme MySQL ne sait pas vraiment qu'il s'agit d'un UUID, il peut être difficile de résoudre les problèmes avec celui-ci stocké en binaire. Cet article explique comment créer une colonne générée qui convertira l'UUID en texte selon les besoins sans prendre de place ni se soucier de garder les versions binaires et texte distinctes synchronisées: https://mysqlserverteam.com/storing-uuid-values-in -mysql-tables /


0

Je ne sais pas si les réponses ci-dessus sont pour une version plus ancienne, mais j'ai vu quelque part que vous pouvez le faire en utilisant la fonction unhex (). Je l'ai essayé et il fonctionne. (maria db version 10.2)

Tu peux faire

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

et il fonctionne. Pour voir l'uuid, faites simplement hex (nom_colonne).


0

Dans MariaDB à partir de la version 10.2.1, vous pouvez. Voir sa documentation .

CREATE TABLE test ( uuid BINARY(16) PRIMARY KEY DEFAULT unhex(replace(uuid(),'-','')) );
INSERT INTO test () VALUES ();
SELECT * FROM test;
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.