使用SELECT和NOT EXISTS检查INSERT上的唯一索引错误

时间:2011-12-07 10:30:24

标签: sql sql-server-2005 stored-procedures insert indexing

如果我正在运行存储过程

,我会收到以下错误
  

无法在具有唯一索引的对象'dbo.tabTac'中插入重复的键行   “IX_tabTac”。

唯一索引IX_tabTac

CREATE UNIQUE NONCLUSTERED INDEX [IX_tabTac] ON [dbo].[tabTAC] 
(
    [TAC] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON, FILLFACTOR = 90) ON [PRIMARY]

tabTac

CREATE TABLE [dbo].[tabTAC](
    [idTAC] [int] IDENTITY(1,1) NOT NULL,
    [TAC] [char](8) NOT NULL,
    [fiModel] [int] NOT NULL,
 CONSTRAINT [PK_tabTac] PRIMARY KEY CLUSTERED 
(
    [idTAC] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON, FILLFACTOR = 90) ON [PRIMARY]
) ON [PRIMARY]

GO
SET ANSI_PADDING OFF
GO
ALTER TABLE [dbo].[tabTAC]  WITH NOCHECK ADD  CONSTRAINT [FK_tabTac_modModel] FOREIGN KEY([fiModel])
REFERENCES [dbo].[modModel] ([idModel])
GO
ALTER TABLE [dbo].[tabTAC] CHECK CONSTRAINT [FK_tabTac_modModel]

存储过程InsertTacsFromClaims

CREATE PROC [dbo].[InsertTacsFromClaims]
with execute as Owner
AS
BEGIN
    INSERT INTO tabTac
        select substring(t.SSN_Number,1,8)as TAC
        ,m.idModel as fiModel
        from tabData t 
        inner join modmodel m 
            ON t.fimodel=m.idmodel 
        WHERE  t.fiproducttype=1
        and m.idModel>1
        and not exists(
            select fiModel from tabTac WHERE TAC=substring(t.SSN_Number,1,8)
        )
        GROUP BY substring(t.SSN_Number,1,8),m.idModel
END 

RETURN @@ROWCOUNT;

我原以为我用以下方法阻止了这个错误:

and not exists(
            select fiModel from tabTac WHERE TAC=substring(t.SSN_Number,1,8)
          )

修改

@Sparkys第二个查询(已添加ModelName)返回以下内容:

TAC         fiModel    ModelName
01233300    777        U5A
01238300    771        W20I
01238300    784        W20
35427603    720        C903
35773704    781        E15I
35905104    451        W595
35946804    793        W150I
35959004    813        ST18I

现在很明显tabData中的一个TAC(SSN_Number的前8个字符)没有独特的模型,但可以链接到多个模型。这会导致错误,因为在tabTac中TAC必须是唯一的。

提前致谢

1 个答案:

答案 0 :(得分:3)

检查TabData表中SSN_Number是否重复,或者modModel的连接是否产生重复。

select substring(t.SSN_Number,8),count(*)
from tabData
groub by substring(t.SSN_Number,8)
having count(*) > 1

  select substring(t.SSN_Number,1,8)as TAC
        ,m.idModel as fiModel
        from tabData t 
        inner join modmodel m 
            ON t.fimodel=m.idmodel 
        WHERE  t.fiproducttype=1
        and m.idModel>1
        GROUP BY substring(t.SSN_Number,1,8),m.idModel
        HAVING count(*) > 1

如果任一查询返回重复的SSN_numbers,您将收到错误。您的代码仅检查您是否未在表中添加SSN号(如果它已存在于您要填充的表中),但不会考虑数据中潜在的欺骗行为

有几种方法只能获取最新的fiModel代码,这里有一个例子:

select SSN_Number,fiModel 
FROM tabData td1
JOIN
(  -- This will get the latest date from tabData
select SSN_Number,max(received_date) as TheLastestDate
FROM tabData td
LEFT JOIN tabTac tc on tc.TAC = substring(TD.SSN_number,1,8) 
                       and tc.fiModel = td.fModel
WHERE tc.fiModel is NULL
GROUP BY SSN_Number) xx ON xx.SSN_number=td1.ssn_number 
                           and td1.received_date = xx.TheLatestDate

请注意,如果您在同一日期有多个fiModel,则上述将无法处理它,因为它不知道如何区分使用哪个。希望这能指出你正确的方向。