你真的了解觸發(fā)器么 數(shù)據(jù)實時同步更新問題剖析
更新時間:2013年01月17日 12:19:02 作者:
觸發(fā)器就是我們想要的神器了。我們可以在那張動態(tài)表上新建觸發(fā)器。觸發(fā)器的實質(zhì)就是個存儲過程,只不過他調(diào)用的時間是根據(jù)所建的動態(tài)表發(fā)生該表而執(zhí)行(即:Insert新數(shù)據(jù),Update或者Delete數(shù)據(jù))具體怎么使用觸發(fā)器,今天我這里就不介紹了
當我們想更新一張動態(tài)表的時候(即:表中的數(shù)據(jù)不斷的添加),也許我們會用數(shù)據(jù)庫代理,通過寫作業(yè),然后讓他定時查詢動態(tài)表中最新添加的數(shù)據(jù),然后更新數(shù)據(jù)。這樣時能實現(xiàn)更新數(shù)據(jù)的要求,但是數(shù)據(jù)卻不能實時同步更新。
這個時候,觸發(fā)器就是我們想要的神器了。我們可以在那張動態(tài)表上新建觸發(fā)器。觸發(fā)器的實質(zhì)就是個存儲過程,只不過他調(diào)用的時間是根據(jù)所建的動態(tài)表發(fā)生該表而執(zhí)行(即:Insert新數(shù)據(jù),Update或者Delete數(shù)據(jù))。
具體怎么使用觸發(fā)器,今天我這里就不介紹了,園子里資料多的很。那么我今天要介紹的是什么呢?
前幾天在寫sql代碼的時候無意間發(fā)現(xiàn)了這么個問題:就是我一直以為每當動態(tài)表中插入一條數(shù)據(jù),觸發(fā)器就執(zhí)行一次,但是我這樣理解的話,當批量插入數(shù)據(jù)的時候,觸發(fā)器執(zhí)行的次數(shù)和插入的行數(shù)相同,但是事實不是這樣。乘著今天有點時間,就想寫出來和大家分享下,講的不對請大家斧正!
下面,我就寫了個簡單的例子供大家參考。
--我們要建觸發(fā)器的動態(tài)表
Create table Table_a
(
ID int identity(1,1),--自增ID
Content nvarchar(50),
UpdateIDForTrigger int
)
然后我們在該表上創(chuàng)建一個觸發(fā)器
Create TRIGGER [dbo].[Table_a_Ins]
ON [dbo].[Table_a]
AFTER INSERT
AS
BEGIN
declare @ID int
set @ID=(select ID from inserted)
--更新Table_a表中的UpdateIDForTrigger字段的值,為了能更明顯的看出實時執(zhí)行的效果
UPDATE Table_a
SET UpdateIDForTrigger = (@ID+10)--為了能看出不同,就直接將比ID大10的值作為變量賦值
WHERE ID = @ID;
END
接下來,我們按照普通一條條的插入結(jié)果測試下:
--給信息表添加數(shù)據(jù)
insert into Table_a(Content) values('信息一');
insert into Table_a(Content) values('信息二');
然后查詢下現(xiàn)在動態(tài)表中的數(shù)據(jù)情況
select * from Table_a
查詢結(jié)果如圖:
我們可以看到觸發(fā)器執(zhí)行了。在每條數(shù)據(jù)插入的時候觸發(fā)器同時執(zhí)行了Update功能。
然后,我們要批量插入數(shù)據(jù),為了方便我們插入,我們這里建立一張臨時的基本信息表:
--基本信息表
Create table Table_Info
(
ID int identity(1,1),
Content nvarchar(50)
)
然后插入數(shù)據(jù)
insert into Table_Info(Content) values('信息三');
insert into Table_Info(Content) values('信息四');
insert into Table_Info(Content) values('信息五');
insert into Table_Info(Content) values('信息六');
insert into Table_Info(Content) values('信息七');
insert into Table_Info(Content) values('信息八');
insert into Table_Info(Content) values('信息九');
insert into Table_Info(Content) values('信息十');
然后我們就可以批量插入數(shù)據(jù)到動態(tài)表中了
insert into Table_a(Content)
select Content from Table_Info
這次重點來了,我們在執(zhí)行這個sql語句的時候消息框中會出現(xiàn)錯誤提示:
有經(jīng)驗的朋友會知道,這個錯誤是由于多個結(jié)果用“=”賦值給一個變量導(dǎo)致的。
即:set @變量=(select 多行結(jié)果 from Table)
這個時候,我就疑惑了,問題出在哪里了呢?不是觸發(fā)器在每插一條數(shù)據(jù)的時候執(zhí)行一次么?
于是,我將觸發(fā)器改了下:
Alter TRIGGER [dbo].[Table_a_Ins]
ON [dbo].[Table_a]
AFTER INSERT
AS
BEGIN
select ID from inserted;
END
然后再執(zhí)行上面的批量插入試試看,看看他inserted表中到底存的是什么值:
果然不出所料,inserted表中的結(jié)果并不是一條數(shù)據(jù):

