データベース エンジンに依存しないページングを実装するにはどうすればよいですか?
質問
タスク:さまざまな RDBMS に適したデータベース レコードのページングを実装します。このメソッドは、MSSQL2000+、Oracle、MySql などの主流エンジンで機能する必要があります。
RDBMS 固有のソリューションを投稿しないでください。私は最新のデータベース エンジンのほとんどでこれを実装する方法を知っています。普遍的な解決策を探しています。現時点では一時テーブルベースのソリューションしか思い浮かびません。
編集:
サードパーティのライブラリではなく、SQL ソリューションを探しています。
解決
SQL 仕様にページングが標準として含まれていれば、普遍的な解決策があったでしょう。RDBMS 言語を RDBMS 言語と呼ぶための要件には、ページングのサポートも含まれていません。
多くのデータベース製品は、標準言語に独自の拡張機能を備えた SQL をサポートしています。それらの中には、limit 句を備えた MySQL や Oracle の Rowid などのページングをサポートするものもあります。それぞれ扱いが異なります。他の DBMS では、rowid などと呼ばれるフィールドを追加する必要があります。
それがデータベース システム自体に組み込まれていない限り、あるいは Oracle、MySQL、SQL Server を使用する ABC のような企業が存在しない限り、普遍的な解決策は得られないと思います (ここで私の間違いを証明するのは誰でも自由です。議論の余地はあります)。さまざまなデータベース システムすべてに、データベース開発者によるページングの独自の実装を提供させ、それを使用するコードにユニバーサル インターフェイスを提供させることを決定しました。
他のヒント
ページングを行う最も自然で効率的な方法は、LIMIT/OFFSET (Sybase の世界では TOP) 構造を使用することです。DB に依存しない方法では、どのエンジンで実行されているかを認識し、適切な SQL 構造を適用する必要があります。
少なくとも、DB 独立ライブラリのコードでそれが行われているのを私が見た方法です。特定のクエリを使用してエンジンからデータを取得したら、ページング ロジックを抽象化できます。
本当に 1 つの SQL 文のソリューションを探しているのであれば、何を考えているか示していただけますか?一時テーブル ソリューションの SQL と同様です。そうすれば、より関連性の高い提案が得られるでしょう。
編集:
エンジン固有の構造を使用せずに一時テーブルを使用してそれを行う方法が見つからなかったので、あなたが何を考えているのか知りたかったのです。この例では特定の構成要素を使用しました。(実装された) 標準 SQL のみを使用してデータベースにページングを実装する方法はまだわかりません。テーブル全体を標準 SQL に取り込み、ページをアプリケーションに取り込むこともできますが、それは明らかに愚かです。
それで、質問は「制限/オフセットまたは同等のものを使用せずにページングを実装する方法がありますか?」のようなものになります。答えは「Sanely、いいえ」だと思います。カーソルを使用してみることもできますが、データベースの特定の文章/行動の餌食になります。
私が今思いついた奇抜な(愚かな)アイデアは、テーブルにページ列を追加することです。たとえば、テーブルテスト(id int、name varchar、phone varchar、page int)を作成すると、select *でページ1を取得できます。ページ = 1 のテーブルから。しかし、それは、その列を維持するためにコードを追加する必要があることを意味します。これも、データベース全体を取り込むか、データベース固有の構成を使用することによってのみ実行できます。それに加えて、考えられる順序ごとに異なる列を追加する必要があるなど、多くの欠陥があります。
証拠は示せませんが、あなたは正気でそれを行うことはできないと思います。
通常どおりに続行します。
まずは標準に従って実装してみましょう。そして、コーナーケースに対処します。標準を実装していない DBMS。特殊なケースに対処する方法は、開発環境によって異なります。
あなたは「普遍的な」アプローチを求めています。ページネーションを行う最も一般的な方法はカーソルを使用することですが、カーソルベースのページネーションは Web アプリケーションのような非ステートフル環境にはあまり適合しません。
標準と実装 (カーソルを含む) についてはここに書きました。http://troels.arvin.dk/db/rdbms/#select-limit-offset
オープンソースを許容できる場合は、SubSonic がこれを実行できます...http://subsonicproject.com/querying/webcast-using-paging/
それ以外では、NHib も同様であることを私は知っています
JPA では、Query クラスを使用してそれを行うことができます。
Query q = ...;
q.setFirstResult (0);
q.setMaxResults (10);
結果セット内の最初の 10 件の結果が表示されます。
DBMS に依存しない生の SQL ソリューションが必要な場合は、残念ながら運が悪いと思います。すべてのベンダーはやり方が異なります。
@ヴィンコ・ヴルサロビッチ
質問に書いたように、私はほとんどのDBでそれを行う方法を知っています。普遍的な解決策を見つけるか、それともそれが存在しないという証明を得るか。
ここでは、一時テーブルに基づいた愚かな解決策を 1 つ示します。明らかに悪質なのでコメントする必要はありません。
N - upper bound
M - lower bound
create #temp (Id int identity, originalId int)
insert into #temp(originalId)
select top N KeyColumn from MyTable
where ...
select MyTable.* from MyTable
join #temp t on t.originalId = MyTable.KeyColumn
where Id between M and M
order by Id asc
drop #temp