質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
SQL Server

SQL Serverはマイクロソフトのリレーショナルデータベース管理システムです。データマイニングや多次元解析など、ビジネスインテリジェンスのための機能が備わっています。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

ASP.NET

ASP.NETは動的なWebサイトやWebアプリケーション、そしてWebサービスを構築出来るようにする為、Microsoftによって開発されたウェブアプリケーション開発フレームワークです。

Q&A

解決済

1回答

20449閲覧

レコード重複エラーの原因が分からず困っています

ladybird

総合スコア163

SQL Server

SQL Serverはマイクロソフトのリレーショナルデータベース管理システムです。データマイニングや多次元解析など、ビジネスインテリジェンスのための機能が備わっています。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

ASP.NET

ASP.NETは動的なWebサイトやWebアプリケーション、そしてWebサービスを構築出来るようにする為、Microsoftによって開発されたウェブアプリケーション開発フレームワークです。

0グッド

0クリップ

投稿2017/05/30 02:49

編集2017/05/30 03:04

ログインユーザがサイト記事を保存(お気に入り)する機能を作っているのですが、
ASPモジュールからストアドを実行する箇所で
ごくまれに下記のエラーが発生します。(発生条件は不明)

SQLErrorCD:2627 %1! 違反、制約 '%2!': オブジェクト '%4!' には重複したキーは挿入できません。

下記のようにレコード存在チェックを行っているので
重複は発生し得ないように見えるのですが、
何か原因として考えられることはありますでしょうか?

###該当のソースコード
ストアド

SQL

1CREATE PROCEDURE[DB].[記事保存ストアド] 2 @WebConfig nvarchar(max) 3 ,@InsUserId nvarchar(max) = '' 4 ,@InsEntryId nvarchar(max) = '' 5 ,@SQLERR_CODE int = null OUTPUT 6AS 7 8BEGIN 9 10 SET XACT_ABORT ON 11 SET NOCOUNT ON 12 13 DECLARE @CNT1 as int 14 DECLARE @RetVal as int 15 SET @RetVal = 0 16 17 --現在日時の取得 18 DECLARE @CurrentTime as datetime 19 SET @CurrentTime = cedar98.F_GetDate(DEFAULT) 20 21 --記事タイトル一時変数を定義する 22 DECLARE @EntryTitle as nvarchar(max) 23 SET @EntryTitle = '' 24 25 BEGIN TRAN 26 27 --存在チェック 28 SELECT 29 @CNT1 = COUNT(1) 30 FROM 31 保存記事 32 WHERE 33 USER_ID = @InsUserId 34 AND ENTRY_ID = @InsEntryId 35 36 --記事IDに対応する記事タイトルを取得(省略) 37 38 BEGIN TRY 39 --ユーザIDと記事IDの一致する保存記事レコードが存在しない場合 40 IF @CNT1 = 0 41 BEGIN 42 INSERT INTO 保存記事( 43 USER_ID 44 ,ENTRY_ID 45 ,ENTRY_TITLE 46 ,INSDATE 47 ) 48 VALUES( 49 @InsUserId 50 ,@InsEntryId 51 ,@EntryTitle 52 ,@CurrentTime 53 ) 54 END 55 ELSE 56 --ユーザIDと記事IDの一致する保存記事レコードが存在した場合 57 BEGIN 58 UPDATE 59 保存記事 60 SET 61 ENTRY_TITLE = @EntryTitle 62 ,INSDATE = @CurrentTime 63 WHERE 64 USER_ID = @InsUserId 65 AND ENTRY_ID = @InsEntryId 66 END 67 68 COMMIT TRAN 69 END TRY 70 71 BEGIN CATCH 72 SET @SQLERR_CODE = ERROR_NUMBER() 73 SET @RetVal = 99 74 ROLLBACK TRAN 75 END CATCH 76 77 Return @RetVal 78END

対象のテーブル

SQL

1CREATE TABLE [DB].[保存記事]( 2 [USER_ID] [nvarchar](16) NOT NULL, 3 [ENTRY_ID] [nvarchar](32) NOT NULL, 4 [ENTRY_TITLE] [nvarchar](255) NULL, 5 [INSDATE] [datetime] NULL, 6 CONSTRAINT [PK_SAVED_KIJI] PRIMARY KEY CLUSTERED 7( 8 [USER_ID] ASC, 9 [ENTRY_ID] ASC 10)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 11) ON [PRIMARY]

※都合により省略や伏字処理をしています。

よろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

ファントムリードの結果です。
トランザクションは「取り消し可能な一連の操作」であってアプリコードのロック取得とは違います。
だから存在チェックを行った後に別セッションからのinsertが成功してそれに引っかかってしまうという現象が起こります。

やりたいことはupsert操作のようですから、mergeコマンド一発で実行するのがこの場合おすすめです。

投稿2017/05/30 03:40

yuba

総合スコア5568

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ladybird

2017/08/21 09:00 編集

あああなるほど・・・! 言われてみればそりゃそうでした。なぜ気づかなかったのか・・・ mergeコマンドの紹介までありがとうございます。 使ったことなかったのですが、便利そうですね。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問