Sql 触发器以防止插入两列的重复数据

Sql 触发器以防止插入两列的重复数据,sql,sql-server,sql-server-2008,Sql,Sql Server,Sql Server 2008,我正在使用SQLServer2008R2,我有下表 ID Name date 1 XYZ 2010 2 ABC 2011 3 VBL 2010 现在,我想防止插入,如果我有一个数据,虽然ID不同,但数据存在 ID Name date 4 ABC 2011 请指导我如何编写此触发器 类似这样: CREATE TRIGGER MyTrigger ON dbo.MyTable AFTER

我正在使用SQLServer2008R2,我有下表

ID     Name     date
 1     XYZ      2010
 2     ABC      2011
 3     VBL      2010
现在,我想防止插入,如果我有一个数据,虽然ID不同,但数据存在

 ID    Name     date
  4    ABC      2011
请指导我如何编写此触发器

类似这样:

CREATE TRIGGER MyTrigger ON dbo.MyTable
AFTER INSERT
AS

if exists ( select * from table t 
    inner join inserted i on i.name=t.name and i.date=t.date and i.id <> t.id)
begin
    rollback
    RAISERROR ('Duplicate Data', 16, 1);
end
go

然后您就可以开始工作了。

如果您使用存储过程将数据插入到表中,那么实际上不需要触发器。首先检查组合是否存在,然后不插入

CREATE PROCEDURE usp_InsertData
@Name varchar(50),
@Date DateTime
AS
BEGIN

IF (SELECT COUNT(*) FROM tblData WHERE Name = @Name AND Date=@Date) = 0
    BEGIN
        INSERT INTO tblData
                    ( Name, Date)
             VALUES (@Name, @Date)
        Print 'Data now added.'
     END
ELSE
    BEGIN
        Print 'Dah! already exists';
    END
END
如果未通过存储过程插入数据,则可以使用以下触发器

CREATE TRIGGER checkDuplicate ON tblData
AFTER INSERT
AS

IF EXISTS ( SELECT * FROM tblData A 
INNER JOIN inserted B ON B.name=A.name and A.Date=B.Date)
BEGIN
    RAISERROR ('Dah! already exists', 16, 1);
END
GO  
试试这个

 CREATE TRIGGER trg ON TableName
 AFTER INSERT 
 AS
  Begin
  Declare @id int,@name varchar(10),@date DateTime
  Declare @cnt1 int,@cnt2 int,@cnt3 int

  INSERT INTO TableName(ID, Name, Date) VALUES(4,'ABC',2011)
  select @id=ID,@name=Name,@date=Date from inserted

  select @cnt2=Count(*) from TableName where Name=@name
  select @cnt3=Count(*) from TableName where Date=@date

  if(@cnt2>1 or @cnt3>1)
    Rollback
  else 
    Commit

  end

你真的不需要触发器。只需为多个列设置一个唯一约束

ALTER TABLE [dbo].[TableName]    
ADD CONSTRAINT [UQ_ID_Name_Date] UNIQUE NONCLUSTERED
(
    [ID], [Name], [Date]
)
还有一个选择,使用insert代替触发器

这是一个关于如何以及何时使用它们的好例子

这个答案的灵感来源于4月13日20日18:34的那一次

在dbo.MyTable上创建触发器MyTrigger 而不是插入 像 如果不存在 从MyT表中选择* 内连接插入i 在i.name=t.name和i.date=t.date和i.id t.id上 开始 插入MyTable名称、日期选择名称、插入日期 终止 其他的 抛出51000,'语句终止,因为找到了对象的重复项',1; 去
你真的需要扳机吗?您是否尝试过唯一索引或约束?以及当我的主键为ID时如何应用??在XXTable name ASC、[date]ASCalow上创建唯一的非聚集索引XXTable\u Unq您可以使用此sql插入:insert into tbname,date选择“ABC”,2048 from dual where not exists select from tb where name='ABC'虽然这会引起错误,但无法停止插入,但我的问题仍然存在哦,是的,这是因为我错过了回滚行-所以像刚才一样将该行添加进来。但是看看James的答案,也许你想要的是一个唯一的约束。例如,如果你需要使用触发器方法,因为你想要一条自定义的错误消息,你还需要检查你是否无意中加入了插入的同一条记录。我一直在寻找一个重复项,直到我在on子句中添加了等价的I.id t.id。唯一约束的问题可能是它的最大长度为900BIn。在我的情况下,唯一密钥会破坏大量正在运行的作业和存储过程中的平衡。我只是希望所有这些都能正常进行,但要避免插入而不会引发错误。这方面有很多使用案例。触发器可能会引发错误,但数据仍在插入表中,如何停止插入数据?约束不应该仅限于名称和日期列?这充满了错误,不会起作用。你的insert语句有硬编码的值,而且它不允许数据具有重复的名称、日期甚至id。要求是不允许重复,即使是不同的id,对吗?
ALTER TABLE [dbo].[TableName]    
ADD CONSTRAINT [UQ_ID_Name_Date] UNIQUE NONCLUSTERED
(
    [ID], [Name], [Date]
)
CREATE TRIGGER MyTrigger ON dbo.MyTable
INSTEAD OF INSERT
AS

if not exists (
    select *
    from MyTable t 
    inner join inserted i
       on i.name=t.name
       and i.date=t.date and i.id <> t.id )
begin
    Insert into MyTable (Name, Date) Select Name, Date from inserted
end
go