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

Учитывая таблицу, такую ​​как:

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

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

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

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

Ответы [ 6 ]

3 голосов
/ 04 января 2009

Проверка на наличие ошибок (т. Е. «ЕСЛИ НЕ СУЩЕСТВУЕТ ...») может сработать, а может и не сработать, поскольку существует потенциальное состояние гонки (если другая транзакция вставляет запись после вашего оператора IF NOT EXISTS, но перед вашим оператором INSERT).

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

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

2 голосов
/ 04 января 2009

Я всегда делаю это одним утверждением:

INSERT INTO dbo.MyTestData (testdata ) VALUES (@ptestdata)
WHERE NOT EXISTS(SELECT 1 FROM dbo.MyTestData WHERE testdata=@ptestdata)
0 голосов
/ 04 января 2009

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

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

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

0 голосов
/ 04 января 2009

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

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

0 голосов
/ 04 января 2009

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

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

0 голосов
/ 04 января 2009

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

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