pdo中使用参数化查询sql


Posted in PHP onAugust 11, 2011

方法 bindParam() 和 bindValue() 非常相似。
唯一的区别就是前者使用一个PHP变量绑定参数,而后者使用一个值。
所以使用bindParam是第二个参数只能用变量名,而不能用变量值,而bindValue至可以使用具体值。

$stm = $pdo->prepare("select * from users where user = :user"); 
$user = "jack"; 
//正确 
$stm->bindParam(":user",$user); 
//错误 
//$stm->bindParam(":user","jack"); 
//正确 
$stm->bindValue(":user",$user); 
//正确 
$stm->bindValue(":user","jack");

另外在存储过程中,bindParam可以绑定为input/output变量,如下面:
$stm = $pdo->prepare("call func(:param1)"); 
$param1 = "abcd"; 
$stm->bindParam(":param1",$param1); //正确 
$stm->execute();

存储过程执行过后的结果可以直接反应到变量上。
对于那些内存中的大数据块参数,处于性能的考虑,应优先使用前者。
--------------------------------------------------
http://zh.wikipedia.org/wiki/%E5%8F%83%E6%95%B8%E5%8C%96%E6%9F%A5%E8%A9%A2
参数化查询
参数化查询(Parameterized Query 或 Parameterized Statement)是指在设计与数据库连结并访问数据时,在需要填入数值或数据的地方,使用参数 (Parameter) 来给值,这个方法目前已被视为最有效可预防SQL注入攻击 (SQL Injection) 的攻击手法的防御方式。有部份的开发人员可能会认为使用参数化查询,会让程序更不好维护,或者在实现部份功能上会非常不便[来源请求],然而,使用参数化查询造成的额外开发成本,通常都远低于因为SQL注入攻击漏洞被发现而遭受攻击,所造成的重大损失。
除了安全因素,相比起拼接字符串的 SQL 语句,参数化的查询往往有性能优势。因为参数化的查询能让不同的数据通过参数到达数据库,从而公用同一条 SQL 语句。大多数数据库会缓存解释 SQL 语句产生的字节码而省下重复解析的开销。如果采取拼接字符串的 SQL 语句,则会由于操作数据是 SQL 语句的一部分而非参数的一部分,而反复大量解释 SQL 语句产生不必要的开销。
目录
* 1 原理
* 2 SQL 指令撰写方法
o 2.1 Microsoft SQL Server
o 2.2 Microsoft Access
o 2.3 MySQL
o 2.4 PostgreSQL/SQLite
* 3 客户端程序撰写方法
o 3.1 ADO.NET
o 3.2 PDO
o 3.3 JDBC
o 3.4 Cold Fusion
[编辑] 原理
在使用参数化查询的情况下,数据库服务器不会将参数的内容视为SQL指令的一部份来处理,而是在数据库完成 SQL 指令的编译后,才套用参数运行,因此就算参数中含有具破坏性的指令,也不会被数据库所运行。
[编辑] SQL 指令撰写方法
在撰写 SQL 指令时,利用参数来代表需要填入的数值,例如:
[编辑] Microsoft SQL Server
Microsoft SQL Server 的参数格式是以 "@" 字符加上参数名称而成,SQL Server 亦支持匿名参数 "?"。
SELECT * FROM myTable WHERE myID = @myID
INSERT INTO myTable (c1, c2, c3, c4) VALUES (@c1, @c2, @c3, @c4)
[编辑] Microsoft Access
Microsoft Access 不支持具名参数,只支持匿名参数 "?"。
UPDATE myTable SET c1 = ?, c2 = ?, c3 = ? WHERE c4 = ?
[编辑] MySQL
MySQL 的参数格式是以 "?" 字符加上参数名称而成。
UPDATE myTable SET c1 = ?c1, c2 = ?c2, c3 = ?c3 WHERE c4 = ?c4
[编辑] PostgreSQL/SQLite
PostgreSQL 和 SQLite 的参数格式是以 “:” 加上参数名而成。当然,也支持类似 Access 的匿名参数。
UPDATE "myTable" SET "c1" = :c1, "c2" = :c2, "c3" = :c3 WHERE "c4" = :c4
[编辑] 客户端程序撰写方法
在客户端代码中撰写使用参数的代码,例如:
[编辑] ADO.NET
ADO.NET用于ASP.NET之内。
SqlCommand sqlcmd = new SqlCommand("INSERT INTO myTable (c1, c2, c3, c4) VALUES (@c1, @c2, @c3, @c4)", sqlconn);
sqlcmd.Parameters.AddWithValue("@c1", 1); // ?定?? @c1 的值。
sqlcmd.Parameters.AddWithValue("@c2", 2); // ?定?? @c2 的值。
sqlcmd.Parameters.AddWithValue("@c3", 3); // ?定?? @c3 的值。
sqlcmd.Parameters.AddWithValue("@c4", 4); // ?定?? @c4 的值。
sqlconn.Open();
sqlcmd.ExecuteNonQuery();
sqlconn.Close();
[编辑] PDO
PDO用于PHP之内。 在使用 PDO 驱动时,参数查询的使用方法一般为:
// 实例化数据抽象层对象 
$db = new PDO('pgsql:host=127.0.0.1;port=5432;dbname=testdb'); 
// 对 SQL 语句执行 prepare,得到 PDOStatement 对象 
$stmt = $db->prepare('SELECT * FROM "myTable" WHERE "id" = :id AND "is_valid" = :is_valid'); 
// 绑定参数 
$stmt->bindValue(':id', $id); 
$stmt->bindValue(':is_valid', true); 
// 查询 
$stmt->execute(); 
// 获取数据 
foreach($stmt as $row) { 
var_dump($row); 
} 
[code] 
对于 MySQL 的特定驱动,也可以这样使用: 
$db = new mysqli("localhost", "user", "pass", "database"); 
$stmt = $mysqli -> prepare("SELECT priv FROM testUsers WHERE username=? AND password=?"); 
$stmt -> bind_param("ss", $user, $pass); 
$stmt -> execute(); 
值得注意的是,以下方式虽然能有效防止 SQL注入 (归功于 mysql_real_escape_string 函数的转义),但并不是真正的参数化查询。其本质仍然是拼接字符串的 SQL 语句。 
[code] 
$query = sprintf("SELECT * FROM Users where UserName='%s' and Password='%s'", 
mysql_real_escape_string($Username), 
mysql_real_escape_string($Password)); 
mysql_query($query);

