我正在迁移一些数据,但在此之前我想生成一个回滚脚本。
表格中的重要列可能如下所示:
id code
----- -------
1234 121212
1345 434343
2345 121212
...
我正在将所有代码121212
和151515
更改为252525
,但如果其他地方出现问题,我需要能够将其更改回来。
所以我开始使用listagg
创建逗号分隔的id列表,我可以在update语句的where子句中使用它们。这些方面的东西:
select '... set code='||code||' where id in ('
|| listagg(id,',') within group (order by id)
|| ');' as RB_STMT
from mytable
where code in (121212,151515)
group by code;
这适用于小型设备,例如在我的开发环境中,但在生产中我达到了字符串长度的限制(ORA-01489)。
所以我希望能够做的是除了代码之外还按x个id分组,这样x = 5的结果就是:
RB_STMT
------------
...set code=121212 where id in (1234,1235,1236,1237,1238);
...set code=121212 where id in (1239,2111,2112,2123,2124);
...set code=121212 where id in (2125,2126,2136);
...set code=151515 where id in (1456,2345,2468,2469,2470);
etc.
(我当然会在现实中使用更大的x;适应ids的长度)
我尝试按floor(id/5)
进行分组并修复了字符串长度问题,但由于ID不是连续的,或者是均匀间隔的,所以我最终会得到很多只有少量ID的结果,而这不是理想的。
答案 0 :(得分:3)
您可以使用子查询(内联视图或CTE)将每个ID分配给存储桶,并将其包含在group-by子句中:
select '... set code='||code||' where id in ('
|| listagg(id,',') within group (order by id)
|| ');' as RB_STMT
from (
select id, code, ceil(row_number() over (partition by code order by id)/5) as bucket
from mytable
)
where code in (121212,151515)
group by code, bucket;
RB_STMT
--------------------------------------------------------------------------------
... set code=121212 where id in (1234,1235,1236,1237,1238);
... set code=121212 where id in (1239,2111,2112,2123,2124);
... set code=121212 where id in (2125,2126,2136);
... set code=151515 where id in (1456,2345,2468,2469,2470);
子查询本身会产生如下输出:
ID CODE BUCKET
---------- ---------- ----------
1234 121212 1
1235 121212 1
1236 121212 1
1237 121212 1
1238 121212 1
1239 121212 2
1456 151515 1
2111 121212 2
2112 121212 2
2123 121212 2
2124 121212 2
2125 121212 3
2126 121212 3
2136 121212 3
2345 151515 1
2468 151515 1
2469 151515 1
2470 151515 1
代码121212的前五个ID都有桶1;接下来的五个都有桶2;最后四个有桶3. 151515的桶再次从1开始。按代码和桶分组为你提供了一个简短的列表,可以聚合成最终的字符串。
要获得更多的每行,只需将5更改为更高的值。
假设在您提交更新之前,您还不知道这是一个问题,因此回滚不是一个选项 - 所以您要创建一个退出策略而不是而不是回滚' script - 其他选项包括:导出表并截断/导入,如果需要还原它;或创建表的备份副本,并还原为副本或使用它来进行更新;或者可能是其他一些我没有想过的。