一个通用的分页存储过程实现-SqlServer(附上sql源码,一键执行即刻搭建运行环境)

使用前提

  查询表必须有ID字段,且该字段不能重复,建议为自增主键

背景

  如果使用ADO.NET进行开发,在查询分页数据的时候一般都是使用分页存储过程来实现的,本文提供一种通用的分页存储过程,只需要传入:

  1. 表名(以DBName.dbo.TableName)的形式
  2. Where条件(ID > 0 AND ID < 100)
  3. Select字段(ID,NAME,CreateDate)
  4. Order字段(NAME ASC,CreateDate DESC)
  5. PageSize (15)
  6. PageIndex(2)
  7. 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,在本地新建查询,并运行上面的代码,会在你的数据库中创建以下内容:

  1. 一个名称为【Util】的数据库,该库下面有一个名为【UP_GeneralPagedQuery_v1】的存储过程,这个存储过程就是通用的分页存储过程。
  2. 一个名称为【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通过链接服务器远程删除数据性能问题解决

 

在上一遍文章中介绍了SQLServer通过链接服务器访问Oracle性能问题的解决方法,本文介绍链接服务器下远程删除SQLServer数据的性能问题解决

1. 问题发现

系统中有个功能,需要远程删除SQLServer实例的表数据,删除语句中有where条件,条件中有一个子查询。

该功能前台执行速度非常慢。所以准备调优。

下面为演示代码,未优化前如下:

DELETE
FROM [LINKSERVERNAME].[AdventureWorks2008].[Sales].[SalesOrderDetail]
WHERE SalesOrderDetailID=5
AND EXISTS(SELECT TOP 1 1 FROM [LINKSERVERNAME].[AdventureWorks2008].[Sales].[SalesOrderDetail])

  此时的执行计划如下图:

可以看到执行计划存在一个远程扫描,然后在本地执行筛选。

在远程服务器开启profiler跟踪,部分内容如下图:

可以看到远程服务器开启了一个游标,然后逐行读取数据并返回给调用端。

可以预见性能会非常差,如何避免不带where条件的远程扫描呢?

2. 问题解决

2.1 OpenQuery

使用OpenQuery将delete数据的筛选提交到远程服务器执行。

DELETE
FROM OPENQUERY([LINKSERVERNAME]
,'SELECT *
FROM [AdventureWorks2008].[Sales].[SalesOrderDetail]
WHERE SalesOrderDetailID=5
AND EXISTS(SELECT TOP 1 1 FROM [AdventureWorks2008].[Sales].[SalesOrderDetail])'
)

此时,执行计划如图:

2.2 sp_executesql

将整个delete语句提交到远程执行

DECLARE @sql nvarchar(max)
SELECT @sql ='
DELETE
FROM [AdventureWorks2008].[Sales].[SalesOrderDetail]
WHERE SalesOrderDetailID=5
AND EXISTS(SELECT TOP 1 1 FROM [AdventureWorks2008].[Sales].[SalesOrderDetail])
'
exec [LINKSERVERNAME].[AdventureWorks2008].dbo.sp_executesql @sql

profiler跟踪到的语句如下:

如有不对的地方,欢迎拍砖;如有其他方法,求分享,谢谢!

 
 
分类: SQL Server

