Чи можу я використовувати функцію для значення за замовчуванням у MySql?


93

Я хочу зробити щось подібне:


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

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

Дякую.

Відповіді:


129

Ні, ти не можеш.

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

СТВОРИТИ TRIGGER before_insert_app_users
  ПЕРЕД ВСТАВЛЕННЯМ в app_users 
  ДЛЯ КОЖНОГО РЯДКУ
  ВСТАНОВИТИ new.api_key = uuid ();

2
@See stackoverflow.com/questions/6280789 / ... для заповнення UUID , в існуючих рядках.
— Sam Barnum

2
Це не зовсім те саме, що мати значення DEFAULT. Як можна було б змінити цю відповідь, встановивши ключ, лише якщо значення було NULL?
— ToolmakerSteve

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

1
@RodolVelasco функція uuid створена так, щоб бути високостійкою до зіткнень. Набагато більше, ніж md5. Як тільки ви md5 uuid, у вас підвищується ризик зіткнення ідентифікатора
— Кранчер

2
SET new.api_key = COALESCE(new.api_key, uuid())для збереження існуючих цінностей.
— Райан

28

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

Значення за замовчуванням, вказане в реченні DEFAULT, може бути літеральною константою або виразом. За одним винятком, вкладіть значення значень за замовчуванням виразу в дужки, щоб відрізнити їх від значень за замовчуванням буквальних констант.

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

1
Зверніть увагу, що відповідно до вже зв’язаних документів у відповіді: ... збережені функції та визначені користувачем функції заборонені . Тобто єдиними функціями, які можна використовувати як вирази за замовчуванням, є вбудовані функції.
— ашербар

1
Станом на травень 2020 року це має бути правильною відповіддю. Інші відповіді за допомогою тригерів застаріли.
— Джон Сток,

20

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

Якщо ви хочете імітувати таку поведінку, ви можете використовувати тригер таким чином:

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());

8

На жаль, ні, MySQL 5 вимагає констант за замовчуванням. Питання було обговорено набагато детальніше за посиланням нижче. Але єдина відповідь - дозволити значення null та додати тригер таблиці.

MySQL лише нещодавно прийняв UUID як частину свого пакету БД, і це не так багато можливостей, як хотілося б.

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


1
Я повинен додати, що дозволити NULL і покладатися на тригери може працювати, але більшість розробників вважають це дуже хакерським рішенням. Я б особисто не рекомендував це, але кожному своє.
— TravisO

6

Я вірю, що ви не можете :

значення за замовчуванням має бути константою; це не може бути функцією чи виразом


Неправда, ви можете використовувати getdate ()
— amr osama

6
@amrosama - Ні, ти не можеш. getdate()навіть не є функцією MySQL. Посилання у відповіді пояснює єдиний виняток: «ви можете вказати CURRENT_TIMESTAMP за замовчуванням для стовпця TIMESTAMP» .
— Альваро Гонсалес

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

3
Технічно я б сказав, що AUTO_INCREMENT також можна розглядати як "функцію" для динамічного встановлення значення за замовчуванням.
— Рікаел,

1

Зверніть увагу, що UUID()повернення MySQL 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 (). Я спробував, і це працює. (maria db версія 10.2)

Ви можете зробити

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

і це працює. Щоб побачити uuid, просто зробіть hex (стовпець_назви).


0

У MariaDB, починаючи з версії 10.2.1, ви можете. Дивіться його документацію .

CREATE TABLE test ( uuid BINARY(16) PRIMARY KEY DEFAULT unhex(replace(uuid(),'-','')) );
INSERT INTO test () VALUES ();
SELECT * FROM test;
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.