我试图为现有表中的每一行生成一个uid,并为两个不同的列设置相同的值。
我写了一个更新语句,我认为应该这样做,但是它为每个列设置了一个不同的uid。为什么?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;
<表类>N RAWTOHEX (R1) RAWTOHEX (R2) tbody><<tr>1 F89B6F66D7C7A52FE050020A02583951 F89B6F66D7C8A52FE050020A02583951 2F89B6F66D7C9A52FE050020A02583951 F89B6F66D7CAA52FE050020A02583951 3 F89B6F66D7CBA52FE050020A02583951 F89B6F66D7CCA52FE050020A02583951 表类>
这是与这个问题和这个问题相同的问题,因为SYS_GUID
函数调用没有在子查询中具体化,并且正在被推送到更新语句并每行调用两次(每列一次);然而,这些问题的答案并不完全适用于UPDATE
语句。
MERGE
语句:
MERGE INTO tbl d
USING (
SELECT ROWID AS rid,
SYS_GUID() AS uuid
FROM tbl s
) s
ON (s.rid = d.ROWID)
WHEN MATCHED THEN
UPDATE
SET d.r1 = uuid,
d.r2 = uuid;
在MERGE
之后,您的样本数据可能包含:
NRAWTOHEX (R1) RAWTOHEX (R2) F89CAC01141C1982E053182BA8C018B2 F89CAC01141D1982E053182BA8C018B2F89CAC01141E1982E053182BA8C018B2
如前所述,这是因为Oracle不存储计算值,而是将原始表达式传播到外部查询。虽然它不会在join
的情况下这样做。
为了避免merge
期间的连接,您可以使用update
的(column [, column ]...) = (subquery)
分支,生成与使用left join
到dual
所需的相同的计算值。
update tbl
set (r1, r2) = (
select a.uuid, a.uuid
from dual
left join (
select sys_guid() as uuid
from dual
) a
on 1 = 1
where tbl.r1 = tbl.r1
or tbl.r1 is null
)
select n, rawtohex(r1), rawtohex(r2)
from tbl
where r1 = r2
NRAWTOHEX (R1) RAWTOHEX (R2) F89DCA00DD9D1CE0E053182BA8C0E348 F89DCA00DD9E1CE0E053182BA8C0E348F89DCA00DD9F1CE0E053182BA8C0E348