1.0          其他语言
 
 

6 SQL 查询结果分页

 
 

当一个 SQL 查询,得到的结果数据太多的时候,这时候就需要将结果数据进行分页,每次只让用户看到一小部分数据。如果一次显示的数据太多,人眼是无法看过来的。

但是,ANSI SQL 标准中,并没有考虑好这一点。在几个流行的数据中,Mysql/PostgreSQL 对这个问题进行自定义扩展,解决了这个问题。这也许是 Mysql 在 Web 应用中流行的原因之一。因为 Web 应用需要关心单个页面数据量大小。

SQL standard 2003 新带来的 SQL 窗口函数(Window function) ROW_NUMBER() OVER () , 数据库 SQL server 2005/DB2/Oracle 都支持,Oracle 与标准略为有点差别。 Mysql/PostgreSQL 则不支持 ROW_NUMBER()。

这已经够了。VelocityWeb 在此基础上,提供了一个统一的接口,可以写出适合各种数据库的分页程序,也支持 select distinct/ group by 之类的特殊操作。网络上通常提供的分页程序,都不支持这些特殊 SQL。

分页操作,一般涉及两个部分:取当前页数据,取总数据量。另外,需要注意的是,取当前页数据,涉及数据排序,也就是 SQL 中的 order by。必须有排序,分页才有意义。

这里面涉及几个类,都实现了 PageDialect 接口: StandardPageDialect(支持 SQL Server 2005,DB2), SQLServer2000PageDialect, OraclePageDialect, MySQLPageDialect, PostgreSQLPageDialect。

下面是一个例子:

sql = new StringBuffer();
sql.append("SELECT i.itemid, qty");
sql.append(" FROM inventory v,item i");
sql.append(" where i.itemid = v.itemid");
sql.append(" and i.itemid > ?");
sql.append(" and v.itemid > ?");

orderBy = "i.itemid,v.qty desc";

paraList = new LinkedList();
paraList.add("aa");
paraList.add("bb");

countSql = dialect.getCountSql(sql.toString());
count = (Number)this.queryScalar(countSql, paraList.toArray(), 1);

pageSql = dialect.getPageSqlWithoutPageInfo(sql.toString(), orderBy);
values = dialect.getPageParemeterValuesWithPageInfo(pageIndex, pageSize);
paraList.add(new Long(values[0]));
paraList.add(new Long(values[1]));

list = this.queryBeanList(pageSql, paraList.toArray(), Inventory.class);

从目前的使用效果来看,还是不错的。

VelocityWeb 在此基础上,提供了更进一步的封装。如果用 JDBC 作为 DAO 则可以这样写:

List resultDataList = new LinkedList();
int recordCount = JdbcPageUtils.getPageData(sql.toString(), paraList, orderBy,
pageIndex, pageSize, con, dialect, resultDataList);
当前页数据 resultDataList 中每个元素是 Object[].

如果用 VelocityWeb 的 JdbcDao,则可以这样写:

List resultDataList = new LinkedList();
int recordCount = VelocitywebPageUtils.getPageData(sql.toString(), paraList, orderBy,
pageIndex, pageSize, dao, dialect, Inventory.class, resultDataList);
当前页数据 resultDataList 中每个元素是 Inventory 对象.