Ошибка уникального индекса на INSERT с проверкой SELECT и NOT EXISTS - PullRequest
1 голос
/ 07 декабря 2011

Я получаю следующую ошибку, если я запускаю хранимую процедуру

Невозможно вставить строку с повторяющимся ключом в объект "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

Теперь очевидно, что один TAC в tabData (первые 8 символов SSN_Number) не имеет отдельной модели, но может быть связан с несколькими моделями. Это вызывает ошибку, потому что в tabTac TAC должен быть уникальным.

Заранее спасибо

1 Ответ

3 голосов
/ 07 декабря 2011

Проверьте, не продублирован ли SSN_Number в таблице TabData или если при объединении с 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 в одну и ту же дату, вышеприведенное не справится с этим, потому что не знает, какразличать, что использовать.Надеюсь, это направит вас в правильном направлении.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...