知道錯誤的原因,我們操作起來就簡單了,我們可以給inserted表建游標,然后通過游標來對批量插入的每行數(shù)據(jù)進行編輯。下面是我們修改后的觸發(fā)器代碼:
Alter TRIGGER [dbo].[Table_a_Ins]
ON [dbo].[Table_a]
AFTER INSERT
AS
BEGIN
declare @ID int
declare cur_Insert cursor
for
select ID from inserted
open cur_Insert
fetch next from cur_Insert into @ID
while @@fetch_status=0
begin
UPDATE Table_a
SET UpdateIDForTrigger = (@ID+10)--為了能看出不同,就直接將比ID大10的值作為變量賦值
WHERE ID = @ID;
fetch next from cur_Insert into @ID
end
close cur_Insert
deallocate cur_Insert
END
然后,我們再按照上面的批量插入數(shù)據(jù),然后查詢下動態(tài)表中的結(jié)果:
insert into Table_a(Content)
select Content from Table_Info;
select * from Table_a;
此時運行沒有錯誤提示了,運行結(jié)果如下:
Alter TRIGGER [dbo].[Table_a_Ins]
ON [dbo].[Table_a]
AFTER INSERT
AS
BEGIN
UPDATE Table_a
SET UpdateIDForTrigger =inserted.ID+10
FROM inserted
Where Table_a.ID=inserted.ID
END
然后再批量插入了幾行數(shù)據(jù),結(jié)果也是可以的。所以學無止境?。?!
總結(jié)下:觸發(fā)器運行是每次執(zhí)行一次Insert操作或者是Update,Delete等操作的時候才執(zhí)行的。它的對象不是針對于修改的行數(shù)(即:每行修改的時候執(zhí)行)。
這個時候,觸發(fā)器就是我們想要的神器了。我們可以在那張動態(tài)表上新建觸發(fā)器。觸發(fā)器的實質(zhì)就是個存儲過程,只不過他調(diào)用的時間是根據(jù)所建的動態(tài)表發(fā)生該表而執(zhí)行(即:Insert新數(shù)據(jù),Update或者Delete數(shù)據(jù))。
具體怎么使用觸發(fā)器,今天我這里就不介紹了,園子里資料多的很。那么我今天要介紹的是什么呢?
前幾天在寫sql代碼的時候無意間發(fā)現(xiàn)了這么個問題:就是我一直以為每當動態(tài)表中插入一條數(shù)據(jù),觸發(fā)器就執(zhí)行一次,但是我這樣理解的話,當批量插入數(shù)據(jù)的時候,觸發(fā)器執(zhí)行的次數(shù)和插入的行數(shù)相同,但是事實不是這樣。乘著今天有點時間,就想寫出來和大家分享下,講的不對請大家斧正!
下面,我就寫了個簡單的例子供大家參考。
復(fù)制代碼 代碼如下:
--我們要建觸發(fā)器的動態(tài)表
Create table Table_a
(
ID int identity(1,1),--自增ID
Content nvarchar(50),
UpdateIDForTrigger int
)
然后我們在該表上創(chuàng)建一個觸發(fā)器
復(fù)制代碼 代碼如下:
Create TRIGGER [dbo].[Table_a_Ins]
ON [dbo].[Table_a]
AFTER INSERT
AS
BEGIN
declare @ID int
set @ID=(select ID from inserted)
--更新Table_a表中的UpdateIDForTrigger字段的值,為了能更明顯的看出實時執(zhí)行的效果
UPDATE Table_a
SET UpdateIDForTrigger = (@ID+10)--為了能看出不同,就直接將比ID大10的值作為變量賦值
WHERE ID = @ID;
END
接下來,我們按照普通一條條的插入結(jié)果測試下:
復(fù)制代碼 代碼如下:
--給信息表添加數(shù)據(jù)
insert into Table_a(Content) values('信息一');
insert into Table_a(Content) values('信息二');
然后查詢下現(xiàn)在動態(tài)表中的數(shù)據(jù)情況
復(fù)制代碼 代碼如下:
select * from Table_a
查詢結(jié)果如圖:

我們可以看到觸發(fā)器執(zhí)行了。在每條數(shù)據(jù)插入的時候觸發(fā)器同時執(zhí)行了Update功能。
然后,我們要批量插入數(shù)據(jù),為了方便我們插入,我們這里建立一張臨時的基本信息表:
復(fù)制代碼 代碼如下:
--基本信息表
Create table Table_Info
(
ID int identity(1,1),
Content nvarchar(50)
)
然后插入數(shù)據(jù)
復(fù)制代碼 代碼如下:
insert into Table_Info(Content) values('信息三');
insert into Table_Info(Content) values('信息四');
insert into Table_Info(Content) values('信息五');
insert into Table_Info(Content) values('信息六');
insert into Table_Info(Content) values('信息七');
insert into Table_Info(Content) values('信息八');
insert into Table_Info(Content) values('信息九');
insert into Table_Info(Content) values('信息十');
然后我們就可以批量插入數(shù)據(jù)到動態(tài)表中了
復(fù)制代碼 代碼如下:
insert into Table_a(Content)
select Content from Table_Info
這次重點來了,我們在執(zhí)行這個sql語句的時候消息框中會出現(xiàn)錯誤提示:

