Пакет DTS завершается из-за повторяющейся ключевой строки

У нас есть старый пакет DTS, который наш сервер SQL 2000 использует для передачи записей о сотрудниках на машины в нашем производственном цеху.

Недавно мы обновили одну из машин, и теперь на ней работает SQL 2008 Express.

Мы перенастроили пакет DTS, чтобы отправить записи сотрудников на этот новый сервер, но теперь мы получаем это сообщение об ошибке:

FETCH_EMPLOYEES:

Заявление было прекращено. Не удается вставить повторяющуюся ключевую строку в объект «dbo.Users» с уникальным индексом «IX_tblUsers_OpID».

скриншот

Если я удаленно подключаюсь к нашему серверу SQL 2000, я могу щелкнуть правой кнопкой мыши, чтобы последовательно выполнить каждый шаг пакета DTS без ошибок.

скриншот

Итак, я вхожу в экземпляр SQL 2008 Express этой машины, чтобы посмотреть, смогу ли я что-нибудь выяснить.

Теперь я смотрю на хранимую процедуру FETCH_EMPLOYEES:

PROCEDURE [dbo].[FETCH_EMPLOYEES] AS
DECLARE @OpID varchar(255)
DECLARE @Password varchar(50)
DECLARE Employee_Cursor CURSOR FOR
SELECT OpID, Password
FROM dbo.vw_Employees
OPEN Employee_Cursor
FETCH NEXT FROM Employee_Cursor
INTO @OpID,@Password
WHILE @@FETCH_STATUS = 0
BEGIN
insert into dbo.Users (OpID,Password,GroupID) 
VALUES (@OpID,@Password,'GROUP01')
FETCH NEXT FROM Employee_Cursor
INTO @OpID,@Password
END
CLOSE Employee_Cursor
DEALLOCATE Employee_Cursor

Я не особо разбираюсь в курсорах, но могу сказать, что данные извлекаются из представления vw_Employees и вставляются в таблицу dbo.Users.

Вид vw_Employees прост:

SELECT DISTINCT FirstName + ' ' + LastName AS OpID, Num AS Password
FROM         dbo.EmployeeInfo
WHERE     (Num IS NOT NULL) AND (FirstName IS NOT NULL)
      AND (LastName IS NOT NULL) AND (Train IS NULL OR Train <> 'EX')

Итак, теперь кажется, что проблема должна быть в таблице dbo.Users.

скриншот

Я не заметил, чтобы это привлекло какое-то особое внимание, поэтому я написал сценарий этой таблицы, используя CREATE TO Query Editor, и получил эту информацию, которую я действительно не понимаю:

