扫二维码与项目经理沟通
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流
回调函数。
虞城网站建设公司创新互联,虞城网站设计制作,有大型网站制作公司丰富经验。已为虞城1000+提供企业网站建设服务。企业网站搭建\外贸网站制作要多少钱,请找那个售后服务好的虞城做网站的公司定做!
1.快取一行
FetchColumn是为应用程序取得一个仅包含单列的数据,代码如下:
$u = $db-query(“SELECT id FROM users WHERE login=
‘login’ AND password=‘password’”);
fetch(PDO::FETCH_COLUMN)
if ($u-fetchColumn()) { //返回一个字符串
//登录成功
} else {
//验证失败
}
?
2.取得一个标准对象
还可以将取得的一行作为一个标准类stdClass的对象实例,其中列名=属性名。
$res = $db-query(“SELECT * FROM foo”);
while ($obj = $res-fetch(PDO::FETCH_OBJ)) {
// $obj == instance of stdClass
}
?
3.存取为一个类
PDO允许将结果保存为一个类,例子如下:
$res = $db-query(“SELECT * FROM foo”);
$res-setFetchMode(
PDO::FETCH_CLASS,
“className”,
array(‘optional’=‘Constructor Params’)
);
while ($obj = $res-fetch()) {
// $obj == instance of className
}
?
4.从一个类取得常量
PDO允许查询的结果可以被用来生成一个目的类。
$res = $db-query(“SELECT * FROM foo”);
$res-setFetchMode(
PDO::FETCH_CLASS |
PDO::FETCH_CLASSTYPE
);
while ($obj = $res-fetch()) {
// $obj == instance of class who’s name is
// found in the value of the 1st column
}
?
5.存取为一个对象
PDO还允许获取数据到一个已经存在的对象。
$u = new userObject;
$res = $db-query(“SELECT * FROM users”);
$res-setFetchMode(PDO::FETCH_INTO, $u);
while ($res-fetch()) {
// 取得的记录集将放在$u这个对象变量中,在此显示
}
?
6.存取为关联数据
PDO实现了迭代器(Iteator)接口,允许一个方法实现迭代的功能。
$res = $db-query(
“SELECT * FROM users”,
PDO::FETCH_ASSOC
);
foreach ($res as $row) {
// $row是一个关联数组,可以直接显示,如$row['id']
}
?
7.fetchAll()方法
PDO也提供了和ADODB类似的fetchAll()方法,它允许从一个结果集中取得数据,然后放于关联数组中。
$db-setAttribute(PDO::ATTR_CASE, PDO::CASE_UPPER);
$qry = “SELECT * FROM users”;
$res = $db-query($qry)-fetchAll(PDO::FETCH_ASSOC);
?
或者获取到索引数组里:
$res = $db-query("SELECT * FROM foo");
$result_arr = $res-fetchAll();
print_r($result_arr);
?
数字索引数组比较浪费资源,请尽量使用关联数组,这样可以在内存中使用相当密集的大型结果集。
相关说明如下:
setAttribute()方法用于设置部分属性,主要属性有:PDO::ATTR_CASE、PDO::ATTR_ERRMODE等,这里需要设置的是PDO::ATTR_CASE,就是使用关联索引获取数据集时,关联索引是大写还是小写,有如下几个选择:
PDO::CASE_LOWER——强制列名是小写;
PDO::CASE_NATURAL——列名按照原始的方式;
PDO::CASE_UPPER——强制列名为大写。
我们使用setFetchMode方法来设置获取结果集的返回值的数据类型,类型有:
PDO::FETCH_ASSOC——关联数组形式;
PDO::FETCH_NUM——数字索引数组形式;
PDO::FETCH_BOTH——两种数组形式都有,这是默认的;
PDO::FETCH_OBJ——按照对象的形式,类似于以前的 mysql_fetch_object()。
当然,一般情况下,我们使用PDO::FETCH_ASSOC取得关联数组。具体使用哪种类型,应按照自己的实际应用选择。
8.fetchColumn()方法
如果想获取指定记录里的一个字段结果,则可以使用PDOStatement::fetchColumn()。
$rs = $db-query("SELECT COUNT(*) FROM foo");
$col = $rs-fetchColumn();
echo $col;
?
一般使用fetchColumn()方法进行count统计,对某些只需要单字段的记录可以很好地操作。
9.回调函数
PDO还规定在每一个fetch模式下,经过处理后的结果中使用一个回调函数。
function draw_message($subject,$email) { … }
$res = $db-query(“SELECT * FROM msg”);
$res-fetchAll(PDO::FETCH_FUNC,“draw_message”);
?
10.直接查询的问题
直接使用Query查询行每次都会直接提交给数据库,如果查询较多,每次频频查询将导致效率降低。
另外,在安全问题上,没有过滤一些特殊字符容易产生SQL注入。
11.过滤字符
下面我们来看看如何使用PDO进行过滤引起SQL注入的方法,即过滤特殊字符。我们在PDO中使用quote()方法,使用例子如下:
$query = “SELECT * FROM users WHERE
login=“.$db-quote($_POST[‘login’]).”
AND
passwd=“.$db-quote($_POST[‘pass’]);
12.事务处理
PDO驱动程序支持所有的事务数据库,并且PDO提供更简便的方法,如下:
$db-beginTransaction();
if ($db-exec($qry) === FALSE) {
$db-rollback();
}
$db-commit();
?
13.执行一个批处理事务
在下面的示例中,假设我们为一个新雇员创建一组条目,这个雇员有一个ID号,即23。除了输入这个雇员的基本数据外,还需要记录雇员的薪水。分别完成两个更新很简单,但通过将这两个更新包括在beginTransaction()和commit()调用中,就可以保证在更改完成之前,其他人无法看到更改。如果发生了错误,catch块可以回滚事务开始以来发生的所有更改,并打印出一条错误消息。代码内容如下:
try {
$dbh = new PDO('odbc:SAMPLE', 'db2inst1', 'ibmdb2',
array(PDO_ATTR_PERSISTENT = true));
echo "Connected\n";
$dbh-setAttribute(PDO_ATTR_ERRMODE, PDO_ERRMODE_EXCEPTION);
$dbh-beginTransaction();
$dbh-exec("insert into staff (id, first, last)
values (23, 'Joe', 'Bloggs')");
$dbh-exec("insert into salarychange (id, amount, changedate)
values (23, 50000, NOW())");
$dbh-commit();
} catch (Exception $e) {
$dbh-rollBack();
echo "Failed: " . $e-getMessage();
}
?
//打开数据库
$conn = mysql_connect("localhost","root","密码");
//设置编码
mysql_query("set names utf8");
//选择数据库
mysql_select_db("库名");
//查询操作
$rs = mysql_query("select * from 查询语句");
while($row = mysql_fetch_array($rs)){
echo "{$row['字段名']}";
echo "{$row['字段名']}";
};
//释放结果集
mysql_free_result($rs);
//关闭数据库
mysql_close($conn);
//手敲代码,给个赞呗
方法 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();
存储过程执行过后的结果可以直接反应到变量上。
对于那些内存中的大数据块参数,处于性能的考虑,应优先使用前者。
--------------------------------------------------
参数化查询
参数化查询(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
$row=$pdo-prepare(select * from A) //A表里有多条数据
$row-execute();
while($rs=$row-fetch()){
echo $rs[aid];
foreach ($pdo-query('select * from B where pid=’.$rs['id'].' order by bid asc') as $res) {
echo $res['bid'];
}
}
这是取多个
取单个的
$row=$pdo-prepare(select * from A) //A表里有多条数据
$row-execute();
while($rs=$row-fetch()){
echo $rs[aid];
$re=$pdo-query('select * from B where pid='.$rs['id'].' order by bid asc');
$res=$re-fetch();
echo $res['bid'];
}
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流