我需要用这句话更新一堆行:
UPDATE "STATISTICS" SET MEDIA = (CASE WHEN TB_STATISTICS.TYPE > 3 THEN 2 ELSE 1 END);
但是,ORA-30036失败,因为没有足够的空间容纳UNDOTBS1。我不拥有数据库,也无法增加表空间来撤消。
该表大约有3000万行,如果每次正常工作时我只更新1000万行,则:
UPDATE "STATISTICS" SET MEDIA = (CASE WHEN TB_STATISTICS.TYPE > 3 THEN 2 ELSE 1 END) where rownum < 10000000;
但是,我无法获取它来更新接下来的1000万行。我已经试过了:
UPDATE "STATISTICS" SET MEDIA = (CASE WHEN TB_STATISTICS.TYPE > 3 THEN 2 ELSE 1 END) where rownum > 10000000 and rownum < 20000000;
但是它总是说“更新了0行”。
我已经看到,在执行SELECT时,可以通过将rownum设置为选定列之一并为其分配别名来实现。但是我不知道如何在UPDATE语句中做到这一点。
谢谢。
您当前的状态是矛盾的,因为一个值不能同时小于1000万和大于2000万。但是即使您撤消了它,由于设置的方式和时间的原因,它仍然无法按预期工作rownum
。从文档中:
条件
ROWNUM
值大于正整数的测试始终为假。例如,此查询不返回任何行:SELECT * FROM employees WHERE ROWNUM > 1;
提取的第一行被分配
ROWNUM
为1,并使条件为假。现在要获取的第二行是第一行,并且也被分配ROWNUM
为1并使条件为假。随后所有行均不满足该条件,因此不返回任何行。
使用rownum
这种不理想,但如果你改变你的声明:
UPDATE "STATISTICS" SET MEDIA = (CASE WHEN TB_STATISTICS.TYPE > 3 THEN 2 ELSE 1 END)
where (MEDIA IS NULL OR MEDIA != (CASE WHEN TB_STATISTICS.TYPE > 3 THEN 2 ELSE 1 END))
and rownum < 10000000 ;
那么每次您运行时,它将排除您已经更新的行,或者(作为奖励)已经具有正确值的行,因为它们将使where
条件失败;但它也允许该值最初也为null。
您也可以在PL / SQL块中执行此操作,最好使用批量查询和更新,也许这样的事情是您具有唯一或主键字段:
declare
type t_tab_type is table of statistics%rowtype;
l_tab t_tab_type;
cursor c is select * from statistics;
begin
open c;
loop
fetch c bulk collect into l_tab limit 10000000;
forall i in 1..l_tab.count
update statistics
set media = case when l_tab(i).tb_statistics.type > 3 then 2 else 1 end
where unique_key = l_tab(i).unique_key;
commit;
exit when c%notfound;
end loop;
close c;
end;
/
但可能的限制是小于一千万(因此提交的频率更高,除非您跟踪一个单独的变量进行控制),因为您不想为集合使用过多的内存。您还可以通过定义记录类型并使用而不是来减少使用的内存%rowtype
,可能只使用唯一键,然后更改select *
为仅与记录类型匹配的特定列。如果只有一列,则使用varray。
(也不确定是否tb_statistics.type
是对象类型,或者更可能是实际的表名和列名,并且在修改要发布的语句时遗漏了一些东西。如果它是同一表中的列,则此计算将始终相同当添加新行时,则media
可能有可能是虚拟列。)
最好有足够的撤消空间来在一个事务中执行操作,以提高效率和可重启性。但是这似乎是一次性的,因此即使是临时的大型撤消表空间,也可能不值得进行更改。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句