2009-10-09 16 views
7

SQL(SQL Server)では、実際に行を挿入する前に、テーブルのID列から次のID(整数)を取得できますか?最新の行が削除された場合、これは必ずしも最も高いIDに1を加えたものではありません。行を挿入しないで次のIDを取得する

ライブDBを新しい行で更新する必要があるため、私はこれを尋ねます。行IDはコード(例:Switch(ID){Case ID:})で使用されており、同じである必要があります。開発DBとライブDBの同期が外れている場合は、前に展開。

私ができるのコース のSET IDENTITY OFF のSET ON INSERT_IDENTITYまたはトランザクションを実行し、次のIDを返した関数があった場合などが、不思議に思った(このバックロールIDが?ん)(インクリメントせずに) 。

+0

トランザクションはIDカウンタをロールバックせず、後で取得すると思われる番号を他のスレッドが使用している可能性があります。 – idstam

+0

ありがとう、この@idstam 私はこれを疑った。 – iWeasel

答えて

8

編集:

ページ全体のダンプを比較する時間数を過ごした後、私はもっと簡単な方法があり実現し、私はのDMVにとどまったの必要があります。

この値は、保存されていることを明確に示しています。データベースにすべてのページをダンプし、レコードが追加されたときの場所/変更を見つけることができませんでした。ページの200kラインダンプを比較するのは楽しいことではありません。

専用の管理コンソールを使用していましたが、1行挿入されたすべての内部テーブルをダンプしてから、システムテーブルをさらにダンプしました。両方のダンプは同一であり、生存している間に保存しなければならないが、そのレベルでさえも露出していないことを示している。

サークル内を回った後、私はDMVに答えがあることを認識しました。

create table foo (MyID int identity not null, MyField char(10)) 
insert into foo values ('test') 
go 10 

-- Inserted 10 rows 
select Convert(varchar(8),increment_value) as IncrementValue, 
    Convert(varchar(8),last_value) as LastValue 
from sys.identity_columns where name ='myid' 


-- insert another row 
insert into foo values ('test') 

-- check the values again 
select Convert(varchar(8),increment_value) as IncrementValue, 
    Convert(varchar(8),last_value) as LastValue 
from sys.identity_columns where name ='myid' 

-- delete the rows 
delete from foo 


-- check the DMV again 
select Convert(varchar(8),increment_value) as IncrementValue, 
    Convert(varchar(8),last_value) as LastValue 
from sys.identity_columns where name ='myid' 

-- value is currently 11 and increment is 1, so the next insert gets 12 
insert into foo values ('test') 
select * from foo 

Result: 
MyID  MyField 
----------- ---------- 
12   test  

(1 row(s) affected) 

行が削除されただけで、最後の値はリセットされないため、最後の値+増分が正しい答えになります。

また、私のブログにエピソードを書きます。

ああ、それはすべての近道:

select ident_current('foo') + ident_incr('foo') 

だから、実際に簡単であることが判明 - が、これは、すべてあなたが戻ってそれを得ながら、誰もが自分のIDを使用していない前提としています。調査のために良いですが、私はコードでそれを使用したくありません。

+0

Yikes!私が笑顔にした答えは+1です。 – iWeasel

+0

私は夜のほとんどを研究し、それがまともなブログアイテムになると思って、それを理解しました。私の答えを編集する。 – Andrew

+0

@Andrew。あなたがあなたの手に余りにも多くの時間を持っているという考えが私に起こりました。一方、大きな感謝。素晴らしい答え。 – iWeasel

2

ではなくIDENTITYカラムを使用して、一意の行識別子ですとしてUNIQUEIDENTIFIER(GUID)カラムを使用し、既知の値を挿入することができた。

(I、使用)他のオプションはSでありますET IDENTITY_INSERT ON。行IDは、ソース管理の単一文書で管理されます。

+1

優れた点ですが、Guidsはこの特定のテーブルで実際には実用的ではなく、少しスペースが空いています。 私は現在、IDENTITY_INSERTを使用しています。それは動作しますが、代替があるかどうか疑問です。 :) – iWeasel

+0

+1のために。 Guidは自動インクリメント列に対してパフォーマンスペナルティを持っています(行に必要な余分なスペースは些細ですが)が、このようなフープを飛ばす必要はありません。 – MusiGenesis

+0

GUIDをクラスター化されたキーとして使用すると、パフォーマンスと領域の両方が重くなります。 – Andrew

2

あなたはかなり簡単に最後の値がを使用することを決定することができます:

SELECT 
    last_value 
FROM 
    sys.identity_columns 
WHERE 
    object_id = OBJECT_ID('yourtablename') 

通常、次のIDは、1 + LAST_VALUEになります - しかし、そのための保証はありません。

マルク・

+1

正確に;保証はありません。そのため、代替案があるのか​​どうか疑問に思っています。 :) – iWeasel

+0

いいえ、他の方法はありません - 実際にINSERTを実行すると、SQL ServerはIDを実際に発行します.--( –

2

これは少し奇妙ですが、それは動作します:

あなたが最大値プラスワン取得することから始め、次の値を知りたい場合は、次の

SELECT max(id) FROM yourtable 

へこの作業を行うには、挿入時にIDをリセットする必要があります:

DECLARE @value INTEGER 

SELECT @value = max(id) + 1 FROM yourtable 

DBCC CHECKIDENT (yourtable, reseed, @value) 

INSERT INTO yourtable ... 

まさに洗練された解決策ですが、私はコーヒーをまだ持っていません;-)

(これは、プロセスや他のプロセスによってコードの第1ブロックと第2ブロックの間に何も行われないことを前提としています)。

+0

これはうまくいかないかもしれませんが、これを答えとしてマークします – iWeasel

+0

残念なことに、Jeffは、@Andrewが一晩中優れた編集をしてくれたので、お手伝いをしましょう。回答を再割り当てする必要があります。 – iWeasel

7

IDENT_CURRENTを試してみてください。

Select IDENT_CURRENT('yourtablename') 

これは、現在のセッション内の任意の行を挿入していない場合でも動作します:

は、指定したテーブルまたはビューのために生成された最後のID値を返します。 。生成された最後のID値は、任意のセッションおよび任意のスコープに適用できます。

+1

ニース。これは最新の値を使用し、MSDNページは次の生成されたID値を予測するためにIDENT_CURRENTを使用することに注意してください:実際の生成値は他のセッションによって挿入されたためIDENT_CURRENTとIDENTITY_SEEDと異なる場合があります。 – PaulG

関連する問題