ID を大まかに順番に保ちながら、INSERT ステートメントですぐに使用される ID 番号を生成する、DBMS に依存しない最良の方法は何ですか?
11 に答える
DBMSに依存しない? それは問題だ。最も一般的な 2 つの方法は、列の自動インクリメントとシーケンスです。ほとんどの DBMS は、どちらか一方を実行しますが、両方を実行することはありません。したがって、データベースに依存しない方法は、ロック、選択、更新、およびロック解除する 1 つの値を持つ 1 つの列を持つ別のテーブルを用意することです。
通常、私は「DBMS の独立性を地獄に」と言って、PostgreSQL のシーケンス、または MySQL の自動インクリメント カラムでそれを行います。私の目的では、どこでも機能する 1 つの方法を見つけようとするよりも、両方をサポートする方が良いと言えます。
選択したプログラミング言語でグローバル一意識別子(GUID)を作成できる場合は、それを ID と見なしてください。
トラブルシューティングの際に作業するのは難しくなりますが ( where
INT である条件を入力する方がはるかに簡単です)、いくつかの利点もあります。GUID をキーとしてローカルに割り当てることで、最初に親をデータベースに保存して ID を取得しなくても、親子レコードの関係を簡単に構築できます。また、定義上、GUID は一意であるため、サーバー上でキーをインクリメントすることについて心配する必要はありません。
私は常にDB固有のソリューションを選びますが、実際にこれを行う通常の方法が必要な場合は、独自のシーケンスを実装することです。RDBMSはトランザクションをサポートする必要があります。
int列を含むシーケンステーブルを作成し、これに最初の番号をシードすると、トランザクションロジックは次のようになります。
トランザクションを開始します tblSeqセットを更新しますintID=intID + 1 tblSeqから@myID=intIDを選択します tblData(intID、...)値(@ myID、...)に挿入 トランザクションの終了
トランザクションは、レコードがtblDataに挿入される前に、次にキューに入れられた挿入がtblSeq値を更新できないように、書き込みロックを強制します。すべての挿入がこのトランザクションを通過する限り、生成されたIDは順番になります。
これを行う普遍的な方法はありません。あったらみんな使っちゃう。定義上、SQL はこの考えを嫌っています。これは、セットベースのロジックのアンチパターンです (実際の多くのケースでは有用ですが)。
他の場所から ID 値を挿入しようとする場合に発生する最大の問題は、SQL ステートメントに複数のレコードが含まれ、複数の値を同時に生成する必要がある場合です。
必要な場合は、アプリケーションで使用するデータベースの選択要件の一部にしてください。本格的な DBMS 製品には、独自のメカニズムが用意されており、DML の違いを考慮してコーディングするのは簡単です。バリエーションはほとんどすべて DDL にあります。
ええ、生の SQL (および私の好みの順序) での明白な方法は、a) シーケンス b) 自動インクリメント フィールドです。より優れた、より現代的で、より DBMS に依存しない方法は、SQL にまったく触れず、(優れた) ORM を使用することです。
自動インクリメントまたはシーケンスがあります
これのポイントは何ですか、それはあなたの心配の最小です?
SQL自体をどのように処理しますか? MySQLには制限があり、
SQL Serverにはトップがあり、
オラクルにはランクがあります
次に、トリガー、テーブル構文の変更など、他にも何百万もあります
少し横方向のアプローチかもしれませんが、優れた ORM タイプのライブラリは、少なくとも違いを隠すことができるでしょう。たとえば、Ruby には、Migrations を備えた ActiveRecord (Ruby the Rails Web フレームワークで一般的に使用されますが、排他的に関連付けられているわけではありません) があります。プラットフォームにとらわれないコードで宣言されたテーブル定義内では、データ型、シーケンシャル ID 生成、インデックス作成などの実装の詳細は、あなたのビジョンの下に押し下げられます。
私は透過的に SQLite でスキーマを開発し、それを MS SQL Server に実装し、その後 Oracle に移植しました。スキーマ定義を生成するコードを変更することなく。
私が言うように、それはあなたが探しているものではないかもしれませんが、変化するものをカプセル化する最も簡単な方法は、すでにカプセル化を行っているライブラリを使用することです.
自動インクリメント ID 列を使用します。
SQL のみを使用する場合、以下がアプローチの 1 つになる可能性があります。
- 必要に応じて開始 ID を含むテーブルを作成します
- アプリケーションが初めてデプロイされるとき、アプリケーションはそのコンテキストで値を読み取る必要があります。
- その後、必要に応じて (スレッドセーフな方法で) id をインクリメントします。 -安全な方法)
- 何らかの理由でサーバーがダウンしている場合は、現在の ID 値をデータベースに書き込みます
- サーバーが再び起動すると、最後に離れた場所から選択されます。
それらが連続していなければならない理由は本当にありますか?ID として使用している場合は、UUID の一部または md5(now()) の最初の数桁を使用できるはずです。
時間をかけてマッサージすることができます。それは次のようなものと同等です
DateTime.Now.Ticks
したがって、YYYYMMDDHHMMSSSS のようなものになります。