如何在MySQL 8的「集合」表中设置UUID为默认主键
解决MySQL 8中JSON文档_id与主键UUID一致的问题
要让JSON文档里的_id和自动生成的UUID主键保持一致,有两种实用方案:
方案一:用触发器自动同步(推荐)
先把表结构改成主键自动生成UUID,再通过触发器把主键的UUID同步到JSON文档里:
1. 修改表结构
把原来从JSON提取的_id生成列,改成带UUID默认值的普通列:
ALTER TABLE `users` -- 改成自动生成紧凑格式的二进制UUID(16字节,更省空间) MODIFY COLUMN `_id` varbinary(16) NOT NULL DEFAULT (UUID_TO_BIN(UUID(), TRUE)), -- 更新JSON Schema校验规则,确保doc包含_id字段 DROP CONSTRAINT `$val_strict`, ADD CONSTRAINT `$val_strict` CHECK (json_schema_valid('{"type":"object","required":["_id"],"properties":{"_id":{"type":"string"}}}',`doc`)) /*!80016 NOT ENFORCED */;
如果偏好36字节的字符串格式UUID,把默认值改成(CAST(UUID() AS BINARY)),同时把varbinary(16)改成varbinary(36)。
2. 创建同步触发器
插入前自动把主键的二进制UUID转成字符串,写入JSON文档的_id字段:
DELIMITER // CREATE TRIGGER sync_users_doc_id BEFORE INSERT ON users FOR EACH ROW BEGIN -- 把紧凑格式的二进制UUID转成标准字符串(如果用36字节格式,直接用CAST(NEW._id AS CHAR)) SET NEW.doc = JSON_SET(COALESCE(NEW.doc, JSON_OBJECT()), '$._id', BIN_TO_UUID(NEW._id, TRUE)); END // DELIMITER ;
这样不管插入时有没有给doc的_id,触发器都会自动用主键的UUID填充,保证两者完全一致。如果要支持更新主键(不建议这么做),可以再建一个BEFORE UPDATE触发器同步。
方案二:插入时手动指定UUID
如果不想用触发器,每次插入时手动生成UUID,同时赋值给主键和JSON文档:
-- 生成UUID并转成二进制(紧凑格式) SET @uuid_str = UUID(); SET @uuid_bin = UUID_TO_BIN(@uuid_str, TRUE); -- 插入数据时同时指定主键和doc里的_id INSERT INTO users (_id, doc) VALUES (@uuid_bin, JSON_OBJECT('_id', @uuid_str, 'username', 'lisi', 'age', 28));
这种方式需要每次插入都显式处理UUID,适合对插入逻辑有完全控制权的场景。
内容的提问来源于stack exchange,提问作者Azucena H
相关产品推荐
相关产品推荐

