单个更新上的交换列值(Oracle)

时间:2013-04-14 09:13:35

标签: oracle sql-update

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

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

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

所以在争夺之后,它可以是

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

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

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

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

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)

2 个答案:

答案 0 :(得分:2)

使用MERGE,您可以使用查询而非过程执行此操作。

获取表t行标识符列表(使用Oracle ROWID伪列)和随机名称,然后将它们匹配回表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, '@'))

答案 1 :(得分: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';

Here is a sqlfiddle demo