Подскажите, пожалуйста, как предотвратить DROP или CREATE ONLY ограничение DEFAULT для таблицы? Триггер DDL DB EventData не сообщает мне, какой это тип ограничения (особенно для DROP). Любые указатели приветствуются.
Пример кода
Настольный скрипт
-- A base table
create table testtrigger (id int, dt datetime);
go
-- Audit event table
create table altertableaudit (id int identity, dt datetime default getdate(), eventdataddl xml);
go
База данных DDL Триггерный код
--trigger code
create TRIGGER [trg_alter_table] ON DATABASE
FOR ALTER_TABLE
AS
declare @EventData xml = EventData();
insert into altertableaudit(eventdataddl) values (@EventData);
declare @isConstraintCreate bit = -1
, @isConstraintDrop bit = -1
, @commandtext nvarchar(max) = N''
, @constraintname sysname
, @action sysname
, @Replicate bit = 1
;
select @isConstraintCreate
=case
when @eventdata.exist('/EVENT_INSTANCE/AlterTableActionList/Create/Constraints') = 1 then 1
else 0
end
,@isConstraintDrop
=case
when @eventdata.exist('/EVENT_INSTANCE/AlterTableActionList/Drop/Constraints') = 1 then 1
else 0
end
;
if @isConstraintCreate = 1
begin
select @commandtext = @eventdata.value('(/EVENT_INSTANCE/TSQLCommand/CommandText)[1]', 'nvarchar(max)');
if charindex('default',lower(@commandtext)) > 0
begin
rollback transaction;
set @action = 'create constraint';
set @Replicate = 0;
end;
end;
if @isConstraintDrop = 1
begin
select @constraintname = @eventdata.value('(/EVENT_INSTANCE/AlterTableActionList/Drop/Constraints/Name)[1]', 'nvarchar(max)');
select @constraintname;
if exists(select * from sys.default_constraints sdf with (nolock) where lower(sdf.name) = lower(@constraintname))
begin
rollback transaction;
set @action = 'drop';
set @Replicate = 0;
end;
end;
if @replicate = 0
begin
select [@isConstraintCreate] = @isConstraintCreate , [@isConstraintDrop] = @isConstraintDrop
, [@commandtext] = @commandtext , [@constraintname] = @constraintname , [@action] =@action;
--insert into altertableaudit(eventdataddl) values (@EventData);
select [@replicate] = 'this schema change cannot be replicated';
end
else
begin
select [@isConstraintCreate] = @isConstraintCreate , [@isConstraintDrop] = @isConstraintDrop
, [@commandtext] = @commandtext , [@constraintname] = @constraintname , [@action] =@action;
select [@replicate] = 'this schema change can be replicated';
end;
GO
Тестовый код
-- Add a column to see if the trigger fires
alter table testtrigger add col1 varchar(10) null;
go
-- select from audit
select * from altertableaudit
-- Alter the table to add a new constraint
ALTER TABLE [dbo].testtrigger ADD CONSTRAINT [df_col1] DEFAULT @@servername for col1
GO
-- select from audit
select * from altertableaudit
-- Drop the above constraint
ALTER TABLE [dbo].testtrigger drop CONSTRAINT [df_col1]
GO
-- select from audit
select * from altertableaudit
Что касается CREATE, я легко могу обнаружить, что это ОГРАНИЧЕНИЕ ПО УМОЛЧАНИЮ, выполнив поиск по шаблону commandtext
. Но для DROP я не могу проверить, является ли это ограничение по умолчанию, прежде чем разрешить продолжить операцию ALTER.
Сведения об окружении
Microsoft SQL Server 2017 (RTM-GDR) (KB4505224) - 14.0.2027.2 (X64)
Jun 15 2019 00:26:19
Copyright (C) 2017 Microsoft Corporation
Developer Edition (64-bit) on Windows 10 Enterprise 10.0 <X64> (Build 17134: )