前言

开发中查询功能是贯穿全文的,我们来盘一盘使用存储过程分页查询,并且支持动态拼接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)。

  1. 需要指定参数名称;
  2. 指定参数数据类型;
  3. 可以指定参数默认值;
  4. 可以指定参数方式(默认为输入参数)。

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条件的更多相关文章

  1. Oracle数据库排序后分页查询数据错误问题解决

    一.问题描述:根据更新时间倒序排序然后分页查询数据,但是点击分页操作的时候,会出现数据重复看似没有操作的情况 二.问题错误原因分析 分页查询的SQL语句: select * FROM (select ...

  2. oracle 分页查询数据重复问题

    最近在做项目的时候发现一个问题,oracle 在查询分页数据的时候,有几条数据重复查询了,并且有几条数据在分页的时候消失了.百度了一下发现,ORACLE 在查询数据的时候返回的行不是固定的,他只是按照 ...

  3. [转]SQLSERVER存储过程调用不同数据库的数据_存储过程中通过链接服务器访问远程服务器

    本文转自:http://blog.csdn.net/nnaabbcc/article/details/7967761 存储过程调用不同数据库的数据 在存储过程调用不同数据库的数据该如何做,比如在存储过 ...

  4. easyui-datagrid连接数据库实现分页查询数据

    一.利用MVC思想建立底层数据库: package com.hanqi.dao; import java.util.ArrayList; import java.util.List; import o ...

  5. mysql存储过程嵌套循环并分页处理数据

    业务背景:公司存证产品升级,随着数据量的增加,存证产品线按业务分表,导致以往的存证关联数据需要做数据同步更新.版本发布前,通过当前存储过程解决数据升级问题. ##创建存证文档关联情况下更新所用存储过程 ...

  6. mysq带条件的分页查询数据结果错误

    记一次mysql分页条件查询的结果出错: 以一张用户表为例,首先我们看表中的所有数据,注意红色框住的部分: 我们使用不带条件的分页查询来查询,数据显示是OK的: SELECT id,login_nam ...

  7. .net下MVC中使用Tuple分页查询数据

    主要是在DAL层写查询分页的代码. 例如DAL层上代码: public Tuple<List<WxBindDto>, int> GetMbersInfo(int start, ...

  8. linq里lambda写的join查询,并附加动态拼接的条件,条件为enum类型的查询

    因为查询条件不固定的原因,sql式的linq查询没法动态拼接条件. 网上搜的资料整理之后终于解决. 参考资料: enum使用 http://blog.csdn.net/slowlifes/articl ...

  9. sqlserver 存储过程 以及统计整个数据库数据

    drop proc test 删除存储过程 go  用于在 SSMS 和 SQLCMD 中将其之前的 T-SQL 语句作为一个批处理提交给 SQL Server 实例.GO 不是 T-SQL 语句,只 ...

随机推荐

  1. TCP编程详解

    目录 数据包格式 建立连接(三次握手) 数据传输 断开连接(四次挥手) 基础 客户端流程 编码 TCP服务端流程 TCP服务端编码 参考文献 TCP把连接作为最基本的对象,每一条TCP连接都有两个端点 ...

  2. mysql事务的实现原理

    此篇文章算是对mysql事务的一个总结,基本把mysql事务相关的知识点都涵盖到了,面试问来问去无非也就是这些,在了解这些之前我们先对mysql在执行的过程中 有一个整体的认识,如下图 如上图所示,M ...

  3. Redis高频面试题总结

    通过面试多家大型互联网企业,总结了如下的高频面试题目: 1.redis 过期键的删除策略? (1)定时删除:在设置键的过期时间的同时,创建一个定时器 timer). 让定时器在键的过期时间来临时,立即 ...

  4. Android 开发学习进程0.28 腾讯TBS接入和相关问题

    TBS 的接入和使用 TBS 的接入 腾讯TBS是X5内核的升级版,可以当作webview 来打开 网页,可以以用来打开docx doc pdf 等文件,这里主要使用的是文件功能. 依赖接入 api ...

  5. Go的包

    目录 go的包 一.包的创建规则 二.包的导入规则 三.包的函数调用 go的包 一.包的创建规则 一个包就是一个文件夹. 同一个包(文件夹)下,所有go文件都只能用同一个package,也就是每个文件 ...

  6. spring boot +dubbo 踩坑记录

    今天初次搭建spring boot +duboo的demo.记录一下踩坑记录. 首先搭建3个小demo,一个maven项目,两个spring boot (服务提供者和服务消费者)项目. 两 sprin ...

  7. elasticsearch如何设计集群

    本文为博客园作者所写: 一寸HUI,个人博客地址:https://www.cnblogs.com/zsql/ 在写本文时就在想,如果让你负责一个elasticsearch集群,从零开始,你会从哪些方面 ...

  8. CVE-2019-10758-Mongo-express-远程代码执行

    漏洞分析 https://xz.aliyun.com/t/7056 漏洞简介 mongo-express是一款mongodb的第三方Web界面,使用node和express开发. 如果攻击者可以成功登 ...

  9. JVM笔记 -- JVM的生命周期介绍

    Github仓库地址:https://github.com/Damaer/JvmNote 文档地址:https://damaer.github.io/JvmNote/ JVM生命周期 启动 执行 退出 ...

  10. Maven基础&&Spring框架阶段常用工具类整理

    常用工具类 1.密码加密工具类: package com.itheima.utils; import java.security.MessageDigest; import sun.misc.BASE ...