即使记录不存在,也会发生主键冲突

时间:2015-08-10 15:49:34

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

我正在使用SQL Server 2012。

我创建了一个触发器,代码如下。

虽然在我的桌子上运行更新查询但我收到错误消息'违反PRIMARY KEY约束'我有点困惑。但是,在我查询表格的情况下,我更新的值并不存在于表格中? directory是主键列。

update myTable
set directory = 'madeup2'
where directory = 'madeup'

因此上面的查询是导致违反主键约束的原因。

但是我在下面做了选择查询,我的表中没有名为madeup2的目录 - 没有返回记录。

select * from myTable where directory = 'madeup2'

这与我的触发器有关吗?

create trigger trDefaultPath on mytable
instead of insert, update, delete
as
begin
declare @defCountIns int
declare @retVal int
declare @permission bit

select @defCountIns = count(userName) from inserted where userName = 'Default'
select @retVal = count(HostName) from UserHostName where HostName = HOST_NAME()

-- workout permissions
if @retVal = 0 and @defCountIns > 0
    set @permission = 0
else
    set @permission = 1

begin                                           
    if @permission = 1
        begin
            update mytable
            set directory = inserted.directory,
            pathNumber = inserted.pathNumber,
            userName = inserted.userName
            from inserted;
        end
    else
        begin
            update mytable
            set directory = inserted.directory,
            pathNumber = inserted.pathNumber,
            userName = inserted.userName
            from inserted
            where inserted.username <> 'Default';
            print 'Do not have permission to update directories'
        end
end         
end

更新

由于注释指出我的触发器中的更新语句缺少where子句。

我不明白的一件事是我用where子句执行了更新查询。在插入的表中虽然我只有新的目录&#39;值,所以如何创建where子句?

是否只是使用已删除表的情况 - 所以从mytable中删除该表中的记录,然后将inserted表中的记录添加到mytable中?

3 个答案:

答案 0 :(得分:1)

您的UPDATE语句将更新整个表 - 而不仅仅是那些已修改的行。 通常不是你想要的。

您需要在JOIN伪表和要更新的实际基础数据表之间添加Inserted

 if @permission = 1
 begin
     update mytable
     set directory = inserted.directory,
         pathNumber = inserted.pathNumber,
         userName = inserted.userName
     from inserted i
     inner join mytable on i.ID = mytable.ID;  -- or whatever column is your PK
    end

答案 1 :(得分:0)

在你的触发器中,你的第一个UPDATE没有WHERE子句。第二个有一个WHERE子句,它不引用正在更新的表。

这意味着它将尝试使用插入表中的相同值更新表中的每一行。

此外,您的触发器未经过编码以处理影响多行的插入/更新。

答案 2 :(得分:0)

此更新语句没有where子句。它将尝试更新表中每条记录的directory字段。只要表中包含多条记录,这将导致主键违规。

        update mytable
        set directory = inserted.directory,
        pathNumber = inserted.pathNumber,
        userName = inserted.userName
        from inserted;