Чи можу я використовувати функцію для значення за замовчуванням у 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.