Вместо триггера для вставки на все таблицы - PullRequest
1 голос
/ 01 июля 2011

Может кто-нибудь предоставить источник о том, как написать универсальный вместо триггера для вставки для всех таблиц в базе данных.Я хотел бы запустить хранимую процедуру, которая будет создавать вместо триггеров вставки для всех таблиц в БД.

Ответы [ 2 ]

1 голос
/ 01 июля 2011

Без точного понимания, почему вы хотите использовать триггер вместо каждой отдельной таблицы, и что еще вы планируете делать в результирующем коде, кроме вставки предоставленных значений в базовую таблицу (точно так же, как если бы не былоа не триггер вообще) вот что я придумала.Вы заметите, что он сбрасывает триггер, если он уже существует, поэтому вы можете запускать его несколько раз в одной и той же базе данных без ошибок «уже существует».Он игнорирует IDENTITY, ROWGUIDCOL, вычисляемые столбцы и столбцы TIMESTAMP / ROWVERSION.Наконец, в конце я показываю, как можно быстро проверить вместо выполнения (что закомментировано) выходной сценарий (до 8 КБ) и преобразовать его в XML, если вы хотите увидеть больше (до 64 КБ).Нет гарантий, что вы можете вернуть все это в SSMS в зависимости от того, сколько таблиц / столбцов существует.Если вы хотите проверить его и / или запустить вручную, вы можете создать таблицу, в которой будет храниться значение, - тогда вы можете извлечь его с помощью приложения или чего-то еще.Теперь, если вы хотите, чтобы это выполнялось автоматически, вы можете следовать указаниям Юка - сохраните это как хранимую процедуру и создайте триггер DDL, который отвечает на определенные события DDL (CREATE TABLE и т. Д.).

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, но они закрыли ошибку, так как не исправят .Просто нужно помнить, если вы используете схемы с подчеркиванием.

0 голосов
/ 01 июля 2011

Вы можете создавать триггеры базы данных только для операторов DDL в SQL Server 2008 +.

Если вам нужны триггеры DML (INSTEAD OF INSERT) для каждой таблицы в базе данных, вам придется либо управлять ими самостоятельно, либо пытаться создать триггер DDL уровня базы данных, который отвечает за создание или обновление триггеров INSTEAD OF INSERT для любых операторов таблицы CREATE или ALTER. Может стать волосатым и почти наверняка потребует использования динамического SQL.

Из любопытства вы пытаетесь создать какой-то механизм одитинга?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...