惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

V
Vulnerabilities – Threatpost
P
Proofpoint News Feed
The Hacker News
The Hacker News
Know Your Adversary
Know Your Adversary
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
T
Tenable Blog
AWS News Blog
AWS News Blog
S
Securelist
T
Threatpost
C
Cybersecurity and Infrastructure Security Agency CISA
IT之家
IT之家
腾讯CDC
WordPress大学
WordPress大学
Spread Privacy
Spread Privacy
C
Check Point Blog
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Engineering at Meta
Engineering at Meta
Latest news
Latest news
A
About on SuperTechFans
The Register - Security
The Register - Security
L
LINUX DO - 热门话题
T
The Exploit Database - CXSecurity.com
C
Cisco Blogs
T
Tailwind CSS Blog
Simon Willison's Weblog
Simon Willison's Weblog
阮一峰的网络日志
阮一峰的网络日志
MyScale Blog
MyScale Blog
大猫的无限游戏
大猫的无限游戏
T
Tor Project blog
L
Lohrmann on Cybersecurity
G
GRAHAM CLULEY
B
Blog RSS Feed
Scott Helme
Scott Helme
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
NISL@THU
NISL@THU
P
Privacy International News Feed
Security Latest
Security Latest
Recorded Future
Recorded Future
L
LangChain Blog
Cyberwarzone
Cyberwarzone
C
Cyber Attacks, Cyber Crime and Cyber Security
C
CXSECURITY Database RSS Feed - CXSecurity.com
博客园 - 聂微东
Google DeepMind News
Google DeepMind News
Last Week in AI
Last Week in AI
Apple Machine Learning Research
Apple Machine Learning Research
F
Fortinet All Blogs
O
OpenAI News
T
Threat Research - Cisco Blogs
Blog — PlanetScale
Blog — PlanetScale

博客园 - 马森

Java IO测试样例-字节流-字符流 java中的io系统详解 MongoDB资料汇总 字符编码笔记:ASCII,Unicode和UTF-8 jQuery和ExtJS的timeOut超时设置和event事件处理 Sybase字符串函数-数学函数-系统函数 inux 设置系统时间和硬件时间 Wordpress XML-RPC协议说明 struts2 action 配置方法 &&struts2的配置文件 理解 SET CHAINED command not allowed within multi-statement transaction. sybase性能优化 - 马森 - 博客园 Java引用对象SoftReference WeakReference PhantomReference(二) [整理]centos下配置和安装 jstl字符串处理 [原]动态打jar包程序,可用于手机图片音乐游戏的动态打包 Java,Tomcat,Mysql乱码总结 [原]output parameters have not yet been processed源自返回了多个数据集 [转]MS SQL Server数据库事务锁机制分析 tomcat支持ssl时Keystore was tampered with, or password was incorrect
Sybase采用固定表+存储过程实现分页
马森 · 2011-09-06 · via 博客园 - 马森

众所周知,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 权限。而这个表数据不重要,分配此权限安全隐患不高。