Продолжить после ошибки нарушения первичного ключа - PullRequest
1 голос
/ 28 июня 2009

Проблема при вставке данных из промежуточной таблицы во время процедуры импорта.

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

К сожалению, средство существует через другое приложение для создания записи в таблицу, которая называется CommReceipt. Ключ называется CR_Key. если это произойдет, то при выполнении автоматической подпрограммы для вставки, скажем, 1000 строк, которые нам нужно импортировать из другой системы (не из моей системы) с уже определенными значениями CR_Key, произойдет сбой.

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

Это часть плана по устранению функциональности в мошенническом приложении (но это устаревшая система, написанная на устаревшем незнакомом языке и может потребовать немного усилий)

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

ОБНОВЛЕНИЕ: первичный ключ CR_Key также является идентификатором, есть ли способ удалить строки, которых там не должно быть, и вставить строки с использованием того же идентификатора. Я предполагаю .... Я выключаю тождество, затем указываю уникальные значения в «пропущенных строках», это правдоподобно? Мне не нужно автоматически увеличивать идентификатор, процедура вставки имеет идентификаторы

Спасибо

Ответы [ 5 ]

4 голосов
/ 28 июня 2009

Вы можете использовать вместо триггера вставки . Внутри триггера выполните вставку в таблицу, где ее не существует CommReceipt.CR_Key = insert.CR_Key.

Create trigger T_CommReceiptInsteadOfInsert on CommReceipt
Instead of Insert
As
Begin

--Insert duplicate records into another table
Insert Into CommReceipt_Duplicates(CR_Key, ...)
Select CR_Key, ...
From inserted i
Where exists (select * from CommReceipt c Where c.CR_Key = i.CR_Key)

--Insert non duplicate records
Insert Into CommReceipt(CR_Key, ...)
Select CR_Key, ...
From inserted i
Where not exists (select * from CommReceipt c Where c.CR_Key = i.CR_Key)

End
1 голос
/ 28 июня 2009

Во-первых, я предполагаю, что столкновения ПК являются случайными, и что вновь вставленные строки действительно являются независимыми объектами (в отличие от чего-то, что лучше обрабатывать UPDATE. Во-вторых, я предполагаю, что вы не может удалить этот первичный ключ и обработать столкновения «ключа» с заданием, выполняющимся после пакетной вставки (или вообще использовать альтернативный первичный ключ).

У вас есть несколько вариантов, если вы используете identity в столбце первичного ключа (в этом случае ваше устаревшее приложение должно обходить идентификацию, используя IDENTITY INSERT для успешных строк):

  • Вы можете создать новую таблицу с той же схемой, что и CommReceipt, и поместить триггер INSTEAD OF в эту таблицу, удалив первичный ключ и вставив в CommReceipt. Затем настройте устаревшее приложение, чтобы вставить его в эту новую таблицу.

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

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

1 голос
/ 28 июня 2009

возможно, вы могли бы использовать триггер, чтобы убедиться, что вставка может быть выполнена (ПК не существует). Если PK уже существует, вы можете сохранить некоторую информацию в другой таблице в виде журнала и отменить вставку, сделав откат и запустив исключение.

0 голосов
/ 28 июня 2009

Мое предложение было бы изменить внешнюю подпрограмму импорта так, чтобы она пропускала сгенерированный извне ключ CR_key и просто использовала тот же автоматически сгенерированный ключ, который используют все остальные.

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

Существуют последствия для таких действий, и они могут быть отрицательными, в зависимости от требований. В общем случае не будет никакой связи между данными вашей основной таблицы и остальными данными в прежней системе. Если кто-то пытается выполнить внутреннее соединение между базами данных, его ждет шок. Мне их жаль, но не очень.

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

Удачи.

0 голосов
/ 28 июня 2009

Нарушение ограничения PK является серьезной ошибкой в ​​sqlserver, который в соответствии с BOL для sqlserver 2000 является уровнем 14, поэтому не считается фатальным, однако это немного похоже на систему проб / ошибок: уровень серьезности ошибки диктует что sqlserver будет делать с выполняемой транзакцией: если уровень серьезности достаточно высок, он завершит транзакцию на уровне сервера, и вы можете только перезапустить ее с самого начала.

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