大概在2年前遇到過,標(biāo)題中的問題,當(dāng)時(shí)研究了幾天很是糾結(jié)沒能徹底解決問題,后來也找了很多方法沒能解決問題。最近又遇到這個(gè)問題,實(shí)在是不解決也不行了,冷靜的想了想,完善了一下分頁查詢的方法,現(xiàn)在把代碼貼上,給大家參考,若有什么漏洞,請(qǐng)及時(shí)聯(lián)系吉日嘎拉,有錯(cuò)我會(huì)積極修正。希望不要重復(fù)浪費(fèi)生命,直接拿過去用就可以了,在通用權(quán)限管理系統(tǒng)組件里也用了這個(gè)方法在進(jìn)行分頁,最近維護(hù)一個(gè)每天有10萬多IP訪問的網(wǎng)站,也是用了這個(gè)分頁存儲(chǔ)過程,分頁效率還可以,最后一頁沒在出現(xiàn)卡死狀態(tài),若有問題及時(shí)聯(lián)系作者QQ:252056973,歡迎大家交流分享。
最后一頁分頁一卡死,整個(gè)網(wǎng)站的性能都會(huì)非常明顯的下降,不知道為啥,微軟有這個(gè)BUG一直沒處理好。希望SQL2012里不要有這個(gè)問題就好了。
參考代碼如下:
-- =============================================
-- Author: 吉日嘎拉
-- Create date: 2012年02月23日
-- Description: 2012年02月23日編碼規(guī)范化
-- =============================================
ALTER PROCEDURE [dbo].[GetRecordByPage]
@TableName VARCHAR(4000), -- 表名
@SelectField VARCHAR(4000), -- 要顯示的字段名(不要加select)
@WhereConditional VARCHAR(4000), -- 查詢條件(注意: 不要加 where)
@SortExpression VARCHAR(255), -- 排序索引字段名
@PageSize INT = 20, -- 頁大小
@PageIndex INT = 1, -- 頁碼
@RecordCount INT OUTPUT, -- 返回記錄總數(shù)
@SortDire VARCHAR(5) = 'DESC' -- 設(shè)置排序類型, 非 0 值則降序
AS
BEGIN
DECLARE @commandText VARCHAR(8000) -- 主語句
DECLARE @TopN INT -- 獲取前幾條記錄
DECLARE @PageCount INT -- 總共會(huì)是幾頁
DECLARE @TopLimit INT -- 獲取多少條記錄
DECLARE @SQLRowCount NVARCHAR(4000) -- 用于查詢記錄總數(shù)的語句
DECLARE @SQLOrder VARCHAR(400) -- 排序類型
DECLARE @SQLTemp VARCHAR(4000) -- 臨時(shí)變量
SET @SortExpression = LTRIM(RTRIM(@SortExpression))
SET @SortDire = UPPER(LTRIM(RTRIM(@SortDire)))
-- 這里是計(jì)算整體記錄行數(shù)
IF @RecordCount IS NULL
BEGIN
IF @WhereConditional != ''
BEGIN
SET @SQLRowCount = 'SELECT @RecordCount=COUNT(1) FROM ' + @TableName + ' WHERE ' + @WhereConditional
END
ELSE
BEGIN
SET @SQLRowCount = 'SELECT @RecordCount=COUNT(1) FROM ' + @TableName
END
END
-- SELECT @RecordCount=@@ROWCOUNT
EXEC sp_executesql @SQLRowCount, N'@RecordCount INT OUT', @RecordCount out
IF @RecordCount IS NULL
BEGIN
SET @RecordCount = 0
END
-- 這里是控制頁數(shù)最多少
SET @PageCount = @RecordCount / @PageSize + 1
-- 這里檢查當(dāng)前頁的有效性
IF (@PageIndex < 1)
BEGIN
SET @PageIndex = 1
END
-- 這里限制最后一頁的有效性
IF (@PageIndex > @PageCount)
BEGIN
SET @PageIndex = @PageCount
END
IF @SortDire != 'ASC'
BEGIN
SET @SQLTemp = '<(SELECT MIN'
SET @SQLOrder = ' ORDER BY ' + @SortExpression + ' DESC'
END
ELSE
BEGIN
set @SQLTemp = '>(SELECT MAX'
set @SQLOrder = ' ORDER BY ' + @SortExpression + ' ASC'
END
-- 這里是調(diào)試信息
-- SELECT @SQLOrder
-- 獲取幾條數(shù)據(jù)? 吉日嘎拉 2010-11-02 更新
SET @TopN = @RecordCount - @PageSize * (@PageIndex - 1)
IF @TopN > @PageSize
BEGIN
SET @TopN = @PageSize
END
SET @TopLimit = @PageSize * (@PageIndex - 1)
IF @TopLimit > @RecordCount
BEGIN
SET @TopLimit = @RecordCount
END
SET @commandText = 'SELECT TOP ' + STR(@TopN) + ' ' + @SelectField + ' FROM '
+ @TableName + ' WHERE ' + @SortExpression + @SQLTemp + '('
+ RIGHT(@SortExpression, LEN(@SortExpression) - CHARINDEX('.', @SortExpression)) + ') FROM (SELECT TOP ' + STR(@TopLimit)
+ ' ' + @SortExpression + ' FROM ' + @TableName + @SQLOrder + ') AS TableTemp)'
+ @SQLOrder
IF @WhereConditional != ''
SET @commandText = 'SELECT TOP ' + STR(@TopN) + ' ' + @SelectField + ' FROM '
+ @TableName + ' WHERE ' + @SortExpression + @SQLTemp + '('
+ RIGHT(@SortExpression, LEN(@SortExpression) - CHARINDEX('.',@SortExpression)) + ') FROM (SELECT TOP ' + STR(@TopLimit)
+ ' ' + @SortExpression + ' FROM ' + @TableName + ' WHERE ' + @WhereConditional + ' '
+ @SQLOrder + ') AS TableTemp) AND ' + @WhereConditional + ' ' + @SQLOrder
IF @PageIndex = 1
BEGIN
-- 第一頁的顯示效率提高
SET @SQLTemp = ''
IF @WhereConditional != ''
SET @SQLTemp = ' WHERE ' + @WhereConditional
SET @commandText = 'SELECT TOP ' + STR(@TopN) + ' ' + @SelectField
+ ' FROM ' + @TableName + @SQLTemp + ' ' + @SQLOrder
END
ELSE
BEGIN
-- 解決大數(shù)據(jù)最有一頁卡死的問題
IF @PageIndex = @PageCount
BEGIN
IF @SortDire = 'ASC'
BEGIN
SET @SQLOrder = ' ORDER BY ' + @SortExpression + ' DESC'
END
ELSE
BEGIN
SET @SQLOrder = ' ORDER BY ' + @SortExpression + ' ASC'
END
SET @SQLTemp = ''
IF @WhereConditional != ''
SET @SQLTemp = ' WHERE ' + @WhereConditional
SET @commandText = 'SELECT TOP ' + STR(@TopN) + ' ' + @SelectField
+ ' FROM ' + @TableName + @SQLTemp + ' ' + @SQLOrder
SET @commandText = 'SELECT ' + @SelectField
+ ' FROM (' + @commandText + ') AS TableTemp ORDER BY ' + @SortExpression + ' ' + @SortDire
END
END
EXEC (@commandText)
-- 這個(gè)是調(diào)試程序用的
-- SELECT @commandText
END
將權(quán)限管理、工作流管理做到我能力的極致,一個(gè)人只能做好那么很少的幾件事情。