我現在有解決方案,讓我們用一個完整的例子來做一個這樣的學校案例。 :)
在這個例子中,我們的應用程序是一個地址簿。我們希望每次添加,更新或刪除該業務的聯繫人時更新業務活動(業務中的IsActive列) 。如果業務的至少一個聯繫人 處於活動狀態,則認爲該業務處於活動狀態。我們在表格中記錄企業的每個狀態變化,以獲得完整的歷史記錄。
所以,我們有3個表:
表業務(標識符(PK身份),姓名,IsActive), 表聯繫(標識符(PK身份),姓名,IsActive,IdentifierBusiness) 表BusinessHistory(標識符(PK身份),IsActive,日期,IdentifierBusiness)
這裏的是一個觸發我們感興趣的是:
表聯繫(觸發IoInsert):
-- inserting the new rows
INSERT INTO Contact
(
Name
,IsActive
,IdentifierBusiness
)
SELECT
t0.Name
,t0.IsActive
,t0.IdentifierBusiness
FROM
inserted AS t0
-- Updating the business
UPDATE
Business
SET
IsActive = CASE WHEN
(
(t0.IsActive = 1 AND Business.IsActive = 1)
OR
(t0.IsActive = 1 AND Business.IsActive = 0)
) THEN 1 ELSE 0
FROM
inserted AS t0
WHERE
Business.Identifier = t0.IdentifierBusiness
AND
t0.IsActive = 1
AND
Business.IsActive = 0
-- Forcing rowCount for EntityFramework
DECLARE @Identifier BIGINT;
SET @Identifier = scope_identity()
SELECT @Identifier AS Identifier
種
表業(觸發IoUpdate)
UPDATE
Business
SET
IsActive = 1
FROM
Contact AS t0
WHERE
Business.Identifier = t0.IdentifierBusiness
AND
t0.IsActive = 1
AND
Business.IsActive = 0
---- Updating BusinessHistory
INSERT INTO BusinessHistory
(
Date
,IsActive
,IdentifierBusiness
)
SELECT
DATE()
,t0.IsActive
,t0.Identifier
FROM
inserted AS t0
INNER JOIN
deleted AS t1 ON t0.Identifier = t1.Identifier
WHERE
(t0.Identifier <> t1.Identifier)
-- Forcing rowCount for EntityFramework
CREATE TABLE #TempTable (temp INT PRIMARY KEY);
INSERT INTO #TempTable VALUES (1);
DROP TABLE #TempTable
表BusinessHistory:
-- Updating the business
UPDATE
Business
SET
IsActive = CASE WHEN
(
(t0.IsActive = 1 AND Business.IsActive = 1)
OR
(t0.IsActive = 1 AND Business.IsActive = 0)
) THEN 1 ELSE 0
FROM
inserted AS t0
WHERE
Business.Identifier = t0.IdentifierBusiness
AND
t0.IsActive = 1
AND
Business.IsActive = 0
-- inserting the new rows
INSERT INTO BusinessHistory
(
Date
,IsActive
,IdentifierBusiness
)
SELECT
DATE()
,t0.IsActive
,t0.Identifier
FROM
inserted AS t0
-- Forcing rowCount for EntityFramework
DECLARE @Identifier BIGINT;
SET @Identifier = scope_identity()
SELECT @Identifier AS Identifier
因此,概括地說,發生了什麼?
我們有2個表,商業和聯繫。聯繫人正在更新表插入和更新業務。
業務更新時,它插入到BusinessHistory中,當存儲更新的字段IsActive時,該表存儲表Business的更新歷史記錄 。
的事情是,即使我不插入BusinessHistory新行,我啓動插入指示等等,我去的,而不是插入的觸發器的表BusinessHistory內。當然,在這個結尾,有一個scope_identity()。您只能使用scope_identity一次,並且它會返回插入的最後一個標識。 因此,由於我沒有插入任何BusinessHistory,它正在消耗我新插入的聯繫人的scope_identity:聯繫人表的插入的 的scope_identity爲空!
如何隔離問題?
如何解決呢?
這裏有幾種選擇。我所做的是由假設條件表業務圍繞BusinessHistory的插入: 我想只插入插入如果statut「IsActive」發生了變化:
IF EXISTS
(
SELECT
1
FROM
inserted AS t0
INNER JOIN
deleted AS t1 ON t0.Identifier = t1.Identifier
WHERE
(t0.Identifier <> t1.Identifier)
)
BEGIN
INSERT INTO BusinessHistory
(
Date
,IsActive
,IdentifierBusiness
)
SELECT
DATE()
,t0.IsActive
,t0.Identifier
FROM
inserted AS t0
INNER JOIN
deleted AS t1 ON t0.Identifier = t1.Identifier
WHERE
(t0.Identifier <> t1.Identifier)
END
的另一種可能性是,在觸發而不是表BusinessHistory的插入,由IF包圍整個觸發EXISTS條件
IF EXISTS (SELECT 1 FROM inserted)
BEGIN
----Trigger's code here !
END
如何避免呢?
- 那麼,使用這些修復程序之一!
- 在大多數情況下,避免scope_identity(),@@ IDENTITY已經足夠了!在我的公司,我們只使用EF_4的scope_identity!
我知道我的英語並不完美,如果它不夠好,我可以編輯,或者如果有人想在這個主題上添加一些東西!
哪個'scope_identity()'被插入觸發器返回?從看到這個孤立的代碼片段中看不清楚。那一刻插入的記錄是什麼? –
你給了我你的問題的解決方案。在我而不是表B的更新觸發器中,我通過插入另一個表來記錄表的狀態歷史記錄。 我的錯誤是插入沒有被IF EXISTS包圍,第三張表上的插入在錯誤的時刻消耗了我的scope_identity()。 謝謝,你的幫助:) –
嘿嘿,總是很棘手,這些觸發器。也許你可以把它變成答案,這樣人們會更容易找到解決方案。 –