主キーを使用して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) 

また、既知の重複がある外部データのリストからアイテムを追加する際に「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
役に立ちましたか?

解決

常に1つのステートメントで実行します:

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ステートメントが失敗する可能性があるかのようにコーディングする必要があります。

[同様に]を確認するかどうか(代わりにではなく)は、ユーザーとUIに任されています。

ほとんどのプログラマーは例外を回避することを提案すると思います。 T-SQLのパフォーマンスの観点からはわかりませんが、たとえば.NETでは、スローされた例外は追加のif / elseステートメントよりもコストが高いと考えています。

最初の例で懸念しているのは、ユーザーにエラーを返さないことです。修正することもできますが、エラーが返されない限り使用しません。

2つの可能性の間の懸念が大きなテーブルでのパフォーマンスである場合、両方をテストし、一方が他方よりも著しく速いかどうかを確認することをお勧めします。 if selectが特に複雑で、ほとんどの場合に挿入を行う必要がある場合、ほとんどの場合、単純に失敗させる方が高速になる可能性があります。一方、不正な入力の可能性が高く、ここに示すようにifが比較的複雑でない場合は、他のプロセスの方が優れている可能性があります。ただし、実際のデータ構造とデータ、および実際のクエリでの実際のテストのみが、状況によって異なる可能性があるため、どちらがパフォーマンスに優れているかを判断できます。

ストアドプロシージャの性質に依存すると思います。基本的に、エラーと関係がある場合(またはプロシージャのクライアントのためにカプセル化する場合)にエラーを処理し、それらに関係がなく、他のユーザーにとって使いやすいものにできない場合は、エラーを伝播したままにする必要がありますアプリケーションのレイヤー。

ストアドプロシージャが生データを挿入するように設計されている場合、考えられるエラーを処理するためにアプリケーションを残す必要があると思います。ストアドプロシージャが抽象化の層として設計され(特定の statement を実行するのではなく、特定の task を実行する)、エラーを処理してそれを処理できる場合または、適切な方法(たとえば、明確に定義されたエラーコード)でアプリケーションに報告できる場合は、そうする必要があります。それ以外の場合は、データベースではなく重複データが挿入されないように、アプリケーション次第である必要があります(データベースはこれを主キーで既に実施しています)。

ユーザーフレンドリにするために、SELECTを実行することをお勧めします。レコードが既に存在する場合は、ユーザーにそれを表示および/または編集する機会を提供します。

たとえば、ユーザーが新しい顧客レコードを追加している場合、その顧客について既に表示されている情報を確認したい場合があります。電話番号など、レコードに追加する追加情報がある場合があります。

この種のシナリオでは、レコードの追加を拒否することは、既存の複製を表示する機能を提供することよりも役立ちません。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top