一个通用的分页存储过程实现-SqlServer(附上sql源码,一键执行即刻搭建运行环境)
使用前提
查询表必须有ID字段,且该字段不能重复,建议为自增主键
背景
如果使用ADO.NET进行开发,在查询分页数据的时候一般都是使用分页存储过程来实现的,本文提供一种通用的分页存储过程,只需要传入:
- 表名(以DBName.dbo.TableName)的形式
- Where条件(ID > 0 AND ID < 100)
- Select字段(ID,NAME,CreateDate)
- Order字段(NAME ASC,CreateDate DESC)
- PageSize (15)
- PageIndex(2)
- TotalCount,此为output参数
这7个参数,存储过程就能够返回指定条件下的分页数据,和数据总数。
sql源码&测试环境搭建
--创建Util库
CREATE DATABASE Util
GO
--创建通用的分页存储过程
USE Util
GO
/****** Object: StoredProcedure [dbo].[UP_GeneralPagedQuery_v1] Script Date: 04/03/2014 17:32:07 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO -- Author: DeanZhou
-- Create date: 2013-09-24
-- Description: 通用的分页存储过程(一)
CREATE PROCEDURE [dbo].[UP_GeneralPagedQuery_v1]
@TableName VARCHAR(100) , --表名称:如 MKT.dbo.UV_CouponInfo
@WhereField NVARCHAR(1000) = '' , --筛选条件:如 Status = 1 AND CreateUser = 'admin'
@SelectField NVARCHAR(1500) = '*' , --需要查询的列:如 *
@OrderField NVARCHAR(1000) = '' , --需要进行排序的字段:如 CustomerName desc,StartDate asc,Status desc,id asc
@PageSize INT = 15 , --页面大小:如 15
@PageIndex INT = 1 , --当前页面:如 1
@TotalCount INT = 0 OUT --记录总数:输出值
AS
BEGIN IF @OrderField IS NULL OR @OrderField = ''
BEGIN
SET @OrderField = ' ID '
END IF @WhereField IS NULL OR @WhereField = ''
BEGIN
SET @WhereField = ' WHERE ID > 0 '
END
ELSE
BEGIN
SET @WhereField = ' WHERE ' + @WhereField
END DECLARE @ExceptCount INT = @PageSize * ( @PageIndex - 1 )
DECLARE @TakeCount INT = @PageSize
DECLARE @IsNeedSubQuery INT DECLARE @SqlPreview NVARCHAR(MAX) =
'SELECT @C = COUNT(1) FROM ' + @TableName + ' ' + @WhereField + ';'
+ 'IF @EC < 0 SET @EC = 0 IF @EC >= @C SET @EC = @C;'
+ 'IF @TC < 0 SET @TC = 15 IF (@EC + @TC) > @C SET @TC = @C - @EC;'
+ 'IF @EC > 0 AND @TC > 0 SET @NSQ = 1 ELSE SET @NSQ = 0;' EXEC sp_executesql @SqlPreview,
N'@C INT OUTPUT,@EC INT OUTPUT,@TC INT OUTPUT,@NSQ INT OUTPUT',
@TotalCount OUTPUT, @ExceptCount OUTPUT, @TakeCount OUTPUT, @IsNeedSubQuery OUTPUT DECLARE @MaxOrMin VARCHAR(3) = 'MAX'
DECLARE @DescOrAsc VARCHAR(4) = ''
IF @ExceptCount > @TotalCount / 2
BEGIN
SET @MaxOrMin = 'MIN'
SET @DescOrAsc = 'DESC'
SET @ExceptCount = @TotalCount - @ExceptCount + 1
END DECLARE @SqlQuery NVARCHAR(MAX) =
' DECLARE @T_IDS TABLE (ID INT) '
+ ' IF @NSQ = 1' +
' BEGIN ' +
' SELECT @MD = ' + @MaxOrMin + '(ID) FROM '+
' (SELECT TOP ' + CONVERT(VARCHAR(15), @ExceptCount) + ' ID FROM ' + @TableName + ' ' + @WhereField + ' ORDER BY ' + @OrderField + ')T1;' +
' INSERT INTO @T_IDS '+
' SELECT TOP ' + CONVERT(VARCHAR(15), @TakeCount) + ' ID FROM ' + @TableName + ' ' + @WhereField + ' AND ID > @MD ORDER BY ' + @OrderField +
' SELECT ' + @SelectField + ' FROM ' + @TableName + ' S WHERE ID IN (SELECT ID FROM @T_IDS) ORDER BY ' + @OrderField +
' END ' +
' ELSE' +
' BEGIN ' +
' INSERT INTO @T_IDS SELECT ID FROM (SELECT TOP ' + CONVERT(VARCHAR(15), @TakeCount) + ' ID FROM ' + @TableName + ' ' + @WhereField + ' ORDER BY ' + @OrderField + ')T;' +
' SELECT ' + @SelectField + ' FROM ' + @TableName + ' S WHERE ID IN (SELECT ID FROM @T_IDS) ORDER BY ' + @OrderField +
' END ' EXEC sp_executesql @SqlQuery, N'@MD INT,@NSQ INT', 0, @IsNeedSubQuery END GO --创建测试库
CREATE DATABASE Test
GO --创建测试表
USE [Test]
CREATE TABLE TableTest (ID INT,NAME NVARCHAR(50),CreateDate DATETIME)
GO --插入测试数据
INSERT INTO TableTest
SELECT 1,'dean1',GETDATE() UNION
SELECT 2,'dean2',GETDATE() UNION
SELECT 3,'dean3',GETDATE() UNION
SELECT 4,'dean4',GETDATE()
打开您的sqlserver,在本地新建查询,并运行上面的代码,会在你的数据库中创建以下内容:
- 一个名称为【Util】的数据库,该库下面有一个名为【UP_GeneralPagedQuery_v1】的存储过程,这个存储过程就是通用的分页存储过程。
- 一个名称为【Test】的数据库,该库下面有一个名为【TableTest】的表,这个表里面有4条数据

请注意:在执行sql之前确认一下没有重名数据库,以免出错
测试
新建一个查询,执行下面sql,就完成了分页数据的获取
DECLARE @TotalCount int
EXEC Util.[dbo].[UP_GeneralPagedQuery_v1]
@TableName = N'Test.dbo.TableTest',
@WhereField = N'ID > 0 AND ID < 100',
@SelectField = N'ID,NAME,CreateDate',
@OrderField = N'NAME ASC,CreateDate DESC',
@PageSize = 2,
@PageIndex = 2,
@TotalCount = @TotalCount OUTPUT SELECT @TotalCount as N'@TotalCount'

一个通用的分页存储过程实现-SqlServer(附上sql源码,一键执行即刻搭建运行环境)的更多相关文章
- 我用 Python 撸了一个 plist 图集拆图工具!附上github源码
这些年,我一直在使用 JavaScript .CocosCreator 做开发,只要是他们不能解决的,我都不太愿意去弄,或者说是不太情愿去做.真的是手中有把锤子,看什么都是钉子,越是熟悉一样东西,越容 ...
- 分页存储过程实现-SqlServer
一个通用的分页存储过程实现-SqlServer(附上sql源码,一键执行即刻搭建运行环境) 使用前提 查询表必须有ID字段,且该字段不能重复,建议为自增主键 背景 如果使用ADO.NET进行开发,在查 ...
- 如此高效通用的分页存储过程是带有sql注入漏洞的
原文:如此高效通用的分页存储过程是带有sql注入漏洞的 在google中搜索“分页存储过程”会出来好多结果,是大家常用的分页存储过程,今天我却要说它是有漏洞的,而且漏洞无法通过修改存储过程进行补救,如 ...
- 分享一个通用的分页SQL
又很久没写博客,今天记录一个SQLserver通用分页存储过程(适用于SqlServer2000及以上版本) 1.支持连表 2.支持条件查询 USE [MYDB] GO /****** Object: ...
- 分享一个客户端程序(winform)自动升级程序,思路+说明+源码
做winform的程序,不管用没用过自动更新,至少都想过自动更新是怎么实现的. 我这里共享一个自动更新的一套版本,给还没下手开始写的人一些帮助,也希望有大神来到,给指点优化意见. 本初我是通过sock ...
- 一个功能齐全的IOS音乐播放器应用源码
该源码是在ios教程网拿过来的,一个不错的IOS音乐播放器应用源码,这个是我当时进公司时 我用了一晚上写的 图片都是在别的地方扒的,主要是歌词同步,及上一曲,下一曲,功能齐全了 ,大家可以学习一下吧 ...
- SQLServer中SQL语句与可执行二进制语句
SQLServer可以执行正常SQL语句也可以执行被转换的二进制语句,一般会用此方法进行数据库注入操作,骗过基本的字符过滤 --将二进制格式转为普通SQL语句 ) = 0x53454C45435420 ...
- Java实践:一个简易的http server和client的java源码学习和总结。
一.基本思路: 1.服务器端通过socket(), 监听在TCP 8080端口,等待客户端来连接. 2.服务器端解析客户端的HTTP请求中的URI值,把本地的目录下指定文件通过java的读取文件的方式 ...
- 一个Python开源项目-腾讯哈勃沙箱源码剖析(上)
前言 2019年来了,2020年还会远吗? 请把下一年的年终奖发一下,谢谢... 回顾逝去的2018年,最大的改变是从一名学生变成了一位工作者,不敢说自己多么的职业化,但是正在努力往那个方向走. 以前 ...
随机推荐
- Spring中统一相同版本的api请求路径的一些思考
Spring中统一相同版本的api请求路径的一些思考 问题场景 当我们在实际开发中,可能会遇到开发相同同版本的api, 假设相同版本的api请求路径为/v1/functionA,/v1/functio ...
- spring事务的开启方式(编程式和声明式)
1.编程式事务:编码方式实现事务管理(代码演示为JDBC事务管理) Spring实现编程式事务,依赖于2大类,分别是上篇文章提到的PlatformTransactionManager,与模版类Tran ...
- Myeclipse连接数据库删除数据库(JDBC)
package com.test.jdbc; import java.sql.Connection; import java.sql.DriverManager; import java.sql.Pr ...
- C#调用C++接口返回字符串的做法
作者:朱金灿 来源:http://blog.csdn.net/clever101 现在有这样一种情景,假如C#调用C++接口需要返回一个字符串.因为字符串是不定长的,因此传递一个定长的字符串进去是不合 ...
- IT部门域事件与业务分析
IT event--->system--->IT dept |--------------->IT dept |--------------->system 域事件分类: 直接 ...
- Python3+Selenium3+webdriver学习笔记8(单选、复选框、弹窗处理)
#!/usr/bin/env python# -*- coding:utf-8 -*-'''Selenium3+webdriver学习笔记8(单选.复选框.弹窗处理)''' from selenium ...
- 使用Selennium实现短信轰炸机
前言 可以用来轰炸一下骗子,但最好不要乱用.本来初学Python,仅当学习. selenium和ChromeDriver的安装与配置 可参考这篇博客,这里不再赘述. 程序实现 短信轰炸机的原理是利用一 ...
- C++内联函数、宏定义和普通函数的区别
C++内联函数.宏定义和普通函数的区别? 宏定义:在预处理阶段进行简单的文本替换,不会进行参数类型检查: 内联函数:在编译器的时候进行代码插入,编译器会在每次调用内联函数的地方直接将内联函数的内容展开 ...
- 【0624课外作业】将一个double类型的小数,四舍五入保留两位小数
package com.work0624; /** * 课外作业 *将一个double类型的小数,四舍五入保留两位小数 * @author L * */ import java.util.Scanne ...
- java基础—java对象的序列化和反序列化
一.序列化和反序列化的概念 把对象转换为字节序列的过程称为对象的序列化. 把字节序列恢复为对象的过程称为对象的反序列化. 对象的序列化主要有两种用途: 1) 把对象的字节序列永久地保存到硬盘上,通常存 ...