需多次执行sql语句时,使用预编译语句怎么解决

Oracle预编译的SQL语句处理_数据库技术_Linux公社-Linux系统门户网站
你好,游客
Oracle预编译的SQL语句处理
来源:Linux社区&
作者:Magister_Feng
一、预编译的SQL语句处理
预编译语句PreparedStatement 是java.sql中的一个接口,它是Statement的子接口。通过Statement对象执行SQL语句时,需要将SQL语句发送给DBMS,由DBMS首先进行编译后再执行。预编译语句和Statement不同,在创建PreparedStatement 对象时就指定了SQL语句,该语句立即发送给DBMS进行编译。当该编译语句被执行时,DBMS直接运行编译后的SQL语句,而不需要像其他SQL语句那样首先将其编译。预编译的SQL语句处理性能稍微高于普通的传递变量的办法。
&二、预编译语句的作用
·提高效率:当需要对数据库进行数据插入、更新或者删除的时候,程序会发送整个SQL语句给数据库处理和执行。数据库处理一个SQL语句,需要完成解析SQL语句、检查语法和语义以及生成代码;一般说来,处理时间要比执行语句所需要的时间长。预编译语句在创建的时候已经是将指定的SQL语句发送给了DBMS,完成了解析、检查、编译等工作。因此,当一个SQL语句需要执行多次时,使用预编译语句可以减少处理时间,提高执行效率。
·提高安全性:假如有恶意的SQL语句:String sql = "select * from t_student where name= '"+varname+"' and passwd='"+varpasswd+"'";如果我们把" or '1' = '1' "作为varpasswd传入进来.用户名随意,看看会成为什么?select * from&t_student = '随意' and passwd = '' or '1' = '1'; 因为'1'='1'肯定成立,所以可以任何通过验证.更有甚者:把" ';drop table t_"作为varpasswd传入进来,则:select * from tb_name = '随意' and passwd = '';drop table tb_有些数据库是不会让你成功的,但也有很多数据库就可以使这些语句得到执行.而如果使用预编译语句.传入的任何内容就不会和原来的语句发生任何匹配的关系.只要全使用预编译语句,就用不着对传入的数据做任何过虑.而如果使用普通的statement,有可能要对drop,;等做费尽心机的判断和过虑。
三、预编译语句的使用
1、创建 PreparedStatement 对象&&&&&& 以下的代码段(其中 conn 是 Connection 对象)创建包含带4个 IN 参数占位符的 SQL 语句的 PreparedStatement 对象:
&&&&&& String sql = "insert into t_customer values(?,?,?,?)";//组织一条含有参数的SQL语句  PreparedStatement ps = conn.prepareStatement(sql);  ps对象包含语句 insert into t_customer values(?,?,?,?),它已发送给DBMS,并为执行作好了准备。2、传递 IN 参数&&& 在执行 PreparedStatement 对象之前,必须设置每个 ? 参数的值。这可通过调用 setXXX 方法来完成,其中 XXX 是与该参数相应的类型。例如,如果参数具有Java 类型 long,则使用的方法就是 setLong。setXXX 方法的第一个参数是要设置的参数的序数位置,第二个参数是设置给该参数的值。例如,以下代码将第一个参数设为 输进来的account,第二个参数设为 password:  ps.setString(1, account);  ps.setString(2, password); 一旦设置了给定语句的参数值,其值将一直保留,直到被设置为新值或者调用clearParameters()方法清除它为止。代码如下:
相关资讯 & & &
& (07/29/:43)
& (07/29/:55)
& (08/11/:36)
& (07/29/:28)
& (07/29/:37)
& (04/08/:32)
   同意评论声明
   发表
尊重网上道德,遵守中华人民共和国的各项有关法律法规
承担一切因您的行为而直接或间接导致的民事或刑事法律责任
本站管理人员有权保留或删除其管辖留言中的任意内容
本站有权在网站内转载或引用您的评论
参与本评论即表明您已经阅读并接受上述条款 上传我的文档
 下载
 收藏
该文档贡献者很忙,什么也没留下。
 下载此文档
