求一通用分页SQL(不要存储过程)(C#实现)
智能大石头 2007-02-17 10:44:42 要实现这么一个功能的函数:
输入参数:一个取得记录集的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。
我现在没办法了,请各位帮帮忙。
存储过程的方法就不用啦,谢谢^_^