而不是触发器并保持列中的唯一值

时间:2015-08-11 07:52:19

标签: sql sql-server triggers sql-server-2012

我有一个表(如下所示),而不是触发器(代码如下所示)

MyTable的:

 ID    directory    manager
 ---------------------------
 1     C:\Blah\     Bob
 2     C:\Blob\     Dave

ID是主键。

我的触发器处理insert,update&删除。删除不是问题。我希望在我的表中插入或更新记录时确保该目录是唯一的。做这个的最好方式是什么? ID必须作为主键保存。

我的触发器代码(剥离),

create trigger trMyTable on MyTable
instead of insert, update, delete
as
begin
    declare @permission bit

    if exists(select * from inserted)
    begin
        if exists(select * from deleted)
        begin                               -- its an update query
            update MyTable
            set directory = inserted.directory,
                manager = inserted.manager
            from inserted 
            inner join MyTable on inserted.ID = MyTable.ID;
        end             
        else
            insert into MyTable(directory, manager) 
                select 
                    directory, manager 
                from inserted;
    end
end

1 个答案:

答案 0 :(得分:0)

到目前为止,最好和最简单的方法是DavidG建议的唯一约束:

ALTER TABLE MyTable ADD CONSTRAINT ux_MyTable_Directory UNIQUE (directory)

要完成触发器,您可以执行以下操作以确保满足您的业务需求,但除非有其他原因需要触发器(审计或其他),否则请务必考虑UNIQUE约束。即使您使用触发器进行安全性或审计,我仍然会使用UNIQUE约束,因此您可以将触发器更改为AFTER而不是INSTEAD OF,这样您就可以执行这些功能,而不是处理所有数据操作。

create trigger trMyTable on MyTable
instead of insert, update, delete
as
begin
    declare @permission bit

    -- Verify no duplicate
    if exists(
        select *
        from inserted
        where exists (
            select *
            from MyTable
            where directory = inserted.directory
                and id <> inserted.id
        ))
    begin
        raiserror('Duplicate directory', 15, 99)
    end
    else
    begin

        -- Perform data changes
        if exists(select * from inserted)
        begin
            if exists(select * from deleted)
            begin                               -- its an update query
                update MyTable
                set directory = inserted.directory,
                    manager = inserted.manager
                from inserted 
                inner join MyTable on inserted.ID = MyTable.ID;
            end             
            else
                insert into MyTable(directory, manager) 
                    select 
                        directory, manager 
                    from inserted;
        end
        else
        begin
            delete MyTable where id in (select id from deleted)
        end
    end
end