`
lbmydream
  • 浏览: 17118 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

需要多次执行sql语句时,使用预编译

阅读更多
1、Statement为每一条Sql语句生成执行计划, 如果要执行两条sql语句
select colume from table where colume=1;
select colume from table where colume=2;
会生成两个执行计划,一千个查询就生成一千个执行计划。而生成计划是非常消耗资源的
2、PreparedStatement用于使用绑定变量重用执行计划
select * from xxx.sometable t where t.id=?;
通过set方法给sql语句按占位符"?"先后顺序赋值,只需要生成一个执行计划,可以重复使用。
   当处理批量SQL语句时,这个时候就可以体现PrepareStatement的优势,由于采用Cache机制,则预先编译的语句,就会放在Cache中,下次执行相同SQL语句时,则可以直接从Cache中取出来,效率要比statement高好几倍

PreparedStatement类是Statement类的子类,它直接继承并重写了Statement的方法。PrepardStatement类有两大特点:
  特点一:一个PreparedStatement的对象中包含的SQL声明是预编译的,因此当需要多次执行同一条SQL声明时,利用PreparedStatement传送这条SQL声明可以大大提高执行效率。
  特点二:PreparedStatement的对象所包含的SQL声明中允许有一个或多个IN参数。创建类PreparedStatement的实例时,IN参数用“?”代替。在执行带参数的SQL声明前,必须对“?”进行赋值,为了对“?”赋值,PreparedStatement类中增添了大量的setXXX方法,完成对IN参数赋值。
  ⑴创建PreparedStatement对象
  与创建Statement类的实例方法类似,创建一个PreparedStatement类的对象也只需在建立连接后,调用Connection类中的方法
  public abstract PreparedStatement prepareStatement(String sql) throws SQLException;
  例 创建一个PreparedStatement的对象,其中包含一条带参数的SQL声明。
  PreparedStatement pstmt=con.prepareStatement("INSERT INTO testTable(id,name) VALUES(?,?)");
  ⑵IN参数的赋值
  PreparedStatement中提供了大量的setXXX方法对IN参数进行赋值。根据IN参数的SQL类型应选用合适的setXXX方法。
  例 对上例,若需将第一个参数设为3,第二个参数设为XU,即插入的记录id=3,name="XU",可用下面的语句实现:
  pstmt.setInt(1,3);
  pstmt.setString(2,"XU");
除了setInt,setLong,setString,setBoolean,setShort,setByte等常见的方法外,PreparedStatement还提供了几种特殊的setXXX方法。
  ①setNull(int ParameterIndex,int sqlType)
  这个方法将参数值赋为Null。sqlType是在java.sql.Types中定义的SQL类型号。
  例 语句
  pstmt.setNull(1,java.sql.Types.INTEGER);
将第一个IN参数的值赋成Null。
  ②setUnicodeStream(int Index,InputStream x,int length);
   setBinaryStream(int Index,inputStream x,int length);
   setAsciiStream(int Index,inputStream x,int length);
  当参数的值很大时,可以将参数值放在一个输入流x中,再通过调用上述三种方法将其赋于特定的参数,参数length表示输入流中字符串长度。


    每一种数据库都会尽最大努力对预编译语句提供最大的性能优化.因为预编译语句有可能被重复调用.所以语句在被DB的编译器编译后的执行代码被缓存下来,那么下次调用时只要是相同的预编译语句就不需要编译,只要将参数直接传入编译过的语句执行代码中(相当于一个涵数)就会得到执行.这并不是说只有一个Connection中多次执行的预编译语句被缓存,而是对于整个DB中,只要预编译的语句语法和缓存中匹配.那么在任何时候就可以不需要再次编译而可以直接执行.而statement的语句中,即使是相同一操作,而由于每次操作的数据不同所以使整个语句相匹配的机会极小,几乎不太可能匹配.比如:
insert into tb_name (col1,col2) values ('11','22');
insert into tb_name (col1,col2) values ('11','23');
    即使是相同操作但因为数据内容不一样,所以整个个语句本身不能匹配,没有缓存语句的意义.事实是没有数据库会对普通语句编译后的执行代码缓存.这样每执行一次都要对传入的语句编译一次.

    当然并不是所以预编译语句都一定会被缓存,数据库本身会用一种策略,比如使用频度等因素来决定什么时候不再缓存已有的预编译结果.以保存有更多的空间存储新的预编译语句.

Code Fragment 1:
String updateString = "UPDATE COFFEES SET SALES = 75 " + "WHERE COF_NAME LIKE ′Colombian′";
stmt.executeUpdate(updateString);
Code Fragment 2:
PreparedStatement updateSales = con.prepareStatement("UPDATE COFFEES SET SALES = ? WHERE COF_NAME LIKE ? ");
updateSales.setInt(1, 75);
updateSales.setString(2, "Colombian");
updateSales.executeUpdate();

片断2和片断1的区别在于,后者使用了PreparedStatement对象,而前者是普通的Statement对象。PreparedStatement对象不仅包含了SQL语句,而且大多数情况下这个语句已经被预编译过,因而当其执行时,只需DBMS运行SQL语句,而不必先编译。当你需要执行Statement对象多次的时候,PreparedStatement对象将会大大降低运行时间,当然也加快了访问数据库的速度。
    这种转换也给你带来很大的便利,不必重复SQL语句的句法,而只需更改其中变量的值,便可重新执行SQL语句。选择PreparedStatement对象与否,在于相同句法的SQL语句是否执行了多次,而且两次之间的差别仅仅是变量的不同。如果仅仅执行了一次的话,它应该和普通的对象毫无差异,体现不出它预编译的优越性。


package com.ys;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;

public class DbUtil {
private static String dbDriver = "oracle.jdbc.driver.OracleDriver";
private static String dbURL = "jdbc:oracle:thin:@localhost:1521:orcl";
private static String user = "jhfund";
private static String password = "jhfund";

static {
try {

Class.forName( dbDriver ).newInstance();

} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

public static Connection loadConnection() throws Exception{
Connection connection =
DriverManager.getConnection(dbURL, user, password);  
return connection;
}

public static void close(Connection connection) throws Exception{
if(connection!=null)
connection.close();
}

public static void close(Statement statement) throws Exception{
if(statement!=null)
statement.close();
}

public static void close(ResultSet rs) throws Exception{
if(rs!=null)
rs.close();
}


public static void close(PreparedStatement preparedStatement) throws Exception{
if(preparedStatement!=null)
preparedStatement.close();
}
}


package com.ys;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.PreparedStatement;

public class PreparedStatementTest {

public void Add() throws Exception{
String SQL = "insert into student(S_NUM,S_NAME,ID_CARD,ADR) values(?,?,?,?)";
Connection conn = null;
PreparedStatement st = null;
try{
conn = DbUtil.loadConnection();
st = conn.prepareStatement(SQL);
st.setInt(1, "201307043");
st.setDouble(2, "李阳");
st.setString(3,"510724199705181231");
st.setDate(4, "白桥大街15号");
st.execute();
}
catch(Exception e){
throw e;
}
finally{
DbUtil.close(st);
DbUtil.close(conn);
}
}

public void AddBatch()throws Exception{
int a = 1;
double b = 99999.99;
String c = "cat";
java.sql.Date d = new java.sql.Date(2010,1,3);
Connection conn = null;
String SQL = "insert into test(a,b,c,d) values(?,?,?,?)";
PreparedStatement st = null;
try{
conn = DbUtil.loadConnection();
st = conn.prepareStatement(SQL);
for( a = 1;a<1000;a++){
st.setInt(1, a);
st.setDouble(2, b);
st.setString(3,c);
st.setDate(4, d);
st.addBatch();
}
st.executeBatch();
}
catch(Exception e){
throw e;
}
finally{
DbUtil.close(st);
DbUtil.close(conn);
}
}

public void update() throws Exception{
int a = 1;
double b = 10000.00;
String c = "cat";
java.sql.Date d = new java.sql.Date(2010,1,3);
String SQL = "update test set b=?,c=?,d=? where a = ?";
Connection conn = null;
PreparedStatement st = null;
try{
conn = DbUtil.loadConnection();
st = conn.prepareStatement(SQL);
st.setDouble(1, b);
st.setString(2,c);
st.setDate(3, d);
st.setInt(4, a);
st.execute();
}
catch(Exception e){
throw e;
}
finally{
DbUtil.close(st);
DbUtil.close(conn);
}
}

public void del()throws Exception{
int a = 1;
String SQL = "delete test where a = ?";
Connection conn = null;
PreparedStatement st = null;
try{
conn = DbUtil.loadConnection();
st = conn.prepareStatement(SQL);
st.setInt(1, a);
st.execute();
}
catch(Exception e){
throw e;
}
finally{
DbUtil.close(st);
DbUtil.close(conn);
}
}

public void delIN()throws Exception{
String SQL = "delete test where a in ?";
Connection conn = null;
PreparedStatement st = null;
try{
conn = DbUtil.loadConnection();
st = conn.prepareStatement(SQL);
st.setString(1, "(1,2,3)");
st.execute();
}
catch(Exception e){
throw e;
}
finally{
DbUtil.close(st);
DbUtil.close(conn);
}
}

public void query(int a)throws Exception{
Connection conn = null;
PreparedStatement st = null;
ResultSet rs = null;
try{
conn = DbUtil.loadConnection();
st = conn.prepareStatement(SQL);
st.setInt(1, a);
rs = st.executeQuery();
}
catch(Exception e){
throw e;
}
finally{
DbUtil.close(rs);
DbUtil.close(st);
DbUtil.close(conn);
}
}

public void query()throws Exception{
query(0);
}
}
分享到:
评论

相关推荐

    SQL Server中存储过程比直接运行SQL语句慢的原因

    1. 存储过程只在创造时进行编译即可,以后每次执行存储过程都不需再重新编译,而我们通常使用的SQL语句每执行一次就编译一次,所以使用存储过程可提高数据库执行速度。 2. 经常会遇到复杂的业务逻辑和对数据库的...

    MySQL预编译功能详解

     当客户发送一条SQL语句给服务器后,服务器总是需要校验SQL语句的语法格式是否正确,然后把SQL语句编译成可执行的函数,最后才是执行SQL语句。其中校验语法,和编译所花的时间可能比执行SQL语句花的时间还要多。  ...

    SQL Server 存储过程与实例

    而批处理的T-SQL语句每次运行都需要预编译和优化,所以速度就要慢一些。 C、 存储过程减轻网络流量 对于同一个针对数据库对象的操作,如果这一操作所涉及到的T-SQL语句被组织成一存储过程,那么当在客户机上调用该...

    SQL Server 中 EXEC 与 SP_EXECUTESQL 的区别.doc

    3、EXEC 执行纯动态SQL,执行时可能无法使用预编译的执行计划,关键是不安全,可以导致 SQL 注入 ,而 SP_EXECUTESQL 执行参数化动态 SQL ,执行时能使用预编译的执行计划,而且保存存储过程时就可以确定可以使用的预...

    SQL存储过程

    当存储过程执行一次后,可以将语句缓存中,这样下次执行的时候直接使用缓存中的语句。这样就可以提高存储过程的性能。 Ø 存储过程的概念 存储过程Procedure是一组为了完成特定功能的SQL语句集合,经编译后存储在...

    Oracle教程

    Pro*C/C++语言就是在标准C/C++语言中通过嵌入SQL 语句完成对数据库操作的一种语言组织方式,为了编译成可执行程序必须经过Oracle 预编译程序预编译成.c/.cpp 源程序,并由系统c/c++编译器编译成可执行程序。...

    JDBC之PreparedStatement类中预编译的综合应用解析

    SQL 语句被预编译并存储在 PreparedStatement 对象中。然后可以使用此对象多次高效地执行该语句

    Visual SQLTools 2012 Pro – 高效率SQL开发工具

    14、一次执行多条SQL语句。 15、代码及文档自定义生成。 16、表、视图、存储过程、触发器等的创建、编译和执行。 17、DB设计书关联功能。(能将表字段逻辑名称关联到工具中) 18、代码及文档生成。 19、二次开发。...

    SQL Server数据库查询速度慢原因及优化方法

     6、查询出的数据量过大(可以采用多次查询,其他的方法降低数据量)  7、锁或者死锁(这也是查询慢最常见的问题,是程序设计的缺陷)  8、sp_lock,sp_who,活动的用户查看,原因是读写竞争资源。  9、返回了不必要...

    SQL经典面试题目

    如果某次操作需要执行多次SQL,使用存储过程比单纯SQL语句执行要快。可以用一个命令对象来调用存储过程。 3。索引的作用?和它的优点缺点是什么? 答:索引就一种特殊的查询表,数据库的搜索引擎可以利用它加速...

    SQL查询安全性及性能优化

     优化:【检查SQL语句是否能够使用索引,SQL语句如何执行效率高,制定一个执行计划】  编译:  执行SQL语句:【把编译过的查询要求提交并进行处理】 如何优化SQL 完善开发的管理 完善代码审核、测试机制,...

    SQL Server内存释放器 v3.3

    软件介绍 大家都知道 sql的使用时间越长.其占用的内存数就越大.由于Sql Server对于...还有一些其他类型的缓存,如执行存储过程时,Sql Server需要先编译再运行,编译后的结果也会缓存起来,下一次就无需再次编译了。

    Oracle SQL高级编程(资深Oracle专家力作,OakTable团队推荐)--随书源代码

    6.2.4 标识SQL语句以便以后取回计划 153 6.2.5 深入理解DBMS_XPLAN的细节 156 6.2.6 使用计划信息来解决问题 161 6.3 小结 169 第7章 高级分组 170 7.1 基本的GROUP BY用法 171 7.2 HAVING子句 174 7.3 GROUP...

    剑儿SQL Server内存释放器 V3.3

    还有一些其他类型的缓存,如执行存储过程时,Sql Server需要先编译再运行,编译后的结果也会缓存起来,下一次就无需再次编译了。 这个软件就是为了解决大家的这个问题. 2012年8月11日 3.3版本 1.修正一些软件错误...

    JDBC笔记 JDBC笔记

    java.sql.PreparedStatement 继承Statement接口,表示预编译的SQL语句的对象,SQL语句被预编译并且存储在PreparedStatement对象中。然后可以使用此对象高效地多次执行该语句。 java.sql.CallableStatement 用来...

    剑儿SQL Server内存释放器 v3.3.zip

    还有一些其他类型的缓存,如执行存储过程时,Sql Server需要先编译再运行,编译后的结果也会缓存起来,下一次就无需再次编译了。 这个软件就是为了解决大家的这个问题。 剑儿SQL Server内存释放器 v3.2更新内容: ...

    剑儿SQL Server内存释放器1.0

    还有一些其他类型的缓存,如执行存储过程时,Sql Server需要先编译再运行,编译后的结果也会缓存起来,下一次就无需再次编译了。 这个软件就是为了解决大家的这个问题. ========== 作者:剑儿 QQ:157322145 ★...

    mysqli预处理编译的深入理解

    这些处理很慢的,php里面有很多操作mysql数据库的函数,无非是把sql语句传递给mysql数据库,真正处理sql语句的是mysql,mysql数据库是要编译sql语句进行执行的,上面这两种操作会对相同的sql语句进行多次编译,有这...

    PL/SQL Developer8.04官网程序_keygen_汉化

    另外,还含有历史缓存,您可以轻松调用先前执行过的SQL语句。该SQL编辑器提供了同PL/SQL编辑器相同的强大特性。 命令窗口  使用PL/SQL Developer 的命令窗口能够开发并运行SQL脚本。该窗口具有同SQL*Plus相同的感观...

Global site tag (gtag.js) - Google Analytics