SqlServer存储过程应用二:分页查询数据并动态拼接where条件
前言
开发中查询功能是贯穿全文的,我们来盘一盘使用存储过程分页查询,并且支持动态拼接where条件。
划重点:支持动态拼接where条件
对存储过程的使用有疑问的同学去【SqlServer存储过程的创建与使用】补补课。
至于大家是使用自定义sql查询还是相关ORM框架查询就不讨论了,我们就简单介绍存储过程的查询(自定义sql查询)。
创建存储过程并执行
流程图如下,我们根据流程图进行代码实现。
1、创建带参的存储过程
创建带参数的存储过程首先要在存储过程中声明该参数,每个存储过程参数都必须用惟一的名称进行定义。
与标准的Transact-SQL变量相同,参数名必须以@为前缀,并且遵从对象标识符规则。
当用户不提供该参数的值时可以使用一个默认值来代替。
在执行带参数的存储过程时,既可以通过显式指定参数名称并赋予适当的值,也可以通过提供在CREATE PROCEDURE语句中给定的参数值(不指定参数名称)来向存储过程传递值。
在存储过程PRO_Student_IN中命名4个参数,其定义顺序为@Chinese、@English、@maths和@class。
例如,将值传递给存储过程指定的参数名称。
EXEC PRO_Student_IN @class="三年一班",@Chinese=85,@maths=85,@English=85
例如,按照参数的位置传递,而不命名参数名称。
EXEC PRO_Student_IN 85,85,85,"三年一班"
2、定义一个参数,用于接受拼接后的sql语句
通过指定过程参数,调用程序可以将值传递给过程的主体。
如果将参数标记为 OUTPUT 参数,则过程参数还可以将值返回给调用程序。
一个过程最多可以有 2100 个参数,每个参数都有名称、数据类型和方向。 还可以为参数指定默认值(可选)。
使用过程调用提供的参数值必须为常量或变量,不能将函数名称作为参数值。 变量可以是用户定义的变量或系统变量(如 @@spid)。
- 需要指定参数名称;
- 指定参数数据类型;
- 可以指定参数默认值;
- 可以指定参数方式(默认为输入参数)。
3、创建一个临时表,用于存储查询拼接条件后的结果集
临时表与永久表相似,但临时表存储在tempdb中,当不再使用时会自动删除。临时表有两种类型:本地和全局。它们在名称、可见性以及可用性上有区别。
对于临时表有如下几个特点:
- 本地临时表就是用户在创建表的时候添加了“#”前缀的表,其特点是根据数据库连接独立。只有创建本地临时表的数据库连接有表的访问权限,其它连接不能访问该表;
- 不同的数据库连接中,创建的本地临时表虽然“名字”相同,但是这些表之间相互并不存在任何关系;
- 在SQLSERVER中,通过特别的命名机制保证本地临时表在数据库连接上的独立性。
真正的临时表利用了数据库临时表空间,由数据库系统自动进行维护,因此节省了表空间。并且由于临时表空间一般利用虚拟内存,大大减少了硬盘的I/O次数,因此也提高了系统效率。
临时表在事务完毕或会话完毕数据自动清空,不必记得用完后删除数据。
本地临时表
- 本地临时表的名称以单个数字符号 (#) 打头;
- 它们仅对当前的用户连接(也就是创建本地临时表的connection)是可见的;
- 当用户从 SQL Server 实例断开连接时被删除。
4、分页查询返回最终的sql语句和总行数,查询条件加上临时表的数据,最后删除临时表
Sqlserver数据库分页查询一直是Sqlserver的短板,分页方式也有好几种,假设有表ARTICLE,字段ID、YEAR...(其他省略),
数据53210条(客户真实数据,量不大),分页查询每页30条,查询第1500页(即第45001-45030条数据),字段ID聚集索引,YEAR无索引。
第一种方案、最简单、普通的方法:
SELECT TOP 30 * FROM ARTICLE WHERE ID NOT IN(SELECT TOP 45000 ID FROM ARTICLE ORDER BY YEAR DESC, ID DESC) ORDER BY YEAR DESC,ID DESC平均查询100次所需时间:45s
第二种方案:
SELECT * FROM ( SELECT TOP 30 * FROM (SELECT TOP 45030 * FROM ARTICLE ORDER BY YEAR DESC, ID DESC) f ORDER BY f.YEAR ASC, f.ID DESC) s ORDER BY s.YEAR DESC,s.ID DESC平均查询100次所需时间:138S
第三种方案:
SELECT * FROM ARTICLE w1,
(
SELECT TOP 30 ID FROM
(
SELECT TOP 50030 ID, YEAR FROM ARTICLE ORDER BY YEAR DESC, ID DESC
) w ORDER BY w.YEAR ASC, w.ID ASC
) w2 WHERE w1.ID = w2.ID ORDER BY w1.YEAR DESC, w1.ID DESC平均查询100次所需时间:21S
第四种方案:
SELECT * FROM ARTICLE w1
WHERE ID in
(
SELECT top 30 ID FROM
(
SELECT top 45030 ID, YEAR FROM ARTICLE ORDER BY YEAR DESC, ID DESC
) w ORDER BY w.YEAR ASC, w.ID ASC
)
ORDER BY w1.YEAR DESC, w1.ID DESC平均查询100次所需时间:20S
第五种方案:
SELECT w2.n, w1.* FROM ARTICLE w1, ( SELECT TOP 50030 row_number() OVER (ORDER BY YEAR DESC, ID DESC) n, ID FROM ARTICLE ) w2 WHERE w1.ID = w2.ID AND w2.n > 50000 ORDER BY w2.n ASC平均查询100次所需时间:15S
完整存储过程代码
/**author:熊泽 date:2021-04-16 project:SqlServer存储过程应用二:分页查询数据并动态拼接where条件*/
--创建一个查询学生的存储过程
CREATE PROCEDURE ProcedureStudent
@pageIndex INT , --当前页(如1:第1页)
@pageCount INT, --每页条数(如50:每页50条)
@rowTotal INT OUTPUT , --返回的总行数
@strWhere VARCHAR(5000) --程序动态拼接的sql查询条件
AS
BEGIN
/**begin创建拼接动态条件 */
DECLARE @sq_temp AS VARCHAR(2000) --定义拼接后的sql语句
CREATE TABLE #temp ( --创建一个拼接查询条件查询出来的结果用于做子查询
Number VARCHAR(50)
) SET @sq_temp ='SELECT Number FROM a_Students where 1 = 1 '
+ CASE WHEN ISNULL(@strWhere,'') = '' THEN '' ELSE @strWhere END --动态拼接的条件 --将拼接的条件写入临时表
INSERT INTO #temp (Number) EXEC (@sq_temp); /**end创建拼接动态条件 */ --分页查询语句sql
SELECT * FROM (SELECT
row_number()over (order by a.Number desc)Id,
a.Number 学号 ,
a.Name 姓名 ,
b.ClassName 班级 ,
c.Java ,
c.Python ,
c.C# ,
c.SqlDB
FROM a_Students a
LEFT JOIN a_StudentClass b ON a.ClassId = b.ClassId
LEFT JOIN a_StudentsScore c ON a.Number = c.Number
WHERE a.Number IN (SELECT Number FROM #temp)
)temp
WHERE temp.Id between (@pageIndex-1)*@pageCount+1 and @pageIndex*@pageCount; --返回总条数
SELECT @rowTotal=COUNT(*) FROM dbo.a_Students WHERE Number IN (SELECT Number FROM #temp) DROP TABLE #temp --删除临时表
END
GO
调用存储过程
1、没有动态拼接where条件
--调用分页存储过程,没有where条件
DECLARE @total INT
EXEC ProcedureStudent 1,5,@total OUT,''
SELECT @total 返回的总行数
2、有动态拼接where条件
--调用分页存储过程,有where条件:学号为100014的数据
DECLARE @total INT
EXEC ProcedureStudent 1,5,@total OUT,' and Number=''100014''' --动态拼接条件:学号为100014的数据
SELECT @total 返回的总行数
我们就介绍到这里吧,拜拜。
欢迎关注订阅微信公众号【熊泽有话说】,更多好玩易学知识等你来取
作者:熊泽-学习中的苦与乐 公众号:熊泽有话说 出处:https://www.cnblogs.com/xiongze520/p/14667408.html 创作不易,任何人或团体、机构全部转载或者部分转载、摘录,请在文章明显位置注明作者和原文链接。 |
SqlServer存储过程应用二:分页查询数据并动态拼接where条件的更多相关文章
- Oracle数据库排序后分页查询数据错误问题解决
一.问题描述:根据更新时间倒序排序然后分页查询数据,但是点击分页操作的时候,会出现数据重复看似没有操作的情况 二.问题错误原因分析 分页查询的SQL语句: select * FROM (select ...
- oracle 分页查询数据重复问题
最近在做项目的时候发现一个问题,oracle 在查询分页数据的时候,有几条数据重复查询了,并且有几条数据在分页的时候消失了.百度了一下发现,ORACLE 在查询数据的时候返回的行不是固定的,他只是按照 ...
- [转]SQLSERVER存储过程调用不同数据库的数据_存储过程中通过链接服务器访问远程服务器
本文转自:http://blog.csdn.net/nnaabbcc/article/details/7967761 存储过程调用不同数据库的数据 在存储过程调用不同数据库的数据该如何做,比如在存储过 ...
- easyui-datagrid连接数据库实现分页查询数据
一.利用MVC思想建立底层数据库: package com.hanqi.dao; import java.util.ArrayList; import java.util.List; import o ...
- mysql存储过程嵌套循环并分页处理数据
业务背景:公司存证产品升级,随着数据量的增加,存证产品线按业务分表,导致以往的存证关联数据需要做数据同步更新.版本发布前,通过当前存储过程解决数据升级问题. ##创建存证文档关联情况下更新所用存储过程 ...
- mysq带条件的分页查询数据结果错误
记一次mysql分页条件查询的结果出错: 以一张用户表为例,首先我们看表中的所有数据,注意红色框住的部分: 我们使用不带条件的分页查询来查询,数据显示是OK的: SELECT id,login_nam ...
- .net下MVC中使用Tuple分页查询数据
主要是在DAL层写查询分页的代码. 例如DAL层上代码: public Tuple<List<WxBindDto>, int> GetMbersInfo(int start, ...
- linq里lambda写的join查询,并附加动态拼接的条件,条件为enum类型的查询
因为查询条件不固定的原因,sql式的linq查询没法动态拼接条件. 网上搜的资料整理之后终于解决. 参考资料: enum使用 http://blog.csdn.net/slowlifes/articl ...
- sqlserver 存储过程 以及统计整个数据库数据
drop proc test 删除存储过程 go 用于在 SSMS 和 SQLCMD 中将其之前的 T-SQL 语句作为一个批处理提交给 SQL Server 实例.GO 不是 T-SQL 语句,只 ...
随机推荐
- NGK数字增益平台中如何分配代币产出
最近很多朋友听说NGK公链的主网和数字增益平台即将上线以后都纷纷表示非常感兴趣,已经基本了解了NGK代币的产出方式,但还是对代币产出分配的问题不是很明确.今天小编就给大家科普一下,NGK代币在NGK数 ...
- canal数据同步 客户端代码实现
1.引入相关依赖 <dependencies> <dependency> <groupId>org.springframework.boot</groupId ...
- Basic认证时添加请求头
http Basic认证 http协议定义的一种认证方式,将客户端id和客户端密码按照"客户端ID:客户端密码"的格式拼接,并用base64编 码,放在header中请求服务端, ...
- zabbix Python3管理
import requests import json import os # user config here ip = '192.168.52.130' user = "root&quo ...
- Markdown的基本用法与下载
Markdown的基本用法与下载typora 下载typora 1.在浏览器搜索typora 2.然后点进去 3.往下翻点击Download 4.看自己是什么系统然后在选择 5.选好系统以后再去去选择 ...
- 使用windbg定位内存问题【入门级】
1. 背景 在开发过程中,我们可能遇到应用程序线程占用过大的问题,可以通过windbg命令去定位哪些类型,哪些内存一直占用堆资源,从而查出问题,解决问题. 2. 准备工作 工具: 抓取DUMP文件的工 ...
- dubbo实战之一:准备和初体验
欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...
- python工业互联网应用实战7—业务层
本章我们演示代码是如何"进化"的,实战的企业日常开发过程中,系统功能总伴随着业务的不断增加,早期简单的代码慢慢的越来越复杂,敏捷编程中的"禅"--简单设计.快速 ...
- golang——gRPC学习
1.获取gRPC 环境变量GOPATH的src目录下执行: git clone https://github.com/grpc/grpc-go.git google.golang.org/grpc g ...
- JAVA面试题:输出100以内所有的素数
转载:https://www.cnblogs.com/onway/archive/2012/11/15/2771912.html Java输出1-100中所有的素数 很多人笔试时都会遇到这个问题,小农 ...