发一段非万能的sql分页代码
百度一下,发现N多万能的sql分页办法, 不过大都有一个共性,就是把一段sql的各个部分折成几个参数,然后拼接sql
而且很多都只支持单表.
我发的代码就是为了解决上面这两个问题的.
使用注意事项:
1.传入的sql必须是可以正常执行的sql
2.传入的sql必须有排序(order by )
3.如果使用的是SqlServerDialect,最好传入正确totalCount,否则最后一页的数据可能跟你想像中的不太一样,
如果是SqlServer2005Dialect的话,不存在此问题
4.基本上可以满足绝大部分的sql语句,大家可以试试复杂的sql,有兴趣的话,可以跟我联系,大家一起完善
下面这段是针对sql server 2000的,不过2005与2008一样可以用
publicclass SqlServerDialect:ISqlDialect
{
#region ISqlDialect 成员
publicstring GetPageSqlText(string sql, int pageSize, int pageNum, int totalCount)
{
if (string.IsNullOrEmpty(sql))
return sql;
string orderByText = GetOrderByText(sql);
if (string.IsNullOrEmpty(orderByText))
thrownew ArgumentException("缺少order by ");
if (pageNum ==1)
return GetFirstPageSqlText(sql, pageSize);
int rowCount = pageSize;
if (totalCount >0)
{
if (totalCount < pageNum * pageSize)
{
rowCount = totalCount - (pageNum -1) * pageSize;
}
if (rowCount <0)
rowCount =0;
}
int pos = sql.IndexOf("select", StringComparison.OrdinalIgnoreCase);
if (pos <0)
thrownew ArgumentException("缺少select关键字", sql);
//string orderByText = GetOrderByText(sql);
string reverseOrderByText = GetReverseOrderByText(orderByText);
StringBuilder sb =new StringBuilder();
sb.AppendFormat("select * from ( select top {0} * from ( select top {1}", rowCount, pageSize * pageNum);
sb.Append(sql.Substring(pos +"select".Length));
sb.Append(") as temptable1 order by ");
sb.Append(reverseOrderByText);
sb.Append(") as temptable2 order by ");
sb.Append(orderByText);
return sb.ToString();
}
#endregion
privatestaticstring GetFirstPageSqlText(string sql, int pageSize)
{
int pos = sql.IndexOf("select", StringComparison.OrdinalIgnoreCase);
if (pos <0)
thrownew ArgumentException("缺少select关键字", sql);
StringBuilder sb =new StringBuilder(sql.Length +20);
sb.Append(sql);
sb.Insert(pos +"select".Length +1, String.Format("top {0} ", pageSize));
return sb.ToString();
}
privatestaticstring GetOrderByText(string sql)
{
int len ="order by".Length;
int pos = sql.LastIndexOf("order by", StringComparison.OrdinalIgnoreCase);
if (pos <0)
{
returnstring.Empty; ;
}
return RemoveAlias(sql.Substring(pos + len));
}
privatestaticstring GetReverseOrderByText(string orderByText)
{
StringBuilder sb =new StringBuilder();
string[] cols = orderByText.Split(',');
for (int i =0; i < cols.Length; i++)
{
if (i >0)
sb.Append(",");
int pos = cols[i].LastIndexOf(" desc", StringComparison.OrdinalIgnoreCase);
if (pos >-1)
{
sb.Append(cols[i].Substring(0, pos)).Append(" asc");
}
else
{
pos = cols[i].LastIndexOf(" asc", StringComparison.OrdinalIgnoreCase);
if (pos >-1)
{
sb.Append(cols[i].Substring(0, pos)).Append(" desc");
}
else
{
sb.Append(cols[i]).Append(" desc");
}
}
}
return sb.ToString();
}
privatestaticstring RemoveAlias(string orderByText)
{
StringBuilder sb =new StringBuilder();
string[] cols = orderByText.Split(',');
for (int i =0; i < cols.Length; i++)
{
if (i >0)
sb.Append(",");
int pos = cols[i].IndexOf(".");
if (pos >-1)
{
sb.Append(cols[i].Substring(pos +1));
}
else
{
sb.Append(cols[i]);
}
}
return sb.ToString();
}
}
接着来个sqlserver2005的
publicclass SqlServer2005Dialect : ISqlDialect
{
#region ISqlDialect 成员
publicstring GetPageSqlText(string sql, int pageSize, int pageNum, int totalCount)
{
if (string.IsNullOrEmpty(sql))
return sql;
string orderByText = GetOrderByText(sql);
if (string.IsNullOrEmpty(orderByText))
thrownew SqlNullValueException("缺少order by ");
if (pageNum ==1)
return GetFirstPageSqlText(sql, orderByText, pageSize);
int startIndex = (pageNum -1) * pageSize;
int endIndex = startIndex + pageSize;
int pos = sql.IndexOf("select", StringComparison.OrdinalIgnoreCase);
if (pos <0)
thrownew ArgumentException("缺少select关键字", sql);
StringBuilder sb =new StringBuilder();
sb.Append(sql);
sb.Insert(pos +"select".Length +1, String.Format(" top 100 percent row_number() OVER(order by {0}) AS _rowNum, ", orderByText));
sb.AppendFormat(" ) select * from _pageSql where _rowNum between {0} and {1} ", startIndex +1, endIndex);
sb.Insert(0, "with _pageSql as ( ");
return sb.ToString();
}
#endregion
privatestaticstring GetFirstPageSqlText(string sql, string orderBySql, int pageSize)
{
int pos = sql.IndexOf("select", StringComparison.OrdinalIgnoreCase);
if (pos <0)
thrownew ArgumentException("缺少select关键字", sql);
StringBuilder sb =new StringBuilder(sql.Length +20);
sb.Append(sql);
sb.Insert(pos +"select".Length +1, String.Format("top {0} ", pageSize));
//sb.Append(" " + orderBySql);
return sb.ToString();
}
privatestaticstring GetOrderByText(string sql)
{
int len ="order by".Length;
int pos = sql.LastIndexOf("order by", StringComparison.OrdinalIgnoreCase);
if (pos <0)
{
returnstring.Empty; ;
}
return sql.Substring(pos + len);
}
}
像oracle/sqlite/mysql的,就很简单,不发了.
顺便把接口也发一下
publicinterface ISqlDialect
{
string GetPageSqlText(string sql, int pageSize, int pageNum, int totalCount);
}