正在努力加载中...
SQLite的SQL语句高速缓存技术
下载积分:5000
内容提示:SQLite的SQL语句高速缓存技术
文档格式:PDF|
浏览次数:74|
上传日期: 14:07:49|
文档星级:
该用户还上传了这些文档
SQLite的SQL语句高速缓存技术
官方公共微信SQL语句预编译
一、预编译的SQL语句处理
预编译语句PreparedStatement 是java.sql中的一个接口,它是Statement的子接口。通过Statement对象执行SQL语句时,需要将SQL语句发送给DBMS,由DBMS首先进行编译后再执行。预编译语句和Statement不同,在创建PreparedStatement 对象时就指定了SQL语句,该语句立即发送给DBMS进行编译。当该编译语句被执行时,DBMS直接运行编译后的SQL语句,而不需要像其他SQL语句那样首先将其编译。预编译的SQL语句处理性能稍微高于普通的传递变量的办法。
二、预编译语句的作用
提高效率:当需要对数据库进行数据插入、更新或者删除的时候,程序会发送整个SQL语句给数据库处理和执行。数据库处理一个SQL语句,需要完成解析SQL语句、检查语法和语义以及生成代码;一般说来,处理时间要比执行语句所需要的时间长。预编译语句在创建的时候已经是将指定的SQL语句发送给了DBMS,完成了解析、检查、编译等工作。因此,当一个SQL语句需要执行多次时,使用预编译语句可以减少处理时间,提高执行效率。
提高安全性:防止sql注入。
三、预编译语句的使用
创建 PreparedStatement 对象
以下的代码段(其中 conn 是 Connection 对象)创建包含带4个 IN 参数占位符的 SQL 语句的 PreparedStatement 对象:
String sql = “insert into t_customer values(?,?,?,?)”;//组织一条含有参数的SQL语句
PreparedStatement ps = conn.prepareStatement(sql);ps对象包含语句 insert into t_customer values(?,?,?,?),它已发送给DBMS,并为执行作好了准备。
传递 IN 参数
在执行 PreparedStatement 对象之前,必须设置每个 ? 参数的值。这可通过调用 setXXX 方法来完成,其中 XXX 是与该参数相应的类型。例如,如果参数具有Java 类型 long,则使用的方法就是 setLong。setXXX 方法的第一个参数是要设置的参数的序数位置,第二个参数是设置给该参数的值。例如,以下代码将第一个参数设为 输进来的account,第二个参数设为 password:
ps.setString(1, account);
ps.setString(2, password);
一旦设置了给定语句的参数值,其值将一直保留,直到被设置为新值或者调用clearParameters()方法清除它为止。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:7202次
排名:千里之外
原创:27篇
转载:21篇
(3)(12)(6)(15)(8)(5)java_database(7)
1. SQL语句的执行过程——Statement直接执行的弊病:
& & 1) SQL语句和编程语言一样,仅仅就会普通的文本字符串,首先数据库引擎无法识别这种文本字符串,而底层的CPU更不理解这些文本字符串(只懂二进制机器指令),因此SQL语句在执行之前肯定需要编译的;
& & 2) SQL语句的执行过程:提交SQL语句 -& 数据库引擎对SQL语句进行编译得到数据库可执行的代码 -& 执行SQL代码;
& & 3) 现在再来看Statement的执行机制:
& & & & &i. Statement的execute系列方法直接将SQL语句作为参数传入并提交给数据库执行;
& & & & &ii. 也就是说每提交一次都需要先经过编译然后再执行;
& & & & &iii. 那么有一个最大的问题就是如果一条SQL语句需要再短时间内被反复执行,那么每次都需要经过编译这样不是效率非常非常低吗??
!!可能你会问哪有需要反复大量执行的相同语句呢?仔细一想可能是的,因此上面说的并不完全精确,精确地讲应该是反复执行一系列模型相似的语句,比如:
!你每次执行时只是values中的值不同,但是总体的语句还是insert into语句,那么你每次提交都需要编译岂不是会把大把时间浪费在编译上面了,非常不值;
2. PreparedStatement的预编译机制——类似于Properties配置文件:
& & 1) 通过Connection(conn)还可以得到另一种SQL语句对象,即PreparedStatement,该方法就是:PreparedStatement Connection.prepareStatement(String sql);
& & 2) 注意细节:这里就不是create了,而是准备一个SQL语句句柄,精确地讲是一个PreparedStatement语句句柄,并且创建该句柄时直接传入了SQL语句;
& & 3) 预编译机制:
& & & & &i. 调用prepareStatement时会直接将该SQL语句提交给数据库进行编译,得到的PreparedStatement句柄其实是一个预编译好的SQL语句;
& & & & &ii. 之后调用PreparedStatement的execute方法(其execute系列方法都是无参的),就直接将该预编译的语句提交给数据库直接运行而不需要再编译一次了;
& & & & &iii. 因此这种方法只需要编译一次就够了,后面就是直接提交执行无需再编译,因此效率最高;
& & 4) 而预编译语句最大的特点就是支持占位符(支持的占位符就是?,代表任意长度的字符串),比如:insert into table1 values(null, ?, ?);
!!也就是说可以用带占位符的SQL语句来创建预编译SQL句柄:PreparedStatement pstmt = conn.prepareStatement(&insert into table1 values(null, ?, ?)&);
!!这样的语句也能通过,也可以成功编译,并且可以再后期决定这些占位符具体的值,即使改变这些值后依然不需要编译而直接提交运行;
& & 5) 设定占位符具体的值:
& & & & i. 可以使用PreparedStatement的setXxx方法设定预编译语句中占位符的值;
& & & & ii. 其原型是这个模式的:void PreparedStatement setXxx(int parameterIndex, Xxx x);
& & & & iii. Xxx几乎涵盖了所有Java基础类型(String、int、double、Date等等);
& & & & iv. parameterIndex代表语句中第几个占位符(从1开始),而x就是具体设定的值;
& & 6) 设置好占位符的值之后无需编译可以直接提交执行;
!!这种机制其实是跟Properties配置文件完全一样,修改值后无需编译即可运行!
& & 7) 直接提交执行:
& & & & &i. 使用PreparedStatement的execute系列方法即可,和Statement的execute系列方法相对应,只不过无需SQL语句参数了,因为已经存在预编译的SQL语句了,因此都是无参的,就表示直接提交执行;
& & & & &ii. 方法:
& & & & & & &a.&ResultSet PreparedStatement.executeQuery();
& & & & & & &b.&int PreparedStatement.executeUpdate();
& & & & & & &c.&boolean PreparedStatement.execute();
!!返回值的意义和Statement的完全相同;
3. 比较直接提交和预编译运行的执行效率(各执行100次):
!!可以看到预编译比直接提交少用很多时间;
4. 预编译SQL的安全性能:
& & 1) 首先最明显的一点就是Statement不支持占位符,因此SQL语句中包含可变内容时必须要进行字符串拼接,而字符串拼接不仅加大了编程的难度,降低了代码的可读性,而且非常容易发生因拼接错误而导致地极难发现的bug,因此从这点来看PreparedStatement更加安全;
& & 2) 其次是字符串拼接容易埋下SQL注入的漏洞:
& & & & &i. SQL注入是指黑客在应用程序端恶意地往查询信息中填写SQL语句实现入侵(因为客户端输入的要查询的信息往往都是一些正常信息,例如姓名、电话、学号等,没人会无聊地往里面输入代码之类的东西);
& & & & &ii. 一个典型的例子:比如SQL语句的目的是select * from member_table where name = input_name and pass = input_ input_name和input_pass是用户在客户端输入框中输入的账号名和登陆密码,如果该查询语句能查询到该用户(即返回记录不为空)就表示该用户登陆成功;
如果用预编译占位符来表示该语句就是:select * from member_table where name = ? and pass = ?; & // 然后后期用input_name和input_pass来填补占位符,这没什么问题
但如果用Statement拼接的方式来写该语句就是:&select * from member_table where name = '& + input_name + &' and pass = '& + input_pass +&'&;,而此时如果黑客在任意一个输入框(账户名或者密码)中填入'or true or'(就比如账户名输入框吧),那么得到的结果就是:
select * from member_table where name = '' or true or '' and pass = '';
!!也就是说最后的逻辑表达式变成了name = ''、true、'' and pass = ''三者通过or连接在了一起,因为or了一个true因此整个where表达式的结果都是true,因此必然会select处记录,因此即使这样也可以正常登陆!!这就被成功入侵了
& & & & &iii. 这最主要是由于不带占位符的拼接必须要用单引号'来包裹SQL字符串,而占位符的填写无需单引号,JDBC会自动将Java变量转换成纯字符串然后再自动加上SQL单引号填入占位符中,即使填入的变量是String str = &'Lala'&,那么JDBC也会将其中的单引号' '转化成纯字符单引号处理,而不会被当做SQL的特殊字符单引号'来处理,因为在SQL中单引号'是字符串常量符号!
5. 占位符使用问题注意:
& & 1) 占位符只能占位SQL语句中的普通值,决不能占位表名、列名、SQL关键字(select、insert等);
& & 2) 原因很简单,以为PreparedStatement的SQL语句是要预编译的,如果关键字、列名、表名等被占位那就直接代表该SQL语句语法错误而无法编译,会直接抛出异常,因此只有不影响编译的部分可用占位符占位!!
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:172831次
积分:3171
积分:3171
排名:第8320名
原创:13篇
转载:825篇
评论:16条
(2)(22)(55)(42)(47)(51)(17)(65)(21)(10)(25)(52)(15)(10)(5)(14)(8)(14)(70)(44)(32)(98)(119)(15)

我要回帖

更多关于 navicat执行sql语句 的文章

 

随机推荐