数据库系列之T-SQL(存储过程实现分页查询)
根据TOP ID
CREATE PROC [dbo].[proc_select_page_top] @pageindex INT=1,--当前页数 @pagesize INT=10,--每页大小 @tablename VARCHAR(50)='',--表名 @fields VARCHAR(1000)='',--查询的字段集合 @keyid VARCHAR(50)='',--主键 @condition NVARCHAR(1000)='',--查询条件 @orderstr VARCHAR(500),--排序条件 @totalRecord BIGINT OUTPUT--总记录数 AS IF ISNULL(@orderstr,N'')=N'' SET @orderstr=N' ORDER BY '+@keyid+N' DESC ' IF ISNULL(@fields,N'')=N'' SET @fields=N'*' IF ISNULL(@condition,N'')=N'' SET @condition=N'1=1' DECLARE @sql NVARCHAR(4000) --表的总记录数 --IF(@totalRecord IS NULL) --BEGIN SET @sql=N'SELECT @totalRecord=COUNT(*)' +N' FROM '+@tablename +N' WHERE '+@condition EXEC sp_executesql @sql,N'@totalRecord INT OUTPUT',@totalRecord OUTPUT —END IF(@pageindex=1) BEGIN SET @sql=N'SELECT TOP '+STR(@pagesize)+N' '+@fields+N' FROM '+@tablename+N' WHERE '+@condition+N' '+@orderstr EXEC(@sql) END ELSE BEGIN SET @sql=N'SELECT TOP '+STR(@pagesize)+N' '+@fields+N' FROM '+@tablename+ N' WHERE '+@keyid+N' NOT IN(SELECT TOP '+STR((@pageindex-1)*@pagesize)+N' '+@keyid+ N' FROM '+@tablename+N' WHERE '+@condition+N' '+@orderstr+N') AND '+@condition+N' '+@orderstr EXEC(@sql) END GO
根据ROW_NUMBER() OVER
CREATE PROC [dbo].[proc_select_page_row] @pageindex INT=1,--当前页数 @pagesize INT=10,--每页大小 @tablename VARCHAR(50)='',--表名 @fields VARCHAR(1000)='*',--查询的字段集合 @keyid VARCHAR(50)='',--主键 @condition NVARCHAR(1000)='',--查询条件 @orderstr VARCHAR(500),--排序条件 @totalRecord BIGINT OUTPUT--总记录数 AS IF ISNULL(@orderstr,N'')=N'' SET @orderstr=N' ORDER BY '+@keyid+N' DESC ' IF ISNULL(@fields,N'')=N'' SET @fields=N'*' IF ISNULL(@condition,N'')=N'' SET @condition=N'1=1' DECLARE @sql NVARCHAR(4000) --表的总记录数 -- IF @totalRecord IS NULL -- BEGIN SET @sql=N'SELECT @totalRecord=COUNT(*)' +N' FROM '+@tablename +N' WHERE '+@condition EXEC sp_executesql @sql,N'@totalRecord bigint OUTPUT',@totalRecord OUTPUT --END IF(@pageindex=1) BEGIN SET @sql=N'SELECT TOP '+STR(@pagesize)+N' '+@fields+N' FROM '+@tablename+N' WHERE '+@condition+N' '+@orderstr EXEC(@sql) END ELSE BEGIN DECLARE @StartRecord INT SET @StartRecord = (@pageindex-1)*@pagesize + 1 SET @sql=N'SELECT * FROM (SELECT ROW_NUMBER() OVER ('+ @orderstr +N') AS rowId,'+@fields+ N' FROM '+ @tablename+N') AS T WHERE rowId>='+STR(@StartRecord)+ N' and rowId<='+STR(@StartRecord + @pagesize - 1) EXEC(@sql) END GO
根据MAX(MIN)ID
--根据MAX(MIN)ID CREATE PROC [dbo].[proc_select_id] @pageindex int=1,--当前页数 @pagesize int=10,--每页大小 @tablename VARCHAR(50)='',--表名 @fields VARCHAR(1000)='',--查询的字段集合 @keyid VARCHAR(50)='',--主键 @condition NVARCHAR(1000)='',--查询条件 @orderstr VARCHAR(500),--排序条件 @totalRecord BIGINT OUTPUT--总记录数 AS IF ISNULL(@orderstr,N'')=N'' SET @orderstr=N' ORDER BY '+@keyid+N' DESC ' IF ISNULL(@fields,N'')=N'' SET @fields=N'*' IF ISNULL(@condition,N'')=N'' SET @condition=N'1=1' DECLARE @sql NVARCHAR(4000) --表的总记录数 --IF(@totalRecord IS NULL) --BEGIN SET @sql=N'SELECT @totalRecord=COUNT(*)' +N' FROM '+@tablename +N' WHERE '+@condition EXEC sp_executesql @sql,N'@totalRecord INT OUTPUT',@totalRecord OUTPUT --END IF(@pageindex=1) BEGIN SET @sql=N'SELECT TOP '+STR(@pagesize)+N' '+@fields+N' FROM '+@tablename+N' WHERE '+@condition+N' '+@orderstr EXEC(@sql) END ELSE BEGIN DECLARE @operatestr CHAR(3),@comparestr CHAR(1) SET @operatestr='MAX' SET @comparestr='>' IF(@orderstr<>'') BEGIN IF(CHARINDEX('desc',LOWER(@orderstr))<>0) BEGIN SET @operatestr='MIN' SET @comparestr='<' END END SET @sql=N'SELECT top '+STR(@pagesize)+N' '+@fields+N' FROM '+@tablename+N' WHERE '+@keyid+@comparestr +N'(SELECT '+@operatestr+N'('+@keyid+N') FROM '+@tablename+N' WHERE '+@keyid +N' IN (SELECT TOP '+STR((@pageindex-1)*@pagesize)+N' '+@keyid+N' FROM '+@tablename+N' WHERE ' +@condition+N' '+@orderstr+N')) AND '+@condition+N' '+@orderstr EXEC(@sql)
END GO
建表脚本
USE [TestDB] GO /****** Object: Table [dbo].[T_User] Script Date: 03/04/2015 20:07:45 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO CREATE TABLE [dbo].[T_User]( [Id] [int] IDENTITY(1,1) NOT NULL, [Name] [nvarchar](50) NOT NULL, [Password] [nchar](10) NULL, [InputTime] [datetime] NULL, CONSTRAINT [PK_T_User] PRIMARY KEY CLUSTERED ( [Id] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] GO
插入数据
declare @num int declare @count int set @num = 1 set @count = 100000 while @num <= @count begin insert into T_User(Name, password, InputTime) values('cm', @num, GETDATE()) set @num = @num + 1 end print '执行成功'
测试
--分组查询实例:查询第3页,每页有10行记录 select * from T_User order by Id --实例1的SQL语句: select * from (select row_number() over (order by Id) as rowId, * from T_User) as T where rowId >= 21 and rowId <= (21 + 10 -1) --实例1的SQL分析: --首先将表的记录按某个字段进行排序并编号(从1开始),然后查询满足第N页的编号范围的记录. --实例2的SQL语句: select top 10 * from T_User where Id > (select MAX(Id) from T_User where Id in (select top 20 Id from T_User where 1=1 order by Id)) and 1=1 order by Id --实例2的SQL分析: --首先按某个字段进行排序,然后查询第N页之前的记录集A,然后从记录集A中找出最大的主键,最后查询大于该主键的所有记录中的前10条记录. --实例3的SQL语句: select top 10 * from T_User where Id not in (select top 20 Id from T_User order by Id) order by Id --实例3的SQL分析: --首先按某个字段进行排序,然后查询第N页之前的记录集A,然后查询非记录集A的前10条记录.