[编辑] JDBC
JDBC用于Java之内。
java.sql.PreparedStatement prep = connection.prepareStatement(
"SELECT * FROM `users` WHERE USERNAME = ? AND PASSWORD = ?");
prep.setString(1, username);
prep.setString(2, password);
prep.executeQuery();
[编辑] Cold Fusion
<cfquery name="Recordset1" datasource="cafetownsend">
SELECT *
FROM COMMENTS
WHERE COMMENT_ID =<cfqueryparam value="#URL.COMMENT_ID#" cfsqltype="cf_sql_numeric">
</cfquery>
PHP 相关文章推荐
用PHP实现WEB动态网页静态
Oct 09 PHP
洪恩在线成语词典小偷程序php版
Apr 20 PHP
解析PHP中intval()等int转换时的意外异常情况
Jun 21 PHP
PHP curl伪造IP地址和header信息代码实例
Apr 27 PHP
php猴子选大王问题解决方法
May 12 PHP
ThinkPHP路由机制简介
Mar 23 PHP
php简单统计在线人数的方法
May 10 PHP
Laravel Memcached缓存驱动的配置与应用方法分析
Oct 08 PHP
thinkPHP自定义类实现方法详解
Nov 30 PHP
thinkPHP框架实现的短信接口验证码功能示例
Jun 20 PHP
php语法检查的方法总结
Jan 21 PHP
Laravel如何实现适合Api的异常处理响应格式
Jun 14 PHP
php 广告调用类代码(支持Flash调用)
Aug 11 #PHP
php 中英文语言转换类代码
Aug 11 #PHP
php中计算中文字符串长度、截取中文字符串的函数代码
Aug 09 #PHP
php数据结构 算法(PHP描述) 简单选择排序 simple selection sort
Aug 09 #PHP
php的urlencode()URL编码函数浅析
Aug 09 #PHP
php简单的会话类代码
Aug 08 #PHP
php中将时间差转换为字符串提示的实现代码
Aug 08 #PHP
You might like
PHP数字格式化
2006/12/06 PHP
JS异常处理try..catch语句的作用和实例
2014/05/05 PHP
php中json_encode UTF-8中文乱码的更好解决方法
2014/09/28 PHP
php制作的简单验证码识别代码
2016/01/26 PHP
laravel自定义分页的实现案例offset()和limit()
2019/10/15 PHP
jQuery数据显示插件整合实现代码
2011/10/24 Javascript
JQuery的Ajax请求实现局部刷新的简单实例
2014/02/11 Javascript
Javascript中常用类型的格式化方法小结
2016/12/26 Javascript
javascript+css3开发打气球小游戏完整代码
2017/11/28 Javascript
angular2实现统一的http请求头方法
2018/08/13 Javascript
微信小程序左滑删除功能开发案例详解
2018/11/12 Javascript
JavaScript利用键盘码控制div移动
2020/03/19 Javascript
如何使用JavaScript实现无缝滚动自动播放轮播图效果
2020/08/20 Javascript
[04:44]DOTA2英雄梦之声_第12期_矮人直升机
2014/06/21 DOTA
星球大战与Python之间的那些事
2016/01/07 Python
Python实现获取前100组勾股数的方法示例
2018/05/04 Python
获取python的list中含有重复值的index方法
2018/06/27 Python
python单例模式的多种实现方法
2019/07/26 Python
python实现图片横向和纵向拼接
2020/03/05 Python
python中 _、__、__xx__()区别及使用场景
2020/06/30 Python
scrapy在python爬虫中搭建出错的解决方法
2020/11/22 Python
美国婚礼和派对礼品网站:Kate Aspen(新娘送礼会、迎婴派对)
2018/03/28 全球购物
女子锻炼服装和瑜伽服装:Splits59
2019/03/04 全球购物
计算机专业大学生的自我评价
2013/11/14 职场文书
《北大荒的秋天》教学反思
2014/04/14 职场文书
励志广播稿300字(5篇)
2014/09/15 职场文书
镇党政领导班子民主生活会思想汇报
2014/10/11 职场文书
病人家属写给医院的感谢信
2015/01/23 职场文书
药店营业员岗位职责
2015/04/14 职场文书
《狮子和鹿》教学反思
2016/02/16 职场文书
实用求职信模板范文
2019/05/13 职场文书
解决go在函数退出后子协程的退出问题
2021/04/30 Golang
MySQL系列之十二 备份与恢复
2021/07/02 MySQL
springboot集成springCloud中gateway时启动报错的解决
2021/07/16 Java/Android
JVM之方法返回地址详解
2022/02/28 Java/Android
2022年四月新番
2022/03/15 日漫