分页存储过程实现-SqlServer的更多相关文章

  1. 一个通用的分页存储过程实现-SqlServer(附上sql源码,一键执行即刻搭建运行环境)

    使用前提 查询表必须有ID字段,且该字段不能重复,建议为自增主键 背景 如果使用ADO.NET进行开发,在查询分页数据的时候一般都是使用分页存储过程来实现的,本文提供一种通用的分页存储过程,只需要传入 ...

  2. SqlServer分页存储过程(多表查询,多条件排序),Repeater控件呈现数据以及分页

        存储过程(Stored Procedure)是在大型数据库系统中,一组为了完成特定功能的SQL 语句集,存储在数据库中,经过第一次编译后再次调用不需要再次编译,用户通过指定存储过程的名字并给出 ...

  3. 通用sqlserver分页存储过程

    来自:http://www.cnblogs.com/vagerent/archive/2007/10/17/927825.html 单主键: CREATE PROC P_viewPage    /** ...

  4. SQLserver 的分页存储过程

      -- 1.建立修改学生数据的存储过程 -- 2.建立根据班级Id和学生姓名模糊查询的分页存储过程,要求正确输出总记录数,总页数-- (输入班学生姓名 计算总记录数 计算总页数) -- @name ...

  5. MYSQL分页存储过程及事务处理

    最近给客户做的一小系统是SQLSERVER的数据库,因为特殊原因要切换到MYSQL上去,切换数据库确实让人头疼的,SQLSERVER和MYSQL的存储过程还是有很大差别的,下面是我做切换时转换的MYS ...

  6. EF框架 与 Dapper框架 调用分页存储过程

    1. SqlServer创建存储过程: --创建存储过程 create proc sp_Show ( @index int, --当前页 @size int, --每页大小 @totalcount i ...

  7. 完整的分页存储过程以及c#调用方法

    高效分页存储过程 USE [db] GO /****** 对象: StoredProcedure [dbo].[p_Page2005] 脚本日期: // :: ******/ SET ANSI_NUL ...

  8. 1、SQL可搜索可排序可分页存储过程, 2、范围内的随机时间 适用于sql 2008以上

    -- ============================================= -- Author: 蜘蛛王 -- Create date: 2015-10-29 -- Descri ...

  9. SQL Server 2008 通用分页存储过程

    1.alert USE [数据库名称] GO /****** Object: StoredProcedure [dbo].[dbTab_PagerHelper] Script Date: 08/22/ ...

随机推荐

  1. Xcode5和6共处,如何发布应用程序存储

    怎样你和我一样手贱安装了Xcode6,同一时候又须要公布应用到商店时,你会发现打好的包是通只是审核的. 验证报错: unable to validate application archives of ...

  2. unix cd使用命令

    [语法]:     cd   [夹] [说明]:此命令用于工作文件以改变当前的文件夹,使用环境变量没有参数$HOME 作为它的参数,$HOME 路径通常在注册时输入. [抽样]: cd   文件夹 c ...

  3. 利用BBED恢复UPDATE改动前的值

    转载请注明出处:http://blog.csdn.net/guoyjoe/article/details/30615151 实验步骤例如以下: 1.创建表guo_test1 gyj@PROD> ...

  4. BFS、双向BFS和A*

    BFS.双向BFS和A* Table of Contents 1. BFS 2. 双向BFS 3. A*算法 光说不练是无用的.我们从广为人知的POJ 2243这道题谈起:题目大意:给定一个起点和一个 ...

  5. Ambari-部署文档

    Ambari-server搭建过程 部署环境要求 操作系统:centos 5 或 centos 6 能够使用yum jdk版本号 1.7 官网安装教程 https://cwiki.apache.org ...

  6. [dp] hdu 4472 Count

    意甲冠军: 鉴于n节点,满足子节点的相同的树节点号的同一层较少不同的形式. 思考: dp[i][j] 代表i节点.最后,一个层j方法节点 由于满足同层节点,所以j一层又一层必须是j 整数倍 所以就能得 ...

  7. XMLHttpRequest创建对象

    首先,介绍一下XMLHttpRequest对象,我们都知道Ajax这不是一个简单的技术,但一些技术的融合.XMLHttpRequest这是Ajax中最为核心的技术.假设没有XMLHttpRequest ...

  8. EF4.1: Add/Attach and Entity States(EF中的实体状态转换说明)

    实体的状态,连接以及 SaveChanges 方法 数据库上下文对象维护内存中的对象与数据库中数据行之间的同步.这些信息在调用 SaveChanges方法被调用的时候使用.例如,当使用 Add 方法传 ...

  9. sql事务,在sql2000里判断执行是否成功用@@ERROR 判断

    原文:sql事务,在sql2000里判断执行是否成功用@@ERROR 判断 贴个sql事务,在sql2000里判断执行是否成功用@@ERROR 判断 这个东西多少还是有点问题,sql2005了可以用t ...

  10. Android Intent 其中一个分析

    Intent该架构由三个区域组成: Client.正在发送此Intent的activity. Server,那是,activityManagerService.java,它是主要负责这些分布Inten ...