當前位置:首頁 » 服務存儲 » 存儲過程沒啟用事務
擴展閱讀
webinf下怎麼引入js 2023-08-31 21:54:13
堡壘機怎麼打開web 2023-08-31 21:54:11

存儲過程沒啟用事務

發布時間: 2022-11-25 06:31:15

1. 關於存儲過程與事務

這兩個概念可以說是兩個范疇的概念,事務是資料庫操作范疇的概念,保證資料庫數據的完整性和一致性;存儲過程是高級程序設計中模塊化設計思想的重要內容。

事務是包含一組修改(插入、更新和刪除)的工作的邏輯單位。事務的操作要麼被保存到資料庫commit,要麼回滾rollback,事務中的所有修改要麼全部提交,要麼什麼也不做,這樣保證了資料庫中數據的完整性和一致性。

資料庫操作中為了完成一個完整的資料庫任務,從而引進高級程序的設計要素。過程就是高級程序設計語言中的模塊概念,將一些內部聯系的命令組成一個個過程,通過參數在過程間傳遞數據來完成一個完整的資料庫任務,這就是模塊化設計思想的重要內容。

有的時候可以把一個過程看作一個事務,但是有的過程運行過程中因為滿足某些條件而從過程中跳出,這時就不能把過程看作事務;反之,一個事務可能是一個過程,也可能一個事務中包含對一個或多個過程的調用。

二者概念所述的范疇不同,在資料庫中,是相互聯系相互區別的;而且兩者都是具體的,不是抽象的,因為都可以拿出一段代碼,說它是事務或是存儲過程。

以上是個人理解,希望對你有所幫助。

2. 東軟醫保軟體客服提示開啟事務失敗,執行存儲過程出錯是怎麼回事該怎麼解決

是可以解決的

3. CALL存儲過程,報錯.該怎麼處理

一、存儲過程中使用事務的簡單語法
在存儲過程中使用事務時非常重要的,使用數據可以保持數據的關聯完整性,在sql server存儲過程中使用事務也很簡單,用一個例子來說明它的語法格式:
1
2
3
4
5
6
7
8
9
10
11
12
13
Create Procere MyProcere
( @Param1 nvarchar(10),
@param2 nvarchar(10)
)
AS
Begin
Set NOCOUNT ON;
Set XACT_ABORT ON;
Begin Tran
Delete from table1 where name=』abc』;
Insert into table2 values(value1,value2,value3);
Commit Tran
End
說明:
1 、使用存儲過程執行事物,需要開啟XACT_ABORT參數(默認值為Off),將該參數設置為On,表示當執行事務時,如果出錯,會將transcation設置為uncommittable狀態,那麼在語句塊批處理結束後將回滾所有操作;如果該參數設置為Off,表示當執行事務時,如果出錯,出錯的語句將不會執行,其他正確的操作繼續執行。

2、當SET NOCOUNT 為 ON 時,不返回計數(計數表示受 Transact-SQL 語句影響的行數,例如在Sql server查詢分析器中執行一個delete操作後,下方窗口會提示(3)Rows Affected)。當 SET NOCOUNT 為 OFF 時,返回計數,我們應該在存儲過程的頭部加上SET NOCOUNT ON 這樣的話,在退出存儲過程的時候加上 SET NOCOUNT OFF這樣的話,以達到優化存儲過程的目的。

二、事務內設置保存點
用戶可以在事務內設置保存點或標記。保存點定義如果有條件地取消事務的一部分,事務可以返回的位置。如果將事務回滾到保存點,則必須(如果需要,使用更多的 Transact-SQL 語句和 COMMIT TRANSACTION 語句)繼續完成事務,或者必須(通過將事務回滾到其起始點)完全取消事務。若要取消整個事務,請使用 ROLLBACK TRANSACTION transaction_name 格式。這將撤消事務的所有語句和過程。如:
代碼
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Create Procere MyProcere
AS
Begin
Set NOCOUNT ON;
Set XACT_ABORT ON;
begin tran ok --開始一個事務OK
delete from rxqz where qz= 'rx015 ' --刪除數據
save tran bcd --保存一個事務點命名為bcd
update sz set name='李麗s' where name= '李麗'--修改數據

if @@error<>0 --判斷修改數據有沒有出錯
begin --如果出錯
rollback tran bcd -- 回滾事務到BCD 的還原點
commit tran ok --提交事務
end
else --沒有出錯
commit tran ok --提交事務
End
說明:1、@@error判斷是否有錯誤,為0表示沒有錯誤,但是對那種重大錯誤無法捕捉,而且@@error只能前一句sql語句生效。

