2

標準パターンを使用して代理キーを設定する Oracle アプリケーションがあります。一連の外部行 (代理キーに特定の値を持つ) と、固有の値を持つその他の行があります。次の Oracle トリガー スニペットを使用して、挿入時にサロゲート キーをどうするかを決定します。

IF :NEW.SurrogateKey IS NULL THEN

 SELECT SurrogateKey_SEQ.NEXTVAL INTO :NEW.SurrogateKey FROM DUAL;

END IF;

提供された代理キーが null の場合は、指定されたシーケンスから値を取得します。それ以外の場合は、提供された代理キーを行に渡します。

これを行う簡単な方法がT-SQLであるとは思えません。あらゆる種類のアプローチがありますが、Oracle やその他の SQL-92 準拠の DB のようにシーケンス ジェネレーターの概念を使用するものはありません。

SQL Server T-SQL でこれを行うための本当に効率的な方法を知っている人はいますか? ところで、私たちは SQL Server 2008 を使用しています。

4

3 に答える 3

0

テーブルを使用して最後のシーケンス番号を保存する方法を次に示します。ストアド プロシージャは非常に単純です。そこにあるもののほとんどは、私が怠け者で、何かを忘れた場合の驚きが好きではないためです...ここにあります:

----- シーケンス値テーブルを作成します。

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[SequenceTbl]
(
  [CurrentValue] [bigint]
) ON [PRIMARY]

GO

-----------------ストアド プロシージャの作成

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE procedure [dbo].[sp_NextInSequence](@SkipCount BigInt = 1)
AS

BEGIN

  BEGIN TRANSACTION

    DECLARE @NextInSequence BigInt;

    IF NOT EXISTS
    (
      SELECT
        CurrentValue
      FROM
        SequenceTbl
    )

    INSERT INTO SequenceTbl (CurrentValue) VALUES (0);

    SELECT TOP 1
      @NextInSequence = ISNULL(CurrentValue, 0) + 1
    FROM
      SequenceTbl WITH (HoldLock);

    UPDATE SequenceTbl WITH (UPDLOCK)
      SET CurrentValue = @NextInSequence + (@SkipCount - 1);

  COMMIT TRANSACTION

  RETURN @NextInSequence
END;
GO

--------Sql Manager のストアド プロシージャを使用して、テスト値を取得します。

declare @NextInSequence BigInt

exec @NextInSequence = sp_NextInSequence;

--exec @NextInSequence = sp_NextInSequence <skipcount>;

select NextInSequence = @NextInSequence;

-----現在のテーブル値を表示します。

select * from SequenceTbl;

賢明な人は、ストアド プロシージャのパラメーター (オプション) があることに気付くでしょう。これは、呼び出し元が一意の ID を必要とする複数のレコードを持っている場合に、呼び出し元が ID のブロックを予約できるようにするためです。テーブルの作成時にレコードを挿入することを覚えていれば、「IF EXISTS...INSERT INTO...」ブロック全体を削除できます。そのレコードに値 (シード値 - ID として使用されることのない数値) を挿入することも忘れない場合は、select の ISNULL(...) 部分を削除して、CurrentValue + 1 を使用することもできます。誰かがコメントする前に、私はデータベース管理者ではなくソフトウェア エンジニアであることに注意してください。だから、どんな建設的な"Top 1"、"With (HoldLock)"、"With (UPDLock)" の使用に関する批判は大歓迎です。これがどれだけうまくいくかはわかりませんが、これまでのところうまくいきます...

于 2010-07-25T22:47:23.760 に答える
0

ID は 1 つのアプローチですが、テーブル レベルごとに一意の識別子が生成されます。

別のアプローチは、一意の識別子を使用することです。特に NewSequantialID() を使用して、生成された ID が常に最後より大きくなるようにします。このアプローチの問題は、もはや整数を扱っていないことです。

オラクルの方法をエミュレートする最も近い方法は、カウンター フィールドを持つ別のテーブルを用意し、このフィールドをクエリしてインクリメントし、値を返すユーザー定義関数を作成することです。

于 2009-02-27T06:56:26.910 に答える