Posso usare una funzione per un valore predefinito in MySql?


93

Voglio fare qualcosa del genere:


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

Tuttavia questo si traduce in un errore, c'è un modo per chiamare una funzione per un valore predefinito in mysql?

Grazie.

Risposte:


129

No, non puoi.

Tuttavia, potresti facilmente creare un trigger per farlo, come ad esempio:

CREATE TRIGGER before_insert_app_users
  PRIMA DI INSERIRE SU app_users 
  PER OGNI RIGA
  SET new.api_key = uuid ();

2
@See stackoverflow.com/questions/6280789/... per la compilazione UUID in righe esistenti.
Sam Barnum

2
Non è esattamente come avere un valore PREDEFINITO. Come si cambierà questa risposta per impostare la chiave solo se il valore fosse NULL?
ToolmakerSteve

1
Triste che MySQL sia in circolazione da sempre, ma non è possibile implementare un UUID predefinito per una colonna senza un trigger. La ragione di ciò è incorporata nella tecnologia degli anni '80 che apparentemente esiste ancora nel codice di base MySQL (cerca "non possiamo avere cose belle"): percona.com/blog/2013/04/08/…
RyanNerd

1
@RodolVelasco la funzione uuid è costruita per essere altamente resistente alle collisioni. Molto più di md5. Non appena md5 l'uuid hai un rischio maggiore di collisione id
Cruncher

2
SET new.api_key = COALESCE(new.api_key, uuid())per preservare i valori esistenti.
Ryan

29

A partire da mysql v8.0.13 è possibile utilizzare un'espressione come valore predefinito per un campo:

Il valore predefinito specificato in una clausola DEFAULT può essere una costante letterale o un'espressione. Con un'eccezione, racchiudere i valori predefiniti dell'espressione tra parentesi per distinguerli dai valori predefiniti costanti letterali.

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

1
Nota che come per i documenti già collegati in risposta: ... le funzioni memorizzate e le funzioni definite dall'utente non sono consentite . Cioè, le uniche funzioni che possono essere utilizzate come espressioni predefinite sono le funzioni integrate.
Asherbar

2
A partire da maggio 2020 questa dovrebbe essere la risposta corretta. Le altre risposte che utilizzano i trigger sono obsolete.
John Stock,

20

Come già affermato non puoi.

Se vuoi simulare questo comportamento puoi usare un trigger in questo modo:

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;

Devi ancora aggiornare le righe esistenti in precedenza, in questo modo:

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

8

Purtroppo no, MySQL 5 richiede costanti per l'impostazione predefinita. La questione è stata discussa in modo molto più dettagliato nel collegamento sottostante. Ma l'unica risposta è consentire null e aggiungere un trigger di tabella.

MySQL ha accettato l'UUID solo di recente come parte del pacchetto DB e non è così ricco di funzionalità come vorremmo.

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


1
Dovrei aggiungere che consentire NULL e fare affidamento sui trigger può funzionare, ma la maggior parte degli sviluppatori la considererebbe una soluzione molto hacker. Non lo consiglierei personalmente ma a ciascuno il proprio.
TravisO

6

Credo che tu non possa :

il valore predefinito deve essere una costante; non può essere una funzione o un'espressione


Non è vero, puoi usare getdate ()
amr osama

6
@amrosama - No, non puoi. getdate()non è nemmeno una funzione MySQL. Il link nella risposta spiega l'unica eccezione: «puoi specificare CURRENT_TIMESTAMP come predefinito per una colonna TIMESTAMP» .
Álvaro González

1
CURRENT_TIMESTAMP è l'unica "funzione" che può essere utilizzata come valore predefinito. Tutto il resto deve essere una costante (purtroppo).
Troy Morehouse

3
Tecnicamente direi che AUTO_INCREMENT può anche essere visto come una "funzione" per impostare dinamicamente un valore predefinito.
Rikaelus

1

Si noti che i UUID()ritorni di MySQL CHAR(36)e la memorizzazione degli UUID come testo (come mostrato nelle altre risposte) è ovviamente inefficiente. Invece, la colonna dovrebbe essere BINARY(16), e puoi usarla UUID_TO_BIN()quando inserisci i dati e BIN_TO_UUID()quando li rileggi.

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;

Nota che poiché MySQL non sa davvero che questo è un UUID, può essere difficile risolvere i problemi con esso memorizzato come binario. Questo articolo spiega come creare una colonna generata che convertirà l'UUID in testo secondo necessità senza occupare spazio o preoccuparsi di mantenere sincronizzate versioni binarie e di testo separate: https://mysqlserverteam.com/storing-uuid-values-in -mysql-tabelle /


0

Non sono sicuro che le risposte di cui sopra siano per una versione precedente, ma ho visto da qualche parte che puoi farlo usando la funzione unhex (). Ho provato e funziona. (maria db versione 10.2)

Tu puoi fare

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

e funziona. Per vedere l'uuid basta fare hex (nome_colonna).


0

In MariaDB a partire dalla versione 10.2.1 puoi. Vedi la sua documentazione .

CREATE TABLE test ( uuid BINARY(16) PRIMARY KEY DEFAULT unhex(replace(uuid(),'-','')) );
INSERT INTO test () VALUES ();
SELECT * FROM test;
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.