C#拼接SQL语句 用ROW_NUMBER实现的高效分页排序_C#教程

如果项目中要用到数据库,铁定要用到分页排序。之前在做数据库查询优化的时候,通宵写了以下代码,来拼接分页排序的SQL语句

复制代码 代码如下:

/// <summary>
/// 单表(视图)获取分页SQL语句
/// </summary>
/// <param name="tableName">表名或视图名</param>
/// <param name="key">唯一键</param>
/// <param name="fields">获取的字段</param>
/// <param name="condition">查询条件(不包含WHERE)</param>
/// <param name="collatingSequence">排序规则(不包含ORDER BY)</param>
/// <param name="pageSize">页大小</param>
/// <param name="pageIndex">页码(从1开始)</param>
/// <returns>分页SQL语句</returns>
public static string GetPagingSQL(
string tableName,
string key,
string fields,
string condition,
string collatingSequence,
int pageSize,
int pageIndex)
{
string whereClause = string.Empty;
if (!string.IsNullOrEmpty(condition))
{
whereClause = string.Format("WHERE {0}", condition);
}

if (string.IsNullOrEmpty(collatingSequence))
{
collatingSequence = string.Format("{0} ASC", key);
}

StringBuilder sbSql = new StringBuilder();

sbSql.AppendFormat("SELECT {0} ", PrependTableName(tableName, fields, ','));
sbSql.AppendFormat("FROM ( SELECT TOP {0} ", pageSize * pageIndex);
sbSql.AppendFormat(" [_RowNum_] = ROW_NUMBER() OVER ( ORDER BY {0} ), ", collatingSequence);
sbSql.AppendFormat(" {0} ", key);
sbSql.AppendFormat(" FROM {0} ", tableName);
sbSql.AppendFormat(" {0} ", whereClause);
sbSql.AppendFormat(" ) AS [_TempTable_] ");
sbSql.AppendFormat(" INNER JOIN {0} ON [_TempTable_].{1} = {0}.{1} ", tableName, key);
sbSql.AppendFormat("WHERE [_RowNum_] > {0} ", pageSize * (pageIndex - 1));
sbSql.AppendFormat("ORDER BY [_TempTable_].[_RowNum_] ASC ");

return sbSql.ToString();
}

/// <summary>
/// 给字段添加表名前缀
/// </summary>
/// <param name="tableName">表名</param>
/// <param name="fields">字段</param>
/// <param name="separator">标识字段间的分隔符</param>
/// <returns></returns>
public static string PrependTableName(string tableName, string fields, char separator)
{
StringBuilder sbFields = new StringBuilder();

string[] fieldArr = fields.Trim(separator).Split(separator);
foreach (string str in fieldArr)
{
sbFields.AppendFormat("{0}.{1}{2}", tableName, str.Trim(), separator);
}

return sbFields.ToString().TrimEnd(separator);
}

假设有如下产品表:

复制代码 代码如下:

CREATE TABLE [dbo].[Tbl_Product]
(
[ID] [int] IDENTITY(1, 1)
NOT NULL ,
[ProductId] [varchar](50) NOT NULL ,
[ProductName] [nvarchar](50) NOT NULL ,
[IsDeleted] [int] NOT NULL
CONSTRAINT [DF_Tbl_Product_IsDeleted] DEFAULT ( (0) ) ,
CONSTRAINT [PK_Tbl_Product] PRIMARY KEY CLUSTERED ( [ProductId] ASC )
WITH ( PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON ) ON [PRIMARY]
)
ON [PRIMARY]

Tbl_Product->ID(序号,非空,自增)
Tbl_Product->ProductId(产品Id,主键)
Tbl_Product->ProductName(产品名称,非空)
Tbl_Product->IsDeleted(虚拟删除标记,非空)
调用BasicFunction.GetPagingSQL("Tbl_Product", "ID", "ID,ProductId,ProductName", "IsDeleted=0", "ProductName ASC, ID DESC", 5, 5),BasicFunction为分页排序方法所在的静态类,生成的分页排序SQL语句如下(已手动调整了格式):

复制代码 代码如下:

SELECT Tbl_Product.ID ,
Tbl_Product.ProductId ,
Tbl_Product.ProductName
FROM ( SELECT TOP 25
[_RowNum_] = ROW_NUMBER() OVER ( ORDER BY ProductName ASC, ID DESC ) ,
ID
FROM Tbl_Product
WHERE IsDeleted = 0
) AS [_TempTable_]
INNER JOIN Tbl_Product ON [_TempTable_].ID = Tbl_Product.ID
WHERE [_RowNum_] > 20
ORDER BY [_TempTable_].[_RowNum_] ASC

查询的字段列表,去掉了不关心的字段(这里为IsDeleted,因为条件里面IsDeleted=0,查出来的产品都是没被删除的);
排序依据,在调用该方法时,应尽量确保排序的依据可以唯一确定记录在结果集中的位置(这里添加了辅助排序依据,ID DESC,如果产品重名,添加的晚的排在前面);
性能优化的一点儿建议:如果字段的值是计算出来的,如:总价=单价*数量,而此时需要总价大于多少的记录,还得拿总价递增或者递减排序,如果不要临时表,数据量大的时候,就等着买新电脑吧!你问我为什么要买新电脑,哦,因为你会把现在的电脑砸掉!O(∩_∩)O~
另外一点儿建议,使用ROW_NUMBER时,切记一定要和“TOP n”一起使用,n等于int.MaxValue都比不加“TOP n”时要快。
最后,拜托哪位好心人士给测试下性能,拜托了,本人数据库菜鸟,不太懂得数据库的性能测试。

