UUID()每次调用该函数本身都会产生一个不同的值,正如我期望的那样:
SELECT UUID() from INFORMATION_SCHEMA.TABLES LIMIT 3;
3bb7d468-f9c5-11e9-8349-d05099466715
3bb7d482-f9c5-11e9-8349-d05099466715
3bb7d492-f9c5-11e9-8349-d05099466715
Run Code Online (Sandbox Code Playgroud)
但是,一旦我们在REPLACE()函数中使用它,它就会开始产生相同的值:
SELECT REPLACE(UUID(),'-','-') from INFORMATION_SCHEMA.TABLES LIMIT 3;
e0f2d47a-f9c5-11e9-8349-d05099466715
e0f2d47a-f9c5-11e9-8349-d05099466715
e0f2d47a-f9c5-11e9-8349-d05099466715
Run Code Online (Sandbox Code Playgroud)
这样“中断”了Select语句中的Insert语句,我们希望插入的每一行都具有唯一的值:
INSERT INTO MyTable (uid, tableName) -- uid is binary(16)
SELECT UNHEX(REPLACE(UUID(),'-','')), TABLE_NAME from INFORMATION_SCHEMA.TABLES;
Run Code Online (Sandbox Code Playgroud)
注意,为了方便起见,我使用信息模式的表列表。没关系,但是对于那些好奇的人,我们的PK是binary(16)形式的UUID。我不能改变它;请不要专注于此。
该UUID()功能具有不确定性,而REPLACE()函数是确定性的。我本来希望UUID()函数的非确定性特征导致该REPLACE()函数的行为好像每一行都有不同的自变量,但是似乎DB引擎通过假设UUID()常量是过度优化了。
我还使用另一个非确定性函数来测试了此行为RAND(),在这种情况下,该REPLACE()函数按预期工作!
SELECT REPLACE(RAND(),' ',' ') from INFORMATION_SCHEMA.TABLES LIMIT 3;
0.911571646026868
0.626416072832808
0.6977608461843439
Run Code Online (Sandbox Code Playgroud)
问题:
有没有一种方法可以执行“从选择插入”并在选择中每行以二进制16格式生成唯一的UUID?
为什么会这样呢?这是错误吗?
更新
我在本地使用5.7.27:
mysql Ver 14.14 Distrib 5.7.27, for Linux (x86_64) …
我重新访问了我的数据库并注意到我有一些 INT 类型的主键。
这还不够独特,所以我想我会有一个指导。我来自 microsoft sql 背景,在 ssms 中,您可以选择类型为“uniqeidentifier”并自动增加它。
但是,在 mysql 中,我发现您必须为要为其生成指南 ID 的表创建在插入时执行的触发器。例子:
桌子:
CREATE TABLE `tbl_test` (
`GUID` char(40) NOT NULL,
`Name` varchar(50) NOT NULL,
PRIMARY KEY (`GUID`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
Run Code Online (Sandbox Code Playgroud)
扳机:
CREATE TRIGGER `t_GUID` BEFORE INSERT ON `tbl_test`
FOR EACH ROW begin
SET new.GUID = uuid();
Run Code Online (Sandbox Code Playgroud)
或者,您必须自己在后端插入 guid。
我不是数据库专家,但仍然记得触发器会导致性能问题。