`
lbmydream
  • 浏览: 17336 次
  • 性别: 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);
}
}
分享到:
评论

相关推荐

    Oracle批处理:使用C# 自带Oracle驱动一次执行多条Sql语句

    执行批处理时,我们不需要调用多次ExecuteNonQuery()方法,而是只需调用一次,即可执行所有SQL语句: ```csharp int rowsAffected = command.ExecuteNonQuery(); Console.WriteLine("Rows affected: " + rows...

    java批量执行SQL

    在Java开发过程中,经常需要与数据库进行交互,尤其是在处理大量数据时,如何高效地执行SQL语句变得尤为重要。本文将详细介绍如何利用Java进行批量SQL执行,包括其背景、实现原理、代码示例及优化策略等。 #### 一...

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

    在了解这个问题之前,我们通常认为存储过程具有以下优点:首先,存储过程只在创造时进行编译即可,以后每次执行存储过程都不需再重新编译,而我们通常使用的 SQL 语句每执行一次就编译一次,所以使用存储过程可以...

    SQL语句执行顺序说明

    4. **减少访问数据库的次数**:在一个SQL语句中尽量减少对同一张表的多次访问。例如,可以通过JOIN操作一次性获取所需的所有数据,而不是通过多个独立的查询。 5. **使用DECODE函数来减少处理时间**:使用DECODE...

    sql语句中用问号代替参数

    2. **提高性能**:预编译的SQL语句可以在数据库中缓存,多次执行相同结构但不同参数的查询时,可以显著提高执行效率。数据库只需解析一次SQL模板,然后用新参数替换问号即可。 3. **减少错误**:动态构建SQL字符串...

    SQL语句使用教程

    在实际工作中,你可能还会遇到事务处理(用于确保数据的一致性和完整性),视图(虚拟表)以及存储过程(预编译的SQL语句集合)等概念。 在MySQL中,还有一些特定的特性,比如索引的创建和管理,触发器的使用,以及...

    如何使用ORACLE中的高级动态SQL语句.pdf

    2. 预编译/执行语句:使用`PREPARE`和`EXECUTE`,首先预编译SQL语句,然后多次执行。 3. 预编译/成组取语句:结合`PREPARE`, `OPEN`, 和 `FETCH`,可以用于批量处理结果集。 4. 高级动态SQL语句:使用赋值和定义描述...

    java_JDBC预编译相关知识点参照.pdf

    - **提高效率**:预编译语句通过提前编译减少了数据库的解析和语法检查工作,尤其对于需要多次执行的SQL语句,避免了重复编译,从而节省了处理时间,提升了执行效率。 - **增强安全性**:预编译语句可以防止SQL...

    非常好用的SQL语句优化34条+sql语句基础

    20. **预编译SQL语句**:在多次执行相同的SQL时,预编译可以提高执行速度。 21. **数据库设计优化**:合理的设计模式,如范式化和反范式化,可以帮助优化数据存储和查询效率。 22. **分区表**:对于大数据量的表,...

    JDBC+注册驱动+获取连接+定义sql语句+获取执行sql对象+执行sql

    `PreparedStatement`用于预编译SQL,可以防止SQL注入,提高性能,适用于多次执行相同的SQL语句。而`Statement`则用于执行一次性SQL命令。下面是一个`PreparedStatement`的例子: ```java String sql = "INSERT INTO ...

    《SQL预编译和批量提交对性能提升效果探索》测试代码

    这种方式可以避免SQL注入攻击,同时由于编译过程只需要进行一次,对于多次执行相同结构但不同参数的SQL语句,预编译能显著提高执行效率。例如,在Java的JDBC中,我们可以使用PreparedStatement对象来实现预编译,它...

    SQL语句英文翻译成中文

    6. **PREPARE** - 预编译SQL语句,提高执行效率。 7. **EXECUTE** - 动态执行已准备好的SQL语句。 8. **DESCRIBE** - 描述准备好的查询,显示其结构。 **局部变量** - 在BEGIN...END块内声明的变量,如`DECLARE @id...

    JAVA的SQL帮助类,帮助快速使用SQL语句更新,删除,查询数据

    7. **性能优化**:可能包含批处理(Batch Processing)功能,允许一次性执行多条SQL语句,提升效率。 在实际项目中,开发者只需关注SQL语句本身,无需关心数据库连接的创建和关闭,这极大地提高了开发效率。例如,...

    常用Sql注入语句 常用Sql注入语句

    2. Prepared Statements:使用预编译语句可以防止 SQL 注入。 3. Error Handling:正确处理错误信息,避免泄露敏感信息。 常用 Sql 注入语句: 1. SELECT * FROM Users WHERE Username='$username' AND Password='...

    SQL语句集锦 SQL语句集锦

    - **PREPARE**:预编译SQL语句,提高执行效率。 - **EXECUTE**:执行已准备好的SQL语句。 - **DESCRIBE**:描述预编译查询的结构。 6. **局部变量**和**全局变量**: - **DECLARE**:声明局部变量,示例中的`@...

    sql 语言批执行语句

    在批量执行SQL语句时,往往需要编写脚本或使用特定的工具来完成。针对“sql语言批执行语句”这个主题,我们可以深入探讨以下几个关键知识点: 1. **批处理(Batch Processing)**: 批处理是SQL中的一个重要概念,...

    最新整理的常用sql语句及优化大全

    3. **减少子查询**:如果可能,应尽可能使用连接查询替代子查询,因为子查询可能导致多次表扫描。 4. **避免在`WHERE`子句中使用`NOT`和`OR`**:这可能导致优化器无法使用索引。 5. **使用`EXPLAIN`分析查询**:`...

    SQL语句大全和存储过程

    1. **性能优化**:存储过程可以缓存执行计划,多次调用比单独执行SQL语句更高效。 2. **模块化编程**:将复杂的逻辑封装起来,便于管理和复用。 3. **安全性**:可以设置访问权限,限制对数据的直接操作。 4. **减少...

    oracle 中使用批处理文件,同时执行,多个.sql文件。

    另外,如果你需要在Java或其他编程语言环境中实现批处理,可以通过JDBC连接Oracle数据库,调用Statement对象的`executeBatch()`方法来执行预编译的SQL语句集合。这通常涉及以下步骤: 1. 创建数据库连接。 2. 预编译...

Global site tag (gtag.js) - Google Analytics