我要如何在SQL觸發器更新的記錄的價值 - 是這樣的:SQL觸發器 - 如何獲取更新的值?
CREATE TRIGGER TR_UpdateNew
ON Users
AFTER UPDATE
AS
BEGIN
SET NOCOUNT ON;
EXEC UpdateProfile (SELECT UserId FROM updated AS U);
END
GO
顯然,這是不行的,但你可以看到什麼,我想要知道的。
我要如何在SQL觸發器更新的記錄的價值 - 是這樣的:SQL觸發器 - 如何獲取更新的值?
CREATE TRIGGER TR_UpdateNew
ON Users
AFTER UPDATE
AS
BEGIN
SET NOCOUNT ON;
EXEC UpdateProfile (SELECT UserId FROM updated AS U);
END
GO
顯然,這是不行的,但你可以看到什麼,我想要知道的。
提供你一定只有一個值永遠不會被更新,你可以做到這一點...
CREATE TRIGGER TR_UpdateNew
ON Users
AFTER UPDATE
AS
BEGIN
SET NOCOUNT ON;
DECLARE @user_id INT
SELECT
@user_id = inserted.UserID
FROM
inserted
INNER JOIN
deleted
ON inserted.PrimaryKey = deleted.PrimaryKey
-- It's an update if the record is in BOTH inserted AND deleted
EXEC UpdateProfile @user_id;
END
GO
如果有多個值可以一次更新,只是其中之一將得到處理這段代碼。 (儘管它不會出錯。)
您可以使用遊標,或者如果它是SQL Server 2008+,則可以使用表變量。
或者更常見的,只是將StoredProcedure代碼移入觸發器。
根據我的知識,您需要創建一個CURSOR來遍歷所有更新的值以執行UpdateProfile過程。請記住,這會減慢更新過程。
Declare @UserID int --Assuming
Declare UpdateProfile_Cursor Cursor for Select UserID From inserted;
Open Cursor UpdateProfile_Cursor;
Fetch Next from UpdateProfile_Cursor Into @UserID;
While @@FETCH_STATUS == 0
Begin
Exec UpdateProfile @UserID
Fetch Next from UpdateProfile_Cursor Into @UserID;
End
CLOSE UpdateProfile_Cursor
DEALLOCATE UpdateProfile_Cursor
我的語法可能有點偏離,但這會給你想要的效果。再次考慮修改你的邏輯來處理多個更新,因爲使用遊標是資源密集型的。
你可以這樣做例子,我記錄更改爲交易歷史記錄表:
create table dbo.action
(
id int not null primary key ,
description varchar(32) not null unique ,
)
go
insert dbo.action values(1 , 'insert')
insert dbo.action values(2 , 'update')
insert dbo.action values(3 , 'delete')
go
create table dbo.foo
(
id int not null identity(1,1) primary key ,
value varchar(200) not null unique ,
)
go
create table dbo.foo_history
(
id int not null ,
seq int not null identity(1,1) ,
action_date datetime not null default(current_timestamp) ,
action_id int not null foreign key references dbo.action (id),
old_value varchar(200) null ,
new_value varchar(200) null ,
primary key nonclustered (id , seq) ,
)
go
create trigger foo_update_01 on dbo.foo for insert, update , delete
as
set nocount on
set xact_abort on
set ansi_nulls on
set concat_null_yields_null on
--
-- record change history
--
insert dbo.foo_history
(
id ,
action_id ,
old_value ,
new_value
)
select id = coalesce(i.id , d.id) ,
action_id = case
when i.id is not null and d.id is null then 1 -- insert
when i.id is not null and d.id is not null then 2 -- update
when i.id is null and d.id is not null then 3 -- delete
end ,
old_value = d.value ,
new_value = i.value
from inserted i
full join deleted d on d.id = i.id
go
但是你可以使用相同的排序技術,它有點混合起來,並通過整個集合的值存儲到存儲過程中,就像我在下面的示例中所做的(使用上面的表格模式)。
首先,創建一個存儲過程需要一個特殊的臨時表在運行時存在,因此:
--
-- temp table must exist or the stored procedure won't compile
--
create table #foo_changes
(
id int not null primary key clustered ,
action_id int not null ,
old_value varchar(200) null ,
new_value varchar(200) null ,
)
go
--
-- create the stored procedure
--
create procedure dbo.foo_changed
as
--
-- do something useful involving the contents of #foo_changes here
--
select * from #foo_changes
return 0
go
--
-- drop the temp table
--
drop table #foo_changes
go
一旦你做到了這一點,創建一個觸發器,它會創建並填充由預計的臨時表存儲過程,然後執行存儲過程:
create trigger foo_trigger_01 on dbo.foo for insert, update , delete
as
set nocount on
set xact_abort on
set ansi_nulls on
set concat_null_yields_null on
--
-- create the temp table. This temp table will be in scope for any stored
-- procedure executed by this trigger. It will be automagickally dropped
-- when trigger execution is complete.
--
-- Any changes made to this table by a stored procedure — inserts,
-- deletes or updates are, of course, visible to the trigger upon return
-- from the stored procedure.
--
create table #foo_changes
(
id int not null primary key clustered ,
action_id int not null ,
old_value varchar(200) null ,
new_value varchar(200) null ,
)
--
-- populate the temp table
--
insert #foo_changes
(
id ,
action_id ,
old_value ,
new_value
)
select id = coalesce(i.id , d.id) ,
action_id = case
when i.id is not null and d.id is null then 1 -- insert
when i.id is not null and d.id is not null then 2 -- update
when i.id is null and d.id is not null then 3 -- delete
end ,
old_value = d.value ,
new_value = i.value
from inserted i
full join deleted d on d.id = i.id
--
-- execute the stored procedure. The temp table created above is in scope
-- for the stored procedure, so it's able to access the set of changes from
-- the trigger.
--
exec dbo.foo_changed
go
這是對所有有它。它很簡單,很容易,適用於任何尺寸的變化套件。而且,它是安全的,沒有競爭條件或與系統中的其他用戶發生衝突。