2009-01-30 30 views
15

這個問題是非常相似的SQL Server 2005: T-SQL to temporarily disable a triggerMSSQL:禁用觸發一個INSERT

不過我不想禁用所有觸發器和甚至不是一個批處理命令的,但只是一個單一的INSERT。

我不得不面對一個商店系統,原始作者將一些應用邏輯放入觸發器(壞主意!)。只要您不嘗試以與原始「管理前端」不同的方式插入數據,該應用程序邏輯就可以正常工作。我的工作是編寫一個「從分期系統導入」工具,所以我準備好了所有數據。當我嘗試插入它時,觸發器會用生成的代碼覆蓋現有的產品代碼(不是IDENTITY數字ID!)。爲了生成代碼,它使用插入到另一個表的自動生成的ID,這樣我甚至不能使用@@ IDENTITY來查找我剛插入的列,並使用實際的產品代碼更新插入的行。

任何我可以去避免極端笨拙的代碼的方式(在產品名稱中插入一些隨機字符,然後嘗試用隨機字符來查找行來更新它)。

因此:是否有一種方法來禁用觸發器(即使只是一個)只有一個 INSERT?

+1

Kristof的文章有幾個解決方案,看起來像他們可能實際上解決您的問題 - 只是想讓你知道,如果你打開改變你接受的答案。 – SqlRyan 2010-01-06 17:46:08

回答

12

可以使用禁用表上的觸發器:

ALTER TABLE MyTable DISABLE TRIGGER ALL 

但是,這將做到這一點對所有會話,不只是你的當前連接..這顯然是一個非常糟糕的事情:-)

最好的辦法是改變觸發器本身的狀態,以便決定它是否需要運行,無論是在桌面上使用「插入類型」標誌還是其他方式,如果你已經存儲了某種類型的類型。

+3

「這顯然是一件非常糟糕的事情「 - >這就是爲什麼我不想這樣做;) – BlaM 2009-01-30 14:40:04

+1

好..不要這樣做;) – 2009-01-30 14:42:06

+2

很高興我們都同意這一點;) – andynormancx 2009-01-30 14:45:55

1

您可以檢查SUSER_SNAME(),並且只能在管理前端的上下文中運行嗎?

+0

只有一個用戶用於訪問數據庫。所以很不幸:No. – BlaM 2009-01-30 14:30:10

5

而不是禁用觸發器,你不能改變觸發器的行爲。在名爲「insertedFromImport」的表格中添加一個新的可空列。

在觸發器中更改代碼,以便觸發器的違規位僅在「insertedFromImport」爲null的行上運行。插入記錄時,將「insertedFromImport」設置爲非空值。

+0

我真的很喜歡這個,因爲它非常整齊。但是我稍微修改了一下,以檢查這個列是否已更新,這是否觸發了其他表更新 `IF NOT(UPDATE(insertedFromImport)AND EXISTS(SELECT insertedFromImport FROM INSERTED WHERE insertedFromImport IS NOT NULL))BEGIN` – 2011-08-10 10:06:11

15

您可能會有所幫助:

Disabling a Trigger for a Specific SQL Statement or Session

但有可能面臨以及其他問題。 如果我瞭解您的情況正確,系統默認會自動插入產品代碼(通過生成值)。 現在您需要插入由某個分段系統創建的產品,並且該產品的產品代碼由分段系統創建,並且您希望手動將其插入到實時系統。

如果您確實需要這樣做,您需要確保將來生成的應用程序生成的代碼不會與手動插入的代碼發生衝突 - 我認爲它們必須是唯一的。

其他方法是允許系統生成新代碼並在需要時覆蓋任何相應的數據。

0

如果使用BULK INSERT插入,則可以僅爲插入禁用觸發器。

我敢肯定,批量插入將需要文件系統上的數據文件導入,所以你不能只使用T-SQL。

要使用BULK INSERT,您需要INSERT和ADMINISTRATOR BULK OPERATION權限。 如果您禁用觸發器或約束,則還需要ALTER TABLE權限。

如果您使用Windows身份驗證,您的Windows用戶將需要從文件讀取訪問權限。如果使用混合模式身份驗證,SQl服務器服務帳戶需要從文件讀取訪問權限。

使用BULK IMPORT導入時,默認情況下禁用觸發器。

的更多信息:http://msdn.microsoft.com/en-us/library/ms188365.aspx

1

我看到就會產生問題,很多東西。首先更改觸發器以考慮多個記錄導入。這可能可以解決您的問題。不要關閉觸發器,因爲它不僅適用於所有人而且關閉。如果您必須先將數據庫置於單用戶用戶模式,然後才能在下班時間完成任務。

接下來,在任何情況下都不要使用@@ identity來獲取剛插入的值!改用scope_identity。如果表上有觸發器,@@ identity將返回錯誤的值,這些觸發器也會插入到具有標識字段的其他表中。如果您現在通過您的系統使用@@身份(因爲我們知道您的系統具有觸發器),您絕對優先的首要任務就是立即在您的代碼中查找並更改@@身份的所有實例。如果不這樣做,您可能會遇到嚴重的數據完整性問題。這是一個「停止所有工作,直到這個問題得到解決」的問題。

至於剛剛插入的信息,請考慮創建一個batchid作爲插入的一部分,然後向該表中添加一個名爲batchid的列(它可以爲空,以免影響其他插入)。然後,您可以通過批量標識回調您插入的內容。

4

禁用觸發器,插入,提交。

SET IDENTITY_INSERT Test ON 
GO 

BEGIN TRAN 

DISABLE TRIGGER trg_Test ON Test 

INSERT INTO Test (MyId, MyField) 
    VALUES (999, 'foo') 

ENABLE TRIGGER trg_Test ON Test 

COMMIT TRAN 

SET IDENTITY_INSERT Test OFF 
GO