Question

I am trying to anonymize the 'name' field of a customer table. I want to replace the 'name' of every record with the name from the customer in the next record. (I know: That's not really anonymous but 'name' and 'customerId' won't match after that. That's enough for my purposes)

I tried this, but I get an ORA-01747 error.

UPDATE Customer A
   SET NAME =
          (SELECT NAME
             FROM Customer 
            WHERE ROWNUM = A.ROWNUM + 1)

What is wrong? How can I update every 'name'-field with the content of the next 'name'-field in the table?

Was it helpful?

Solution 2

Mix'em all!!!

merge into Customer dest
using (
   select r, name from
   (select name, row_number() over (order by dbms_random.value) n from Customer)
   join (select rowid r, rownum n from Customer) using(n) 
) src
on (dest.rowid = src.r)
when matched then update set
   dest.name = src.name;

OTHER TIPS

ROWNUM is a pseudocolumn, it's not stored with the data, its part of your result set. Additionally, typically relational databases have no concept of row order.

We can probably work out a kludgy way to do it, but instead, couldn't you just instead do something like:

UPDATE CUSTOMER SET NAME = DBMS_RANDOM.STRING('a', 10);

In Oracle, this updates every customer with a random string of 10 alphanumeric digits.

You need to use LEAD().

Corrected as per 'a_horse_with_no_name' comments: LEAD(sal, 1, sal)

UPDATE emp_test a 
   SET sal = 
 (
  SELECT LEAD(sal, 1, sal) OVER (ORDER BY sal) AS sal_next
    FROM scott.emp b
   WHERE a.empno = b.empno
 )
 /

Same with ename:

SELECT empno, ename, job, sal,
       LEAD(ename, 1, ename) OVER (ORDER BY ename) AS name_next
  FROM scott.emp
 /

 EMPNO    ENAME    JOB        SAL    NAME_NEXT
 --------------------------------------------
 7876    ADAMS    CLERK       1100    ALLEN
 7499    ALLEN    SALESMAN    1600    BLAKE
 7698    BLAKE    MANAGER     2850    CLARK
 7782    CLARK    MANAGER     2450    FORD
 ....
 7844    TURNER   SALESMAN    1500    WARD
 7521    WARD     SALESMAN    1250    WARD

This will not work:

SELECT * FROM scott.emp
  WHERE ROWNUM = 5
/

But this will:

SELECT * FROM scott.emp
 WHERE ROWNUM <= 5
/

This might work but is untested.

UPDATE Customer A
   SET NAME =
          (SELECT NAME
             FROM Customer 
            WHERE ROWNUM = (SELECT (A.ROWNUM + 1))
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top