sql >> データベース >  >> RDS >> Access

MicrosoftSQLシーケンスとの数値の競合を回避する

    MicrosoftSQLシーケンスとの数値の競合を回避する

    注:このトピックについては、Access withSQLServerグループでオンラインで紹介します。 9月13日午後6時30分(米国中部標準時)に参加してください。グループに参加して、会議の詳細がすべて記載されたメールを受け取ります。無料です。

    • フィールド内の番号が1回だけ使用され、他のユーザーによって複製されないことを保証する必要がありますか?
    • テーブルに複数の自動番号が必要な状況がありましたか?
    • 連番の下限と上限が必要で、それを超えることができなかったことがありますか?
    • 最後の番号を超えた後にリサイクルしたい番号のリストがある場合がありますか?

    SQL Serverには、これを非常に簡単に処理できる機能があり、シーケンスと呼ばれます。 SQLServer2012以降で利用可能です。

    自動番号のように、リサイクルしない限り、毎回一意の番号が付けられることを保証できます。

    最近、クライアントのシーケンスを実装するように依頼されました。複数のユーザーが新しいレコードを作成し、特定のシーケンスで次の番号を「フェッチ」する必要があります。顧客が上限しきい値を超えないように特定の範囲に制限されていたため、自動番号を使用できませんでした。数がなくなると、管理者はシーケンスを新たに補充します。

    Accessテーブルの使用が機能しない理由

    SQL Serverにアップグレードする前に、ユーザーは次に使用する番号を把握するテーブルを共有していました。このアプローチの問題は、それが絶対確実ではないことです。2人のユーザーがまったく同時に同じ番号を要求する可能性があります。ビジネスルールに違反しています。

    SQLServerシーケンスの作成と使用

    シーケンスを使用する前に、SQL Serverで次の構文を使用して作成する必要があります。これは、1回だけ実行する必要があります。
    CREATE SEQUENCE dbo.seqPolicyNumber AS int MIN 50005000 MAX 50005999;
    次のステートメントを使用して、次のシーケンス番号を取得します。
    SELECT NEXT VALUE FOR dbo.seqPolicyNumber as NextValue
    ユーザーはシーケンスを使用するために更新権限が必要になりますが、シーケンスの範囲を変更できないようにする必要があります。更新権限は、次の構文を使用して指定できます。
    GRANT UPDATE ON dbo.seqPolicyNumber TO [MyDatabaseUserOrRole];
    Microsoft Access VBAプログラムからシーケンスの次の値を取得するには、次のステートメントを使用して次の値をADODBレコードセットに読み込むことができます。
    strSQL = "SELECT NEXT VALUE FOR dbo.seqPolicyNumber as NextValue"
    OpenMyRecordset rs, strSQL
    NextValue = rs("NextValue")

    これは、私たちが通常、会社でADODBレコードセットを開く方法です。 OpenMyRecordsetの使用方法の詳細については、ブログの別の記事をクリックしてください:

    アクセスにおける簡単なADODBレコードセットとコマンド

    次のシーケンス番号を取得するための構文の良いところは、T-SQLで非常に簡単に使用できることです。通常はフィールド名、パラメータ、または定数から値を取得する<シーケンス名>の代わりに次の値を使用します。次に、Insertステートメントでの使用方法を示します。
    INSERT dbo.Orders (OrderID, Name, Qty)
    VALUES (NEXT VALUE FOR dbo.OrderNumberSequence, 'Tire', 2);

    自動番号よりも柔軟性が高い

    シーケンスは、Accessの自動番号やSQLServerのIDENTITYフィールドよりも柔軟性があります。まず、テーブルに含めることができる自動番号またはIDフィールドは1つだけです。 IDENTITYフィールドを再シードすることはできますが、値をリサイクルすることはできません。 IDENTITYフィールドは、レコードを識別するために任意の番号が必要で、意味がない場合でも、主キーに役立ちます。ただし、シーケンス範囲には意味が埋め込まれている場合があります。

    IDENTITYのような整数の使用に制限されていませんが、シーケンス番号は10進数または数値にすることもできます。また、上だけでなく下に向かってインクリメントすることもできます。

    また、シーケンスは特定のテーブルに関連付けられておらず、特定のテーブルに新しいシーケンス番号が必要なため、テーブル間で使用できます。

    シーケンスを補充する

    新しい範囲のポリシー番号が必要な場合など、シーケンスの範囲を変更する場合は、ストアドプロシージャを使用して行う必要があります。これを実行できるストアドプロシージャは次のとおりです。
    SET ANSI_NULLS ON
    GO
    SET QUOTED_IDENTIFIER ON
    GO

    CREATE PROCEDURE [dbo]。[usp_AlterPolicySequence](
    @SeqName AS sysname、
    @InpMin AS int、
    @InpMax AS int
    )WITH EXECUTE AS OWNER AS
    BEGIN
    SET NOCOUNT ON;

    DECLARE @sql nvarchar(MAX)、
    @err nvarchar(MAX);

    存在しない場合(
    SELECT NULL
    FROM sys.sequences AS s
    WHERE s.name =@SeqName
    AND s.schema_id =SCHEMA_ID('dbo')

    THROW 50000、'シーケンス名が無効です。'、1;

    @InpMinがNULLまたは@InpMaxがNULLの場合
    THROW50000、「値をnullにすることはできません。」、1;

    SET @sql =CONCAT(N'ALTER SEQUENCE[dbo]。'、QUOTENAME(@SeqName)、N' RESTART WITH'、@ InpMin、N' INCREMENT BY 1'、N' MINVALUE'、@InpMin、N' MAXVALUE ' 、@ InpMax、N'NO CYCLE NO CACHE;');
    EXEC sys.sp_executesql @sql;

    ;

    終了

    このストアドプロシージャには、注目に値することがいくつかあります。まず、実行しています
    EXECUTE ASOWNERAS。

    日常のユーザーがシーケンスを変更できるようにしたくありません。ただし、ストアドプロシージャを介してのみ変更する機能を制限したいと考えています。 (ユーザーはストアドプロシージャへの権限のみが必要です。)
    GRANT EXECUTE ON dbo.usp_AlterPolicySequence TO [MyDatabaseUserOrRole];
    このストアドプロシージャは、シーケンス内の新しい範囲をインストールする必要があるときはいつでも、Accessフロントエンドから実行できます。これは通常、通常のユーザーよりも多くのSQLServer特権を持つ管理者ユーザーが実行します。

    ただし、このストアドプロシージャは、現在のシーケンスが使い果たされた直後に、新しい範囲の数値がシーケンスにロードされるのを待機しているときにも実行できます。この場合、ストアドプロシージャは、新しい範囲の最初のポリシー番号を必要とするすべてのユーザーが呼び出すことができます。そのため、WITH EXECUTE AS OWNER ASを使用して、この限定的な使用のためだけに、より多くの権利を付与します。

    もう1つの注意点は、SQL文字列を作成してから、
    EXEC sys.sp_executesql
    を使用する必要があることです。

    パラメータを使用している場合は、その文字列に。

    次のステートメントは、SSMSクエリウィンドウに入力するか、ストアドプロシージャで使用する場合に機能します。

    ALTER SEQUENCE dbo.seqPolicyNumber
    RESTART WITH 50005000
    INCREMENT BY 1
    MINVALUE 50005000
    MAXVALUE 50005999
    NO CYCLE
    NO CACHE

    ただし、以下はストアドプロシージャのパラメータを使用して機能しません。
    ALTER SEQUENCE dbo.seqPolicyNumber
    RESTART WITH @InpMin
    INCREMENT BY 1
    MINVALUE @InpMin
    MAXVALUE @InpMax
    NO CYCLE
    NO CACHE

    したがって、パラメータ値を貼り付けて文字列ステートメントを作成する必要があります。
    SET @sql = CONCAT(N'ALTER SEQUENCE [dbo].', QUOTENAME(@SeqName), N' RESTART WITH ', @InpMin, N' INCREMENT BY 1', N' MINVALUE ', @InpMin, N' MAXVALUE ', @InpMax, N' NO CYCLE NO CACHE;');

    EXEC sys.sp_executesql @sql;
    この文字列@sqlは、関数CONCATおよびQUOTENAMEを使用して作成されます。プラス記号を使用して最終的な文字列を作成した場合にも機能しますが、Nullセーフの例のように実行することをお勧めします。

    このストアドプロシージャは、欠落した値または不正な値を指定するとエラーを生成(スロー)し、続行できなくなります。すべてのシーケンス番号を使い切ると、自動的にエラーが発生します。

    フロントエンドのアクセス手順では、エラーが発生していないことを確認する必要があります。エラーが発生したのは、適切なパラメータ入力を提供している場合に、シーケンスの番号が不足した場合のみです。エラーが発生した場合、フロントエンドは何らかの方法で操作をキャンセルする必要があります。

    引数を使用して設定できる機能は他にもいくつかあります。 CYCLEは、シーケンスが最後に到達した後、シーケンスを再び循環させてから、MINVALUEに移動します。 RESTART値を指定することで、シーケンスの途中で明示的に再起動することもできます。

    また、CACHEを指定することもできます。たとえば、一度に50のシーケンス番号を要求でき、50の番号ごとにシステムシーケンステーブルを更新します。これにより高速になりますが、停電が発生した場合のリスクも高まります。 、これらの番号は再利用できないため

    このストアドプロシージャで最後に注目する価値があるのは、sys.sequencesと呼ばれるシステムビューからシーケンスに関する情報(メタデータ)を取得できることです。次の情報が含まれています。


    読んでユーザーに伝えたい便利な列には、minimum_value、maximum_value、およびcurrent_value。


    興味がある場合は、MSDNの次のページにシーケンスに関する非常に役立つ情報があります。

    シーケンス番号
    シーケンスについて説明し、一般的な使用法の非常に良い例があります

    CREATE SEQUENCE(Transact-SQL)

    ALTER SEQUENCE(Transact-SQL)

    (Transact-SQL)の次の値

    sys.sequences(Transact-SQL)
    シーケンスでクエリできるメタデータについて説明します


    1. MySQL ASIN()関数–数値のアークサインを返します

    2. 非同期スレーブからMySQLGaleraクラスターを回復する方法

    3. SQLServer2019でのデータベースリカバリの高速化

    4. AndroidSQLiteデータベースとアプリのアップデート