學(xué)習(xí)存儲(chǔ)過(guò)程中使用斷點(diǎn)回滾事務(wù)時(shí),發(fā)現(xiàn)目前網(wǎng)絡(luò)上存在一個(gè)問(wèn)題,那就是使用斷點(diǎn)回滾后,都忘記了一個(gè)很重要的事情,提交事務(wù)。雖然使用了斷點(diǎn)回滾,但是斷點(diǎn)回滾不像rollBack或commit一樣結(jié)束當(dāng)前事務(wù),而使用斷點(diǎn)回滾只會(huì)回滾到聲明斷點(diǎn)的地方,之前的產(chǎn)生的事務(wù)仍需要提交的,如果不提交,事務(wù)一直在數(shù)據(jù)庫(kù)中緩存.
站在用戶的角度思考問(wèn)題,與客戶深入溝通,找到安吉網(wǎng)站設(shè)計(jì)與安吉網(wǎng)站推廣的解決方案,憑借多年的經(jīng)驗(yàn),讓設(shè)計(jì)與互聯(lián)網(wǎng)技術(shù)結(jié)合,創(chuàng)造個(gè)性化、用戶體驗(yàn)好的作品,建站類型包括:成都網(wǎng)站設(shè)計(jì)、網(wǎng)站制作、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣、國(guó)際域名空間、網(wǎng)站空間、企業(yè)郵箱。業(yè)務(wù)覆蓋安吉地區(qū)。
Demo:
procedure doSomeThing(p_number out number) as
begin
insert into t_test_user_mingming(id,loginname,password,realname,type)
values(se_test_user_mingming_id.nextval,'xiaoming','1234','小明',1);
p_number := 1;
savepoint ps;--- 設(shè)置斷點(diǎn) ps
insert into t_test_info_mingming(id,pal,type,create_time,note)
values(se_test_info_id.nextval,'我想買(mǎi)臺(tái)thinkPad 可以俺莫有錢(qián)',1,sysdate,'ceshi');
p_number := 2;
savepoint sp;----設(shè)置斷點(diǎn) sp
insert into t_test_agent(agent_id) values(1);---我這里此行會(huì)拋出異常 ORA-01400 可以替換為下句 手動(dòng)拋出一個(gè)異常
-----RAISE_APPLICATION_ERROR (-20004,'拋出的異常玩玩');
commit;
exception --捕獲異常
when others then
rollback to ps; ---- 如果產(chǎn)生異常,回滾到斷點(diǎn) ps
p_number :=0;
commit; --- 提交事務(wù)
end doSomeThing;
這里本人做了實(shí)驗(yàn),如果在異常中不加 commit 語(yǔ)句,使用PL/SQL測(cè)試時(shí),異常在緩存,t_test_user_mingming 表中沒(méi)有數(shù)據(jù)記錄。
存儲(chǔ)過(guò)程里的事務(wù)操作:
create or replace procedure pr_mypro2(p_a in varchar2,p_b in varchar2,p_count out number)
temp varchar2(1000); /*定義臨時(shí)變量*/
is
begin
select code into p_count from table1 where a=p_a; /*查詢并返回值*/
temp := p_count; /*將返回值賦給臨時(shí)變量*/
savepoint point1; /*保存點(diǎn)*/
insert into table2(a,b)values(temp,p_b); /*將臨時(shí)變量值添加到新表的字段*/
savepoint point2;
insert into
exception
when others then
rollback to savepoint point1; /*異常處理,保存點(diǎn)下面的操作都不會(huì)被執(zhí)行*/
return;
end;
保存點(diǎn)(SAVEPOINT)是事務(wù)處理過(guò)程中的一個(gè)標(biāo)志,與回滾命令(ROLLBACK)結(jié)合使用,主要的用途是允許用戶將某一段處理回滾而不必回滾整個(gè)事務(wù)。
如果定義了多個(gè)savepoint,當(dāng)指定回滾到某個(gè)savepoint時(shí),那么回滾操作將回滾這個(gè)savepoint后面的所有操作(即使后面可能標(biāo)記了N個(gè)savepoint)。
例如,在一段處理中定義了五個(gè)savepoint,從第三個(gè)savepoint回滾,后面的第四、第五個(gè)標(biāo)記的操作都將被回滾,如果不使用ROLLBACK TO savepoint_name而使用ROLLBACK,將會(huì)滾整個(gè)事務(wù)處理。
create or replace procedure my_update(vempno in number,vsal in number)as vint stu.sal%type:=vsal; my_exception exception; rint stu.sal%type;begin update stu set sal = vint where empno = vempno; select sal into rint from stu where empno = vempno; if rint0 then raise my_exception; end if; exception when my_exception then rollback;
commit; --提交
EXCEPTION WHEN OTHERS THEN --如果出錯(cuò)
ROLLBACK; --回滾
execute執(zhí)行后 可以回滾
commit提交后 不可以回滾
其實(shí)Oracle提交數(shù)據(jù)是分兩步操作的,第一步execute執(zhí)行,第二步commit提交。對(duì)應(yīng)的PL\SQL也是要先點(diǎn)execute執(zhí)行,執(zhí)行后再點(diǎn)commit提交。
但是 commit提交后 可以用閃回查詢恢復(fù)原來(lái)的數(shù)據(jù) 因?yàn)閛racle會(huì)將近期的數(shù)據(jù)保存到快照中 如:
SELECT * FROM TABLE_1 AS OF TIMESTAMP TO_TIMESTAMP('20080606 20:00:00','YYYYMMDD HH24:MI:SS');
這里'20080606 20:00:00'就是你想恢復(fù)數(shù)據(jù)到哪個(gè)時(shí)間狀態(tài) TABLE_1是數(shù)據(jù)庫(kù)的表名 這樣查詢到的數(shù)據(jù)就是執(zhí)行更新操作之前的數(shù)據(jù)