asp.net 分頁存儲(chǔ)過程實(shí)例剖析心得
ALTER PROCEDURE [dbo].[sp_Sql_Paging]
(
@SqlDataTable NVARCHAR(4000), -- 表名
@PrimaryKey NVARCHAR(4000), -- 主鍵名稱
@Fields NVARCHAR(4000), -- 要返回的字段
@pageSize INT, -- 頁尺寸
@pageIndex INT, -- 頁碼
@recordCount INT OUTPUT, -- 記錄總數(shù)
@strOrderBy NVARCHAR(4000), -- 排序
@strWhere NVARCHAR(4000) -- 查詢條件
)
AS
BEGIN
SET NOCOUNT ON
DECLARE @strSQL1 NVARCHAR(4000) -- SQL語句1
DECLARE @strSQL2 NVARCHAR(4000) -- SQL語句2
-- 創(chuàng)建臨時(shí)表
-- 用來保存表的編號(hào)以及主鍵
CREATE TABLE #Temp_Paging
(
Temp_Paging_Id INT,
RowNumber INT
)
SET @strSQL1 = 'INSERT INTO [#Temp_Paging](Temp_Paging_Id, RowNumber) SELECT ' + @PrimaryKey + ', ROW_NUMBER() OVER (' + @strOrderBy + ') AS RowNumber FROM ' + @SqlDataTable + ' ' + @strWhere
EXEC SP_EXECUTESQL @strSQL1
SET @recordCount = @@ROWCOUNT -- 取得總記錄數(shù)
-- 判斷頁索引
IF @pageIndex > @recordCount * 1.0 / @pageSize + 1.0 OR @recordCount <= @pageSize
BEGIN
SET @pageIndex = 1
END
-- 分頁查詢
SET @strSQL2 = 'SELECT ' + @Fields + ' FROM ' + @SqlDataTable + ' WHERE ' + @PrimaryKey + ' IN (SELECT Temp_Paging_Id FROM [#Temp_Paging] WHERE RowNumber BETWEEN ' + Str((@pageIndex - 1) * @pageSize + 1) + ' AND ' + Str(@pageIndex * @pageSize) + ') ' + @strOrderBy
EXEC SP_EXECUTESQL @strSQL2
DROP TABLE #Temp_Paging -- 刪除臨時(shí)表
END
從原分頁存儲(chǔ)過程很容易看出,這里運(yùn)用了臨時(shí)表保存編號(hào),然后在通過pageIndex和pageSize計(jì)算所得,進(jìn)行分頁。
因?yàn)檫@里還以主鍵作為查詢條件,故臨時(shí)表中也保存了主鍵值。
很顯然,這里的臨時(shí)表無法做到通用,因?yàn)橹麈I的類型不一定是上面定義的INT型,也可以是其它的類型,比如:uniqueidentifier(全球唯一標(biāo)識(shí))。
這樣的話,這個(gè)存儲(chǔ)過程就碰到了問題,所以必須進(jìn)行改進(jìn)。
2.思路一
思路一很簡單,那就把這個(gè)類型聲明成一個(gè)變量,然后通過系統(tǒng)表獲取表的主鍵類型,再賦給變量不就可以了嗎??雌饋砗苊烂睿环猎囈辉囅?。
我們可以插入下面一段代碼:
DECLARE @colType NVARCHAR(50) --主鍵列類型
DECLARE @strSQL3 NVARCHAR(500) --創(chuàng)建臨時(shí)表語句
SET @colType = (SELECT typ.name as 數(shù)據(jù)類型
FROM sys.columns col
left join sys.types typ
on (col.system_type_id = typ.system_type_id AND col.user_type_id = typ.user_type_id)
WHERE col.object_id = (SELECT object_id FROM sys.tables WHERE name = @SqlDataTable)
and exists
( SELECT 1 FROM sys.indexes idx
join sys.index_columns idxCol
on (idx.object_id = idxCol.object_id)
WHERE idx.object_id = col.object_id
AND idxCol.index_column_id = col.column_id
AND idx.is_primary_key = 1
))
SET @strSQL3 = 'CREATE TABLE #Temp_Paging
(
Temp_Paging_Id '+ @colType+',
RowNumber INT
)'
PRINT @strSQL3
--EXEC(@strSQL3)
打印結(jié)果:
CREATE TABLE #Temp_Paging
(
Temp_Paging_Id uniqueidentifier,
RowNumber INT
)
很顯然我們得到了所需要的臨時(shí)表。這時(shí)我很開心,因?yàn)榈玫搅宋蚁胍臇|西。但似乎還沒有結(jié)束,我要執(zhí)行下該存儲(chǔ)過程。
壞結(jié)果往往在這時(shí)出現(xiàn):

