0

我们需要打乱某些表上的某些字段值,但某些字段之间存在逻辑链接。

例如,如果表是:table t(name varchar2(30), email varchar2(60)),则 email 值必须以名称的完整值开头:

Name        Email
----        ----
Smith       Smitha@any.com

所以打乱之后可以

Name        Email
----        ----
xubal       xubaly@any.com

我们使用 dbms_random.string 函数,因此每次调用它都会返回一个不同的值。

是否可以在一次独特的运行中进行更新并保持字段之间的逻辑链接?(我不能使用数据库触发器)

在接下来我尝试的两个选项中,Oracle 返回名称字段的旧值而不是新值。

update t
set name=dbms_random.string('l',length(name)),
    email=name || dbms_random.string('l',2) || '@any.com';

update t t1
set name=dbms_random.string('l',length(name)),
    email=(select t1.name || dbms_random.string('l',2) || '@any.com'
           from t t2
           where t2.rowid = t1.rowid)
4

2 回答 2

2

您可以使用MERGE查询而不是过程来执行此操作。

获取表t行标识符列表(使用 OracleROWID伪列)和随机名称,然后将它们匹配回表t并使用它们来更新名称和电子邮件。查询(我已经测试过)如下:

MERGE INTO t
USING (
  SELECT ROWID AS ID, DBMS_Random.String('l', LENGTH(name)) AS RandName
  FROM t) newNames
ON (t.ROWID = newNames.ID)
WHEN MATCHED THEN
  UPDATE SET
    name = newNames.RandName,
    email = newNames.RandName || SUBSTR(email, INSTR(email, '@'))
于 2013-04-14T23:24:02.000 回答
0

您可以创建一个包并在包中使用一个变量。
像这样的东西:

create package pck as

v t.name%TYPE;
function rnd_next(in_name t.name%TYPE) return t.name%TYPE;
function rnd_cur return t.name%TYPE;
end;
/

create package body pck as

function rnd_next(in_name t.name%TYPE) return t.name%TYPE is

begin
v := dbms_random.string('l',length(in_name));
return v;
end;

function rnd_cur return t.name%TYPE is

begin
return v;
end;
end;
/

然后你可以像这样更新:

update t
set name = pck.rnd_next(name),
email = pck.rnd_cur || '@aaa.com';

这是一个 sqlfiddle 演示

于 2013-04-14T09:42:58.207 回答