14

Oracle には、シーケンス番号を生成するメカニズムがあります。

CREATE SEQUENCE supplier_seq

    MINVALUE 1
    MAXVALUE 999999999999999999999999999
    START WITH 1
    INCREMENT BY 1
    CACHE 20;

そして、ステートメントを実行します

supplier_seq.nextval

次のシーケンス番号を取得します。

MS SQL Server で同じ機能をどのように作成しますか?

編集: テーブル レコードのキーを自動的に生成する方法を探しているわけではありません。プロセスの (論理) ID として使用できる一意の値を生成する必要があります。したがって、オラクルが提供する正確な機能が必要です。

4

10 に答える 10

15

完全一致はありません。

同等のものは、テーブルの作成中にデータ型として設定できる IDENTITY です。SQLSERVER は、挿入中に実行中のシーケンス番号を自動的に作成します。最後に挿入された値は、SCOPE_IDENTITY() を呼び出すか、システム変数 @@IDENTITY を調べることで取得できます (Frans が指摘したように)。

正確に同等のものが必要な場合は、テーブルを作成してから、次の値とその他の操作を返すプロシージャを作成する必要があります。これに関する落とし穴に関するマークの応答を参照してください。

編集:
SQL Server は、Oracle と同様のシーケンスを実装しています。詳細については、この質問を参照してください。

Microsoft SQL Server でシーケンスをどのように実装しますか?

于 2009-03-19T12:24:31.593 に答える
6

ID は最適で最もスケーラブルなソリューションですが、00A、00B、00C などのインクリメント int でないシーケンス、またはいくつかの特別なシーケンスが必要な場合は、次善の方法があります。正しく実装されている場合は問題なくスケーリングされますが、実装が不適切な場合はスケーリングが不十分です。私はそれをお勧めすることを躊躇しますが、あなたがすることは次のとおりです。

  1. 「次の値」をテーブルに格納する必要があります。テーブルは、その値だけを持つ単純な 1 行 1 列のテーブルにすることができます。複数のシーケンスがある場合、それらはテーブルを共有できますが、それぞれに別のテーブルを用意することで競合が少なくなる可能性があります。
  2. その値を 1 間隔ずつインクリメントする単一の update ステートメントを記述する必要があります。更新をストアド プロシージャに配置して、使いやすくし、別の場所のコードで繰り返さないようにすることができます。
  3. シーケンスを正しく使用して、合理的にスケーリングできるようにする (いいえ、Identitiy ほどではありません :-) には、次の 2 つのことが必要です。update ステートメントには、この正確な問題のために作成された特別な構文があり、単一のステートメントで値をインクリメントして返すことができます。b. トランザクションの開始前およびトランザクション スコープ外で、カスタム シーケンスから値を取得する必要があります。これが、Identity がスケーリングする理由の 1 つです。トランザクションのスコープに関係なく、挿入の試行に対して新しい値を返しますが、失敗してもロールバックしません。これは、ブロックされないことを意味し、失敗したトランザクションのギャップが生じることも意味します.

特別な更新構文はバージョンによって少し異なりますが、要点は、同じステートメントで変数への代入と更新を行うことです。2008 年の場合、Itzik Ben-Gan は次の優れたソリューションを提供しています

古い学校の 2000 年以降の方法は次のようになります。

UPDATE SequenceTable SET @localVar = value = value + 5 -- 末尾をインクリメント ロジックに変更します。

これにより、インクリメントされ、次の値が返されます。

絶対にギャップを設けることができない場合 (その要件に抵抗する:-)、その更新またはプロシージャをトランザクションの残りの部分に配置することは技術的に可能ですが、すべての挿入が前の挿入がコミットされるのを待つため、大きな同時実行ヒットが発生します。

私はこれを信用できません。Itzik からすべてを学びました。

于 2009-07-29T04:34:00.050 に答える
1

SQL Server 2012 に更新できる場合は、SEQUENCE オブジェクトを使用できます。SQL Server 2012 Express でさえ、シーケンスをサポートしています。

CREATE SEQUENCE supplier_seq
    AS DECIMAL(38)
    MINVALUE 1
    MAXVALUE 999999999999999999999999999
    START WITH 1
    INCREMENT BY 1
    CACHE 20;

