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 相关文章推荐
BBS(php &amp; mysql)完整版(四)
Oct 09 PHP
常用的PHP数据库操作方法(MYSQL版)
Jun 08 PHP
php中防止伪造跨站请求的小招式
Sep 02 PHP
php模板原理讲解
Nov 13 PHP
php获取数组元素中头一个数组元素值的实现方法
Dec 20 PHP
PHP实用函数分享之去除多余的0
Feb 06 PHP
php实现比较全的数据库操作类
Jun 18 PHP
CI框架入门之MVC简单示例
Nov 21 PHP
PHP手机号中间四位用星号*代替显示的实例
Jun 02 PHP
php将从数据库中获得的数据转换成json格式并输出的方法
Aug 21 PHP
gearman中worker常驻后台,导致MySQL server has gone away的解决方法
Feb 27 PHP
Thinkphp集成抖音SDK的实现方法
Apr 28 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
咖啡的化学
2021/03/03 咖啡文化
PHP内核学习教程之php opcode内核实现
2016/01/27 PHP
thinkphp实现附件上传功能
2017/05/26 PHP
PHP+redis实现的悲观锁机制示例
2018/06/12 PHP
jquery鼠标放上去显示悬浮层即弹出定位的div层
2014/04/25 Javascript
javascript动画之模拟拖拽效果篇
2016/09/26 Javascript
JS三目运算(三元运算)方法详解
2017/03/01 Javascript
js实现水平滚动菜单导航
2017/07/21 Javascript
Iphone手机、安卓手机浏览器控制默认缩放大小的方法总结(附代码)
2017/08/18 Javascript
提升node.js中使用redis的性能遇到的问题及解决方法
2018/10/30 Javascript
Vue列表循环从指定下标开始的多种解决方案
2020/04/08 Javascript
python插入排序算法的实现代码
2013/11/21 Python
Android 兼容性问题:java.lang.UnsupportedOperationException解决办法
2017/03/19 Python
利用Python将时间或时间间隔转为ISO 8601格式方法示例
2017/09/05 Python
python中文件变化监控示例(watchdog)
2017/10/16 Python
Python递归实现汉诺塔算法示例
2018/03/19 Python
Python3随机漫步生成数据并绘制
2018/08/27 Python
对Xpath 获取子标签下所有文本的方法详解
2019/01/02 Python
django 获取字段最大值,最新的记录操作
2020/08/09 Python
Python Map 函数的使用
2020/08/28 Python
使用Python操作MySQL的小技巧
2020/09/10 Python
python单元测试框架pytest的使用示例
2020/10/07 Python
欧洲第一的摇滚和金属乐队服装网站:EMP
2017/10/26 全球购物
鞋子女王塔玛拉·梅隆同名奢侈品牌:Tamara Mellon
2017/11/22 全球购物
中国首家奢侈品O2O网购平台:第五大道奢侈品网
2017/12/14 全球购物
车间统计员岗位职责
2014/01/05 职场文书
信息技术专业大学生职业生涯规划书
2014/01/24 职场文书
英文留学推荐信范文
2014/01/25 职场文书
会议邀请书范文
2014/02/02 职场文书
2014年公司庆元旦活动方案
2014/03/05 职场文书
学校领导班子四风问题整改意见
2014/10/02 职场文书
银行党员批评与自我批评
2014/10/15 职场文书
迎新生晚会主持词
2015/06/30 职场文书
2016年教师节慰问信
2015/12/01 职场文书
MySQL中rank() over、dense_rank() over、row_number() over用法介绍
2022/03/23 MySQL
Java 多线程并发FutureTask
2022/06/28 Java/Android