這里就出現(xiàn)奇怪的事了,按打印出來的明明是正確的創(chuàng)建臨時(shí)表語句,而且也執(zhí)行了,為什么接下來對(duì)臨時(shí)表的操作又是無效的了?
找資料問同事,終于明白,原來臨時(shí)表分本地臨時(shí)表和全局臨時(shí)表。本地臨時(shí)表需要注意實(shí)際刪除的時(shí)間。
這里說得簡單一點(diǎn):當(dāng)在用EXEC(@strSQL3) 創(chuàng)建臨時(shí)表的時(shí)候,同時(shí)已經(jīng)刪除了臨時(shí)表。因?yàn)镋XEC這個(gè)過程的會(huì)話已經(jīng)結(jié)束,臨時(shí)表就被刪除了。
這里有一篇博文做了更具體的解釋,大家可以參考:點(diǎn)滴在心頭_SQL臨時(shí)表
3.思路二
上面的思路似乎行不通,那不如再換個(gè)思路,干脆不要建立臨時(shí)表,用Select * from (select * from table) as temptable 這種思路代替創(chuàng)建臨時(shí)表。
代碼如下:
ALTER PROCEDURE [dbo].[sp_Sql_Paging]
(
@SqlDataTable NVARCHAR(4000), -- 表名
@PrimaryKey NVARCHAR(4000), -- 主鍵名稱
@Fields NVARCHAR(4000), -- 要返回的字段
@pageSize INT, -- 頁尺寸
@pageIndex INT, -- 頁碼
@recordCount INT OUTPUT, -- 記錄總數(shù)
@strOrderBy NVARCHAR(4000), -- 排序
@strWhere NVARCHAR(4000) -- 查詢條件
)
AS
BEGIN
SET NOCOUNT ON
DECLARE @strSQL1 NVARCHAR(4000) -- SQL語句1
DECLARE @strSQL2 NVARCHAR(4000) -- SQL語句2
DECLARE @strSQL3 NVARCHAR(4000) -- SQL語句3
SET @strSQL1 = 'SELECT ' + @PrimaryKey + ', ROW_NUMBER() OVER (' + @strOrderBy + ') AS RowNumber FROM ' + @SqlDataTable + ' ' + @strWhere
--獲取總記錄數(shù)
SET @strSQL3 = 'SELECT @recordCount = COUNT(*) FROM ' + @SqlDataTable + ' ' + @strWhere
EXEC SP_EXECUTESQL
@stmt = @strSQL3,
@params = N'@recordCount AS INT OUTPUT',
@recordCount = @recordCount OUTPUT
--分頁查詢
IF @pageIndex > @recordCount * 1.0 / @pageSize + 1.0 OR @recordCount <= @pageSize
BEGIN
SET @pageIndex = 1
END
SET @strSQL2 = 'SELECT ' + @Fields + ' FROM ' + @SqlDataTable + ' WHERE ' + @PrimaryKey + ' IN (SELECT '+@PrimaryKey+' FROM ('+@strSQL1+') TempTable WHERE RowNumber BETWEEN ' + Str((@pageIndex - 1) * @pageSize + 1) + ' AND ' + Str(@pageIndex * @pageSize) + ') ' + @strOrderBy
EXEC SP_EXECUTESQL @strSQL2
END
這里有個(gè)小知識(shí)點(diǎn),注意EXEC SP_EXECUTESQL的寫法以及和EXEC(@strsql)的區(qū)別。大家可以去找資料了解下。
關(guān)于分頁的一些事就寫到這了,僅供參考。
- asp.net 結(jié)合mysql存儲(chǔ)過程進(jìn)行分頁代碼
- asp.net安全、實(shí)用、簡單的大容量存儲(chǔ)過程分頁
- asp.net SQL存儲(chǔ)過程分頁
- asp.net安全、實(shí)用、簡單的大容量存儲(chǔ)過程分頁
- asp.net結(jié)合aspnetpager使用SQL2005的存儲(chǔ)過程分頁
- asp.net 數(shù)據(jù)訪問層 存儲(chǔ)過程分頁語句
- asp.net利用存儲(chǔ)過程和div+css實(shí)現(xiàn)分頁(類似于博客園首頁分頁)
- asp.net中如何調(diào)用sql存儲(chǔ)過程實(shí)現(xiàn)分頁
相關(guān)文章
.NET實(shí)現(xiàn)熱插拔功能(動(dòng)態(tài)替換功用)方案實(shí)例
如果某個(gè)"功能"需要?jiǎng)討B(tài)更新?這種動(dòng)態(tài)更新,可能是需求驅(qū)動(dòng)的,也可能是為了修改 BUG,面對(duì)這種場(chǎng)景,如何實(shí)現(xiàn)“熱插拔”呢?先解釋一下“熱插拔”:在系統(tǒng)運(yùn)行過程動(dòng)態(tài)替換某些功能,不用重啟系統(tǒng)進(jìn)程。下面看例子2013-11-11Entity Framework Core對(duì)Web項(xiàng)目生成數(shù)據(jù)庫表
這篇文章介紹了Entity Framework Core對(duì)Web項(xiàng)目生成數(shù)據(jù)庫表的方法,文中通過示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-03-03剖析ASP.NET MVC的DependencyResolver組件
這篇文章主要為大家剖析ASP.NET MVC的DependencyResolver組件,感興趣的小伙伴們可以參考一下2016-04-04ASP.Net WebAPI與Ajax進(jìn)行跨域數(shù)據(jù)交互時(shí)Cookies數(shù)據(jù)的傳遞
本文主要介紹了ASP.Net WebAPI與Ajax進(jìn)行跨域數(shù)據(jù)交互時(shí)Cookies數(shù)據(jù)傳遞的相關(guān)知識(shí)。具有很好的參考價(jià)值。下面跟著小編一起來看下吧2017-05-05WeakReference(弱引用)讓GC需要時(shí)回收對(duì)象
我們平常用的都是對(duì)象的強(qiáng)引用,如果有強(qiáng)引用存在,GC是不會(huì)回收對(duì)象的,我們能不能同時(shí)保持對(duì)對(duì)象的引用,而又可以讓GC需要的時(shí)候回收這個(gè)對(duì)象呢?本文將為您詳細(xì)解答,需要了解的朋友可以參考下2012-12-12Asp.Net 網(wǎng)站性能優(yōu)化之緩字決 (上) 緩沖寫數(shù)據(jù)
通常情況下Asp.Net 網(wǎng)站的底層數(shù)據(jù)存儲(chǔ)都是關(guān)系數(shù)據(jù)庫,關(guān)系數(shù)據(jù)庫資源比較昂貴,而且也很容易造成瓶頸。緩字決文章就是為大家介紹如何有效使用緩存,異步寫緩沖數(shù)據(jù)庫的壓力,從而保證網(wǎng)站的性能。2010-06-06asp.net實(shí)現(xiàn)固定GridView標(biāo)題欄的方法(凍結(jié)列功能)
這篇文章主要介紹了asp.net實(shí)現(xiàn)固定GridView標(biāo)題欄的方法,即凍結(jié)列功能,涉及GridView結(jié)合前端js操作數(shù)據(jù)顯示的相關(guān)技巧,需要的朋友可以參考下2016-06-06asp.net 錯(cuò)誤:0x8007000B 異常的解決方法
這篇文章主要介紹了asp.net 錯(cuò)誤:0x8007000B 異常的解決方法,需要的朋友可以參考下2015-01-01