Могу ли я использовать функцию для значения по умолчанию в 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.