Запрет CREATE или DROP DEFAULT CONSTRAINT с использованием DDL Trigger - SQL Server 2017 - PullRequest
1 голос
/ 24 апреля 2020

Подскажите, пожалуйста, как предотвратить 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: )
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...