連絡先を保存する SQL データベースを作成しています。連絡先を削除できるようにしたいのですが、ソフトウェアが接続するためには、各連絡先の正しい ID が重要です。James に連絡があり、彼が最初の連絡先だとしましょう。彼の ID は 0 です。Mary を追加すると、彼女の ID は 1 です。James を削除した場合、Mary の ID を 1 のままではなく、0 に設定するにはどうすればよいですか? 彼女は今最初のものなので、リセットする必要があります。つまり、誰かが削除されたときにデータベース内のすべての ID をリセットするにはどうすればよいでしょうか? ありがとう
10 に答える
これは多くの点で非常に悪い考えです。私はこれを行う方法をあなたに示すべきかどうかを議論しています。一度設定した行のIDを変更する理由はありません。
存在する場合は、PK識別子として間違ったフィールドを使用している可能性があります。ここでは、ID列でもあるPKフィールドについて話していると仮定しています。
連絡先テーブルにリンクするテーブルを作成し、IDの変更を開始する場合は、それらのテーブルもすべて更新する必要があることに注意してください。どちらが高くなるでしょう...
データベースに些細な量以上のレコードがあると、これは非常に遅くなります。ID 列は機能しません。カスタム T-SQL を実行して、すべての数値を変更し続ける必要がありますが、IMO は非常に悪い考えです。
追加された順序を追跡する必要がある場合は、日付/時刻スタンプを使用しないでください。
設計を再考する必要があります。
これは ID の仕組みではなく、ID が機能する方法でもありません。ID は決して変更しないでください。そうしないと、リンクされたすべての情報が間違った行を指すことになります。
代わりに、制御する「External_ID」列を追加してみませんか? または、クエリで動的に番号を付けます (計算列を使用しますか?)
IDは、行の一意の識別子です。
行を別のテーブルの別の行にリンクするために使用できます。IDがないこと自体も、削除されたことを明確に示しているため、情報を保持しています。ID番号のリサイクルを開始すると、一意の識別子を持つという目的が完全に無効になり、実際には意味がありません。IDが行に割り当てられたら、それを任意に変更してはなりません。
誰かが亡くなったときに、その社会保険番号(ID)を他の人に渡すことを少し想像してみてください。その結果、死亡した人の社会保険番号にリンクされていたすべての古い情報がその新しい人に転送されますが、これは意味がありません。IDについても同じことが起こります。IDが再割り当てされると、以前にリンクされていた古いデータが継承されます。
自動インクリメントの主キー列でこれを行うのは意味がありません。たとえそれが些細なことであったとしても、関連するテーブルで大量の更新がなければデータの整合性に影響を与えるからです。そのためには、列からインデックスと主キー制約を削除し (その時点でアプリケーションがフレークアウトする可能性があります)、それ以降のすべてのレコードの番号を付け直し、関連するすべてのテーブルの番号を付け直してから、主キーの制約とインデックスを再度適用する必要があります。
常に 0 で始まる何らかの形式の線形識別子が本当に必要な場合 (これは、ソフトウェア設計の問題を示している可能性があります)、主キーに加えてセカンダリ ID 列を使用できます。これを更新して、より高い値をシャッフルします。次のようなステートメントでラングを下ります。
UPDATE table
SET secondaryID = secondaryID - 1
WHERE secondaryID > (SELECT secondaryID FROM table WHERE primaryID = [id to delete]);
DELETE FROM table
WHERE primaryID = [id to delete];
私はそのような慣行を強く思いとどまらせます - レコードが削除されたために ID の値が「欠落」している場合、ソフトウェアは単にウィッグアウトするのではなく、これらの値の存在をテストする必要があります。
これは、行が削除されるたびにID列の番号を付け直すよりも、別の方法を使用して解決する方がはるかに適切です。
アプリケーションにこの必要性がある理由を知らずに他に何をするかを正確に言うのは難しいですが、アプリケーションがこの機能を必要としているという事実は、おそらくどこかの設計上の問題を示しています。
ID を単なる識別子以上のものとして使用しています。その場合、自動インクリメント フィールドを使用することはできません。コードでこれを処理する必要があります。
1分間のGoogle検索で、表示できないページが表示されました。これを Google で検索すると、2009 年 6 月 1 日時点で最初のリンクになります: tsql fix "identity column"
基本的に、再番号付けを行う前に、すべての関係フィールド間の外部キー制約を問題の ID フィールドに追加することをお勧めします (これは、何らかの関係がある場合は恐ろしい考えです。厳密に言えば、この質問をしている場合、あなたはかなりの時間を過ごすでしょう)。
連絡先テーブルが唯一のテーブルであるか、この ID フィールドに基づくリレーションシップがゼロの場合、Identity プロパティを NO に設定し、値を 1 から COUNT(ID) に再番号付けしてから、Identity プロパティを YES に設定し、ID を再シードできます。を使用して完了するには:
DECLARE @MaxID INT
SELECT @MaxID = COUNT(ID) FROM テーブル ID
DBCC CHECKIDENT('TableID', RESEED, @MaxID)
このシナリオでは、削除の各セットの後に上記の reseed スクリプトを使用できます (ただし、すべてが最初に正しく設定されたら、COUNT(ID) を MAX(ID) に変更します。これにより、テーブルが大きくなるにつれて速度が少し向上します)。追加の挿入または外部キー制約の更新。削除ブロックと再シード ブロックを囲むように TRANSACTIONS を使用していることを確認し、テーブルが同期トランザクションのみを許可するようにします。
コンプレックスね?そのため、右足から始めるのが最善です。;) (私はこれを経験から学びました) さらに質問がある場合は、mraarone et yahoo d0t com に電子メールを送信してください。
複数レベルの販売プログラムを処理するアプリケーションを作成しました。もちろん、人々はドロップアウトします。私たちの場合、人も挿入する必要がありました。
1 つの変更で正しい軌道に乗っています。
ID 番号 (ID) とシーケンス番号 (seq) は 2 つの異なるものです。彼らはお互いにまったく関係がありません。
ID は絶対に変更しないでください。一度割り当てられると、常に割り当てられます。
シーケンスのテーブルに列 (cNEXT) を作成し、ID を入力します。「このシーケンスの次の ID は何ですか?」
cNEXT の ID をシャッフルし、いつでも cNEXT を再割り当てします。どのストアド プロシージャでもそれを実行できます。
また、連続していない ID チェーンを柔軟に作成することもできます。これは、人々が別の地域に移動したり、別のグループに昇進したりする場合に役立ちます。
お役に立てれば!:)