介绍
从Java编程记录 --- 工具箱(填充中...)文章中拆分出来的一个模块。该模块主要记录,平时遇到的一些sql方面的问题,以便后面查阅使用。下面按照问题场景分类。
随机取页
问题场景
现在需要从表中查询定量(假设1000条数据)的数据(定时加载),而一些数据因为某些问题而无法进行处理,但是又不能废弃掉,所以在处理的时候就进行continue跳过。但是当这部分无法处理的数据堆积达到1000条是,负责处理的线程就会进入空转状态,没有处理任何有用数据。
方案
利用随机取页的方式。
private List<Person> selectPersonInfo(int limit){
Random r = new Random();
int sum = dao.queryMessageCountByStatus("user_info", 0);
//page=0~9
int page = sum%limit==0?r.nextInt(sum/limit):r.nextInt((sum/limit)+1);
return dao.getPersonInfo(page*limit, limit); //从0开始
}
mysql:
select * from user_info where status=0 order by insert_time desc limit index,limit;
需要注意的是参数含义:例如,`limit 1, 2`,则表示从第二条记录开始往后取2条;
oracle:
select * from (
select rownum rn, mi.* from (
select * from (
select * from user_info where status=0 order by insert_time desc
) where rownum <= (index+limit)
) mi
) where rn >= (index+1);
oracle有点特殊,需要这么写(先排序然后找最大值,再取最小值),而且rownum是从1开始的,所以最小值需要+1;
sqlserver:
select top limit * from user_info where primary_key not in (
select top index primary_key from user_info order by insert_time desc
) and status=0 order by insert_time desc;
sqlserver是先排除,然后再排序来选;
删除所有的表,序列,存储过程
----删除所有表
select 'drop table ' || table_name ||';'||chr(13)||chr(10) from user_tables;
----删除所有序列
select 'drop sequence ' || sequence_name||';'||chr(13)||chr(10) from user_sequences;
----删除所有存储过程
select 'drop procedure ' || object_name||';'||chr(13)||chr(10) from user_objects where object_type='PROCEDURE';
执行完成后会生成删除语句,然后复制执行即可(存储过程的目前没用过);
实现插入或更新
实现插入或更新,若有该主键,则更新,若没有就插入;
mysql:
insert ignore into 表名 (字段1,字段2,...) values(?,?,...) on duplicate key update count = count + ?, time = now();
update后面直接跟需要更新的字段即可;
oracle:
merge into 表名 using dual on (定位记录的条件(例如:主键=?))
when matched then update set 字段1=值1, ...
when no matched then insert(字段1, 字段2, ...)
values(?, ?, ...);
举例说明:
merge into user_info ui using dual on (ui.id = ?)
when matched then update set status=?
when no matched then insert(id, name, age, status)
values(?, ?, ?, ?);
测试的效率说明(14个字段,使用批处理):
- 单词插入1w条记录,merge into 用时22.92s,insert用时(测试两次3s和12s);如果先select确认,再insert的极端情况,需要1394.37s;
- 单词更新1w条记录,merge into用时38.899s,update平均29s;如果先select确认,然后再update的极端情况,需要1200.759s;
- 单次select在0.1s以上,在navicat中单词select在0.08s以上
总的来说还是merge into性能还是比select+update/insert的组合好
三目运算(类似)
场景
比如我想要统计某表数据在该状态下更新的次数(假设而已)。每次更新时判断待更新的数据中的状态是否和表中的状态相同,若相同则累加,否则则重置为1.;
方案
mysql:
update_count = if(status = ?, update_count + ?, 1)
oracle:
update_count = decode(status, ?, update_count + ?, 1)
在navicat中执行测试命令:
select decode('1', '2', 'y', 'n') from dual; --- n
select decode('1', '1', 'y', 'n') from dual; --- y
select decode(1, 2, 'y', 'n') from dual; --- n
select decode(1, 1, 'y', 'n') from dual; --- y
select decode(1, '1' 'y', 'n') from dual; --- y 这个很奇怪
可以看出在同类型的情况是可以使用的。
格式对应:
decode(比较值, 被比较值1, 比较成功返回的值1, 被比较值2, 比较成功返回的值2, 默认值)
if 比较值=被比较值1
比较成功返回的值1
else if 比较值=被比较值2
比较成功返回的值2
else
默认值