我想做这样的事情:
create table app_users
(
app_user_id smallint(6) not null auto_increment primary key,
api_key char(36) not null default uuid()
);
但是,这会导致错误,是否可以在mysql中为默认值调用函数?
谢谢。
Answers:
不,你不能。
但是,您可以轻松创建触发器来执行此操作,例如:
创建触发器before_insert_app_users 在app_users上插入之前 每行 SET new.api_key = uuid();
SET new.api_key = COALESCE(new.api_key, uuid())
保留现有价值。
从mysql v8.0.13开始,可以使用表达式作为字段的默认值:
DEFAULT子句中指定的默认值可以是文字常量或表达式。除一个例外,将表达式默认值放在括号内,以将其与文字常量默认值区分开。
CREATE TABLE t1 (
uuid_field VARCHAR(32) DEFAULT (uuid()),
binary_uuid BINARY(16) DEFAULT (UUID_TO_BIN(UUID()))
);
不幸的是,MySQL 5要求使用常量作为默认值。在下面的链接中对该问题进行了更详细的讨论。但是唯一的答案是允许null并添加表触发器。
MySQL直到最近才将UUID作为其数据库包的一部分接受,并且它没有我们想要的功能丰富。
我相信你不能:
默认值必须为常数;它不能是函数或表达式
getdate()
甚至不是MySQL函数。答案中的链接解释了唯一的例外:«您可以将CURRENT_TIMESTAMP指定为TIMESTAMP列的默认值»。
需要注意的是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表/
我不确定以上答案是否适用于较旧版本,但我发现可以使用unhex()函数执行此操作。我试过了,它有效。(Maria DB版本10.2)
你可以做
.... column_name binary(16) not null default unhex(replace(uuid(),'-',''))
而且有效。要查看uuid,只需执行hex(column_name)。