Перемешать столбец между строками

Как можно эффективно перетасовать содержимое большой таблицы (от 1 м до 5 м)? Известно, что столбец имеет уникальные значения, но вы можете предположить, что все ограничения удалены для целей этого. Мои головные боли в первую очередь потому, что я обновляю ту же колонку, которую я выбираю. Моя цель – сделать это с помощью PL / SQL, чтобы я мог выполнять дополнительные действия программно, например, регистрировать или обновлять другие таблицы.

**Original table:** +----+-----------+ | id | fname | +----+-----------+ | 1 | mike | | 2 | ricky | | 3 | jane | | 4 | august | | 6 | dave | | 9 | Jérôme | +----+-----------+ **Possible output:** +----+-----------+ | id | fname | +----+-----------+ | 1 | dave | | 2 | jane | | 3 | mike | | 4 | ricky | | 6 | Jérôme | | 9 | august | +----+-----------+ 

Мои последние попытки заключались в создании курсора, который использует over (order by dbms_random.value) и попытаться выполнить слияние или обновление, возможно, на основе rownum. Возможно, я смогу обойти измененное ограничение личности, создав временную таблицу? Я достаточно уверен, что у Oracle есть какой-то причудливый способ сделать это, но я ограничен в своих возможностях SQL для основных команд CRUD.

Полное решение здесь, основываясь на ответе Гордона:

 merge into t using ( select t.id, t2.name from (select t.*, rownum as seqnum from t ) t join (select t.*, row_number() over (order by dbms_random.value) as seqnum from t ) t2 on t.seqnum = t2.seqnum ) src on (t.id = src.id) when matched then update set t.name = src.name; 

Вы можете сделать самостоятельное соединение, используя случайные номера строк:

 select t.id, t2.name from (select t.*, row_number() over (order by dbms_random.value) as seqnum from t ) t join (select t.*, row_number() over (order by dbms_random.value) as seqnum from t ) t2 on t.seqnum = t2.seqnum; 

На самом деле, вам не нужно, чтобы оба были рандомизированы:

 select t.id, t2.name from (select t.*, rownum as seqnum from t ) t join (select t.*, row_number() over (order by dbms_random.value) as seqnum from t ) t2 on t.seqnum = t2.seqnum; 

Взятый непосредственно из этого ответа (он был моим, поэтому я считаю, что мне разрешено его повторно использовать): https://community.oracle.com/thread/3995265

подготовка

 create table original_table ( id number, name varchar2(30) ); insert into original_table select 1, 'mike' from dual union all select 2, 'ricky' from dual union all select 3, 'jane' from dual union all select 4, 'august' from dual union all select 6, 'dave' from dual union all select 9, 'Jérôme' from dual ; select * from original_table; ID NAME -- ------ 1 mike 2 ricky 3 jane 4 august 6 dave 9 Jérôme 

Обновление строк с переименованными именами:

 merge into original_table o using ( with helper ( id, rn, rand_rn ) as ( select id, row_number() over (order by id), row_number() over (order by dbms_random.value()) from original_table ) select ot.name, h2.id from original_table ot inner join helper h1 on ot.id = h1.id inner join helper h2 on h1.rand_rn = h2.rn ) p on (o.id = p.id) when matched then update set o.name = p.name ; select * from original_table; ID NAME -- ------ 1 ricky 2 dave 3 Jérôme 4 jane 6 august 9 mike