任務:實現適用於不同RDBMS的數據庫記錄的分頁。方法應該適用於主流引擎 - MSSQL2000 +,Oracle,MySql等。如何實現數據庫引擎獨立分頁?
請不要發佈RDBMS特定的解決方案,我知道如何爲大多數現代數據庫引擎實現這一點。我正在尋找通用解決方案。目前只有臨時表的解決方案出現在我的腦海中。
編輯:
我正在尋找SQL解決方案,而不是第三方庫。
任務:實現適用於不同RDBMS的數據庫記錄的分頁。方法應該適用於主流引擎 - MSSQL2000 +,Oracle,MySql等。如何實現數據庫引擎獨立分頁?
請不要發佈RDBMS特定的解決方案,我知道如何爲大多數現代數據庫引擎實現這一點。我正在尋找通用解決方案。目前只有臨時表的解決方案出現在我的腦海中。
編輯:
我正在尋找SQL解決方案,而不是第三方庫。
如果SQL規範包含了作爲標準的分頁,就會有一個通用的解決方案。任何RDBMS語言被稱爲RDBMS語言的要求也不包括分頁支持。
許多數據庫產品都支持帶標準語言專有擴展的SQL。其中一些支持使用限制條款Rowid with Oracle進行類似MySQL的分頁;每個處理不同。其他DBMS將需要添加一個名爲rowid或類似的字段。我不認爲你可以有一個通用的解決方案(任何人都可以自由地在這裏證明我是錯誤的;開放辯論),除非它是內置於數據庫系統本身,或除非有公司說ABC使用Oracle,MySQL, SQL Server,他們決定讓所有各種數據庫系統通過其數據庫開發人員提供他們自己的分頁實現,爲使用它的代碼提供通用接口。
亞音速能爲你做這個,如果你,如果你能忍受開源... http://subsonicproject.com/querying/webcast-using-paging/
除此之外,我知道NHib確實還有
JPA可以讓你與查詢類做到這一點:
Query q = ...;
q.setFirstResult (0);
q.setMaxResults (10);
爲您提供結果集中的前10個結果。
如果你想要一個DBMS獨立的原始SQL解決方案,恐怕你運氣不好。所有的供應商都以不同的方式做。
執行分頁的最自然有效的方法是使用LIMIT/OFFSET(Sybase世界中的TOP)構造。獨立於DB的方式必須知道它正在運行哪個引擎並應用適當的SQL構造。
至少,這是我在數據庫獨立庫的代碼中看到的。一旦從具有特定查詢的引擎獲取數據,就可以抽象出分頁邏輯。
如果您確實在尋找單一的一個SQL語句解決方案,您能否展示您的想法?就像臨時表解決方案的SQL一樣。這可能會讓你更相關的建議。
編輯:
我想看看你在想什麼,因爲我看不到的方式與臨時表做到這一點,而不是使用一個引擎特定結構。您在示例中使用了特定的結構。我仍然沒有看到只有(實現的)標準SQL在數據庫中實現分頁的方法。你可以把整個表格放在標準的SQL和應用程序的頁面中,但這顯然很愚蠢。
所以這個問題現在更像是「是否有一種方法來實現分頁而不使用LIMIT/OFFSET或等價的?」我想這個答案是「Sanely,不。」你可以嘗試使用遊標,但你也會遇到數據庫特定的句子/行爲。
我剛纔想到的一個奇怪的想法就是在表格中添加一個頁面列,比如create table test(id int,name varchar,phone varchar,page int),然後就可以獲取頁面1與select * from table where page = 1。但是這意味着必須添加代碼來維護該列,這也只能通過整個數據庫或使用特定於數據庫的構造來完成。除了必須爲每個可能的排序和許多其他缺陷添加不同的列。
我不能提供證據,但我真的認爲你不能這樣做。
照常進行:
首先按照標準實施。然後處理角落案例,即不執行標準的DBMS。如何處理角落案件取決於您的開發環境。
您正在尋找一種「通用」方法。分頁的最普遍方式是使用遊標,但基於光標的分頁與Web應用程序等非有狀態環境不太吻合。
我已經寫了有關標準和實現方式(包括光標)位置: http://troels.arvin.dk/db/rdbms/#select-limit-offset
@Vinko Vrsalovic,
正如我在寫的問題,我知道該怎麼做,在大多數數據塊。我該如何找到通用的解決方案或獲得它不存在的證據。
這是一個基於臨時表的愚蠢解決方案。這顯然很糟糕,所以不必評論它。
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
這種方法的問題是雖然IDENTITY是標準的SQL,但它不適用於所有數據庫。另外,SELECT TOP既不是標準的SQL,也不是廣泛的實現。除此之外,與不使用臨時表的方法相比,數據的複製操作可能會慢得多。 – 2008-09-15 08:01:03
也許應用視圖而不是創建臨時表?你可以創建一個視圖,其中一列是標識列嗎? – 2008-09-15 09:00:52
Troels Arvin,非常有用的頁面,謝謝! – aku 2008-09-15 07:42:46