SELECT NEXT VALUE FOR supplier_seq
SELECT NEXT VALUE FOR supplier_seq
SELECT NEXT VALUE FOR supplier_seq
SELECT NEXT VALUE FOR supplier_seq
SELECT NEXT VALUE FOR supplier_seq

結果:

---------------------------------------
1

(1 row(s) affected)


---------------------------------------
2

(1 row(s) affected)


---------------------------------------
3

(1 row(s) affected)


---------------------------------------
4

(1 row(s) affected)


---------------------------------------
5

(1 row(s) affected)

正しいデータ型を指定するように注意してください。指定しなかった場合、提供された MAXVALUE は受け入れられません。そのため、可能な限り最高の精度で DECIMAL を使用しました。

SEQUENCES の詳細: http://msdn.microsoft.com/en-us/library/ff878091.aspx

于 2013-03-25T03:11:39.610 に答える
1

これはかなり前にすでに回答されている可能性があります...しかし、SQL 2005以降では、ROW_NUMBER関数を使用できます...例は次のとおりです。

select ROW_NUMBER() OVER (ORDER BY productID) as DynamicRowNumber, xxxxxx,xxxxx

私の場合、OVERステートメントはORDER BY一意の主キーにを使用します...

これが役に立てば幸いです...一時テーブルや奇妙な結合はもうありません!!

于 2009-05-17T14:26:04.270 に答える
1

SQL Server にこの機能があればいいのにと思います。それは非常に多くのことをより簡単にします。

これが私がこれを回避した方法です。

tblIdentities というテーブルを作成します。この表に、最小値と最大値、およびシーケンス番号をリセットする頻度を記載した行を入力します。また、新しいテーブルの名前を入力します (tblMySeqNum と呼びます)。これを行うと、後でシーケンス番号ジェネレーターを追加するのがかなり簡単になります。

tblMySeqNum には 2 つの列があります。ID (int ID) および InsertDate (デフォルト値が GetDate() の日時列)。

新しい seq num が必要な場合は、このテーブルに挿入する sproc を呼び出し、SCOPE_IDENTITY() を使用して ID を作成します。tblIdentities の最大値を超えていないことを確認してください。その場合は、エラーを返します。そうでない場合は、シーケンス番号を返します。

さて、リセットしてクリーンアップします。tblIdentites にリストされているすべてのテーブル (今のところ 1 つだけ) をチェックして、それらをリセットする必要があるかどうかを確認する、必要に応じて定期的に実行するジョブを作成します。リセット値または時間に達した場合は、行にリストされているテーブルの名前 (この例では tblMySeqNum) に対して DBCC IDENT RESEED を呼び出します。これは、そのテーブルで実際には必要のない余分な行をクリアする良い機会でもあります。

ID を取得する sproc でクリーンアップや再シードを行わないでください。そうすると、シーケンス番号ジェネレーターはまったくうまくスケーリングしません。

前述したように、SQL Server のこの機能を使用すると、非常に多くのことが簡単になりますが、この回避策はかなりうまく機能することがわかりました。

ヴァッカーノ

于 2009-03-20T16:39:25.287 に答える
0

本当の答えではありませんが、2012 年にシーケンスが SQLServer に登場するようです。

http://www.sql-server-performance.com/2011/sequence-sql-server-2011/

于 2012-02-10T14:08:50.457 に答える
0

Exactly because of this IDENT_CURRENT is not limited by scope and session; it is limited to a specified table. we need to use SCOPE_IDENTITY() because scope identity will give us unique number generated in our session, and uniqueness is provided by identity itself.

于 2012-11-29T12:43:21.707 に答える
0

正確な答えではありませんが、いくつかの既存の答えへの追加

SCOPE_IDENTITY (Transact-SQL)

SCOPE_IDENTITY、IDENT_CURRENT、および @@IDENTITY は、ID 列に挿入される値を返すため、同様の関数です。

IDENT_CURRENT はスコープとセッションによって制限されません。指定されたテーブルに限定されます。IDENT_CURRENT は、任意のセッションおよび任意のスコープで特定のテーブルに対して生成された値を返します。詳細については、「IDENT_CURRENT (Transact-SQL)」を参照してください。

これは、2 つの異なるセッションが同じ ID 値またはシーケンス番号を持つ可能性があることを意味するため、これを回避し、すべてのセッションで一意の番号を取得します。IDENT_CURRENT

于 2012-04-26T12:35:51.980 に答える