我想用另一个表中的随机名更新表中的名称。表Users中有真实的用户名。表tmp_users中有名称。我想用tmp_users表中的随机名更新Users表中的所有名称。我们的想法是用假客户匿名化真实的生产数据。 tmp_users表中的条目较少,因此我认为我无法关联id。
我遇到的问题是所有用户都设置为相同的名称。
一些示例数据:
create table users
(
name varchar2(50)
);
create table tmp_users
(
name varchar2(50)
);
insert into users values ('Cora');
insert into users values ('Rayna');
insert into users values ('Heidi');
insert into users values ('Gilda');
insert into users values ('Dorothy');
insert into users values ('Elena');
insert into users values ('Providencia');
insert into users values ('Louetta');
insert into users values ('Portia');
insert into users values ('Rodrick');
insert into users values ('Rocco');
insert into users values ('Nelson');
insert into users values ('Derrick');
insert into users values ('Everett');
insert into users values ('Nisha');
insert into users values ('Amy');
insert into users values ('Hyun');
insert into users values ('Brendon');
insert into users values ('Gabriela');
insert into users values ('Melina');
insert into tmp_users values ('Snow White');
insert into tmp_users values ('Cinderella');
insert into tmp_users values ('Aurora');
insert into tmp_users values ('Ariel');
insert into tmp_users values ('Belle');
insert into tmp_users values ('Jasmine');
insert into tmp_users values ('Pocahontas');
insert into tmp_users values ('Mulan');
insert into tmp_users values ('Tinker Bell');
insert into tmp_users values ('Anna');
insert into tmp_users values ('Elsa');
--Wrong, sets all users to the same random name
update users set name = (select name from (select name from tmp_users order by sys_guid()) where rownum = 1);
--Wrong, sets all users to the same random name
update users set name = (select name from (select name from tmp_users order by dbms_random.value) where rownum = 1);
这样做时:
select * from users;
我得到的结果是这样的,我不想要。
Cinderella
Cinderella
Cinderella
Cinderella
Cinderella
...
我想为Users表中的每一行分配一个随机名称。所有行的名称不同。我喜欢这样的事情:
Mulan
Cinderella
Belle
Elsa
Jasmine
Tinker Bell
...
知道如何做到这一点?我正在使用Oracle Database 11g Express Edition 11.2.0.2.0。使用游标很容易,但我试图弄清楚如何使用set操作。
更新:
我现在已经在两个不同的Oracle版本上进行了测试。相关子查询解决方案不适用于Oracle Database 11g Express Edition 11.2.0.2.0。 但它有时在Oracle Database 11g企业版11.2.0.4.0上有效。在一张桌子上它一直在工作,在另一张桌子上它永远不会工作。
答案 0 :(得分:2)
使用11.2.0.4测试以下作品,类似于@ VR46建议:
mess = {'default': 'default', 'this': 'that'}
jmess = json.dumps(mess)
response = self.boto_client.publish(
TopicArn=self.TopicArn,
MessageStructure='json',
Message=jmess
)
答案 1 :(得分:1)
我认为关联子查询会从子查询中提取随机名称
UPDATE users
SET name = (SELECT name
FROM (SELECT name
FROM tmp_users tu
ORDER BY Sys_guid())
WHERE ROWNUM = 1
AND users.name <> name );
答案 2 :(得分:1)
你需要一些相关性,正如@ VR46建议的那样;但是sys_guid()并不适用于此(无论如何在11gR2中;我认为优化器只是出于某种原因在这种情况下只评估它一次);你可以使用dbms_random.value:
update users u set name = (
select name from (
select name from tmp_users order by dbms_random.value
)
where rownum = 1 and u.name is not null
);
NAME
--------------------------------------------------
Jasmine
Tinker Bell
Ariel
Elsa
Elsa
Elsa
Belle
Snow White
...
如果你不想要aubquery,你可以使用keep dense rank来代替:
update users u set name = (
select max(name) keep (dense_rank first order by dbms_random.value)
from tmp_users
where u.name is not null
);
NAME
--------------------------------------------------
Mulan
Anna
Snow White
Elsa
Tinker Bell
Belle
Belle
Elsa
...
相关性必须是真实的;如果你的用户表中有空值,这会将它们更新为null,如果这是一个问题,你可以使用不同的条件。
根据评论,11.2.0.2中的dbms_random
与11.2.0.3和11.2.0.4中sys_guid
的问题似乎相同。如果您的用户表还有一个数字唯一/主键(例如ID),您可以将其用于关联并将其传递到value
函数,可能会产生影响,但我没有合适的实例来测试:
update users u set name = (
select max(name) keep (dense_rank first order by dbms_random.value(0, u.id))
from tmp_users
);
MOS注释420779.1包含行&#34;在子查询中包含DBMS_RANDOM.VALUE可能会也可能不会起作用,具体取决于所选的优化和执行代码路径&#34;,这似乎是这里的问题。
你也可以尝试合并变体,例如(再次假设您可以使用ID):
merge into users u
using (
select u.id, max(tu.name) keep (dense_rank first
order by dbms_random.value(0, u.id)) as name
from users u
cross join tmp_users tu
group by u.id
) tu
on (tu.id = u.id)
when matched then update set u.name = tu.name;
交叉连接可能会使这不切实际,具体取决于您在每个表中实际拥有的行数。
答案 3 :(得分:1)
这是另一种方法,它使用rowid和模数:
MERGE into users_tab u
USING (
select
actual.row_id as actual_rowid,
actual.rnum actual_rnum,
actual.name actual_name,
fake.rnum fake_rnum,
fake.name fake_name,
mod(actual.rnum, fake_count.cnt) modulus
from
(
select rownum rnum, name, rowid as row_id
from users_tab
) actual,
(
select rownum-1 rnum, name
from (select distinct name from tmp_users_tab)
) fake,
(select count(distinct name) cnt from tmp_users_tab) fake_count
where mod(actual.rnum, fake_count.cnt) = fake.rnum
) x
ON (x.actual_rowid = u.rowid)
WHEN MATCHED THEN UPDATE
set name = x.fake_name;
不确定这将如何在非常大的用户表上执行。它不是随机的,而是遵循一系列假名。因此,如果您有10个假名,则用户中的记录1-&gt; 10将被分配假名1 - > 10,而用户11将从假名#1开始。
USING查询有额外的测试字段。