如何在 MySQL 中插入数据时自动生成/自增 GUID,而不使用触发器或手动插入?

6

我正在重新审视我的数据库,并注意到一些主键的类型是INT。

这不够唯一,所以我想使用GUID。我来自Microsoft SQL背景,在SSMS中您可以选择类型为“uniqeidentifier”并自动递增它。

然而,在MySQL中,我发现您必须为您想要生成GUID ID的表创建在插入时执行的触发器。例如:

表:

CREATE TABLE `tbl_test` (
  `GUID` char(40) NOT NULL,
  `Name` varchar(50) NOT NULL,
  PRIMARY KEY (`GUID`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

触发器:

CREATE TRIGGER `t_GUID` BEFORE INSERT ON `tbl_test`
 FOR EACH ROW begin
 SET new.GUID = uuid();

或者你需要在后端自己插入guid。

我不是数据库专家,但仍然记得触发器会导致性能问题。

上述内容来自这里,已有9年历史了,所以我希望有些东西已经改变了吗?


2
“这不够独特”:主键本来就是通过设计保证唯一性的。为什么你要使用 GUID 而不是自增整数键呢? - GMB
就像我所说的,它不够独特。我的主键是1、2、3、4、5等等。当我从前端向后端发送请求时,我需要使用这些主键。因此,我希望有一个更独特的标识符,以防止一些不怀好意的人猜测出主键。 - CodingLittle
@CodingLittle 值1、2、3、4、5仍然是唯一的,没有重复值(唯一的定义)。但是您仍然可以为UUID添加新列,并在INSERT INTO查询中插入uuid()函数的值。 - Progman
我从来没有说过它不是独特的,只是从我的角度来看,就安全性而言它还不够独特。至于手动插入,这也是问题的一部分,我想知道是否可能在没有触发器和手动插入的情况下获得生成的GUID。 - CodingLittle
你把外部引用和内部键混淆了。 - Strawberry
3个回答

20

根据文档中所述,自MySQL 8.0.13版本起,您可以使用uid()作为列默认值,因此类似以下内容的语句应该可行:

create table tbl_test (
    guid binary(16) default (uuid_to_bin(uuid())) not null primary key,
    name varchar(50) not null
);

这几乎是从文档中复制的。我手边没有足够新的MySQL版本来测试它。


不知道“default”参数。会尝试一下。 - CodingLittle
@CodingLittle:只需确保您的版本足够新:select version() - GMB
已经有版本“8.0.18”,所以不用担心。非常感谢! - CodingLittle
1
二进制转换怎么了,它没有 GUID 类型吗? - Dan Chase

8

You can make a

INSERT INTO  `tbl_test` VALUES  (uuid(),'testname');

当您调用此函数时,它将生成一个新的uuid。

或者,您也可以使用现代uuid v4之一来代替标准的uuid(),这比mysql中的uuid更随机。

如何在MySQL中生成UUIDv4?

8.0.13版本以后可用。

CREATE TABLE t1 (
    uuid_field     VARCHAR(40) DEFAULT (uuid())
);

但是你需要更多的不仅仅是唯一标识,这里只允许使用内部函数而不是用户定义函数,就像 uuid v4 一样,你需要触发器来实现。


我在询问是否可以不使用触发器和手动插入来实现。上述仍然是手动插入。 - CodingLittle
我编辑了我的答案,包括更新的mysql版本。 - nbk
谢谢更新,给了我两个相似的选择。 - CodingLittle
稍作修改...uuid 生成了40个字符。我尝试自己编辑答案,但未被允许。 - CodingLittle
1
我已经为您修改了。 - nbk

0
根据文档BINARY(x)会在每个条目的末尾添加一些隐藏的填充字节,而VARCHAR(40)也会浪费空间,因为它没有直接以二进制编码。使用VARBINARY(16)将更加高效。
此外,RANDOM_BYTES(16)比标准化的UUID具有更高的熵(不可预测性/安全性)每个字节,因为它们使用某些部分来编码常量元数据。
也许以下内容适合您的需求。
-- example
CREATE TABLE `tbl_test` (
  `GUID` VARBINARY(16) DEFAULT (RANDOM_BYTES(16)) NOT NULL PRIMARY KEY,
  `Name` VARCHAR(50) NOT NULL
);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接