CREATE TABLE [dbo].[Users](
[ID] [int] IDENTITY(1,1) NOT NULL,
[OpID] [nvarchar](255) NOT NULL,
[Password] [nvarchar](50) NOT NULL,
[GroupID] [nvarchar](10) NOT NULL,
[IsLocked] [bit] NOT NULL,
    CONSTRAINT [PK_tblUsers] PRIMARY KEY CLUSTERED 
(
[ID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

ALTER TABLE [dbo].[Users]  WITH CHECK ADD  CONSTRAINT [FK_tblUsers_tblGroups] FOREIGN KEY([GroupID])
REFERENCES [dbo].[Groups] ([GroupID])
GO

ALTER TABLE [dbo].[Users] CHECK CONSTRAINT [FK_tblUsers_tblGroups]
GO

ALTER TABLE [dbo].[Users] ADD  CONSTRAINT [DF_tblUsers_IsLocked]  DEFAULT ((0)) FOR [IsLocked]
GO

Хорошо, я чувствую, что проблема где-то в этом определении таблицы, но я действительно не понимаю, что она делает (после создания базовой таблицы).

В нем есть раздел CONSTRAINT с множеством переменных, которые я не понимаю, затем он изменяет эти таблицы, добавляя FOREIGN KEY и CONSTRAINTS.

Мой вопрос: может ли кто-нибудь помочь мне понять, о чем мне говорит ошибка (кроме нарушения двойного ключа).

Какой столбец может вызывать дублирование ключа?

Включил ли я достаточно данных и скриншотов?

ОБНОВЛЕНИЕ:

Основываясь на комментариях, похоже, что этот скриншот необходим.

В таблице Пользователи есть список индексов, и один из них под названием IX_tblUsers_OpID говорит, что он уникальный и некластеризованный.

Я думаю, что мы устранили повторяющиеся значения Op_ID в нашей таблице исходных данных EmployeeInfo, найдя их все с помощью этого скрипта:

select num as 'Op_ID', count(num) as 'Occurrences'
from employeeInfo
group by num
having 1<count(num);

Это должно было избавиться от всех моих дубликатов. Правильно?

Мы покупаем производственные машины, которые поставляются с ПК для хранения локальных данных. Они предоставляют этот сценарий, который я разместил, поэтому я не могу комментировать, почему они выбрали именно то, что сделали. Мы просто запускаем задание, которое загружает данные на наш сервер.

скриншот


person jp2code    schedule 07.10.2013    source источник
comment
Браво за попытку предоставить подробности. На первом снимке экрана ошибка указывает на то, что вставка конфликтует с уникальным индексом IX_tblUsers_OPID. В приведенном выше сценарии я не вижу этого индекса. Есть ли шанс, что вы написали сценарий из неправильного места?   -  person billinkc    schedule 08.10.2013
comment
Просто из-за имени уникального индекса (IX_tblUsers_OpID) он кажется в столбце OpID (хотя мне это кажется неправильным). В любом случае, можете ли вы опубликовать это определение индекса? С другой стороны, ваш sp, похоже, не проверяет наличие строк в этой таблице, он просто вставляет их все (я также не вижу причин использовать там курсор)   -  person Lamak    schedule 08.10.2013
comment
Теперь есть обновление вопроса с новым скриншотом Indexes, в том числе под названием IX_btlUsers_OpID. Компания-производитель поставляет свои машины с уже установленными базами данных и скриптами. Мы просто пытаемся подключить наши старые пакеты DTS к этим новым машинам.   -  person jp2code    schedule 08.10.2013
comment
Но, согласно вашему sp, значения для opID поступают из представления, и они состоят из этого: FirstName + ' ' + LastName, а не из этого столбца num   -  person Lamak    schedule 08.10.2013
comment
Повторюсь, я его не создавал. Итак, он жалуется на неуникальность FirstName + ' ' + LastName?   -  person jp2code    schedule 08.10.2013
comment
Кажется, да. Но, как я уже говорил в комментарии ранее, я не вижу, где вы проверяете наличие строк в своей таблице до INSERT (или вы всегда сначала удаляете эту таблицу?). Возможно, вы пытаетесь вставить уже существующую строку.   -  person Lamak    schedule 08.10.2013
comment
Я тоже не вижу, где есть какие-либо проверки на наличие строки перед INSERT, но тогда я не разбираюсь в пакетах DTS. Я рассмотрю возможность разрешения повторяющихся записей FirstName + ' ' + LastName из нашей исходной базы данных.   -  person jp2code    schedule 08.10.2013


Ответы (2)


Наличие столбцов с уникальными значениями всегда имело большое значение для любого набора данных. Это ограничение можно добавить к любому столбцу или индексу.

Ошибка, которую вы получаете, очень четкая и очень конкретная. Буквально дает ответ.

Заявление было прекращено. Не удается вставить повторяющуюся ключевую строку в объект «dbo.Users» с уникальным индексом «IX_tblUsers_OpID».

Он говорит: "НЕТ дубликатов... УНИКАЛЬНЫЙ индекс...", а затем сообщает имя ограничения "IX_tblUsers_OpID".

Имея это в виду, вы пытаетесь вставить в этот столбец значения, которые вы создаете на лету, объединяя две строки; имя плюс фамилия.

Каковы шансы, что двое из них будут «Джоном Смитом»? Высоко, очень высоко!

Возможные решения:

  • Вы можете снять ограничение и разрешить дубликаты.
  • Измените запрос, чтобы значения, которые пытаются вставить, были действительно уникальными.
  • Используйте ссылку 'WITH (IGNORE_DUP_KEY = ON)': index_option (Transact-SQL)
person Ricardo C    schedule 26.08.2015
comment
Это хороший ответ. Я понимаю что ты имеешь в виду. Производитель, изготовивший машины на нашем заводе, сопоставил имя сотрудника нашей базы данных со своим полем OpID, а номер нашего сотрудника со своим полем пароля. Эти данные восходят к 2004 году или около того. Замена каждой машины потребует отправки их обратно производителю для перенастройки. Это старые вакуумные камеры стоимостью 10 миллионов долларов для змеевиков кондиционеров. Вероятно, этого никогда не произойдет. :) - person jp2code; 26.08.2015
comment
Я предлагаю вам следовать варианту 2, изменив представление [vw_Employees]. Добавьте идентификатор сотрудника к имени: Имя + ' ' + Фамилия + CAST(число AS VARCHAR(10)) AS OpID. или просто используйте num в качестве OpID в том же представлении. - person Ricardo C; 26.08.2015
comment
Подождите... вы должны иметь возможность изменить это представление самостоятельно, не отправляя его производителю... нет? - person Ricardo C; 26.08.2015
comment
Вы знаете эти пункты, в которых говорится, что вы не можете вмешиваться в программное обеспечение другой компании? У них 10 машин одной фирмы. В любой из них вмешиваются, и они отказываются от какой-либо работы над ними. Однако это старый вопрос. Я сделал это так, чтобы мое программное обеспечение предотвращало дублирование имен Джона Смита (John Smith1 и т. д.). - person jp2code; 27.08.2015
comment
Ах ха! Я понимаю. В любом случае, я рад, что вы нашли решение. знак равно - person Ricardo C; 27.08.2015

Другой парень на работе нашел эту скрытую функцию, которая решает насущную проблему, но может вызвать другие неизвестные проблемы.

В представлении конструктора таблиц Users мы можем щелкнуть правой кнопкой мыши столбец OpID, выбрать Индексы/ключи..., найти этот созданный ключ IX_tblUsers_OpID и изменить его значение Уникально. :

скриншот

Похоже, это сделало так, что пакет DTS будет работать, и это то, что у нас происходит прямо сейчас.

Я вернулся к исходной таблице EmployeeInfo на нашем сервере SQL 2000, чтобы проверить наличие повторяющихся значений OpID с помощью этого скрипта:

select FirstName + ' ' + LastName as 'OpID',
       Count(FirstName + ' ' + LastName) as 'Occurrences'
from EmployeeInfo
group by FirstName + ' ' + LastName
having 1 < count(FirstName + ' ' + LastName)

...но никаких записей не было возвращено.

Я не знаю, почему не работал пакет DTS или почему нам пришлось отключить функцию Unique.

Если кто-то когда-нибудь в будущем придумает лучшее решение для этого, пожалуйста, напишите!

person jp2code    schedule 08.10.2013