zoukankan      html  css  js  c++  java
  • Sybase采用固定表+存储过程实现分页

    众所周知,sybase没有mysql的limit关键字,也不支持sqlserver的 ROW_NUMBER() 来对查询行数据动态设置ID来帮助索引分页。

    网上大部分流传的都是使用临时表,网上搜一搜就可以搜到相关例子,没有用过,言称是很通用。

    为了实现简单快速的分页,自己写了一套分页的工具。没有使用临时表,而使用了一个固定表的原因是:

    1. 临时表管理上比较麻烦,需要分配表管理的权限,并且临时表一般会放在master库下,如果查询数据很大或者临时表创建drop频繁,对系统性能会有影响。

    2.之前的经验认识到,其实大表如果是只写和查,没有数据合并或复杂的联表运算,在索引合理的情况下,速度还是非常好的。这是在我之前做大数据统计时得到的经验。

    下面开始建表:

    其中id为int型的索引,数据分页就靠他来算。id1和id2一个是int型,一个是varchar型,

    CREATE TABLE mytemptable (
    id integer NOT NULL,
    id1 integer NULL,
    id2 varchar(32) NULL
    )
    ALTER TABLE mytemptable ADD CONSTRAINT pk_orderform PRIMARY KEY (id)

    存储过程:

    其中type是类型

    countsql是分页计算的sql ,比如 select tableid as id from table1 ,其中as id 是必须的

    countordersql是分页时的order语句,因为sybase不支持在子查询里加排序,因此只能放在这个里面拼串

    sql是真正的查询显示的sql,比如 select tableid as id,name,createdate from table1,其中as id仍旧是必须的

    pagesize和currentpage分别是页大小和当前页

    CREATE PROCEDURE pageUtil
    @type integer ,
    @countsql varchar(2048) ,
    @countordersql varchar(256) ,
    @sql varchar(16284) ,
    @pagesize integer ,
    @currentpage integer
    AS

    BEGIN TRAN
    DECLARE @minid int
    DECLARE @beginid varchar(20)
    DECLARE @endid varchar(20)
    DECLARE @total int
    IF (@type=1)
    BEGIN
    set @countsql="insert mytemptable(id1,id2) select id," from ("+@countsql+")temptemptemp "+@countordersql
    END
    ELSE
    BEGIN
    set @countsql="insert mytemptable(id1,id2) select 0,id from ("+@countsql+")temptemptemp "+@countordersql
    END

    execute (@countsql)

    select @minid=min(id) from mytemptable
    set @beginid=convert(varchar(20),@minid+(@currentpage-1)*@pagesize)
    set @endid=convert(varchar(20),@minid+@currentpage*@pagesize-1)
    IF (@type=1)
    BEGIN
    set @sql="select * from ("+@sql+")temptemptemp where id in ( select id1 from mytemptable where id > ="+@beginid+" and id < ="+@endid+")"
    END
    ELSE
    BEGIN
    set @sql="select * from ("+@sql+")temptemptemp where id in ( select id2 from mytemptable where id > ="+@beginid+" and id < ="+@endid+")"
    END

    execute (@sql)
    select @total=count(*) from mytemptable
    delete from mytemptable
    IF (@total>0)
    BEGIN
    return @total
    END
    COMMIT TRAN
    RETURN 0

    go


    ===========================================================

    原理说明:

    1. 存储过程pageUtil根据countsql,把对应的id插入到临时表mytemptable(根据type的不同,type=1 Int型 插入到id1字段,type=2 varchar 型 插入到id2字段)

    2. 一般的分页数据是有顺序的,这时候的order就可以放到countordersql中,可以按照自定义的方式排序,countsql里的select语句也可以查询多个字段为后面的order做准备,这也是countsql中必须要有 as id的原因。

    3.执行countsql将数据插入到mytemptable

    4.根据分页参数换算出当前页在mytemptable中的索引 @beginid ,@endid,拼sql串。并执行此sql串。

    5. mytemptable的数据数即查询记录总条数,删除mytemptable中的数据,返回总条数。

    ============================================================

    调用例子:

    /*******

    ***分页查询某个用户的所有订单,要求按照时间倒序排序

    *****/

    public HashMap<Object,Object> getUserConsumeRecord(String username, int pagesize,int currentpage) {
    String countsql=" select a.ordernumber as id,a.createdate as createdate from orderform a where a.username='"+username+"' ";
    String countordersql=" order by createdate desc ";
    String sql="select a.ordernumber as id, a.merchantid,a.orderid,a.chargeamount,a.payamount," +
    " from orderform a " +
    " where a.username='"+username+"' ";
    return this.getPage(2, countsql,countordersql, sql, pagesize, currentpage);
    }


    /******

    **********调用存储过程pageUtil的通用方法***

    ***********/
    public HashMap<Object,Object> getPage(int type,String countsql,String countordersql,String sql,int pagesize,int currentpage)
    {
    HashMap<Object,Object> result=new HashMap<Object,Object>();
    result.put("pagesize", pagesize);
    result.put("currentpage", currentpage);
    Connection connection=null;
    Context context=null;
    try
    {
    connection=getConnection();//获取数据库连接,使用时自行修改
    java.sql.CallableStatement cs = connection.prepareCall("{?= call pageUtil(?,?,?,?,?,?)}");
    cs.registerOutParameter(1, java.sql.Types.INTEGER);
    cs.setInt(2, type);
    cs.setString(3, countsql);
    cs.setString(4, countordersql);
    cs.setString(5, sql);
    cs.setInt(6, pagesize);
    cs.setInt(7, currentpage);
    ResultSet data= cs.executeQuery();
    List<HashMap<String,Object>> list=new ArrayList<HashMap<String,Object>>();
    while(data.next())
    {
    int datasize=data.getMetaData().getColumnCount();
    HashMap<String,Object> thisdata=new HashMap<String,Object>();
    for(int i=1;i<=datasize;i++)
    {
    thisdata.put(data.getMetaData().getColumnName(i), data.getObject(i));
    }
    data.getMetaData().getColumnCount();
    System.out.println(data.getMetaData().getColumnCount());
    System.out.println(data.getString("id"));
    list.add(thisdata);
    }
    int ret=cs.getInt(1);
    result.put("totalrecord",ret);
    result.put("data", list);
    }catch(Exception e)
    {
    System.out.println(e);
    }
    finally
    {
    //关闭数据库连接,使用时自己修改
    }
    return result;
    }

    ============================================================

    注意:mytemptable的锁级别为表锁。

    用户需要持有 mytemptable的select insert delete 权限。而这个表数据不重要,分配此权限安全隐患不高。

  • 相关阅读:
    rac11.2.0.4私网公网修改
    OGG应用复制进程报错OGG 01161
    顺序容器vector拷贝使用总结
    C++迭代器(STL迭代器)
    C++容器(STL容器)
    win10桌面和手机的扩展API,判断是否有实体后退键API
    python Django 之 Model ORM inspectdb(数据库表反向生成)
    flask框架-大结局
    flask框架-下
    flask框架-中
  • 原文地址:https://www.cnblogs.com/pony/p/2169063.html
Copyright © 2011-2022 走看看