2011-07-01 65 views
1

有人可以提供關於如何爲數據庫中的所有表格插入通用而不是觸發器的源代碼。我想要運行存儲過程,而不是爲db中的所有表創建插入觸發器。而不是在所有表格上插入觸發器

+1

仍然不明白觸發點。除了將值插入基表中之外,他們還會做什麼? –

回答

1

不明白爲什麼你想要在每張表上不用觸發器,除了將提供的值插入基表中之外,你還打算在結果代碼中做什麼(就像發生了什麼,如果有的話)沒有,而不是觸發器),這是我想出的。你會注意到,如果觸發器已經存在,它會丟棄這個觸發器,所以你可以在同一個數據庫中多次運行,而不會出現「already exists」錯誤。它忽略IDENTITY,ROWGUIDCOL,計算列和TIMESTAMP/ROWVERSION列。最後,我將展示如何快速檢查,而不是執行(已註釋掉)輸出腳本(最多8K),並將其轉換爲XML,以便查看更多(最多64K)。不保證你可以在SSMS中返回整個事情,具體取決於有多少表/列。如果你想檢查它並/或者手動運行它,你可能需要創建一個表來存儲這個值 - 然後你可以通過一個應用程序或者你有什麼。現在如果你想讓它自動執行,你可以遵循Yuck的觀點 - 將它保存爲一個存儲過程並創建一個響應某些DDL事件(CREATE TABLE等)的DDL觸發器。

SET NOCOUNT ON; 

DECLARE 
    @cr VARCHAR(2) = CHAR(13) + CHAR(10), 
    @t VARCHAR(1) = CHAR(9), 
    @s NVARCHAR(MAX) = N''; 

;WITH t AS 
(
    SELECT [object_id], 
    s = OBJECT_SCHEMA_NAME([object_id]), 
    n = OBJECT_NAME([object_id]) 
    FROM sys.tables WHERE is_ms_shipped = 0  
) 
SELECT @s += 'IF OBJECT_ID(''dbo.ioTrigger_' + t.s + '_' + t.n + ''') IS NOT NULL 
    DROP TRIGGER [dbo].[ioTrigger_' + t.s + '_' + t.n + ']; 
G' + 'O 
CREATE TRIGGER ioTrigger_' + t.s + '_' + t.n + ' 
    ON ' + QUOTENAME(t.s) + '.' + QUOTENAME(t.n) + ' 
    INSTEAD OF INSERT 
AS 
BEGIN 
    SET NOCOUNT ON; 

    -- surely you must want to put some other code here? 

    INSERT ' + QUOTENAME(t.s) + '.' + QUOTENAME(t.n) + ' 
    (
' + 
(
    SELECT @t + @t + name + ',' + @cr 
     FROM sys.columns AS c 
     WHERE c.[object_id] = t.[object_id] 
     AND is_identity = 0 
     AND is_rowguidcol = 0 
     AND is_computed = 0 
    AND system_type_id <> 189 
    FOR XML PATH(''), TYPE 
).value('.[1]', 'NVARCHAR(MAX)') + '--' 
+ @cr + @t + ')' 
+ @cr + @t + 'SELECT 
' + 
(
    SELECT @t + @t + name + ',' + @cr 
     FROM sys.columns AS c 
     WHERE c.[object_id] = t.[object_id] 
     AND is_identity = 0 
     AND is_rowguidcol = 0 
     AND is_computed = 0 
    AND system_type_id <> 189 
    FOR XML PATH(''), TYPE 
).value('.[1]', 'NVARCHAR(MAX)') + '--' 
+ @cr + @t + 'FROM 
     inserted; 
END' + @cr + 'G' + 'O' + @cr 
FROM t 
ORDER BY t.s, t.n; 

SELECT @s = REPLACE(@s, ',' + @cr + '--' + @cr, @cr); 

-- you can inspect at least part of the script by running the 
-- following in text mode: 

SELECT @s; 

-- if you want to see more of the whole thing (but not necessarily 
-- the whole thing), run this in grid mode and click on result: 

SELECT CONVERT(XML, @s); 

需要注意幾個問題:

1)我不稀疏列,XML集合,文件流等處理,所以如果你有特殊的表格,你可能會遇到的一些這些功能的併發症。

2)觸發器的名稱沒有真正的「保護」 - 您可以有一個名爲foo的模式,另一個名爲foo_bar的模式,然後foo中的表名爲bar_none,而foo_bar中的表名稱爲none。這會導致重複的觸發器名稱,因爲我使用下劃線作爲分隔符。我對CDC抱怨,但they closed the bug as won't fix。如果您碰巧使用具有下劃線的模式,請注意一點。

+0

這讓我開始了我想要的方向。謝謝。 – Lrn

0

您只能在SQL Server 2008+中爲DDL語句創建數據庫觸發器。

如果您需要DML觸發器上數據庫中的每個表INSTEAD OF INSERT),你將不得不必須要麼自己管理他們或嘗試創建一個數據庫級別的DDL觸發器,負責然後創建或更新任何CREATEALTER表語句中的INSTEAD OF INSERT觸發器。會變得毛茸茸的,幾乎肯定會需要使用動態SQL。

出於好奇,你是否想要建立某種審計機制?

+0

如果審計是目標,那麼我懷疑SQL Server Audit,或者至少是CDC或Change Tracking,會是一個不那麼幹擾和有問題的方法。然而,其中一些是版本特定的。 –

+0

@Aaron:在獲得批准之前,不要過於偏離主題,但我個人更喜歡將解決方案放入SQL數據庫。我修改了一個腳本,類似於http://weblogs.asp.net/jgalloway/archive/2008/01/27/adding-simple-trigger-based-auditing-to-your-sql-server-database.aspx很多我自己的項目。當然,你所說的沒什麼錯。 – Yuck

相關問題