36

SQLサーバーでシーケンスのようなものを実装する良い方法はありますか?

場合によっては、GUID が醜いという事実以外に、GUID を使用したくない場合もあります。たぶん、あなたが望むシーケンスは数値ではありませんか? その上、行を挿入してからDBに番号を尋ねるのは、とてもハックに思えます。

4

16 に答える 16

52

Sql Server 2012 ではSEQUENCEオブジェクトが導入されました。これにより、テーブルに関連付けられていない連続した数値を生成できます。

それらの作成は簡単です:

CREATE SEQUENCE Schema.SequenceName
AS int
INCREMENT BY 1 ;

挿入前の使用例:

DECLARE @NextID int ;
SET @NextID = NEXT VALUE FOR Schema.SequenceName;
-- Some work happens
INSERT Schema.Orders (OrderID, Name, Qty)
  VALUES (@NextID, 'Rim', 2) ;

シーケンスの使用方法の詳細については、私のブログを参照してください。

http://sqljunkieshare.com/2011/12/11/sequences-in-sql-server-2012-implementingmanaging-performance/

于 2011-12-11T15:55:17.393 に答える
5

Identity 列は、シーケンスにほぼ似ています。

于 2008-11-12T03:44:14.760 に答える
5

普通の古いテーブルを使用して、それらをシーケンスとして使用できます。つまり、挿入は常に次のようになります。

BEGIN TRANSACTION  
SELECT number from plain old table..  
UPDATE plain old table, set the number to be the next number  
INSERT your row  
COMMIT  

しかし、これをしないでください。ロックはダメだろうな…

私は SQL Server から始めましたが、Oracle の「シーケンス」スキームはハックのように見えました。私はあなたが別の方向からあなたに来ていると思います.scope_identity()はハックのように見えます.

それを乗り越えてください。ローマにいるときは、ローマ人がするようにしなさい。

于 2008-11-12T03:44:26.210 に答える
4

この問題を解決するために使用した方法は、すべてのシーケンスと「nextval」ストアド プロシージャを格納するテーブル「Sequences」でした。

SQL テーブル:

CREATE TABLE Sequences (  
    name VARCHAR(30) NOT NULL,  
    value BIGINT DEFAULT 0 NOT NULL,  
    CONSTRAINT PK_Sequences PRIMARY KEY (name)  
);

PK_Sequencesは、同じ名前のシーケンスが存在しないようにするために使用されます

SQL ストアド プロシージャ:

IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'nextVal') AND type in (N'P', N'PC')) DROP PROCEDURE nextVal;  
GO  
CREATE PROCEDURE nextval  
    @name VARCHAR(30)  
AS  
    BEGIN  
        DECLARE @value BIGINT  
        BEGIN TRANSACTION  
            UPDATE Sequences  
            SET @value=value=value + 1  
            WHERE name = @name;  
            -- SELECT @value=value FROM Sequences WHERE name=@name  
        COMMIT TRANSACTION  
        SELECT @value AS nextval  
    END;  

いくつかのシーケンスを挿入します:

INSERT INTO Sequences(name, value) VALUES ('SEQ_Workshop', 0);
INSERT INTO Sequences(name, value) VALUES ('SEQ_Participant', 0);
INSERT INTO Sequences(name, value) VALUES ('SEQ_Invoice', 0);  

最後にシーケンスの次の値を取得し、

execute nextval 'SEQ_Participant';

シーケンス テーブルから次の値を取得するいくつかの c# コード、

public long getNextVal()
{
    long nextval = -1;
    SqlConnection connection = new SqlConnection("your connection string");
    try
    {
        //Connect and execute the select sql command.
        connection.Open();

        SqlCommand command = new SqlCommand("nextval", connection);
        command.CommandType = CommandType.StoredProcedure;
        command.Parameters.Add("@name", SqlDbType.NVarChar).Value = "SEQ_Participant";
        nextval = Int64.Parse(command.ExecuteScalar().ToString());

        command.Dispose();
    }
    catch (Exception) { }
    finally
    {
        connection.Dispose();
    }
    return nextval;
}
于 2013-08-28T19:48:26.643 に答える
3

SQL Server 2012 では、単純に使用できます。

CREATE SEQUENCE

2005 および 2008 では、共通のテーブル式を使用して連番の任意のリストを取得できます。

次に例を示します (MAXRECURSION オプションが重要であることに注意してください)。

DECLARE @MinValue INT = 1;
DECLARE @MaxValue INT = 1000;

WITH IndexMaker (IndexNumber) AS
(
    SELECT 
        @MinValue AS IndexNumber
    UNION ALL SELECT 
        IndexNumber + 1
    FROM
        IndexMaker
    WHERE IndexNumber < @MaxValue
)
SELECT
    IndexNumber
FROM
    IndexMaker
ORDER BY
    IndexNumber
OPTION 
    (MAXRECURSION 0)
