Как реализовать независимую от ядра базы данных подкачку? - PullRequest
7 голосов
/ 15 сентября 2008

Задача: реализовать разбиение на страницы записей базы данных, подходящих для разных СУБД. Метод должен работать для основных двигателей - MSSQL2000 +, Oracle, MySql и т. Д.

Пожалуйста, не публикуйте конкретные решения СУБД, я знаю, как реализовать это для большинства современных систем баз данных Я ищу универсальное решение. На данный момент мне приходят в голову только решения на основе временных таблиц.

EDIT:
Я ищу решение SQL, а не стороннюю библиотеку.

Ответы [ 6 ]

5 голосов
/ 24 сентября 2008

Было бы универсальным решением, если бы спецификации SQL включали пейджинг в качестве стандарта. Требование, чтобы любой язык СУБД назывался языком СУБД, также не включает поддержку подкачки.

Многие продукты баз данных поддерживают SQL с проприетарными расширениями стандартного языка. Некоторые из них поддерживают разбиение на страницы, такие как MySQL с предложением limit, Rowid с Oracle; каждый обрабатывается по-разному. Другие СУБД должны будут добавить поле с именем rowid или что-то в этом роде.

Я не думаю, что у вас может быть универсальное решение (любой может свободно доказать, что я здесь неправ; открыт для дебатов), если оно не встроено в саму систему баз данных или если не существует компании, которая говорит ABC, которая использует Oracle, MySQL, SQL Сервер, и они решили, что все различные системы баз данных обеспечивают собственную реализацию подкачки разработчиками своих баз данных, предоставляя универсальный интерфейс для кода, который его использует.

3 голосов
/ 15 сентября 2008

Самый естественный и эффективный способ сделать пейджинг - использовать конструкцию LIMIT / OFFSET (TOP в мире Sybase). DBin-зависимый способ должен знать, на каком движке он работает, и применять правильную конструкцию SQL.

По крайней мере, я так и видел в коде независимых библиотек БД. Вы можете абстрагировать логику подкачки, как только получите данные из движка с конкретным запросом.

Если вы действительно ищете решение с одним предложением SQL, не могли бы вы показать, что вы имеете в виду? Как и SQL для решения временной таблицы. Это, вероятно, даст вам более актуальные предложения.

РЕДАКТИРОВАТЬ:

Я хотел увидеть, о чем ты думаешь, потому что я не мог найти способ сделать это с временными таблицами и не использовать конструкцию, специфичную для движка. Вы использовали конкретные конструкции в примере. Я до сих пор не вижу способа реализовать подкачку в базе данных только с помощью (реализованного) стандартного SQL. Вы можете привести всю таблицу в стандартном SQL и страницу в приложении, но это явно глупо.

Таким образом, вопрос теперь будет больше похож на «Есть ли способ реализовать пейджинг без использования LIMIT / OFFSET или эквивалентного?» и я думаю, что ответ "Sanely, нет". Вы можете попробовать использовать курсоры, но вы также станете жертвой конкретных предложений / поведения базы данных.

Мне пришла в голову глупая идея (читай глупо): добавить в таблицу столбец страницы, скажем, создать тест таблицы (id int, имя varchar, phone varchar, page int), а затем получить страницу 1 с помощью select * из таблицы, где page = 1. Но это означает необходимость добавления кода для поддержки этого столбца, что опять-таки может быть сделано либо путем объединения всей базы данных, либо с использованием специальных конструкций базы данных. Это помимо необходимости добавлять разные столбцы для каждого возможного заказа и многих других недостатков.

Я не могу предоставить доказательства, но я действительно думаю, что вы просто не можете сделать это разумно.

1 голос
/ 15 сентября 2008

Действуйте как обычно:
Начните с реализации в соответствии со стандартом. А затем обработайте угловые случаи, то есть СУБД, которые не реализуют стандарт. Как работать с угловыми случаями, зависит от вашей среды разработки.

Вы ищете «универсальный» подход. Самый универсальный способ разбивки на страницы - использование курсоров, но разбиение на страницы на основе курсора не очень хорошо подходит для среды без состояний, такой как веб-приложение.

Я написал о стандарте и реализациях (включая курсоры) здесь: http://troels.arvin.dk/db/rdbms/#select-limit-offset

0 голосов
/ 15 сентября 2008

@ Винко Врсалович,

как я писал в вопросе, я знаю, как это сделать в большинстве БД. Я хочу найти универсальное решение или получить доказательство того, что оно не существует.

Вот одно глупое решение, основанное на временной таблице. Это явно плохо, поэтому не нужно комментировать это.

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
0 голосов
/ 15 сентября 2008

JPA позволяет вам делать это с помощью класса Query:

Query q = ...;
q.setFirstResult (0);
q.setMaxResults (10);

дает первые 10 результатов в наборе результатов.

Если вам нужно независимое от СУБД решение для исходного SQL, боюсь, вам не повезло. Все поставщики делают это по-разному.

0 голосов
/ 15 сентября 2008

SubSonic может сделать это для вас, если вы, если вы можете терпеть Open Source ... http://subsonicproject.com/querying/webcast-using-paging/

Кроме того, я знаю, что NHib делает то же самое

...