0

Windows サーバー上に一部のユーザーのデータベース レコードがあります。列の 1 つはユーザーの SID (そのユーザーの一意の文字列) です。

ユーザー宛てのメッセージを受け取ったら、最初に SID 列の SID 値を使用してレコードのクエリを実行したいと考えています。レコードが返されない場合は、その SID 値でレコードを作成します。ただし、クエリと追加の間に、別のスレッドが同じユーザー/SID を持つメッセージを取得できます。したがって、2回追加することになります。

  1. トランザクションが完了するまで他のレコードをテーブルに追加できないトランザクションを作成する方法はありますか?

  2. または、テーブル全体をロックするより良い方法はありますか?クエリ/追加がどれほど速くても、それはチョーク ポイントです。(これが最善の方法である場合、トランザクションなしでクエリを実行し、存在する場合は返し、まれに存在しない場合にのみトランザクションを実行し、再度クエリを実行して追加します。)

  3. 列が一意であることを SQL Server に伝える方法はありますか? SQL Server Management Studio で無効になっている設定のプロパティは、varchar.

ありがとう - デイブ

4

1 に答える 1

0

列に一意のインデックスを作成して、列の値の一意性を強制することができます。次のコードを使用して、データベースの仕様に合わせて調整できます。Warring Transaction Isolation Level を SERIALIZABLE に設定しているため、クエリが遅くなる可能性があります。このトランザクション分離レベルが SERIALIZABLE に設定されている場合、他のユーザーがテーブルにデータを変更または追加することを許可しないため、複数のユーザーがデータを追加しようとします...

CREATE Procedure usp_InsertSID
@SID varchar(225)

AS
BEGIN
  SET NOCOUNT ON;
    BEGIN TRY

           IF @SID IS NULL
             RAISERROR('Validation Failed: SID is cannot be null', 16,1)

           IF EXISTS (SELECT SID from tableName
                        WHERE SID= @SID)
              RAISERROR('Validation Failed: SID already Exists',16,1)
        SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
        BEGIN TRANSACTION

          INSERT INTO tableName(ColumnNames)
          VALUES (@SID)

          COMMIT TRANSACTION
        SELECT @ReturnMessage = 'Sucess! New SID is added.'
    END TRY

    BEGIN CATCH 
       IF (@@TRANCOUNT > 0)
         ROLLBACK TRAN

       SELECT  @ReturnMessage = ERROR_MESSAGE()

          SELECT @ReturnCode AS ReturnCode, @ReturnMessage AS ReturnMessage,
                 ERROR_LINE()   AS ErrorLine,
                 ERROR_SEVERITY() AS ErrorSeverity,
                 ERROR_STATE() AS ErrorState
    END CATCH
END

GO
于 2013-10-13T23:14:27.077 に答える