于 2013-01-23T15:27:35.870 に答える
3

Oracle によって実装されているシーケンスでは、挿入の前にデータベースへの呼び出しが必要です。SQL Server によって実装される ID では、挿入後にデータベースへの呼び出しが必要です。

一方は他方よりもハックではありません。最終的な効果は同じです。一意の人工キー値を提供するためのデータ ストアへの依存/依存と、(ほとんどの場合) ストアへの 2 つの呼び出しです。

あなたのリレーショナル モデルは人工キーに基づいていると想定しています。このコンテキストでは、次の観察結果を提供します。

人工的な鍵に意味を持たせようとしてはなりません。それらの唯一の目的は、関連するレコードをリンクすることです。

データの注文に関して、どのようなニーズがありますか? ビュー(プレゼンテーション)で処理できますか、それとも永続化する必要があるデータの真の属性ですか?

于 2008-11-12T05:33:09.533 に答える
2

識別子を持つステージ テーブルを作成します。

ステージ テーブルをロードする前に、識別子を切り捨てて再シードし、1 から開始します。

テーブルをロードします。各行には、1 から N までの一意の値が含まれるようになりました。

シーケンス番号を保持するテーブルを作成します。これは、シーケンスごとに 1 つずつ、複数の行になる場合があります。

作成したシーケンス テーブルからシーケンス番号を検索します。ステージ テーブルの行数をシーケンス番号に追加して、シーケンス番号を更新します。

検索したシーケンス番号を追加して、ステージ テーブル識別子を更新します。これは簡単な 1 ステップのプロセスです。または ターゲット テーブルをロードし、ETL にロードする際に識別子にシーケンス番号を追加します。これにより、一括ローダーを利用して、他の変換を行うことができます。

于 2011-01-13T18:45:29.367 に答える
2

sqljunkiesshare が述べているように、SQL Server 2012 にシーケンスが追加されました。GUI でそれを行う方法は次のとおりです。これは次のものと同等です。

CREATE SEQUENCE Schema.SequenceName
AS int
INCREMENT BY 1 ;
  1. オブジェクト エクスプローラーで、Programmabilityフォルダーを展開します。
  2. Programmabilityフォルダーの下で、 以下に示すようにSequencesフォルダーを右クリックします。

ここに画像の説明を入力

  1. 下線は、上記の SQL ステートメントと同等のものを取得するために更新する値ですが、必要に応じてこれらを変更することを検討します (以下の注を参照)。

ここに画像の説明を入力

ノート:

于 2016-09-28T22:14:59.407 に答える
0

私は完全に同意し、昨年プロジェクトでこれを行いました。

シーケンスの名前、現在の値、および増分量を含むテーブルを作成しました。

次に、それらを追加および削除するための2つのprocを作成しました。そして、次を取得するための2つの機能と、最新のものを取得します。

于 2008-11-12T03:47:19.280 に答える
0

ID 列のもう 1 つの問題は、シーケンス番号を一意にする必要があるテーブルが複数ある場合、ID 列が機能しないことです。また、Corey Trager が言及しているように、ロール ユア オウン タイプのシーケンス実装では、ロックの問題が発生する可能性があります。

最も直接的に同等のソリューションは、ID 用の単一の列を持つ SQL Server テーブルを作成することのようです。これは、別のタイプの「シーケンス」オブジェクトの代わりになります。たとえば、Oracle で Dogs <-- sequence object --> Cats などの 1 つのシーケンスから 2 つのテーブルがある場合、SQL Server では 3 つのデータベース オブジェクトを作成します。すべてのテーブルは Dogs <-- Pets with identity column --> のようになります。猫。Pets テーブルに行を挿入して、通常は NEXTVAL を使用するシーケンス番号を取得し、ユーザーから実際のペットの種類を取得したら、通常どおりに Dogs または Cats テーブルに挿入します。追加の共通列は、Dogs/Cats テーブルから Pets スーパータイプ テーブルに移動できます。その結果、1) シーケンス番号ごとに 1 つの行が存在することになります。

于 2011-10-17T14:52:37.250 に答える
0

SQL Server 2005 を使用している場合は、Row_Number を使用するオプションがあります

于 2008-12-15T15:56:28.900 に答える
0

シーケンシャルキーを使用してデータを挿入したいが、挿入したばかりのキーを取得するためにデータベースに再度クエリを実行する必要がない場合は、次の 2 つの選択肢しかないと思います。

  1. 新しく挿入されたキー値を返すストアド プロシージャを介して挿入を実行します。
  2. シーケンスのクライアント側を実装します (挿入する前に新しいキーを知ることができるように)

クライアント側のキー生成を行っている場合、GUIDが大好きです。私は彼らがめちゃくちゃ美しいと思います。

row["ID"] = Guid.NewGuid();

そのラインは、スポーツカーのボンネットのどこかにあるはずです。

于 2008-11-12T04:13:10.833 に答える