我只知道我对我写的分页排序还是很有信心的,(*^__^*) 嘻嘻!

首发:博客园->剑过不留痕

时间: 2024-09-22 11:49:53

C#拼接SQL语句 用ROW_NUMBER实现的高效分页排序_C#教程的相关文章

row num-关于设置参数值和直接拼接SQL语句问题

问题描述 关于设置参数值和直接拼接SQL语句问题 DECLARE @SysBranchSysNo int,@C1SysNo int,@RepeatNum INT SET @SysBranchSysNo=1; SET @C1SysNo=1073; SET @RepeatNum=1 SELECT * FROM (SELECT ROW_NUMBER() OVER(ORDER BY Quantity desc ) AS DATA_ROW_NUM, * FROM ( SELECT * FROM (SELE

mssql-存储过程不让拼接SQL语句

问题描述 存储过程不让拼接SQL语句 公司DBA不允许创建的存储过程中有拼接SQL语句的行为,请问,该怎么解决?说是这样做有风险,说我非要用的话,可以签一份风险协议,出了问题我负责之类的.请问:各位在多条件查询这种情况下,存储过程都是怎么写的?有不拼接又省事的办法吗?另外,这个风险难道微软没有提供解决方案吗? 解决方案 真正的风险, 不在于拼SQL, 而是输入值没有参数化. 比如: delare @sql nvarchar(max), @name nvarchar(20) set @name='

多条件查询拼接sql语句如何防止sql注入

问题描述 假如有四个条件可以任意输入1到4个条件取交集求解 解决方案 解决方案二:引用楼主abc12346579的回复: 假如有四个条件可以任意输入1到4个条件取交集求解 你的"任意输入条件"是什么意思?如果说随便输入sql,那么这其实根本不需要注入,你都随便让人家写代码了,还要想什么"注入"方式干什么?直接干就行了.解决方案三:你要是让人家输入sql,那就相当于超市敞开大门让顾客把东西搬回家,再来讨论"如何防止盗窃"就没有意义了.解决方案四:在

存储过程中拼接SQL语句

很多时候我们需要利用参数在存储过程中重新组织SQL语句,在存储过程中拼接的SQL语句只是一个字符串,不会被直接执行,所以加一个execute执行它就可以了.具体看如下演示代码: 代码: set ANSI_NULLS ON set QUOTED_IDENTIFIER ON go -- ============================================= -- Author:  yy -- Create date: 2012-1-17 -- Description: 存储过程S

sqlserver 存储过程中拼接sql语句 动态执行

ALTER PROC [dbo].[Student_Friend_Get] @startRowIndexId INT, @maxNumberRows INT, @schoolId INT, @gradeId INT, @cId INT, @keyWords NVARCHAR(100), @userName VARCHAR(50) AS BEGIN DECLARE @sqlfilter VARCHAR(max) SET @sqlfilter = ' ' IF(@schoolId <> -1) S

C#与SQL连接:GridView控件对数据库的操作_C#教程

GridView和DataGrid的异同 GridView 是 DataGrid的后继控件,在.net framework 2 中,虽然还存在DataGrid,但是GridView已经走上了历史的前台,取代DataGrid的趋势已是势不可挡.GridView和DataGrid功能相似,都是在web页面中显示数据源中的数据,将数据源中的一行数据,也就是一条记录,显示为在web页面上输出表格中的一行. GridView相对于DataGrid来说,具有如下优势,功能上更加丰富,因为提供了智能标记面板(

几种SqlServer2005高效分页sql查询语句

几种sqlserver2005高效分页sql查询语句 top方案: sql codeselect top 10 * from table1 where id not in(select top 开始的位置 id from table1) max: sql codeselect top 10 * from table1 where id>(select max(id) from (select top 开始位置 id from table1order by id)tt) row: sql code

LINQ to SQL语句(2)之Select/Distinct

[1] Select介绍1 [2] Select介绍2 [3] Select介绍3和 Distinct介绍 Select/Distinct操作符 适用场景:o(∩_∩) o- 查询呗. 说明:和SQL命令中的select作用相似但位置不同, 查询表达式中的select及所接子句是放在表达式最后并把子句中的变量也就是结 果返回回来:延迟. Select/Distinct操作包括9种形式,分别为简单用 法.匿名类型形式.条件形式.指定类型形式.筛选形式.整形类型形式.嵌套 类型形式.本地方法调用形式

LINQ体验(5)——LINQ to SQL语句之Select/Distinct和Count/Sum/Min/Max/Avg

上一篇讲述了LINQ,顺便说了一下Where操作,这篇开始我们继续说LINQ to SQL语句,目的让大家从语句的角度了解LINQ,LINQ包括LINQ to Objects.LINQ to DataSets.LINQ to SQL.LINQ to Entities.LINQ to XML,但是相对来说LINQ to SQL在我们程序中使用最多,毕竟所 有的数据都要在数据库运行着各种操作.所以先来学习LINQ to SQL,其它的都差不多了,那么就从Select说起吧,这个在编写程序中也最为常