三、存儲過程使用try…catch捕獲錯誤
在存儲過程中可以使用try…catch語句來捕獲錯誤,如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Create Procere MyProcere
( @Param1 nvarchar(10),
@param2 nvarchar(10)
)
AS
Begin
Set NOCOUNT ON;
Begin try
Delete from table1 where name=』abc』;
Insert into table2 values(value1,value2,value3);
End try
Begin Catch
SELECT ERROR_NUMBER() AS ErrorNumber,
ERROR_MESSAGE() AS ErrorMessage;
End Catch
End

說明:1、捕獲錯誤的函數有很多,如下:
ERROR_NUMBER() 返回錯誤號。
ERROR_SEVERITY() 返回嚴重性。
ERROR_STATE() 返回錯誤狀態號。
ERROR_PROCEDURE() 返回出現錯誤的存儲過程或觸發器的名稱。
ERROR_LINE() 返回導致錯誤的常式中的行號。
ERROR_MESSAGE() 返回錯誤消息的完整文本。該文本可包括任何可替換參數所提供的值,如長度、對象名或時間。
2、有些錯誤,如sql語句中的表名稱輸入錯誤,這是資料庫引擎無法解析這個表名稱時,所發生的錯誤在當前的try…catch語句中無法捕獲,必須由外層調用該存儲過程的地方使用 try…catch來進行捕獲。

四、存儲過程中事務和try…catch聯合使用
在存儲過程中使用事務時,如果沒有try…catch語句,那麼當set xact_abort on時,如果有錯誤發生,在批處理語句結束後,系統會自動回滾所有的sql操作。當set xact_abort off時,如果有錯誤發生,在批處理語句結束後,系統會執行所有沒有發生錯誤的語句,發生錯誤的語句將不會被執行。
在存儲過程中使用事務時,如果存在try…catch語句塊,那麼當捕獲到錯誤時,需要在catch語句塊中手動進行Rollback操作,否則系統會給客戶端傳遞一條錯誤信息。如果在存儲過程開始處將set xact_abort on,那麼當有錯誤發生時,系統會將當前事務置為不可提交狀態,即會將xact_state()置為-1,此時只可以對事務進行Rollback操作,不可進行提交(commit)操作,那麼我們在catch語句塊中就可以根據xact_state()的值來判斷是否有事務處於不可提交狀態,如果有則可以進行rollback操作了。如果在存儲過程開始處將set xact_abort off,那麼當有錯誤發生時,系統不會講xact_state()置為-1,那麼我們在catch塊中就不可以根據該函數值來判斷是否需要進行rollback了,但是我們可以根據@@Trancount全局變數來判斷,如果在catch塊中判斷出@@Trancount數值大於0,代表還有未提交的事務,既然進入catch語句塊了,那麼還存在未提交的事務,該事務應該是需要rollback的,但是這種方法在某些情況下可能判斷的不準確。推薦的方法還是將set xact_abort on,然後在catch中判斷xact_state()的值來判斷是否需要Rollback操作。
下面我們來看看兩個例子:
一.使用Set xact_abort on

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Create proc myProcere
As
begin
set xact_abort on;
begin try
begin tran
insert into TestStu values('Terry','boy',23);
insert into TestStu values('Mary','girl',21);
commit tran
end try
begin catch
--在此可以使用xact_state()來判斷是否有不可提交的事務,不可提交的事務
--表示在事務內部發生錯誤了。Xact_state()有三種值:-1.事務不可提交;
--1.事務可提交;0.表示沒有事務,此時commit或者rollback會報錯。
if xact_state()=-1
rollback tran;
end catch
end

二.使用Set xact_abort off
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Create proc myProcere
As
begin
set xact_abort off;
begin try
begin tran
insert into TestStu values('Terry','boy',23);
insert into TestStu values('Mary','girl',21);
commit tran
end try
begin catch
--在此不可以使用xact_state來判斷是否有不可提交的事務
--只可以使用@@Trancount來判斷是否有還未提交的事務,未提交的事務未必
--就是不可提交的事務,所以使用@@TranCount>0後就RollBack是不準確的
if @@TranCount>0
rollback tran;
end catch
end

