Вставка данных в таблицу SQL с первичным ключом.Для обманщиков - разрешить ошибку вставки или выбрать первым?

StackOverflow https://stackoverflow.com/questions/411575

  •  03-07-2019
  •  | 
  •  

Вопрос

Дана таблица, такая как:

CREATE TABLE dbo.MyTestData (testdata varchar(50) NOT NULL) 

ALTER TABLE dbo.MyTestData WITH NOCHECK ADD CONSTRAINT [PK_MyTestData] PRIMARY KEY  CLUSTERED (testdata) 

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

CREATE PROCEDURE dbo.dmsInsertTestData @ptestdata VarChar(50)
AS
  SET NOCOUNT ON

  IF NOT EXISTS(SELECT testdata FROM dbo.MyTestData WHERE testdata=@ptestdata)
  BEGIN
    INSERT INTO dbo.MyTestData (testdata ) VALUES (@ptestdata)
  END

RETURN 0

или просто фиксировать / игнорировать ошибки нарушения PK при выполнении этого?

CREATE PROCEDURE dbo.dmsInsertTestData @ptestdata VarChar(50)
AS
  SET NOCOUNT ON
  INSERT INTO dbo.MyTestData (testdata ) VALUES (@ptestdata)
RETURN 0
Это было полезно?

Решение

Я всегда делаю это в одном заявлении:

INSERT INTO dbo.MyTestData (testdata ) VALUES (@ptestdata)
WHERE NOT EXISTS(SELECT 1 FROM dbo.MyTestData WHERE testdata=@ptestdata)

Другие советы

Ваша проверка на наличие ошибок (т.е."IF NOT EXISTS ...") может работать, а может и не работать, потому что существует потенциальное условие гонки (если другая транзакция вставляет запись после вашего оператора IF NOT EXISTS, но перед вашим оператором INSERT).

Поэтому, независимо от того, проверяли вы это раньше или нет, вы должны закодировать свой оператор INSERT так, как если бы он мог завершиться ошибкой.

Хотите ли вы проверить также (нет, вместо этого) зависит от вас и вашего пользовательского интерфейса.

Я думаю, что большинство программистов предложили бы избежать этого исключения.Я не уверен с точки зрения производительности в T-SQL, но, например, в .NET я считаю, что генерируемое исключение обходится дороже, чем дополнительный оператор if / else.

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

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

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

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

Чтобы быть удобным для пользователя, часто рекомендуется выполнить ВЫБОР и, если запись уже существует, предложить пользователю возможность просмотреть и / или отредактировать ее.

Например, если пользователь добавляет новую запись о Клиенте, он может захотеть просмотреть информацию, которая уже была отображена для этого Клиента.У них может быть дополнительная информация для добавления в запись, например номер телефона.

В таком случае отказ от добавления записи менее полезен, чем предоставление возможности просмотреть существующий дубликат.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top