Oracle异常行为:使用sys_guid()更新时两列UUID不同的原因
问题:UPDATE语句中两列UUID值不同的原因及解决办法
我想给现有表的每一行生成一个UUID,让两个不同列(r1、r2)的值相同,但执行自己写的UPDATE语句后,每列的UUID却不一样,这是为什么?
用到的SQL代码如下:
CREATE TABLE tbl ( n number, r1 raw(32), r2 raw(32) ); insert into tbl (n) values (1); insert into tbl (n) values (2); insert into tbl (n) values (3); update (select r1, r2, sys_guid() as uuid FROM tbl) set r1 = uuid, r2 = uuid; select n, rawtohex(r1), rawtohex(r2) from tbl;
查询结果显示每行的r1和r2UUID不同:
| N | RAWTOHEX(R1) | RAWTOHEX(R2) |
|---|---|---|
| 1 | F89B6F66D7C7A52FE050020A02583951 | F89B6F66D7C8A52FE050020A02583951 |
| 2 | F89B6F66D7C9A52FE050020A02583951 | F89B6F66D7CAA52FE050020A02583951 |
| 3 | F89B6F66D7CBA52FE050020A02583951 | F89B6F66D7CCA52FE050020A02583951 |
原因分析
核心问题是Oracle中SYS_GUID()函数的执行时机:
你在子查询里定义了uuid别名,但Oracle并不会将这个值缓存下来复用。当执行set r1 = uuid, r2 = uuid时,每一次引用uuid都会重新调用SYS_GUID()生成新值,所以r1和r2会得到不同的UUID。
解决办法
以下几种写法都能实现每行生成一个UUID并同步到两列:
方法1:用关联子查询更新
先通过子查询为每行生成唯一UUID,再关联原表批量更新:
UPDATE tbl t SET (t.r1, t.r2) = ( SELECT s.uuid, s.uuid FROM (SELECT n, SYS_GUID() AS uuid FROM tbl) s WHERE s.n = t.n );
方法2:使用MERGE语句
MERGE的逻辑更清晰,先预先生成每行的UUID,再匹配更新:
MERGE INTO tbl t USING (SELECT n, SYS_GUID() AS uuid FROM tbl) s ON (t.n = s.n) WHEN MATCHED THEN UPDATE SET t.r1 = s.uuid, t.r2 = s.uuid;
方法3:PL/SQL循环(适合小表)
通过PL/SQL变量缓存UUID,确保每行只生成一次:
DECLARE v_uuid RAW(32); BEGIN FOR rec IN (SELECT n FROM tbl) LOOP v_uuid := SYS_GUID(); UPDATE tbl SET r1 = v_uuid, r2 = v_uuid WHERE n = rec.n; END LOOP; COMMIT; END; /
执行以上任意一种方法后,再查询表数据,每行的r1和r2就会拥有相同的UUID值。
内容的提问来源于stack exchange,提问作者BCartolo
相关产品推荐
相关产品推荐

