13

私は問題があります。

私の ID プライマリ (IDENTITY) は、自動インクリメント (タイプ: int) に設定されています。しかし、新しい行を挿入すると、この新しい ID は連続しません。何が起こっている?解決策はありますか?

編集:

[...]
[id]int] IDENTITY(1,1) NOT NULL,
[...]
CONTRAINT [PK_Medida] PRIMARY KEY CLUSTERED
(
[id] ASC
) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
4

6 に答える 6

21

列の ID プロパティは、次のことを保証しません

値の一意性 – PRIMARY KEY または UNIQUE 制約または UNIQUE インデックスを使用して、一意性を強制する必要があります。

トランザクション内の連続した値– 複数の行を挿入するトランザクションは、行の連続した値を取得するとは限りません。これは、テーブルで他の同時挿入が発生する可能性があるためです。値が連続している必要がある場合、トランザクションはテーブルで排他ロックを使用するか、SERIALIZABLE 分離レベルを使用する必要があります。

サーバーの再起動またはその他の障害後の連続した値– SQL Server は、パフォーマンス上の理由から ID 値をキャッシュする場合があり、割り当てられた値の一部は、データベースの障害またはサーバーの再起動中に失われる可能性があります。これにより、挿入時に ID 値にギャップが生じる可能性があります。ギャップが受け入れられない場合、アプリケーションは NOCACHE オプションを指定してシーケンス ジェネレーターを使用するか、独自のメカニズムを使用してキー値を生成する必要があります。

値の再利用– 特定のシード/増分を持つ特定の ID プロパティの場合、ID 値はエンジンによって再利用されません。特定の挿入ステートメントが失敗した場合、または挿入ステートメントがロールバックされた場合、消費された ID 値は失われ、再度生成されることはありません。これにより、後続の ID 値が生成されるときにギャップが生じる可能性があります。

また、

頻繁に削除されるテーブルに ID 列が存在する場合、ID 値間にギャップが生じる可能性があります。これが懸念される場合は、IDENTITY プロパティを使用しないでください。ただし、ギャップが作成されていないことを確認するため、または既存のギャップを埋めるために、既存の ID 値を評価してから、明示的に ID 値を入力してSET IDENTITY_INSERT ONください。

また、ID 列のプロパティを確認し、ID 増分値を確認します。1 である必要があります。

ここに画像の説明を入力

于 2013-02-01T08:10:33.553 に答える
17

ID が連続しているとは思わないでください。ギャップを残すことができる多くのシナリオがあります。ID は抽象的な数字のように考え、ビジネス上の意味を持たないでください。

于 2013-02-01T08:07:32.120 に答える
3

ギャップは次の場合に発生します。

  1. レコードが削除されます。
  2. 新しいレコードを挿入しようとしたときにエラーが発生しました (例: not-null 制約エラー)。ID 値はどうしようもなくスキップされます。
  3. 誰かが明示的な値 (identity_insert オプションなど) で挿入/更新しました。
  4. 増分値が 1 より大きい。
于 2015-03-05T03:42:57.987 に答える
1

このエラーを回避するには、increment ステートメントを実行する前に予想されるエラーを評価するか、トランザクションを使用してステートメントが実行されないようにし、エラーが発生した場合にロールバックします。それが役に立てば幸い

于 2015-08-27T18:58:09.403 に答える
0

削除された行の自動 ID は、新しく挿入された行では使用されなくなります。これについては解決策を提供できませんが、これが動作です。

ウーター

于 2013-02-01T08:07:17.337 に答える
-1

大量の挿入ステートメントが失敗する原因となるいくつかの制約を持つテーブルがあります。Identity(1,1) によって処理されるインデックスに大きなギャップが生じていました。

私が考案した解決策は、ID 列のないステージング テーブルを作成することでしたが、テーブルの他のすべての列が含まれています。次に、ステージング テーブル テーブルで実行するトリガーを指定します。挿入が成功すると、レコードはインデックスと共に実際のテーブルに転送されます。この場合、ID の予約は別の時点で行われ、ID のすべての値をグループ化できます。

これは少し非効率に思えることは承知していますが、これまでのところ非常にうまく機能しています。

于 2016-01-24T16:15:22.360 に答える