有經(jīng)驗的朋友會知道,這個錯誤是由于多個結(jié)果用“=”賦值給一個變量導(dǎo)致的。
即:set @變量=(select 多行結(jié)果 from Table)
這個時候,我就疑惑了,問題出在哪里了呢?不是觸發(fā)器在每插一條數(shù)據(jù)的時候執(zhí)行一次么?
于是,我將觸發(fā)器改了下:
復(fù)制代碼 代碼如下:
Alter TRIGGER [dbo].[Table_a_Ins]
ON [dbo].[Table_a]
AFTER INSERT
AS
BEGIN
select ID from inserted;
END
然后再執(zhí)行上面的批量插入試試看,看看他inserted表中到底存的是什么值:
果然不出所料,inserted表中的結(jié)果并不是一條數(shù)據(jù):

知道錯誤的原因,我們操作起來就簡單了,我們可以給inserted表建游標,然后通過游標來對批量插入的每行數(shù)據(jù)進行編輯。下面是我們修改后的觸發(fā)器代碼:
復(fù)制代碼 代碼如下:
Alter TRIGGER [dbo].[Table_a_Ins]
ON [dbo].[Table_a]
AFTER INSERT
AS
BEGIN
declare @ID int
declare cur_Insert cursor
for
select ID from inserted
open cur_Insert
fetch next from cur_Insert into @ID
while @@fetch_status=0
begin
UPDATE Table_a
SET UpdateIDForTrigger = (@ID+10)--為了能看出不同,就直接將比ID大10的值作為變量賦值
WHERE ID = @ID;
fetch next from cur_Insert into @ID
end
close cur_Insert
deallocate cur_Insert
END
然后,我們再按照上面的批量插入數(shù)據(jù),然后查詢下動態(tài)表中的結(jié)果:
復(fù)制代碼 代碼如下:
insert into Table_a(Content)
select Content from Table_Info;
select * from Table_a;
此時運行沒有錯誤提示了,運行結(jié)果如下:
這樣,批量插入插入數(shù)據(jù)時觸發(fā)器也能用了。
然后結(jié)合了幾位前輩的建議,再改了下觸發(fā)器的代碼。將上面的游標改成了下面的方式:
復(fù)制代碼 代碼如下:
Alter TRIGGER [dbo].[Table_a_Ins]
ON [dbo].[Table_a]
AFTER INSERT
AS
BEGIN
UPDATE Table_a
SET UpdateIDForTrigger =inserted.ID+10
FROM inserted
Where Table_a.ID=inserted.ID
END
然后再批量插入了幾行數(shù)據(jù),結(jié)果也是可以的。所以學無止境?。?!

總結(jié)下:觸發(fā)器運行是每次執(zhí)行一次Insert操作或者是Update,Delete等操作的時候才執(zhí)行的。它的對象不是針對于修改的行數(shù)(即:每行修改的時候執(zhí)行)。
相關(guān)文章
SQL Server ltrim(rtrim()) 去不掉空格的原因分析
這篇文章主要介紹了SQL Server ltrim(rtrim()) 去不掉空格的原因分析,原因主要是因為中間存在回車符或者換行符,所以要先將此符號替換掉,具體示例代碼大家參考下本文2017-08-08sql server性能調(diào)優(yōu) I/O開銷的深入解析
這篇文章主要給大家介紹了關(guān)于sql server性能調(diào)優(yōu) I/O開銷的相關(guān)資料,文中通過示例代碼以及圖片介紹的非常詳細,對大家的理解和學習具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2018-07-07揭秘SQL Server 2014有哪些新特性(3)-可更新列存儲聚集索引
可更新的列存儲索引作為SQL Server 2014的一個關(guān)鍵功能之一,在提升數(shù)據(jù)庫的查詢性能方面貢獻非常突出。據(jù)微軟統(tǒng)計,在面向OLAP查詢統(tǒng)計類系統(tǒng)中,相比其他SQL傳統(tǒng)版本的數(shù)據(jù)庫,報表查詢的性能最大可提升上十倍。2014-08-08SQL Server中T-SQL 數(shù)據(jù)類型轉(zhuǎn)換詳解
T-SQL提供了兩個顯示轉(zhuǎn)換的函數(shù):CAST函數(shù)和CONVERT函數(shù)。今天我們就來相信探討下2018-02-02