2017-01-29 2 views
0

У меня есть триггер, который использует CHECKSUM для сравнения определенных столбцов между вставленными и удаленными. Иногда мне нужно обновить, какие столбцы проверены, поэтому я создал другую процедуру, которая считывает текст триггера, изменяет логику CHECKSUM и выдает новую команду триггера UPDATE или DROP/CREATE, чтобы внести изменения.SQL Server: обнаружение ALTER vs CREATE в тексте триггера

Вот моя проблема: я не знаю, стоит ли выдавать команду DROP TRIGGER первым, потому что я не могу обнаружить sysComments.text представляет ли собой ALTER TRIGGER или CREATE TRIGGER синтаксис.

Я мог бы использовать что-то вроде PATINDEX('%CREATE%PROC%', @triggerText), но это было бы ненадежно, поскольку оно могло бы подбирать комментарии и другие неприменимые тексты.

Любые идеи?

+0

Не могли бы вы создать партию с первым 'if (object_id ('triggername) равно null) create trigger ...' с фиктивным содержимым, а затем всегда использовать alter trigger? –

+0

Привет @James - триггер всегда будет существовать до того, как я попытаюсь его изменить, я просто не знаю, есть ли текст, который я возвращаю из sys.sql_modules, имеет ALTER или CREATE. Так как я планирую повторить этот точный текст (только с моими изменениями, в которые он был интерполирован), мне нужно было бы сбросить триггер, если это синтаксис CREATE, а не ALTER. – sisdog

ответ

0

Я действительно не перестроил бы текст триггера, используя строковые манипуляции; или вообще на самом деле. Я бы просто изменил триггер один раз, чтобы выполнить все, что вам нужно для кода контрольной суммы. Вы можете сохранить отдельную таблицу столбцов или даже буквальную строку столбцов в другом месте. Затем просто объедините этот список в контрольную сумму, когда вам это нужно. Что-то вроде этого:

if object_id('tempdb.dbo.#ChecksumColumns') is not null drop table #ChecksumColumns 
create table #ChecksumColumns 
(
    ColumnName nvarchar(128) primary key clustered 
) 

insert into #ChecksumColumns 
values ('Col1', 'Col2', 'Col3') 

declare 
    @sql nvarchar(max), 
    @columns nvarchar(max) 

select 
    @columns = stuff((select ',' + ColumnName 
         from #ChecksumColumns 
         for xml path('')), 1, 1, ''), 
    @Sql = 'select checksum(' + @columns + ') 

Кроме того, только FYI, syscomments устарела в пользу sys.sql_modules. не большая сделка, но стоит сделать переключатель.

+0

Эй @ Xedni - это таблица с высоким трафиком (чтение/запись), поэтому производительность имеет решающее значение. Я не хочу иметь динамический sql в триггере, я бы хотел, чтобы он на 100% был предварительно скомпилирован. Даже если я отложил CHECKSUM, чтобы сказать, еще одна функция, я бы не хотел, чтобы эта функция использовала любой динамический SQL. – sisdog

+0

@sisdog Повторное создание триггера не будет лучше, на самом деле его, вероятно, будет хуже. Если вы соедините sql и используете 'sp_executesql', он будет кэшировать план там (это только' exec ('') ', который не кэширует план выполнения). Если вы изменяете или не дай бог отбрасывать и воссоздавать триггер, это вызовет блокировку схемы на триггере, и перекомпилируйте ее. – Xedni

Смежные вопросы