经过优化测试的SQL分页存储过程
SQLserver分页的4种方法示例(很全面)
SQLserver分页的4种⽅法⽰例(很全⾯)这篇博客讲的是SQL server的分页⽅法,⽤的SQL server 2012版本。
下⾯都⽤pageIndex表⽰页数,pageSize表⽰⼀页包含的记录。
并且下⾯涉及到具体例⼦的,设定查询第2页,每页含10条记录。
⾸先说⼀下SQL server的分页与MySQL的分页的不同,mysql的分页直接是⽤limit (pageIndex-1),pageSize就可以完成,但是SQL server 并没有limit关键字,只有类似limit的top关键字。
所以分页起来⽐较⿇烦。
SQL server分页我所知道的就只有四种:三重循环;利⽤max(主键);利⽤row_number关键字,offset/fetch next关键字(是通过搜集⽹上的其他⼈的⽅法总结的,应该⽬前只有这四种⽅法的思路,其他⽅法都是基于此变形的)。
要查询的学⽣表的部分记录⽅法⼀:三重循环思路先取前20页,然后倒序,取倒序后前10条记录,这样就能得到分页所需要的数据,不过顺序反了,之后可以将再倒序回来,也可以不再排序了,直接交给前端排序。
还有⼀种⽅法也算是属于这种类型的,这⾥就不放代码出来了,只讲⼀下思路,就是先查询出前10条记录,然后⽤not in排除了这10条,再查询。
代码实现-- 设置执⾏时间开始,⽤来查看性能的set statistics time on ;-- 分页查询(通⽤型)select *from (select top pageSize *from (select top (pageIndex*pageSize) *from studentorder by sNo asc ) -- 其中⾥⾯这层,必须指定按照升序排序,省略的话,查询出的结果是错误的。
as temp_sum_studentorder by sNo desc ) temp_orderorder by sNo asc-- 分页查询第2页,每页有10条记录select *from (select top 10 *from (select top 20 *from studentorder by sNo asc ) -- 其中⾥⾯这层,必须指定按照升序排序,省略的话,查询出的结果是错误的。
sqlserver存储过程调试方法
sqlserver存储过程调试方法SQL Server是一种常用的关系型数据库管理系统,它提供了存储过程的功能,可以在数据库中存储一段预编译的SQL代码,并在需要时进行调用。
存储过程通常用于执行复杂的数据库操作,提高数据库的性能和安全性。
在开发和调试存储过程时,我们需要一些方法来验证和调试代码的正确性。
本文将介绍一些常用的SQL Server 存储过程调试方法。
1. 使用PRINT语句输出调试信息在存储过程中,可以使用PRINT语句输出一些调试信息,例如变量的值、执行的步骤等。
通过在关键位置添加PRINT语句,可以观察存储过程执行过程中的中间结果,从而验证代码的正确性。
例如:```PRINT '开始执行存储过程'PRINT '变量@x的值为:' + CONVERT(VARCHAR(10), @x)```2. 使用SELECT语句输出结果集在存储过程中,可以使用SELECT语句返回结果集。
通过在存储过程中添加SELECT语句,可以观察查询结果并验证代码的正确性。
例如:```SELECT * FROM 表名 WHERE 条件```3. 使用TRY...CATCH块捕获异常在存储过程中,可以使用TRY...CATCH块来捕获异常并处理错误。
通过在TRY块中执行代码,在CATCH块中处理异常信息,可以更好地调试存储过程并处理潜在的错误。
例如:```BEGIN TRY-- 执行代码END TRYBEGIN CATCH-- 处理异常END CATCH```4. 使用SET NOEXEC语句暂停执行在存储过程中,可以使用SET NOEXEC语句来暂停执行。
通过在存储过程中添加SET NOEXEC语句,并将其设置为ON或OFF,可以控制存储过程的执行。
例如:```SET NOEXEC ON -- 暂停执行SET NOEXEC OFF -- 恢复执行```5. 使用SET SHOWPLAN_ALL语句显示执行计划在存储过程中,可以使用SET SHOWPLAN_ALL语句来显示执行计划。
Sql中Output参数用法和分页存储过程
Sql中Output参数⽤法和分页存储过程USE [CapitalFortune]GO/****** Object: StoredProcedure [dbo].[SetMultiPages] Script Date: 05/30/2012 10:17:02 ******/SET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGO-- =============================================-- Author: hugejile-- alter date: 2070-9-29-- Description: 分页,请勿随意改动-- =============================================ALTER PROCEDURE [dbo].[SetMultiPages]-- Add the parameters for the stored procedure here@TableName NVARCHAR(2000),@ColumnNames NVARCHAR(2000),@Conditions NVARCHAR(2000),@OrderbyString NVARCHAR(2000),@PageSize INT=1000,@CurrentPage INT=1,@RecordCount INT=0 OUTPUT,@PageCount INT=1 OUTPUTASBEGIN-- SET NOCOUNT ON added to prevent extra result sets FROM-- interfering with SELECT statements.SET NOCOUNT ON;DECLARE @Sql NVARCHAR(4000),@RowCount INTSET @RowCount=0IF @ColumnNames is null or LEN(@ColumnNames)=0BEGINSET @ColumnNames='*'ENDIF @CurrentPage is nullBEGINSET @CurrentPage=1ENDIF @PageSize is nullBEGINSET @PageSize=10ENDIF @Conditions is nullBEGINSET @Conditions=''ENDELSEBEGINIF LEN(@Conditions)<>0BEGINSET @Conditions=' WHERE ' + @ConditionsENDEND-- INSERT statements for procedure hereIF @CurrentPage>0BEGINSET @Sql= N'SELECT * FROM (SELECT , (ROW_NUMBER() over (ORDER BY )) AS RowNum FROM )T WHERE T.RowNum Between '+Cast((@CurrentPage-1)*@PageSize+1 AS NVARCHAR(10)) + ' and ' + Cast(@CurrentPage*@PageSize AS NVARCHAR(10)) + ';SET @RowCount =ROWCOUNT_BIG()'PRINT 'SELECT CommandText: ' + @SqlEXECUTE sp_executesql @Sql,N'@RowCount INT OUTPUT',@RowCount OUTPUTSET @Sql = 'SELECT @RecordCount = COUNT(*) FROMPRINT 'Count CommandText: ' + @SqlEXECUTE sp_executesql @Sql,N'@RecordCount INT OUTPUT',@RecordCount OUTPUTSET @PageCount=ceiling(1.0 * @RecordCount / @PageSize)PRINT @RecordCount--RETURN @RecordCountENDELSE IF @PageSize>0BEGINSET @Sql= N'SELECT TOP ' + Cast(@PageSize as nvarchar(10)) + ' ' + @ColumnNames + ', (ROW_NUMBER() over (ORDER BY )) AS RowNum FROM ORDER BY ' + @OrderbyStringPRINT 'SELECT CommandText: ' + @SqlEXEC (@Sql)SET @Sql = 'SELECT @RecordCount = COUNT(*) FROMPRINT 'Count CommandText: ' + @SqlEXECUTE sp_executesql @Sql,N'@RecordCount INT OUTPUT',@RecordCount OUTPUTSET @PageCount = CEILING(CAST(@RecordCount AS FLOAT)/CAST(@PageSize AS FLOAT))--print cast(@RecordCount as nvarchar(10)) + ' pagesize ' + Cast(@PageSize as nvarchar(10))--print @PageCount--RETURN @RowCountENDELSEBEGINSET @Sql= N'SELECT ' + @ColumnNames + ', (ROW_NUMBER() over (ORDER BY )) AS RowNum FROM ORDER BY ' +@OrderbyString +'; SET @RecordCount = ROWCOUNT_BIG()'PRINT 'SELECT CommandText: ' + @Sql--EXEC (@Sql)--SET @Sql = ''--PRINT 'Count CommandText: ' + @SqlEXECUTE sp_executesql @Sql,N'@RecordCount INT OUTPUT',@RecordCount OUTPUTSET @PageCount = -1ENDRETURN 1END这个是分页存储过程,百万级数据应该没有问题调⽤⽅法DECLARE @return_value INT,@RecordCount INT ,@PageCount INT ,@PageSize INTEXEC @return_value = [dbo].[SetMultiPages]@TableName = 'USERS',@ColumnNames = '*',@Conditions = '',@OrderbyString = 'UserId',@PageSize = 10,@CurrentPage = 0,@RecordCount = @RecordCount output,@PageCount = @PageCount outputSELECT @RecordCount AS N'RecordCount',@PageCount AS N'PageCount',@PageSize AS N'PageSize'@RecordCount = @RecordCount output,@PageCount = @PageCount output这两个参数是输出参数,⽤来接受存储过程中的输出参数的值,计算总数据和总页数。
sqlserver 2008 分页方法
sqlserver 2008 分页方法### SQL Server 2008 分页方法在数据库应用开发中,分页技术是一种常用的手段,它可以帮助我们提高数据检索的效率,减少内存消耗,并且提升用户体验。
SQL Server 2008 提供了多种分页方法,下面将详细介绍几种在SQL Server 2008 中实现分页的技术。
#### 1.使用`ROW_NUMBER()``ROW_NUMBER()` 是SQL Server 2008 中最常用的分页方法之一。
它会为结果集中的每一行分配一个唯一的连续整数。
```sql-- 假设要查询的表名为YourTable,排序字段为SomeColumnSELECT *FROM (SELECT *, ROW_NUMBER() OVER (ORDER BY SomeColumn) AS RowNumFROM YourTable) AS PagedTableWHERE RowNum BETWEEN @StartRow AND @EndRow;```在这里,`@StartRow` 和`@EndRow` 是变量,代表你要查询的页码范围。
#### 2.使用`TOP` 和`OFFSET`虽然`TOP` 子句在SQL Server 2005 中已经存在,但`OFFSET` 关键字是在SQL Server 2012 中引入的。
不过,通过某种方式,我们可以在SQL Server 2008 中模拟这种语法。
```sql-- 假设要查询的页码为PageNumber,每页显示的记录数为PageSize SELECT *FROM YourTableORDER BY SomeColumnOFFSET ((@PageNumber - 1) * @PageSize) ROWSFETCH NEXT @PageSize ROWS ONLY;```请注意,这里的`OFFSET` 和`FETCH NEXT` 语法在SQL Server 2008 中不能直接使用,这里只是展示可能的替代方式。
oracle 分页sql写法
一、概述在进行数据库查询时,经常会遇到需要分页展示数据的情况。
而在Oracle数据库中,需要用到分页查询的SQL语句。
本文将就Oracle 中的分页SQL写法进行详细介绍。
二、基本分页SQL语句在Oracle数据库中,可以使用ROWNUM来实现分页查询。
以下是基本的分页SQL语句示例:```sqlSELECT * FROM (SELECT t.*, ROWNUM rnFROM (SELECT * FROM your_table ORDER BY order_column) t WHERE ROWNUM <= pageSize * pageNum)WHERE rn > pageSize * (pageNum - 1)```其中,your_table是要查询的表名,order_column是用来排序的字段,pageSize是每页展示的数据条数,pageNum是要查询的页数。
三、分页SQL写法解析1. 内部查询和外部查询分页SQL语句中,有一个内部查询和一个外部查询。
内部查询用来获取排序后的数据和每行数据对应的行号,外部查询用来根据行号来筛选需要的数据并展示。
2. 内部查询内部查询中使用了ROWNUM来标记行号,并通过ORDER BY语句来对数据进行排序。
内部查询的结果会被外部查询筛选。
3. 外部查询外部查询使用了WHERE语句来筛选出需要展示的数据,并且通过pageSize和pageNum来计算需要查询的数据范围。
四、使用样例假设有一个名为employee的表,包含字段id、name、age,现需要从该表中查询第2页的数据,每页展示10条数据,并按id字段进行排序。
则对应的分页SQL语句为:```sqlSELECT * FROM (SELECT t.*, ROWNUM rnFROM (SELECT id, name, age FROM employee ORDER BY id) t WHERE ROWNUM <= 10 * 2)WHERE rn > 10 * (2 - 1)```这条SQL语句将返回employee表中第11-20条数据,并按id字段排序。
SQLServer存储过程语法及实例
SQLServer存储过程语法及实例Transact-SQL中的存储过程,⾮常类似于Java语⾔中的⽅法,它可以重复调⽤。
当存储过程执⾏⼀次后,可以将语句缓存中,这样下次执⾏的时候直接使⽤缓存中的语句。
这样就可以提⾼存储过程的性能。
Ø 存储过程的概念存储过程Procedure是⼀组为了完成特定功能的SQL语句集合,经编译后存储在数据库中,⽤户通过指定存储过程的名称并给出参数来执⾏。
存储过程中可以包含逻辑控制语句和数据操纵语句,它可以接受参数、输出参数、返回单个或多个结果集以及返回值。
由于存储过程在创建时即在数据库服务器上进⾏了编译并存储在数据库中,所以存储过程运⾏要⽐单个的SQL语句块要快。
同时由于在调⽤时只需⽤提供存储过程名和必要的参数信息,所以在⼀定程度上也可以减少⽹络流量、简单⽹络负担。
1、存储过程的优点A、存储过程允许标准组件式编程存储过程创建后可以在程序中被多次调⽤执⾏,⽽不必重新编写该存储过程的SQL语句。
⽽且数据库专业⼈员可以随时对存储过程进⾏修改,但对应⽤程序源代码却毫⽆影响,从⽽极⼤的提⾼了程序的可移植性。
B、存储过程能够实现较快的执⾏速度如果某⼀操作包含⼤量的T-SQL语句代码,分别被多次执⾏,那么存储过程要⽐批处理的执⾏速度快得多。
因为存储过程是预编译的,在⾸次运⾏⼀个存储过程时,查询优化器对其进⾏分析、优化,并给出最终被存在系统表中的存储计划。
⽽批处理的T-SQL语句每次运⾏都需要预编译和优化,所以速度就要慢⼀些。
C、存储过程减轻⽹络流量对于同⼀个针对数据库对象的操作,如果这⼀操作所涉及到的T-SQL语句被组织成⼀存储过程,那么当在客户机上调⽤该存储过程时,⽹络中传递的只是该调⽤语句,否则将会是多条SQL语句。
从⽽减轻了⽹络流量,降低了⽹络负载。
D、存储过程可被作为⼀种安全机制来充分利⽤系统管理员可以对执⾏的某⼀个存储过程进⾏权限限制,从⽽能够实现对某些数据访问的限制,避免⾮授权⽤户对数据的访问,保证数据的安全。
MySQL动态SQL的拼接以及执行、分页
MySQL 动态SQL 的拼接以及执⾏、分页1:建⽴存储过程,标记参数2:先打印出sql字符串,判断是否是理想值3:⼲掉注释,执⾏sql 语句,看结果CREATE DEFINER =`root`@`localhost` PROCEDURE `pos_get_drugInList`(IN page integer ,IN limitz integer ,IN drugCodez VARCHAR (50),IN effectDatez VARCHAR (50),IN chainIdz VARCHAR (19))BEGINDECLARE start integer ;set start = (page -1)*limitz;set @sql = 'select * from dsos_vot_drugrecord where 1 = 1';#获取药品信息(最多⼀千条)if drugCodez <> '' thenset @sql = CONCAT(@sql ,' and drugCode= ',drugCodez);end if ;if effectDatez <> '' thenset @sql = CONCAT(@sql,' and effectDate= ','''',effectDatez,'''');end if ;if chainIdz <> '' thenset @sql = CONCAT(@sql ,' and chainId= ',chainIdz);end if ;set @sql = CONCAT(@sql ,' limit ',start,', ',limitz);-- PREPARE distSQL FROM @SQL ;-- EXECUTE distSQL;-- DEALLOCATE PREPARE distSQL ;select @sql ;ENDCREATE DEFINER =`root`@`localhost` PROCEDURE `pos_get_drugInList`(IN page integer ,IN limitz integer ,IN drugCodez VARCHAR (50),IN effectDatez VARCHAR (50),IN chainIdz VARCHAR (19))BEGINDECLARE start integer ;set start = (page -1)*limitz;set @sql = 'select * from dsos_vot_drugrecord where 1 = 1';#获取药品信息(最多⼀千条)if drugCodez <> '' thenset @sql = CONCAT(@sql ,' and drugCode= ',drugCodez);end if ;if effectDatez <> '' thenset @sql = CONCAT(@sql,' and effectDate= ','''',effectDatez,'''');end if ;if chainIdz <> '' then4:结果set @sql = CONCAT(@sql ,' and chainId= ',chainIdz); end if ;set @sql = CONCAT(@sql ,' limit ',start,', ',limitz);PREPARE distSQL FROM @SQL ;EXECUTE distSQL;DEALLOCATE PREPARE distSQL ;#select @sql ;END。
MySql实现分页查询的SQL,mysql实现分页查询的sql语句(转)
MySql实现分页查询的SQL,mysql实现分页查询的sql语句
(转)
/sxdtzhaoxinguo/article/details/51481430
摘要:实现分页查询的SQL语句写法!
⼀:分页需求:
客户端通过传递start(页码),limit(每页显⽰的条数)两个参数去分页查询数据库表中的数据,那我们知道MySql数据库提供了分页的函数limit m,n,但是该函数的⽤法和我们的需求不⼀样,所以就需要我们根据实际情况去改写适合我们⾃⼰的分页语句,具体的分析如下:
⽐如:
查询第1条到第10条的数据的sql是:select * from table limit 0,10; ->对应我们的需求就是查询第⼀页的数据:select * from table limit (1-1)*10,10;
查询第10条到第20条的数据的sql是:select * from table limit 10,20; ->对应我们的需求就是查询第⼆页的数据:select * from table limit (2-1)*10,10;
查询第20条到第30条的数据的sql是:select * from table limit 20,30; ->对应我们的需求就是查询第三页的数据:select * from table limit (3-1)*10,10;
⼆:通过上⾯的分析,可以得出符合我们⾃⼰需求的分页sql格式是:select * from table limit (start-1)*limit,limit; 其中start是页码,limit是每页显⽰的条数。
SqlServer存储过程详解
SqlServer存储过程详解SqlServer存储过程详解1.创建存储过程的基本语法模板:if (exists (select*from sys.objects where name ='pro_name'))drop proc pro_namegocreate proc pro_name@param_name param_type [=default_value]asbeginsql语句endps:[]表⽰⾮必写内容。
sys.objects存储的是本数据库中的信息,不仅仅存储表名,还有存储过程名、视图名、触发器等等。
例如:1if (exists (select*from sys.objects where name ='USP_GetAllUser'))2drop proc USP_GetAllUser3go4create proc USP_GetAllUser5@UserId int=16as7set nocount on;8begin9select*from UserInfo where Id=@UserId10endps:SQL Server 实⽤⼯具将 GO 解释为应将当前的 Transact-SQL 批处理语句发送给 SQL Server 的信号。
当前批处理语句是⾃上⼀ GO 命令后输⼊的所有语句,若是第⼀条 GO 命令,则是从特殊会话或脚本的开始处到这条 GO 命令之间的所有语句。
2.调⽤⽅法:exec P_GetAllUser 2;ps:⼀般在执⾏存储过程是,最好加上架构名称,例如 P_GetAllUser 这样可以可以减少不必要的系统开销,提⾼性能。
因为如果在存储过程名称前⾯没有加上架构名称,SQL SERVER ⾸先会从当前数据库sys schema(系统架构)开始查找,如果没有找到,则会去其它schema查找,最后在dbo架构(系统管理员架构)⾥⾯查找。
insertintoselect优化_分享一个经典的mysql存储过程优化过程
insertintoselect优化_分享一个经典的mysql存储过程优化过程在MySQL中,存储过程是一种预编译的数据库对象,可以包含多个SQL语句,并按照一定的逻辑顺序执行。
存储过程可以提高数据库的性能和可维护性,因为它可以减少网络传输的开销,并避免在每个SQL语句中重复编写相同的代码。
在这篇文章中,我将分享一个经典的MySQL存储过程优化过程,以提高查询的性能。
首先,我们需要了解原始的存储过程代码。
假设我们有一个存储过程,用于根据给定的参数插入数据到一个表中。
这个存储过程使用了INSERTINTO语句,并在执行前进行了一些参数检查和数据准备工作。
以下是原始的存储过程代码:DELIMITER//CREATE PROCEDURE insert_into_table(IN param1 INT, IN param2 VARCHAR(255))BEGINDECLARE var1 INT;--参数检查IF param1 <= 0 THENSELECT 'Invalid value for param1';LEAVE;ENDIF;--数据准备SET var1 = param1 * 2;--插入数据INSERT INTO table1(column1, column2) VALUES(var1, param2);END//DELIMITER;以上代码是一个简化的示例,实际情况中可能会更复杂。
接下来,我将介绍一些可以优化这个存储过程的方法。
1.优化INSERTINTO语句:存储过程中的INSERTINTO语句是执行的最重要的部分,可以通过以下方法来优化它:-使用批量插入:如果需要插入大量数据,可以使用批量插入语句(例如INSERTINTO...VALUES(,(,()而不是逐条插入。
这样可以减少网络传输的开销,并提高插入的效率。
-使用事务:将INSERTINTO语句放在一个事务中可以提高性能并确保数据的完整性。
利用SQL语句实现分页
利⽤SQL语句实现分页1.概述在⽹页中如果显⽰的数据太多就会占据过多的页⾯,⽽且显⽰速度也会很慢。
为了控制每次在页⾯上显⽰数据的数量,就可以利⽤分页来显⽰数据。
2.技术要点在SQL Server中要实现SQL分页,需要使⽤⼦查询来获取上⼀页的数据进⾏对⽐,进⽽获取最新的数据。
使⽤⼦查询获取分页数据的语法格式如下:"SELECT TOP [pageSize] * FROM [table] WHERE id NOT IN(SELECT TOP [preNum] id FROM [table] ORDER BY ID DESC) ORDER BY ID DESC";a. pageSize:数据分页的分页⼤⼩。
b. preNum:上⼀页数据查询的起始范围。
c. table:数据表名称。
例如要从数据库的第10条数据开始查询5条数据,编写的 SQL查询语句如下:"SELECT TOP 5 * FROM tb_SQLServerFenye WHERE id NOT IN(SELECT TOP 10 id FROM tb_SQLServerFenye ORDER BY ID DESC) ORDER BY ID DESC";在JDBCDao数据库操作类的getPageArgs()⽅法中就使⽤getProducts()⽅法中就使⽤了该语法获取指定页码的分页数据,关键代码如下:// 定义查询数据库的SQL语句String sql = "SELECT TOP " + pageSize + " * FROM tb_SQLServerFenye" +" WHERE id NOT IN(SELECT TOP " + (page - 1) * pageSize + " id FROM" +" tb_SQLServerFenye ORDER BY ID DESC) ORDER BY ID DESC";stmt = conn.createStatement();rs = stmt.executeQuery(sql); // 执⾏SQL并获取查询结果集3.实现过程(1)创建操作数据库类UserDao。
如何使用MySQL的游标和存储过程处理分页查询
如何使用MySQL的游标和存储过程处理分页查询MySQL是一种十分流行的开源关系型数据库管理系统,它以其性能高、易用性好等特点备受开发者青睐。
在实际应用中,我们经常会遇到需要处理分页查询的需求,而MySQL的游标和存储过程是两个强大的工具,能够帮助我们高效地处理这类问题。
本文将介绍如何使用MySQL的游标和存储过程来处理分页查询的相关内容。
一、什么是游标和存储过程在开始讨论如何使用MySQL的游标和存储过程处理分页查询之前,我们首先要了解游标和存储过程的概念。
游标是用于遍历结果集的一种机制,它允许我们按一定的顺序逐个访问查询结果。
MySQL的游标类型有两种:隐式游标和显式游标。
隐式游标是MySQL内部自动维护的,无需我们手动处理;而显式游标需要我们自己定义、打开、关闭和管理。
存储过程是一段预编译的程序,可以存储在数据库中并在需要时被调用执行,它可以包含一系列的SQL语句、控制流程语句和变量定义等。
存储过程能够提高执行效率、简化应用程序的开发和维护工作。
二、分页查询的基本原理在了解了游标和存储过程的基本概念之后,我们要先明确分页查询的基本原理。
分页查询是一种将查询结果按照固定的页数和每页显示的记录数进行划分的方式,常见的分页查询方式有两种:基于LIMIT和OFFSET的分页和基于游标的分页。
基于LIMIT和OFFSET的分页是一种常见的实现方式,通过在查询语句中使用LIMIT和OFFSET来限制返回结果的行数和起始位置。
通过调整LIMIT和OFFSET的值,可以实现不同页数的查询。
例如,LIMIT 10 OFFSET 0表示查询第1页的结果,LIMIT 10 OFFSET 10表示查询第2页的结果。
基于游标的分页是较为高级和灵活的实现方式,它通过游标来逐个地获取结果集中的记录。
游标可以根据需要进行上下滚动、跳转和过滤等操作,对于大结果集的处理更加高效。
以上是分页查询的基本原理,接下来我们将具体介绍如何使用MySQL的游标和存储过程来处理分页查询。
sql中存储过程的用法
sql中存储过程的用法一、概述存储过程是一种保存在数据库中的程序,可以执行一系列操作,包括数据查询、数据更新、事务控制和多个SQL语句的执行,等等。
存储过程可以简化许多重复的工作,提高数据库的性能,增加数据的安全性和保密性。
二、创建存储过程在SQL Server中,创建存储过程可以使用CREATE PROCEDURE语句。
例如:```CREATE PROCEDURE [dbo].[proc_SelectUsers]ASBEGINSELECT * FROM UsersEND```上述语句创建了一个名为proc_SelectUsers的存储过程,它会查询Users表中所有的数据。
注意,存储过程创建语句的标准格式如下:```CREATE [OR ALTER] PROCEDURE procedure_name [parameter_list][WITH <procedure_option> [,...n]]ASsql_statement [;] [,...n]```参数列表(parameter_list)是可选的,用于指定存储过程所需的参数。
WITH子句是可选的,用于指定存储过程的一些选项,如ENCRYPTION、EXECUTE AS和RECOMPILE等。
sql_statement则是存储过程要执行的一系列SQL语句。
三、执行存储过程在SQL Server中,可以使用EXECUTE语句或者EXEC语句(两者等效)来执行存储过程。
例如:```EXEC proc_SelectUsers```以上语句将会执行名为proc_SelectUsers的存储过程,返回查询结果。
如果存储过程有参数,则执行语句应该像这样:```EXEC proc_SelectUsersByGender @Gender = 'F'```上述语句将会执行名为proc_SelectUsersByGender的存储过程,传递Gender参数值为“F”,返回查询结果。
MySQL中的存储过程调试和优化
MySQL中的存储过程调试和优化MySQL是一种常用的关系型数据库管理系统,广泛应用于各种Web应用程序和企业级系统中。
在开发和维护MySQL数据库中的存储过程时,调试和优化是非常重要的环节。
本文将介绍MySQL中的存储过程调试和优化的方法和技巧。
一、存储过程调试1. 使用调试输出在存储过程中使用调试输出是最常见和简单的调试方法。
通过在存储过程中插入一些输出语句,我们可以观察并了解存储过程在执行过程中的变量值和执行流程。
例如,我们可以使用SELECT语句将一些变量值输出到控制台或日志文件中,以便进行调试。
2. 使用条件断点条件断点是一种高级调试技术,可以在满足指定条件的情况下自动中断程序的执行。
在MySQL中,我们可以通过设置存储过程中的IF语句来实现条件断点。
例如,我们可以在存储过程的关键位置插入一个IF语句,并设置一个变量的值作为断点条件,当满足条件时,存储过程会中断执行,以便我们观察程序的执行情况。
3. 使用调试工具除了手动调试之外,还可以使用一些专门的调试工具来帮助我们调试存储过程。
例如,MySQL提供了一个官方的调试器工具,可以与MySQL服务器进行交互,并提供了调试器的各种功能,如设置断点、单步执行、查看变量值等。
使用调试器工具可以大大提高我们的调试效率和准确性。
二、存储过程优化1. 减少查询次数在存储过程中,如果存在多个查询语句,那么通过减少查询次数可以降低数据库的负载和提高性能。
例如,我们可以通过使用JOIN语句将多个查询合并为一个查询,或者使用子查询来减少多次查询的次数。
另外,还可以使用缓存技术,将查询结果缓存起来,避免重复查询。
2. 使用索引索引是提高数据库查询性能的重要手段。
在存储过程中,我们可以通过使用索引来加快查询速度。
在MySQL中,可以通过在存储过程中的查询语句中使用关键词"INDEX"或"FORCE INDEX"来强制使用索引。
sqlserver+支持多表联合查询分页存储过程
sqlserver+支持多表联合查询分页存储过程CREATE PROCEDURE usp_PagingLarge@TableNames VARCHAR(300), --表名,可以是多个表,但不能用别名@PrimaryKey VARCHAR(100), --主键,可以为空,但@Order 为空时该值不能为空@Fields VARCHAR(350), --要取出的字段,可以是多个表的字段,可以为空,为空表示select *@PageSize INT, --每页记录数@CurrentPage INT, --当前页,0表示第1页@Filter VARCHAR(200) = '', --条件,可以为空,不用填 where @Group VARCHAR(200) = '', --分组依据,可以为空,不用填group by@Order VARCHAR(200) = '', --排序,可以为空,为空默认按主键升序排列,不用填 order by@RecordCount int = 0 outputASBEGINDECLARE @SortColumn VARCHAR(200)DECLARE @Operator CHAR(2)DECLARE @SortTable VARCHAR(200)DECLARE @SortName VARCHAR(200)DECLARE @TmpSelect NVarchar(200)IF @Fields = ''SET @Fields = '*'IF @Filter = ''SET @Filter = 'WHERE 1=1'ELSESET @Filter = 'WHERE ' + @FilterSET @Group = 'GROUP BY ' + @GroupIF @Order <> ''BEGINDECLARE @pos1 INT, @pos2 INTSET @Order = REPLACE(REPLACE(@Order, ' asc', ' ASC'), ' desc', ' DESC')IF CHARINDEX(' DESC', @Order) > 0IF CHARINDEX(' ASC', @Order) > 0BEGINIF CHARINDEX(' DESC', @Order) < CHARINDEX(' ASC', @Order)SET @Operator = '<='ELSESET @Operator = '>='ENDELSESET @Operator = '<='ELSESET @Operator = '>='SET @SortColumn = REPLACE(REPLACE(REPLACE(@Order, ' ASC', ''), ' DESC', ''), ' ', '')SET @pos1 = CHARINDEX(',', @SortColumn)IF @pos1 > 0SET @SortColumn = SUBSTRING(@SortColumn, 1, @pos1-1) SET @pos2 = CHARINDEX('.', @SortColumn)IF @pos2 > 0BEGINSET @SortTable = SUBSTRING(@SortColumn, 1, @pos2-1)SET @SortName = SUBSTRING(@SortColumn, @pos2+1, @pos1-@pos2-1)ELSESET @SortName = SUBSTRING(@SortColumn, @pos2+1, LEN(@SortColumn)-@pos2)ENDELSEBEGINSET @SortTable = @TableNamesSET @SortName = @SortColumnENDENDELSEBEGINSET @SortColumn = @PrimaryKeySET @SortTable = @TableNamesSET @SortName = @SortColumnSET @Order = @SortColumnSET @Operator = '>='ENDDECLARE @type varchar(50)DECLARE @prec intSELECT@type=/doc/e313809023.html,,@prec=c.precFROM sysobjects oJOIN syscolumns c on o.id=c.idJOIN systypes t on c.xusertype=t.xusertypeWHERE /doc/e313809023.html, = @SortTable AND /doc/e313809023.html, = @SortNameIF CHARINDEX('char', @type) > 0SET @type = @type + '(' + CAST(@prec AS varchar) +')'DECLARE @T opRows INTSET @TopRows = @PageSize * @CurrentPage + 1print @TopRowsprint @OperatorEXEC('DECLARE @SortColumnBegin ' + @type + 'SET ROWCOUNT ' + @T opRows + 'SELECT @SortColumnBegin=' + @SortColumn + ' FROM ' + @TableNames + ' ' + @Filter + ' ' + @Group + ' ORDER BY ' + @Order + 'SET ROWCOUNT ' + @PageSize + 'SELECT ' + @Fields + ' FROM ' + @TableNames + ' ' + @Filter + ' AND ' + @SortColumn + '' + @Operator + '@SortColumnBegin ' + @Group + ' ORDER BY ' + @Order + ' ')DECLARE @str_Count_SQL nvarchar(500)SET @str_Count_SQL= 'SELECT @TotalCount=count('+@PrimaryKey+') FROM ' + @TableNames + ' ' + @FilterEXEC sp_executesql @str_Count_SQL,N'@TotalCount int=0 output',@RecordCount outputEndGO150********。
sql存储过程几个简单例子
sql存储过程⼏个简单例⼦导读:sql存储是数据库操作过程中⽐较重要的⼀个环节,对于⼀些初学者来说也是⽐较抽象难理解的,本⽂我将通过⼏个实例来解析数据库中的sql存储过程,这样就将抽象的事物形象化,⽐较容易理解。
例1:create proc proc_stu@sname varchar(20),@pwd varchar(20)asselect * from ren where sname=@sname and pwd=@pwdgo查看结果:proc_stu 'admin','admin'例2:下⾯的存储过程实现⽤户验证的功能,如果不成功,返回0,成功则返回1.CREATE PROCEDURE VALIDATE @USERNAME CHAR(20),@PASSWORD CHAR(20),@LEGAL BIT OUTPUTASIF EXISTS(SELECT * FROM REN WHERE SNAME = @USERNAME AND PWD = @PASSWORD)SELECT @LEGAL = 1ELSESELECT @LEGAL = 0在程序中调⽤该存储过程,并根据@LEGAL参数的值判断⽤户是否合法。
例3:⼀个⾼效的数据分页的存储过程可以轻松应付百万数据CREATE PROCEDURE pageTest --⽤于翻页的测试--需要把排序字段放在第⼀列(@FirstID nvarchar(20)=null, --当前页⾯⾥的第⼀条记录的排序字段的值@LastID nvarchar(20)=null, --当前页⾯⾥的最后⼀条记录的排序字段的值@isNext bit=null, --true1 :下⼀页;false0:上⼀页@allCount int output, --返回总记录数@pageSize int output, --返回⼀页的记录数@CurPage int --页号(第⼏页)0:第⼀页;-1最后⼀页。
SQL数据库怎么进行优化_SQL数据库有什么优化方式
SQL数据库怎么进行优化_SQL数据库有什么优化方式优化SQLServer数据库的一些经验和注意事项,详细介绍了SQL 语句优化的基本原则,包括索引、查询和游标的使用等。
下面由店铺为大家整理的SQL数据库优化方式,希望大家喜欢!SQL数据库优化的方式1. 利用表分区分区将数据在物理上分隔开,不同分区的数据可以制定保存在处于不同磁盘上的数据文件里。
这样,当对这个表进行查询时,只需要在表分区中进行扫描,而不必进行全表扫描,明显缩短了查询时间,另外处于不同磁盘的分区也将对这个表的数据传输分散在不同的磁盘I/O,一个精心设置的分区可以将数据传输对磁盘I/O竞争均匀地分散开。
对数据量大的时时表可采取此方法。
可按月自动建表分区。
2. 别名的使用别名是大型数据库的应用技巧,就是表名、列名在查询中以一个字母为别名,查询速度要比建连接表快1.5倍。
3. 索引Index的优化设计索引可以大大加快数据库的查询速度。
但是并不是所有的表都需要建立索引,只针对大数据量的表建立索引就好。
缺点:1.创建索引和维护索引要耗费时间,这种时间随着数据量的增加而增加。
2.索引需要占物理空间,除了数据表占数据空间之外,每一个索引还要占一定的物理空间,如果要建立聚簇索引,那么需要的空间就会更大。
3.当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,这样就降低了数据的维护速度。
索引需要维护:为了维护系统性能,索引在创建之后,由于频繁地对数据进行增加、删除、修改等操作使得索引页发生碎块,因此,必须对索引进行维护。
4. 物化视图(索引视图)一般的视图是虚拟的,而物化视图是实实在在的数据区域,是要占据存储空间的,另外系统刷新物化视图也需要耗费一定的资源,但是它却换来了效率和灵活性。
索引视图更适合在OLAP(读取较多,更新较少)的数据库中使用,不适合在OLTP(记录即时的增、删、改、查)的数据库中使用。
物化视图的注意事项:1.对于复杂而高消耗的查询,如果使用频繁,应建成物化视图。
利用SQL Server存储过程实现数据分页
一 临 时变 量 一 排 序 类 型
一 表 名
性 能要求程序必须 设计合理 ,尤 其是查 询数据并将 结果送 显
的 环 节 。 针 对 这 一 问题 ,讨 论 了 利 用 S LSre 数 据 库 的 存 Q evr
d cae@tl mev rh r(5 ) el r bNa ac a 2 5
p prw i usdtem tost i l n p g g yui es rdpoeue f Q e e aaae ae, e s se e d e t ai s gt t e rcd r o LSr r t s. dc h h o mp me n b n h o S v d b
YANG n , ANG e f i W ANG i Fa W F i , e Be
( hn rnn e n uta Sad ri t nR sac stt B in 0 0 9 C iaO d ac d sil t adz i eerhI tue, e ig10 8 ) I r n ao ni j
K e o ds t r d Pr c d e;P g n ;C# ;W if r y w r :S o e o e ur a ig n o m
随着 信 息 化 建设 的 快 速 发展 ,利 用 c .E #N T技 术 开 发
Wiom程序越来越广泛 ,大容量的数据库记录的访 问和显 示 nr f
d cae@sr S ln ac a 4 0 ) e lr tRs q v rh r(0 0
一
1 优 势
随 着 数 据 库 中 存 储 的 数 据 的 增 多 ,满 足 用 户 查 询 条 件 的 数 据 也 随之 增 加 。而 用 户 一 般 不 可 能 一 次 性 看 完 所有 的 数 据 , 很 多 时 候 也 不 需 要 看 完 所 有 数 据 。 因 此 ,在 这 种 情 况 下 ,分 页 返 回 用 户 查 询 的数 据 就 显 得 相 当 重 要 。分 页 返 回用 户 数 据
sql存储过程简单教程
sql存储过程简单教程①为什么要使⽤存储过程?因为它⽐SQL语句执⾏快.②存储过程是什么?把⼀堆SQL语句罗在⼀起,还可以根据条件执⾏不通SQL语句.(AX写作本⽂时观点)③来⼀个最简单的存储过程CREATE PROCEDURE dbo.testProcedure_AXASselect userID from USERS order by userid desc注:dbo.testProcedure_AX是你创建的存储过程名,可以改为:AXzhz等,别跟关键字冲突就⾏了.AS下⾯就是⼀条SQL语句,不会写SQL语句的请回避.④我怎么在中调⽤这个存储过程?下⾯黄底的这两⾏就够使了.public static string GetCustomerCName(ref ArrayList arrayCName,ref ArrayList arrayID){SqlConnection con=ADConnection.createConnection();SqlCommand cmd=new SqlCommand("testProcedure_AX",con);mandType=CommandType.StoredProcedure;con.Open();try{SqlDataReader dr=cmd.ExecuteReader();while(dr.Read()){if(dr[0].ToString()==""){arrayCName.Add(dr[1].ToString());}}con.Close();return "OK!";}catch(Exception ex){con.Close();return ex.ToString();}}注:其实就是把以前SqlCommand cmd=new SqlCommand("select userID from USERS order by userid desc",con);中的SQL语句替换为存储过程名,再把cmd的类型标注为CommandType.StoredProcedure(存储过程)⑤写个带参数的存储过程吧,上⾯这个简单得有点惨不忍睹,不过还是蛮实⽤的.参数带就带两,⼀个的没⾯⼦,太⼩家⼦⽓了.CREATE PROCEDURE dbo.AXzhz/*这⾥写注释*/@startDate varchar(16),@endDate varchar(16)ASselect id from table_AX where commentDateTime>@startDate and commentDateTime<@endDate order by contentownerid DESC注:@startDate varchar(16)是声明@startDate 这个变量,多个变量名间⽤【,】隔开.后⾯的SQL就可以使⽤这个变量了.⑥我怎么在中调⽤这个带参数的存储过程?public static string GetCustomerCNameCount(string startDate,string endDate,ref DataSet ds){SqlConnection con=ADConnection.createConnection();//-----------------------注意这⼀段--------------------------------------------------------------------------------------------------------SqlDataAdapter da=new SqlDataAdapter("AXzhz",con);para0=new SqlParameter("@startDate",startDate);para1=new SqlParameter("@endDate",endDate);da.SelectCommand.Parameters.Add(para0);da.SelectCommand.Parameters.Add(para1);mandType=CommandType.StoredProcedure;//-------------------------------------------------------------------------------------------------------------------------------try{con.Open();da.Fill(ds);con.Close();return "OK";}catch(Exception ex){return ex.ToString();}}注:把命令的参数添加进去,就OK了⑦我还想看看SQL命令执⾏成功了没有.注意看下⾯三⾏红⾊的语句CREATE PROCEDURE dbo.AXzhz/*@parameter1 ⽤户名@parameter2 新密码*/@passWord nvarchar(20),@userName nvarchar(20)ASdeclare @err0 intupdate WL_user set password=@password where UserName=@userNameset @err0=@@errorselect @err0 as err0注:先声明⼀个整型变量@err0,再给其赋值为@@error(这个是系统⾃动给出的语句是否执⾏成功,0为成功,其它为失败),最后通过select把它选择出来,某位⾼⼈说可以通过Return返回,超出本⼈的认知范围,俺暂时不会,以后再补充吧⑧那怎么从后台获得这个执⾏成功与否的值呢?下⾯这段代码可以告诉你答案:public static string GetCustomerCName(){SqlConnection con=ADConnection.createConnection();SqlCommand cmd=new SqlCommand("AXzhz",con);mandType=CommandType.StoredProcedure;para0=new SqlParameter("@startDate","2006-9-10");para1=new SqlParameter("@endDate","2006-9-20");da.SelectCommand.Parameters.Add(para0);da.SelectCommand.Parameters.Add(para1);con.Open();try{Int32 re=(int32)cmd.ExecuteScalar();con.Close();if (re==0)return "OK!";elsereturn "false";}catch(Exception ex){con.Close();return ex.ToString();}}注:就是通过SqlCommand的ExecuteScalar()⽅法取回这个值,这句话是从MSDN上找的,俺认为改成:int re=(int)cmd.ExecuteScalar(); 99%正确,现在没时间验证,期待您的测试1)执⾏⼀个没有参数的存储过程的代码如下:SqlConnection conn=new SqlConnection(“connectionString”);SqlDataAdapter da = new SqlDataAdapter();da.selectCommand = new SqlCommand();da.selectCommand.Connection = conn;mandText = "NameOfProcedure";mandType = CommandType.StoredProcedure;(2)执⾏⼀个有参数的存储过程的代码如下SqlConnection conn=new SqlConnection(“connectionString”);SqlDataAdapter da = new SqlDataAdapter();da.selectCommand = new SqlCommand();da.selectCommand.Connection = conn;mandText = "NameOfProcedure";mandType = CommandType.StoredProcedure;param = new SqlParameter("@ParameterName", SqlDbType.DateTime);param.Direction = ParameterDirection.Input;param.Value = Convert.ToDateTime(inputdate);da.selectCommand.Parameters.Add(param);若需要添加输出参数:param = new SqlParameter("@ParameterName", SqlDbType.DateTime);param.Direction = ParameterDirection.Output;param.Value = Convert.ToDateTime(inputdate);da.selectCommand.Parameters.Add(param);若要获得参储过程的返回值:param = new SqlParameter("@ParameterName", SqlDbType.DateTime);param.Direction = ParameterDirection.ReturnValue;param.Value = Convert.ToDateTime(inputdate);da.selectCommand.Parameters.Add(param);两种不同的存储过程调⽤⽅法为了突出新⽅法的优点,⾸先介绍⼀下在.NET中调⽤存储过程的“官⽅”⽅法。
sql存储过程的使用方法
sql存储过程的使用方法一、什么是SQL存储过程SQL存储过程是一段预编译的SQL语句,它可以被保存在数据库中,并且可以被多次调用。
通过使用存储过程,用户可以将复杂的业务逻辑封装起来,提高数据库的性能和安全性。
二、创建SQL存储过程1. 创建存储过程需要使用CREATE PROCEDURE语句。
例如:CREATE PROCEDURE proc_nameASBEGIN-- 存储过程的代码END2. 存储过程名称应该简短而具有描述性,并且应该遵循数据库命名约定。
3. 在BEGIN和END之间编写存储过程代码。
这些代码可以包括SELECT、INSERT、UPDATE、DELETE等SQL语句以及控制流语句(如IF、WHILE)等。
4. 存储过程还可以接收参数。
例如:CREATE PROCEDURE proc_name @param1 INT, @param2 VARCHAR(50)ASBEGIN-- 存储过程的代码END5. 参数可以是输入参数(IN)、输出参数(OUT)或输入输出参数(INOUT)。
例如:CREATE PROCEDURE proc_name @param1 INT, @param2 VARCHAR(50) OUTPUT, @param3 INT OUTPUTASBEGIN-- 存储过程的代码END6. 存储过程还可以返回值。
例如:CREATE PROCEDURE proc_name @param1 INT, @param2 VARCHAR(50)ASBEGIN-- 存储过程的代码RETURN 0 -- 返回值为0END三、调用SQL存储过程1. 调用存储过程需要使用EXECUTE或EXEC语句。
例如:EXECUTE proc_name @param1=1, @param2='abc'2. 如果存储过程有输出参数,则需要使用SET语句将输出参数的值赋给变量。
例如:DECLARE @output_param VARCHAR(50)EXECUTE proc_name @param1=1, @param2='abc',@param3=@output_param OUTPUTPRINT @output_param3. 如果存储过程有返回值,则可以使用SELECT语句获取返回值。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
经过优化测试的SQL分页存储过程2009-10-24 23:20建立一个 Web 应用,分页浏览功能必不可少。
这个问题是数据库处理中十分常见的问题。
经典的数据分页方法是:ADO 纪录集分页法,也就是利用ADO自带的分页功能(利用游标)来实现分页。
但这种分页方法仅适用于较小数据量的情形,因为游标本身有缺点:游标是存放在内存中,很费内存。
游标一建立,就将相关的记录锁住,直到取消游标。
游标提供了对特定集合中逐行扫描的手段,一般使用游标来逐行遍历数据,根据取出数据条件的不同进行不同的操作。
而对于多表和大表中定义的游标(大的数据集合)循环很容易使程序进入一个漫长的等待甚至死机。
更重要的是,对于非常大的数据模型而言,分页检索时,如果按照传统的每次都加载整个数据源的方法是非常浪费资源的。
现在流行的分页方法一般是检索页面大小的块区的数据,而非检索所有的数据,然后单步执行当前行。
最早较好地实现这种根据页面大小和页码来提取数据的方法大概就是“俄罗斯存储过程”。
这个存储过程用了游标,由于游标的局限性,所以这个方法并没有得到大家的普遍认可。
后来,网上有人改造了此存储过程,下面的存储过程就是结合我们的办公自动化实例写的分页存储过程:CREATE procedure pagination1(@pagesize int, --页面大小,如每页存储20条记录@pageindex int --当前页码)asset nocount onbegindeclare @indextable table(id int identity(1,1),nid int) --定义表变量declare @PageLowerBound int --定义此页的底码declare @PageUpperBound int --定义此页的顶码set @PageLowerBound=(@pageindex-1)*@pagesizeset @PageUpperBound=@PageLowerBound+@pagesizeset rowcount @PageUpperBoundinsert into @indextable(nid) select gid from TGongwenwhere fariqi >dateadd(day,-365,getdate()) order by fariqi descselect O.gid,O.mid,O.title,O.fadanwei,O.fariqi from TGongwenO,@indextable twhere O.gid=t.nid and t.id>@PageLowerBoundand t.id<=@PageUpperBound order by t.id endset nocount off以上存储过程运用了SQL SERVER的最新技术――表变量。
应该说这个存储过程也是一个非常优秀的分页存储过程。
当然,在这个过程中,您也可以把其中的表变量写成临时表:CREATE TABLE #Temp。
但很明显,在SQL SERVER中,用临时表是没有用表变量快的。
所以笔者刚开始使用这个存储过程时,感觉非常的不错,速度也比原来的ADO的好。
但后来,我又发现了比此方法更好的方法。
笔者曾在网上看到了一篇小短文《从数据表中取出第n条到第m条的记录的方法》,全文如下:从publish 表中取出第 n 条到第 m 条的记录:SELECT TOP m-n+1 *FROM publishWHERE (id NOT IN(SELECT TOP n-1 idFROM publish))id 为publish 表的关键字我当时看到这篇文章的时候,真的是精神为之一振,觉得思路非常得好。
等到后来,我在作办公自动化系统(+ C#+SQL SERVER)的时候,忽然想起了这篇文章,我想如果把这个语句改造一下,这就可能是一个非常好的分页存储过程。
于是我就满网上找这篇文章,没想到,文章还没找到,却找到了一篇根据此语句写的一个分页存储过程,这个存储过程也是目前较为流行的一种分页存储过程,我很后悔没有争先把这段文字改造成存储过程:CREATE PROCEDURE pagination2(@SQL nVARCHAR(4000), --不带排序语句的SQL语句@Page int, --页码@RecsPerPage int, --每页容纳的记录数@ID VARCHAR(255), --需要排序的不重复的ID号@Sort VARCHAR(255) --排序字段及规则)ASDECLARE @Str nVARCHAR(4000)SET @Str=''SELECT TOP ''+CAST(@RecsPerPage AS VARCHAR(20))+'' * FROM (''+@SQL+'') T WHERE T.''+@ID+''NOT IN (SELECT TOP''+CAST((@RecsPerPage*(@Page-1))AS VARCHAR(20))+'' ''+@ID+'' FROM (''+@SQL+'') T9 ORDER BY ''+@Sort+'') ORDER BY ''+@SortPRINT @StrEXEC sp_ExecuteSql @StrGO其实,以上语句可以简化为:SELECT TOP 页大小 *FROM Table1 WHERE (ID NOT IN (SELECT TOP 页大小*页数 id FROM 表 ORDER BY id))ORDER BY ID但这个存储过程有一个致命的缺点,就是它含有NOT IN字样。
虽然我可以把它改造为:SELECT TOP 页大小 *FROM Table1 WHERE not exists(select * from (select top (页大小*页数) * from table1 order by id) b where b.id=a.id )order by id即,用not exists来代替not in,但我们前面已经谈过了,二者的执行效率实际上是没有区别的。
既便如此,用TOP 结合NOT IN的这个方法还是比用游标要来得快一些。
虽然用not exists并不能挽救上个存储过程的效率,但使用SQL SERVER中的TOP关键字却是一个非常明智的选择。
因为分页优化的最终目的就是避免产生过大的记录集,而我们在前面也已经提到了TOP的优势,通过TOP 即可实现对数据量的控制。
在分页算法中,影响我们查询速度的关键因素有两点:TOP和NOT IN。
TOP 可以提高我们的查询速度,而NOT IN会减慢我们的查询速度,所以要提高我们整个分页算法的速度,就要彻底改造NOT IN,同其他方法来替代它。
我们知道,几乎任何字段,我们都可以通过max(字段)或min(字段)来提取某个字段中的最大或最小值,所以如果这个字段不重复,那么就可以利用这些不重复的字段的max或min作为分水岭,使其成为分页算法中分开每页的参照物。
在这里,我们可以用操作符“>”或“<”号来完成这个使命,使查询语句符合SARG形式。
如:Select top 10 * from table1 where id>200于是就有了如下分页方案:select top 页大小 *from table1where id>(select max (id) from(select top ((页码-1)*页大小) id from table1 order by id) as Torder by id在选择即不重复值,又容易分辨大小的列时,我们通常会选择主键。
下表列出了笔者用有着1000万数据的办公自动化系统中的表,在以GID(GID是主键,但并不是聚集索引。
)为排序列、提取gid,fariqi,title字段,分别以第1、10、100、500、1000、1万、10万、25万、50万页为例,测试以上三种分页方案的执行速度:(单位:毫秒)从上表中,我们可以看出,三种存储过程在执行100页以下的分页命令时,都是可以信任的,速度都很好。
但第一种方案在执行分页1000页以上后,速度就降了下来。
第二种方案大约是在执行分页1万页以上后速度开始降了下来。
而第三种方案却始终没有大的降势,后劲仍然很足。
在确定了第三种分页方案后,我们可以据此写一个存储过程。
大家知道SQL SERVER的存储过程是事先编译好的SQL语句,它的执行效率要比通过WEB页面传来的SQL语句的执行效率要高。
下面的存储过程不仅含有分页方案,还会根据页面传来的参数来确定是否进行数据总数统计。
--获取指定页的数据:CREATE PROCEDURE pagination3@tblName varchar(255), -- 表名@strGetFields varchar(1000) = ''*'', -- 需要返回的列@fldName varchar(255)='''', -- 排序的字段名@PageSize int = 10, -- 页尺寸@PageIndex int = 1, -- 页码@doCount bit = 0, -- 返回记录总数, 非 0 值则返回@OrderType bit = 0, -- 设置排序类型, 非 0 值则降序@strWhere varchar(1500) = '''' -- 查询条件 (注意: 不要加 where)ASdeclare @strSQL varchar(5000) -- 主语句declare @strTmp varchar(110) -- 临时变量declare @strOrder varchar(400) -- 排序类型if @doCount != 0beginif @strWhere !=''''set @strSQL = "select count(*) as Total from [" + @tblName + "] where "+@strWhereelseset @strSQL = "select count(*) as Total from [" + @tblName + "]"end--以上代码的意思是如果@doCount传递过来的不是0,就执行总数统计。