另外,對於@@Trancount需要說明的是,begin tran 語句將 @@Trancount加 1。Rollback tran將 @@Trancount遞減到 0,但 Rollback tran savepoint_name 除外,它不影響 @@Trancount。Commit tran 或 Commit work 將 @@Trancount 遞減 1。

4. oracle 存儲過程事務控制

把第一個commit去掉既可,如下:

create or replace procere aaa is
var2 number;
begin SELECT Seq_Tbtopic.nextval INTO var2 FROM al;
insert into tbTopic values (var2 , 1, 1, '口語3333',1,3,2,'','');

insert into tbchildtopic values (Seq_Tbchildtopic.Nextval,var2,'','ck','/kangsi/Resource/test/B1/1_2_2_1_Emily_ck_.mp3','ck');

commit;
end aaa;

5. Spring 事務控制-存儲過程事務

事務Id是同一個 也就是使用同一個事務

事務Id不是同一個 也就是使用不同的事務

思考: 存儲過程發生異常應該如何回滾存儲過程修改的數據?參考Spring事務控制-存儲過程異常事務處理機制

6. postgresql 存儲過程的事務處理

一個PostgreSQL存儲過程的例子

需求:
給出如下條件進行批處理編排
- 開始日期時間
- 重復間隔(分鍾)
- 重復次數
要求在檔期內重復安排節目播出, 比如: 2003.01.01 08:00 開始每隔240分鍾播出一次, 一共播出100次

資料庫表格(CO_SCHEDULE)
------------------------------
N_PROGID INT
DT_STARTTIME TIMESTAMP
DT_ENDTIME TIMESTAMP

存儲過程的實現:

create table co_schele(n_progid int,dt_starttime timestamp,dt_endtime timestamp);

//創建函數:
create function add_program_time(int4,timestamp,int4,int4,int4) returns bool as '
declare
prog_id alias for $1;
ration_min alias for $3;
period_min alias for $4;
repeat_times alias for $5;
i int;
starttime timestamp;
ins_starttime timestamp;
ins_endtime timestamp;
begin
starttime :=$2;
i := 0;
while i<repeat_times loop
ins_starttime := starttime;
ins_endtime := timestamp_pl_span(ins_starttime,ration_min || ''mins'');
starttime := timestamp_pl_span(ins_starttime,period_min || ''mins'');
insert into co_schele values(prog_id,ins_starttime,ins_endtime);
i := i+1;
end loop;
if i<repeat_times then
return false;
else
return true;
end if;
end;
'language 'plpgsql';

//執行函數:
select add_program_time(1,'2002-10-20 0:0:0','5','60','5');

//查看結果:select * from co_schele;
n_progid | dt_starttime | dt_endtime
----------+------------------------+------------------------
1 | 2002-10-20 00:00:00+08 | 2002-10-20 00:05:00+08
1 | 2002-10-20 01:00:00+08 | 2002-10-20 01:05:00+08
1 | 2002-10-20 02:00:00+08 | 2002-10-20 02:05:00+08
1 | 2002-10-20 03:00:00+08 | 2002-10-20 03:05:00+08
1 | 2002-10-20 04:00:00+08 | 2002-10-20 04:05:00+08

ps:
1.資料庫一載入 plpgsql語言。如沒有,
su - postgres
createlang plpgsql dbname
2.至於返回類型為bool,是因為我不知道如何讓函數不返回值。等待改進。

7. 在存儲過程中執行一個DML語句需要事務嗎

用事務操作語句,如
SAVE
POINT;
COMMIT;
ROLLBACK;
oracle在執行第一個DML語句啟動一個事務,不需要,自己begin
transaction。
實際上通常不建議存儲過程中直接控制事務。

8. 觸發器調用遠程存儲過程時 報ole db訪問介面''sqlncli'無法啟動分布式事務

看著像sybase。
估計不能這樣調用,考慮其他方法吧。

9. 存儲過程執行出錯,該怎麼解決

第一:如果是存儲過程中拋了異常,那麼結合事務,出現異常的時候,就回滾事務;
第2:如果邏輯不符合需求,這個就只有從新梳理了,這個是沒有辦法的,

10. mysql的存儲過程會自動開啟一個事務嗎

事務是一組原子性的SQL查詢語句,也可以被看做一個工作單元。如果資料庫引擎能夠成功地對資料庫應用所有的查詢語句,它就會執行所有查詢,如果任何一條查詢語句因為崩潰或其他原因而無法執行,那麼所有的語句就都不會執行。也就是說,事務內的語句要麼全部執行,要麼一句也不執行。