java批量插入数据库之写绑定变量
来源:互联网 发布:网络视频广告特点 编辑:程序博客网 时间:2024/05/29 18:01
最近查到关于sql批量写入和绑定变量的问题,看到了很多好的帖子,再次进行总结
数据库在执行SQL语句时会首先解析SQL语句,解析又分为硬解析与软解析。说到硬解析和软解析,就不能不说一下Oracle对sql的处理过程。当你发出一条sql语句交付Oracle,在执行和获取结果前,Oracle对此sql将进行几个步骤的处理过程:
1、语法检查(syntax check)
检查此sql的拼写是否语法。
2、语义检查(semantic check)
诸如检查sql语句中的访问对象是否存在及该用户是否具备相应的权限。
3、对sql语句进行解析(prase)
利用内部算法对sql进行解析,生成解析树及执行计划。
4、执行sql,返回结果(execute and return)。
其中,软、硬解析就发生在第三个过程里,Oracle利用内部的hash算法来取得该sql的hash值,然后在librarycache里查找是否存在该hash值。假设存在,则将此sql与cache中的进行比较(注意此处的比较哪怕是一个字母的大小写、空格个数不一致都会认为不同)。假设“相同”,就将利用已有的解析树与执行计划,而省略了优化器的相关工作。这也就是软解析的过程;如果上面的2个假设中任有一个不成立,那么优化器都将进行创建解析树、生成执行计划的动作。这个过程就叫硬解析。由此可以看出应该极力避免硬解析,尽量使用软解析。
通过http://blog.csdn.net/duanning397/article/details/7586609 我们看出两者的差距还是很大的
那么如何进行软解析,在这里主要通过绑定变量的方法
认识绑定变量:
绑定变量是为了减少解析,比如你有个语句这样的:
select aaa,bbb from ccc where ddd=eee;
如果经常通过改变eee这个谓词赋值来查询,如下:
select aaa,bbb from ccc where ddd=fff;
select aaa,bbb from ccc where ddd=ggg;
select aaa,bbb from ccc where ddd=hhh;
每条语句都要被数据库解析一次,这样比较浪费资源,如果把eee换成绑定变量形式,无论ddd后面是什么值,都不需要重复解析
通过
那么如何在java中实现绑定变量,主要用两种方法,一种是?号法,比较简单粗暴,适合大部分情况
具体可以参考http://blog.csdn.net/wacthamu/article/details/7798393 这里转载一些关键内容
Java实现绑定变量的方法:
PreparedStatement pstmt = con.prepareStatement("UPDATE employees SET salay = ? WHERE id = ?");pstmt.setBigDecimal(1, 15.00);
pstmt.setInt(2, 110592);
//result statmement: UPDATE employees SET salay = 15.00 WHERE id =110592
pstmt.executeQuery();
假设要将id从1到10000的员工的工资都更新为150.00元,不使用绑定变量,则:
sql.executeQuery("UPDATE employees SET salay = 150.00 WHERE id = 1");sql.executeQuery("UPDATE employees SET salay = 150.00 WHERE id = 2");
sql.executeQuery("UPDATE employees SET salay = 150.00 WHERE id = 3");
sql.executeQuery("UPDATE employees SET salay = 150.00 WHERE id = 4");
....
sql.executeQuery("UPDATE employees SET salay = 150.00 WHERE id = 10000");
使用绑定变量,则:
PreparedStatement pstmt;for (id = 1; id < 10000; id++)
{
if (null == pstmt)
pstmt = con.prepareStatement("UPDATE employees SET salay = ? WHERE id = ?");
pstmt.setBigDecimal(1, 150.00);
pstmt.setInt(2, id);
pstmt.executeQuery();
} 需要注意的是pstmt.executeQuery();是每次都打开游标,所以出国处理大数据的话,则需要在后面添加pstmt.close();
这里可以看到通过设置的方式可以让数据库认为成一条语句,这里必须按照这种方法,如果用简单的字符串拼接的方法,数据库依然认为成两条语句具体可以参考http://www.itpub.net/thread-263389-1-1.html
那么第二种方法是什么呢,细心的网友可以看到http://blog.csdn.net/wacthamu/article/details/7798393 已经提及,即使用:x的方式,其中该文章,也给出了一样的赋值方式,
其实Oracle遵循针对PL/SQL存储过程使用占位符名称匹配的原则,而针对SQL语句则采用占位符位置匹配的原则。所以上文的:x更多的是在Oracle中的本身里面,对比两者可以发现,一种是单纯的问号,一种是用变量名,当赋值的变量是重复的时候,用后者可以避免重复书写,但后者由于是变量名,也会导致书写错误,
在近期研究中发现,在hibernate中的hql语言其实也是可以占位符名称匹配,这里给出一个完整的hql的存储例子
<span style="color:#333333;">StringBuffer hql = new StringBuffer(); hql.append("select distinct employee from PreceptPO pre,PlanPO plan, ").append( "EmployeeInfoPO employee,ObjectRelationPO relation "); hql.append(" where pre.oid=plan.preceptID"); hql.append(" and pre.status='").append(PreceptStatusType.STARTUP.getCode()).append("'"); hql.append(" and plan.objectID=employee.oid "); hql.append(" and relation.relationObjectID=:employeeID "); hql.append(" and relation.preceptID=plan.preceptID "); hql.append(" and relation.objectID=plan.objectID "); hql.append(" and relation.phase=plan.phase "); hql.append(" and (relation.performanceRole=3 or relation.performanceRole=4 )"); //员工状态 hql.append(" and "); DAOHelper.buildOrHql(hql, "employee.employeeStatus", StaffStatusAttribute.Normal_Employee.getStatus()); Query q = getSession().createQuery(hql.toString()); /*if(empList.size() > 0){ </span><span style="color:#ff0000;"><strong>q.setParameterList("empList", empList);</strong></span><span style="color:#333333;"> }*/ q.setLong("employeeID", appraiserID);</strong> objectList = q.list(); List voList = new ArrayList(objectList.size()); for (Iterator iter = objectList.iterator(); iter.hasNext();) { EmployeeInfoPO emp = (EmployeeInfoPO) iter.next(); voList.add(EmployeeBasicConvert.convert(emp)); } return voList;}</span>
这个时候很多人会说,既然使用了createQuery,那使用createSQLQuery可不可以用占位符名称匹配,答案是可以的,下面给出了例子
StringBuffer buffer = new StringBuffer();/*buffer.append(" select count(1) as num from TB_PMG_OBJECTRELATION orn,TB_PMG_PLAN pl ") .append(" left join TB_PMG_EVALUATESCORE on TB_PMG_EVALUATESCORE.c_planid = pl.c_oid_plan ") .append(" and TB_PMG_EVALUATESCORE.c_status in (2,3,5,7) ") .append(" where pl.c_oid_plan=").append(planID) .append(" and pl.c_objectid = orn.c_objectid ") .append(" and orn.c_preceptid = pl.c_preceptid and orn.c_phase = pl.c_phase ") .append(" and orn.c_level = '2' and orn.c_businessrole='1' ") .append(" and TB_PMG_EVALUATESCORE.C_OID_EVALUATESCORE is not null");*/buffer.append(" SELECT COUNT(1) AS NUM FROM TB_PMG_OBJECTRELATION ORN ") .append(" LEFT JOIN TB_PMG_EVALUATESCORE e on e.C_STATUS IN (2,3,5,7)") .append(" AND ORN.C_PRECEPTID = e.c_preceptID ") .append(" AND ORN.C_PHASE = e.c_phase ") .append(" AND ORN.C_objectID = e.c_objectID ") .append(" WHERE ") .append(" ORN.C_OBJECTID =:objectID ") .append(" AND ORN.C_PRECEPTID = :preceptID AND ORN.C_PHASE = :phase ") .append(" AND ORN.C_LEVEL = '2' AND ORN.C_BUSINESSROLE='1' ") .append(" AND e.C_OID_EVALUATESCORE IS NOT NULL ");SQLQuery q= loadSession().createSQLQuery(buffer.toString());q.setParameter("preceptID", preceptID);q.setParameter("phase", phase);q.setParameter("objectID", objectID);</strong>q.addScalar("num", Hibernate.LONG);List list = q.list();
其实在大型工程中,占位符名称匹配用的很多,但如果就是用单纯的sql语句怎么实现呢?,下文给出了方式http://blog.csdn.net/keyboardsun/article/details/4275594
这里需要用一个自定义函数,进行拼接赋值,这里面还对不用类型的内容进行转换,比如时间,数字等比较复杂的转换,所以这个自定义函数可以作为一个工具类很感谢以上所有的博主,给我的帮助,在这里也专程感谢
- java批量插入数据库之写绑定变量
- java批量插入数据库之批量处理
- java 数据库批量插入
- 数据库开发之绑定变量
- 批量插入数据库之Transaction测试
- Android数据库操作之--批量插入
- 数据库批量插入——java
- Java 批量插入数据库(MySQL)数据
- Java 批量插入数据库(MySQL)数据
- java 高效批量插入 sqlserver 数据库
- merge 绑定变量批量DML
- DataTable 批量插入数据库
- DataTable批量插入数据库
- Bulk 批量插入数据库
- 批量插入oracle数据库
- DataTable批量插入数据库
- DataTable批量插入数据库 .
- jdbc批量插入数据库
- ACM-正三角形的外接圆面积(经典算法)
- java反射机制
- Contains Duplicate
- 在makefile中写shell注意点
- 关于Class.getResource和ClassLoader.getResource的路径问题
- java批量插入数据库之写绑定变量
- using与命名空间
- 【转载】ListView的使用方法
- 未来码农或可以备份一个自己的大脑
- c++ 单例模式 对数据进行操作
- JAVA小工具1:生成ID
- I()函数分析
- java中log日志的使用
- 实战Pdf怎么分割