我对SQL很新,想知道是否有人可以帮助我。
我有一个大约有1000万行的数据库。
我需要创建一个脚本来查找具有一些NULL字段的记录,然后将其更新为某个值。
我做一个简单的更新语句时遇到的问题是它会破坏回滚空间。
我正在四处阅读,我需要使用BULK COLLECT AND FETCH。
我的想法是一次获取10,000条记录,更新,提交和继续提取。
我尝试在Google上查找示例,但我还没有找到任何内容。
任何帮助?
谢谢!
这是我到目前为止所做的:
DECLARE
CURSOR rec_cur IS
SELECT DATE_ORIGIN
FROM MAIN_TBL WHERE DATE_ORIGIN IS NULL;
TYPE date_tab_t IS TABLE OF DATE;
date_tab date_tab_t;
BEGIN
OPEN rec_cur;
LOOP
FETCH rec_cur BULK COLLECT INTO date_tab LIMIT 1000;
EXIT WHEN date_tab.COUNT() = 0;
FORALL i IN 1 .. date_tab.COUNT
UPDATE MAIN_TBL SET DATE_ORIGIN = '23-JAN-2012'
WHERE DATE_ORIGIN IS NULL;
END LOOP;
CLOSE rec_cur;
END;
答案 0 :(得分:3)
我想我知道你要做什么。关于以下代码与您之间的差异,我想提出一些观点。
forall
循环不会使用索引。通过使用rowid
更新您的表格,这很容易实现。forall
之后提交,减少所需的撤消量;但如果出现问题,请更难以回滚。虽然从逻辑上讲,您的查询可以轻松地在中间重新启动,而不会损害您的目标。rowids
很小,一次收集至少25k;如果不是100k。nvl(date_origin,'x')
这样的函数索引作为一个松散的例子会提高你选择数据的速度。这也意味着你实际上不必使用表本身。您只能从索引中选择。假设根据您的评论date_origin
是一个日期,那么索引应该是这样的:
nvl(date_origin,to_date('absolute_minimum_date_in_Oracle_as_a_string','yyyymmdd'))
我目前无法访问数据库,但要查找amdiOaas
运行以下查询:
select to_date('0001','yyyy') from dual;
它应该为你提出一个有用的错误。
PL / SQL Developer中的工作示例。
create table main_tbl as
select cast( null as date ) as date_origin
from all_objects
;
create index i_main_tbl
on main_tbl ( nvl( to_date(date_origin,'yyyy-mm-dd')
, to_date('0001-01-01' ,'yyyy-mm-dd') )
)
;
declare
cursor c_rec is
select rowid
from main_tbl
where nvl(date_origin,to_date('0001-01-01','yyyy-mm-dd'))
= to_date('0001-01-01','yyyy-mm-dd')
;
type t__rec is table of rowid index by binary_integer;
t_rec t__rec;
begin
open c_rec;
loop
fetch c_rec bulk collect into t_rec limit 50000;
exit when t_rec.count = 0;
forall i in t_rec.first .. t_rec.last
update main_tbl
set date_origin = to_date('23-JAN-2012','DD-MON-YYYY')
where rowid = t_rec(i)
;
commit ;
end loop;
close c_rec;
end;
/