日期:2014-05-20  浏览次数:20477 次

求一通用分页SQL(不要存储过程)(C#实现)
要实现这么一个功能的函数:
输入参数:一个取得记录集的Select   SQL,开始行行号,最大返回行数,唯一键列名
返回:返回一个基于给出的SQL的分页SQL

我实现的一个函数如下:
///   <summary>
///   执行SQL查询,返回分页记录集
///   </summary>
///   <param   name= "sql "> SQL语句 </param>
///   <param   name= "startRowIndex "> 开始行,1开始 </param>
///   <param   name= "maximumRows "> 最大返回行数 </param>
///   <param   name= "keyColumn "> 主键列。用于not   in分页 </param>
///   <returns> </returns>
public   virtual   DataSet   Query(String   sql,   Int32   startRowIndex,   Int32   maximumRows,   String   keyColumn)
{
//   从第一行开始,不需要分页
if   (startRowIndex   <=   1)
{
if   (maximumRows   <   1)
return   Query(sql);
else
return   Query(String.Format( "Select   Top   {0}   *   From   ({1})   a ",   maximumRows,   sql));
}
if   (maximumRows   <   1)
sql   =   String.Format( "Select   *   From   ({1})   b   Where   {2}   Not   In(Select   Top   {0}   {2}   From   ({1})   a) ",   startRowIndex   -   1,   sql,   keyColumn);
else
sql   =   String.Format( "Select   Top   {0}   *   From   ({1})   b   Where   {2}   Not   In(Select   Top   {3}   {2}   From   ({1})   a) ",   startRowIndex   +   maximumRows   -   1,   sql,   keyColumn,   startRowIndex   -   1);
return   Query(sql);
}

在实际应用中发现,对于Access,该方法可行,对于MSSQL,就不一定了。
如果参数中的sql带有order   by,而又没有top,那么,这个SQL是不能作为子查询的,上面的方法就行不通了。

后来我又加了下面一个函数:
///   <summary>
///   为子查询准备。
///   如果一个SQL用了order   by,而没有top时,在SqlServer中是不能作为子查询的。
///   </summary>
///   <param   name= "sql "> </param>
///   <returns> </returns>
private   String   PrepairSqlForSubSelect(String   sql)
{
String   str   =   sql.Trim().ToLower();
//   Select开头,不是存储过程
if   (str.StartsWith( "select   ")   &&   str.Contains( "order   by "))
{
str   =   str.Substring(0,   30);
if   (!Regex.IsMatch(str,   @ "^   *select(   +(all|distinct))?   +top   ",   RegexOptions.IgnoreCase))
{
sql   =   Regex.Replace(sql,   @ "^   *select   +all   ",   "Select   All   Top   100000000   ",   RegexOptions.IgnoreCase);
sql   =   Regex.Replace(sql,   @ "^   *select   +distinct   ",   "Select   Top   100000000   ",   RegexOptions.IgnoreCase);
sql   =   Regex.Replace(sql,   @ "^   *select   + ",   "Select   Top   100000000   ",   RegexOptions.IgnoreCase);
}
}
return   sql;
}

用来检查参数sql是否是这种情况,如果是的话,用正则修改这个sql,在select后面加上Top   100000000。可以解决一部分问题。
后来又发现,如果参数sql中,select后面的选择列中带有ntext类型字段的话,是不能用top。

我现在没办法了,请各位帮帮忙。
存储过程的方法就不用啦,谢谢^_^

------解决方案--------------------