一宪躯、事務(wù)概念
事務(wù)是一種機(jī)制、是一種操作序列夷都,它包含了一組數(shù)據(jù)庫操作命令眷唉,這組命令要么全部執(zhí)行,要么全部不執(zhí)行囤官。因此事務(wù)是一個(gè)不可分割的工作邏輯單元冬阳。在數(shù)據(jù)庫系統(tǒng)上執(zhí)行并發(fā)操作時(shí)事務(wù)是作為最小的控制單元來使用的。這特別適用于多用戶同時(shí)操作的數(shù)據(jù)通信系統(tǒng)党饮。例如:訂票肝陪、銀行、保險(xiǎn)公司以及證券交易系統(tǒng)等刑顺。
二氯窍、事務(wù)屬性
事務(wù)4大屬性:
1?? 原子性(Atomicity):事務(wù)是一個(gè)完整的操作。
2?? 一致性(Consistency):當(dāng)事務(wù)完成時(shí)蹲堂,數(shù)據(jù)必須處于一致狀態(tài)狼讨。
3?? 隔離性(Isolation):對數(shù)據(jù)進(jìn)行修改的所有并發(fā)事務(wù)是彼此隔離的。
4?? 持久性(Durability):事務(wù)完成后柒竞,它對于系統(tǒng)的影響是永久性的政供。
三、創(chuàng)建事務(wù)
T-SQL中管理事務(wù)的語句:
1 開始事務(wù): begin transaction
2 提交事務(wù):commit transaction
3 回滾事務(wù): rollback transaction
事務(wù)分類:
1 顯式事務(wù):用begin transaction明確指定事務(wù)的開始。
2 隱性事務(wù):打開隱性事務(wù):set implicit_transactions on布隔,當(dāng)以隱性事務(wù)模式操作時(shí)离陶,SQL Servler將在提交或回滾事務(wù)后自動(dòng)啟動(dòng)新事務(wù)。無法描述事務(wù)的開始衅檀,只需要提交或回滾事務(wù)招刨。
3 自動(dòng)提交事務(wù):SQL Server的默認(rèn)模式,它將每條單獨(dú)的T-SQL語句視為一個(gè)事務(wù)哀军。如果成功執(zhí)行沉眶,則自動(dòng)提交,否則回滾排苍。
示例:張三轉(zhuǎn)800元到李四帳戶上沦寂。
use stuDB
go
--創(chuàng)建帳戶表bank--
if exists(select* from sysobjects where name='bank')
drop table bank
create table bank
(
customerName char(10),??? --顧客姓名
currentMoney money??????? --當(dāng)前余額
)
go
/**//*--添加約束学密,帳戶不能少于元--*/
alter table bank add
constraint CK_currentMoney check(currentMoney>=1)
/**//*--插入測試數(shù)據(jù)--*/
insert into bank(customerName,currentMoney)
select '張三',1000 union
select '李四',1
select * from bank
go
/**//*--使用事務(wù)--*/
use stuDB
go
--恢復(fù)原來的數(shù)據(jù)
--update bank set currentMoney=currentMoney-1000 where customerName='李'
set nocount on??? --不顯示受影響的行數(shù)
print '查看轉(zhuǎn)帳事務(wù)前的余額'
select * from bank
go
/**//*--開始事務(wù)--*/
begin transaction
declare @errorSum int??? --定義變量淘衙,用于累計(jì)事務(wù)執(zhí)行過程中的錯(cuò)誤
/**//*--轉(zhuǎn)帳--*/
update bank set currentMoney=currentMoney-800 where customerName='張三'
set @errorSum=@errorSum+@@error??? --累計(jì)是否有錯(cuò)誤
update bank set currentMoney=currentMoney+800 where customerName='李四'
set @errorSum=@errorSum+@@error --累計(jì)是否有錯(cuò)誤
print '查看轉(zhuǎn)帳事務(wù)過程中的余額'
select * from bank
/**//*--根據(jù)是否有錯(cuò)誤,確定事務(wù)是提交還是回滾--*/
if @errorSum>0
begin
print '交易失敗腻暮,回滾事務(wù).'
rollback transaction
end
else
begin
print '交易成功彤守,提交事務(wù),寫入硬盤哭靖,永久保存具垫!'
commit transaction
end
go
print '查看轉(zhuǎn)帳后的余額'
select * from bank
go
sql事務(wù)(Transaction)用法介紹及回滾實(shí)例
事務(wù)(Transaction)是并發(fā)控制的單位,是用戶定義的一個(gè)操作序列试幽。這些操作要么都做筝蚕,要么都不做,是一個(gè)不可分割的工作單位铺坞。通過事務(wù)起宽,SQL Server能將邏輯相關(guān)的一組操作綁定在一起,以便服務(wù)器保持?jǐn)?shù)據(jù)的完整性
當(dāng)對多個(gè)表進(jìn)行更新的時(shí)候济榨,某條執(zhí)行失敗坯沪。為了保持?jǐn)?shù)據(jù)的完整性,需要使用事務(wù)回滾擒滑。
顯示設(shè)置事務(wù)
代碼如下
begin try ? www.2cto.com
begin transaction
insert into shiwu (asd) values ('aasdasda');
commit transaction
end try
begin catch
select ERROR_NUMBER() as errornumber
rollback transaction
end catch
隱式設(shè)置事務(wù)
代碼如下
set implicit_transactions on; -- 啟動(dòng)隱式事務(wù)
go
begin try
insert into shiwu (asd) values ('aasdasda');
insert into shiwu (asd) values ('aasdasda');
commit transaction;
end try
begin catch
select ERROR_NUMBER() as errornumber
rollback transaction; --回滾事務(wù)
end catch
set implicit_transactions off; --關(guān)閉隱式事務(wù)
go
顯示事務(wù)以下語句不能使用腐晾,隱式事務(wù)可以
代碼如下
alter database;
backup; ? www.2cto.com
create database;
drop database;
reconfigure;
restore;
update statistics;
顯示事務(wù)可以嵌套使用
代碼如下
--創(chuàng)建存儲(chǔ)過程
create procedure qiantaoProc
@asd nchar(10)
as
begin
begin try
begin transaction innerTrans
save transaction savepoint --創(chuàng)建事務(wù)保存點(diǎn)
insert into shiwu (asd) values (@asd);
commit transaction innerTrans
end try
begin catch
rollback transaction savepoint --回滾到保存點(diǎn)
commit transaction innerTrans
end catch
end
go
begin transaction outrans
exec qiantaoProc 'asdasd';
rollback transaction outrans
事務(wù)嵌套,回滾外層事務(wù)時(shí)丐一,如果嵌套內(nèi)的事務(wù)已經(jīng)回滾過則會(huì)有異常藻糖。此時(shí)需要使用事務(wù)保存點(diǎn)。如下實(shí)例
SQL事務(wù)回滾
指定當(dāng) ? Transact-SQL ? 語句產(chǎn)生運(yùn)行時(shí)錯(cuò)誤時(shí)库车,Microsoft? ? SQL ? Server? ? 是否自動(dòng)回滾當(dāng)前事務(wù)
方案一:
代碼如下
SET ? XACT_ABORT ? ON--如果產(chǎn)生錯(cuò)誤自動(dòng)回滾
GO
BEGIN ? TRAN
INSERT ? INTO ? A ? VALUES ? (4)
INSERT ? INTO ? B ? VALUES ? (5)
COMMIT ? TRAN ?www.2cto.com
也可以使用_ConnectionPtr 對象的方法: BeginTrans巨柒、CommitTrans、RollbackTrans,使用該系列函數(shù)判斷并回滾潘拱。一旦調(diào)用了 BeginTrans 方法, 在調(diào)用 CommitTrans 或 RollbackTrans 結(jié)束事務(wù)之前,數(shù)據(jù)庫將不再立即提交所作的任何更改疹鳄。
方案二
代碼如下
BEGIN TRANSACTION
INSERT INTO A ? values ?(4) ? ----- 該表含有觸發(fā)器,UPDATE其他表
IF @@error <> 0 ?--發(fā)生錯(cuò)誤
BEGIN
ROLLBACK TRANSACTION
END
ELSE
BEGIN
COMMIT TRANSACTION
END
sql事務(wù)結(jié)合asp.net兩種用法
在sql server+ .net 開發(fā)環(huán)境下芦岂,有兩種方法能夠完成事務(wù)的操作瘪弓,保持?jǐn)?shù)據(jù)庫的數(shù)據(jù)完整性;一個(gè)就是用sqlserver/42850.htm target=_blank >sql存儲(chǔ)過程禽最,另一個(gè)就是在ADO.NET中一種簡單的事務(wù)處理腺怯;現(xiàn)在通過一個(gè)典型的銀行轉(zhuǎn)賬的例子來說明一下這兩個(gè)例子的用法我們先來看看sql存儲(chǔ)過程是如何來完成事務(wù)的操作的:首先創(chuàng)建一個(gè)表:
代碼如下
create database aaaa --創(chuàng)建一個(gè)表,包含用戶的帳號(hào)和錢數(shù)gouse aaaacreate table bb( ID int not null primary key, ?--帳號(hào) moneys money ? ?--轉(zhuǎn)賬金額)insert into bb values ('1','2000') --插入兩條數(shù)據(jù)insert into bb values ('2','3000')用這個(gè)表創(chuàng)建一個(gè)存儲(chǔ)過程:
create procedure mon --創(chuàng)建存儲(chǔ)過程川无,定義幾個(gè)變量
@toID int, ? ?--接收轉(zhuǎn)賬的賬戶
@fromID int , ?--轉(zhuǎn)出自己的賬戶
@momeys money --轉(zhuǎn)賬的金額
as
begin tran --開始執(zhí)行事務(wù)
update bb set moneys=moneys-@momeys where ID=@fromID -執(zhí)行的第一個(gè)操作呛占,轉(zhuǎn)賬出錢,減去轉(zhuǎn)出的金額
update bb set moneys=moneys+@momeys where ID=@toID --執(zhí)行第二個(gè)操作懦趋,接受轉(zhuǎn)賬的金額晾虑,增加 ?www.2cto.com
if @@error<>0 --判斷如果兩條語句有任何一條出現(xiàn)錯(cuò)誤
begin rollback tran –開始執(zhí)行事務(wù)的回滾,恢復(fù)的轉(zhuǎn)賬開始之前狀態(tài)
return 0
end
go
else ? --如何兩條都執(zhí)行成功
begin commit tran 執(zhí)行這個(gè)事務(wù)的操作
return 1
end
go
接下來看看C#.net 是如何調(diào)用這個(gè)存儲(chǔ)過程的:
代碼如下
protected void Button1_Click(object sender, EventArgs e)
{
SqlConnection con =new SqlConnection(@"Data Source=.SQLEXPRESS;database=aaaa;uid=sa;pwd=jcx"); //連接字符串
SqlCommand cmd = new SqlCommand("mon",con); //調(diào)用存儲(chǔ)過程
cmd.CommandType = CommandType.StoredProcedure;
con.Open();
SqlParameter prar = new SqlParameter();//傳遞參數(shù)
cmd.Parameters.AddWithValue("@fromID", 1);
cmd.Parameters.AddWithValue("@toID", 2);
cmd.Parameters.AddWithValue("@momeys",Convert.ToInt32( TextBox1.Text) );
www.2cto.com
cmd.Parameters.Add("@return", "").Direction = ParameterDirection.ReturnValue;//獲取存儲(chǔ)過程的返回值
cmd.ExecuteNonQuery();
string value = cmd.Parameters["@return"].Value.ToString();//把返回值賦值給value
if (value == "1")
{
Label1.Text = "添加成功";
}
else
{
Label1.Text = "添加失敗";
}
}
這個(gè)也就是在存儲(chǔ)過程里添加事務(wù)仅叫,再來看看不在數(shù)據(jù)庫寫sql存儲(chǔ)過程帜篇,ADO.NET是如何處理事務(wù)的:
代碼如下
protected void Button2_Click(object sender, EventArgs e)
{
SqlConnection con = new SqlConnection(@"Data Source=.SQLEXPRESS;database=aaaa;uid=sa;pwd=jcx");
con.Open();
SqlTransaction tran = con.BeginTransaction();//先實(shí)例SqlTransaction類,使用這個(gè)事務(wù)使用的是con 這個(gè)連接诫咱,使用BeginTransaction這個(gè)方法來開始執(zhí)行這個(gè)事務(wù)
SqlCommand cmd = new SqlCommand();
cmd.Connection = con;
cmd.Transaction = tran;
try
{
//在try{} 塊里執(zhí)行sqlcommand命令笙隙,
cmd.CommandText = "update bb set moneys=moneys-'" + Convert.ToInt32(TextBox1.Text) + "' where ID='1'";
cmd.ExecuteNonQuery();
cmd.CommandText = "update bb set moneys=moneys+' aa ' where ID='2'";
cmd.ExecuteNonQuery();
tran.Commit();//如果兩個(gè)sql命令都執(zhí)行成功,則執(zhí)行commit這個(gè)方法坎缭,執(zhí)行這些操作
www.2cto.com
Label1.Text = "添加成功";
}
catch
{
Label1.Text = "添加失敗";
tran.Rollback();//如何執(zhí)行不成功竟痰,發(fā)生異常,則執(zhí)行rollback方法掏呼,回滾到事務(wù)操作開始之前坏快;
}
}
這就是兩個(gè)事務(wù)不同用法的簡單例子,ADO.NET 事務(wù)處理的方法看起來比較簡單哄尔,但是他要使用同一個(gè)連接來執(zhí)行這些操作假消,要是同時(shí)使用幾個(gè)數(shù)據(jù)庫來用一個(gè)事務(wù)執(zhí)行,這樣就比較繁瑣岭接,但是要是用sql存儲(chǔ)過程富拗,這樣就相對比較簡單