Могу ли я использовать функцию для значения по умолчанию в MySql?


95

Я хочу сделать что-то вроде этого:


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

Однако это приводит к ошибке, есть ли способ вызвать функцию для значения по умолчанию в mysql?

Спасибо.

Ответы:


130

Нет, не можешь.

Однако вы можете легко создать для этого триггер, например:

СОЗДАТЬ ТРИГГЕР before_insert_app_users
  ПЕРЕД ВСТАВКОЙ НА app_users 
  ДЛЯ КАЖДОЙ РЯДЫ
  УСТАНОВИТЬ new.api_key = uuid ();

2
@See stackoverflow.com/questions/6280789/... для заполнения UUID , в существующих строках.
— Сэм Барнум,

2
Это не совсем то же самое, что иметь значение DEFAULT. Как можно изменить этот ответ, чтобы установить ключ только в том случае, если значение было NULL?
— ToolmakerSteve

1
Печально, что MySQL существует столько, сколько существует, но вы не можете реализовать UUID по умолчанию для столбца без триггера. Причина этого заложена в технологии 1980-х годов, которая, по-видимому, все еще существует в базовом коде MySQL (ищите «у нас не может быть хороших вещей»): percona.com/blog/2013/04/08/…
— RyanNerd

1
@RodolVelasco: функция uuid обеспечивает высокую устойчивость к столкновениям. Намного больше, чем md5. Как только вы md5 uuid, у вас повышается риск столкновения идентификаторов
— Cruncher

2
SET new.api_key = COALESCE(new.api_key, uuid())чтобы сохранить существующие ценности.
— Райан

33

Начиная с mysql v8.0.13, можно использовать выражение как значение по умолчанию для поля:

Значение по умолчанию, указанное в предложении DEFAULT, может быть буквальной константой или выражением. За одним исключением, заключите значения выражения по умолчанию в круглые скобки, чтобы отличать их от буквальных значений констант по умолчанию.

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

2
Обратите внимание, что в соответствии с уже связанными документами в ответе: ... сохраненные функции и пользовательские функции не разрешены . Т.е. единственные функции, которые могут использоваться в качестве выражений по умолчанию, - это встроенные функции.
— Ашербар

2
По состоянию на май 2020 года это должен быть правильный ответ. Другие ответы с использованием триггеров устарели.
— Джон Сток,

мелкая деталь: varchar(32)должно бытьvarchar(36)
— Джаред Бек

@JaredBeck Я думаю, что 32 в порядке, если вы не храните тире.
— Элвин Томпсон,

@JohnStock Этот метод не позволяет использовать определяемые пользователем или сохраненные функции, поэтому может быть немного преждевременно объявлять использование триггеров устаревшим.
— Элвин Томпсон,

21

Как уже было сказано, вы не можете.

Если вы хотите смоделировать это поведение, вы можете использовать триггер следующим образом:

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;

Вам все равно нужно обновить ранее существующие строки, например:

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

9

К сожалению, нет, MySQL 5 требует констант по умолчанию. Более подробно вопрос обсуждался по ссылке ниже. Но единственный ответ - разрешить null и добавить триггер таблицы.

MySQL только недавно принял UUID как часть своего пакета БД, и он не так богат, как хотелось бы.

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


1
Я должен добавить, что разрешение NULL и использование триггеров может работать, но большинство разработчиков сочли бы это очень хакерским решением. Я бы лично не рекомендовал это, но каждому свое.
— TravisO

7

Я считаю, что вы не можете :

значение по умолчанию должно быть постоянным; это не может быть функцией или выражением


Неправда, вы можете использовать getdate ()
— Амр Осама

6
@amrosama - Нет, не можешь. getdate()это даже не функция MySQL. Ссылка в ответе объясняет единственное исключение: «вы можете указать CURRENT_TIMESTAMP как значение по умолчанию для столбца TIMESTAMP» .
— Álvaro González

1
CURRENT_TIMESTAMP - единственная «функция», которая может использоваться как значение по умолчанию. Все остальное должно быть постоянным (к сожалению).
— Трой Морхаус,

3
Технически я бы сказал, что AUTO_INCREMENT также можно рассматривать как «функцию» для динамической установки значения по умолчанию.
— Rikaelus 02

1

Обратите внимание, что MySQL UUID()возвращает CHAR(36)и сохранение UUID в виде текста (как показано в других ответах), очевидно, неэффективно. Вместо этого столбец должен быть BINARY(16), и его можно использовать UUID_TO_BIN()при вставке данных и BIN_TO_UUID()при чтении их обратно.

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;

Обратите внимание, что, поскольку MySQL на самом деле не знает, что это UUID, может быть сложно устранить проблемы с его сохранением в виде двоичного файла. В этой статье объясняется, как создать сгенерированный столбец, который будет преобразовывать UUID в текст по мере необходимости, не занимая места и не беспокоясь о синхронизации отдельных двоичных и текстовых версий: https://mysqlserverteam.com/storing-uuid-values-in -mysql-таблицы /


0

Я не уверен, что приведенные выше ответы относятся к более старой версии, но я где-то видел, что вы можете сделать это с помощью функции unhex (). Я попробовал, и все работает. (Мария дб версия 10.2)

Ты можешь сделать

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

и это работает. Чтобы увидеть uuid, просто введите hex (column_name).


Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.