回調(diào)函數(shù)。
虞城網(wǎng)站建設(shè)公司創(chuàng)新互聯(lián),虞城網(wǎng)站設(shè)計(jì)制作,有大型網(wǎng)站制作公司豐富經(jīng)驗(yàn)。已為虞城1000+提供企業(yè)網(wǎng)站建設(shè)服務(wù)。企業(yè)網(wǎng)站搭建\外貿(mào)網(wǎng)站制作要多少錢,請找那個(gè)售后服務(wù)好的虞城做網(wǎng)站的公司定做!
1.快取一行
FetchColumn是為應(yīng)用程序取得一個(gè)僅包含單列的數(shù)據(jù),代碼如下:
$u = $db-query(“SELECT id FROM users WHERE login=
‘login’ AND password=‘password’”);
fetch(PDO::FETCH_COLUMN)
if ($u-fetchColumn()) { //返回一個(gè)字符串
//登錄成功
} else {
//驗(yàn)證失敗
}
?
2.取得一個(gè)標(biāo)準(zhǔn)對象
還可以將取得的一行作為一個(gè)標(biāo)準(zhǔn)類stdClass的對象實(shí)例,其中列名=屬性名。
$res = $db-query(“SELECT * FROM foo”);
while ($obj = $res-fetch(PDO::FETCH_OBJ)) {
// $obj == instance of stdClass
}
?
3.存取為一個(gè)類
PDO允許將結(jié)果保存為一個(gè)類,例子如下:
$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.從一個(gè)類取得常量
PDO允許查詢的結(jié)果可以被用來生成一個(gè)目的類。
$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.存取為一個(gè)對象
PDO還允許獲取數(shù)據(jù)到一個(gè)已經(jīng)存在的對象。
$u = new userObject;
$res = $db-query(“SELECT * FROM users”);
$res-setFetchMode(PDO::FETCH_INTO, $u);
while ($res-fetch()) {
// 取得的記錄集將放在$u這個(gè)對象變量中,在此顯示
}
?
6.存取為關(guān)聯(lián)數(shù)據(jù)
PDO實(shí)現(xiàn)了迭代器(Iteator)接口,允許一個(gè)方法實(shí)現(xiàn)迭代的功能。
$res = $db-query(
“SELECT * FROM users”,
PDO::FETCH_ASSOC
);
foreach ($res as $row) {
// $row是一個(gè)關(guān)聯(lián)數(shù)組,可以直接顯示,如$row['id']
}
?
7.fetchAll()方法
PDO也提供了和ADODB類似的fetchAll()方法,它允許從一個(gè)結(jié)果集中取得數(shù)據(jù),然后放于關(guān)聯(lián)數(shù)組中。
$db-setAttribute(PDO::ATTR_CASE, PDO::CASE_UPPER);
$qry = “SELECT * FROM users”;
$res = $db-query($qry)-fetchAll(PDO::FETCH_ASSOC);
?
或者獲取到索引數(shù)組里:
$res = $db-query("SELECT * FROM foo");
$result_arr = $res-fetchAll();
print_r($result_arr);
?
數(shù)字索引數(shù)組比較浪費(fèi)資源,請盡量使用關(guān)聯(lián)數(shù)組,這樣可以在內(nèi)存中使用相當(dāng)密集的大型結(jié)果集。
相關(guān)說明如下:
setAttribute()方法用于設(shè)置部分屬性,主要屬性有:PDO::ATTR_CASE、PDO::ATTR_ERRMODE等,這里需要設(shè)置的是PDO::ATTR_CASE,就是使用關(guān)聯(lián)索引獲取數(shù)據(jù)集時(shí),關(guān)聯(lián)索引是大寫還是小寫,有如下幾個(gè)選擇:
PDO::CASE_LOWER——強(qiáng)制列名是小寫;
PDO::CASE_NATURAL——列名按照原始的方式;
PDO::CASE_UPPER——強(qiáng)制列名為大寫。
我們使用setFetchMode方法來設(shè)置獲取結(jié)果集的返回值的數(shù)據(jù)類型,類型有:
PDO::FETCH_ASSOC——關(guān)聯(lián)數(shù)組形式;
PDO::FETCH_NUM——數(shù)字索引數(shù)組形式;
PDO::FETCH_BOTH——兩種數(shù)組形式都有,這是默認(rèn)的;
PDO::FETCH_OBJ——按照對象的形式,類似于以前的 mysql_fetch_object()。
當(dāng)然,一般情況下,我們使用PDO::FETCH_ASSOC取得關(guān)聯(lián)數(shù)組。具體使用哪種類型,應(yīng)按照自己的實(shí)際應(yīng)用選擇。
8.fetchColumn()方法
如果想獲取指定記錄里的一個(gè)字段結(jié)果,則可以使用PDOStatement::fetchColumn()。
$rs = $db-query("SELECT COUNT(*) FROM foo");
$col = $rs-fetchColumn();
echo $col;
?
一般使用fetchColumn()方法進(jìn)行count統(tǒng)計(jì),對某些只需要單字段的記錄可以很好地操作。
9.回調(diào)函數(shù)
PDO還規(guī)定在每一個(gè)fetch模式下,經(jīng)過處理后的結(jié)果中使用一個(gè)回調(diào)函數(shù)。
function draw_message($subject,$email) { … }
$res = $db-query(“SELECT * FROM msg”);
$res-fetchAll(PDO::FETCH_FUNC,“draw_message”);
?
10.直接查詢的問題
直接使用Query查詢行每次都會直接提交給數(shù)據(jù)庫,如果查詢較多,每次頻頻查詢將導(dǎo)致效率降低。
另外,在安全問題上,沒有過濾一些特殊字符容易產(chǎn)生SQL注入。
11.過濾字符
下面我們來看看如何使用PDO進(jìn)行過濾引起SQL注入的方法,即過濾特殊字符。我們在PDO中使用quote()方法,使用例子如下:
$query = “SELECT * FROM users WHERE
login=“.$db-quote($_POST[‘login’]).”
AND
passwd=“.$db-quote($_POST[‘pass’]);
12.事務(wù)處理
PDO驅(qū)動程序支持所有的事務(wù)數(shù)據(jù)庫,并且PDO提供更簡便的方法,如下:
$db-beginTransaction();
if ($db-exec($qry) === FALSE) {
$db-rollback();
}
$db-commit();
?
13.執(zhí)行一個(gè)批處理事務(wù)
在下面的示例中,假設(shè)我們?yōu)橐粋€(gè)新雇員創(chuàng)建一組條目,這個(gè)雇員有一個(gè)ID號,即23。除了輸入這個(gè)雇員的基本數(shù)據(jù)外,還需要記錄雇員的薪水。分別完成兩個(gè)更新很簡單,但通過將這兩個(gè)更新包括在beginTransaction()和commit()調(diào)用中,就可以保證在更改完成之前,其他人無法看到更改。如果發(fā)生了錯(cuò)誤,catch塊可以回滾事務(wù)開始以來發(fā)生的所有更改,并打印出一條錯(cuò)誤消息。代碼內(nèi)容如下:
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();
}
?
//打開數(shù)據(jù)庫
$conn = mysql_connect("localhost","root","密碼");
//設(shè)置編碼
mysql_query("set names utf8");
//選擇數(shù)據(jù)庫
mysql_select_db("庫名");
//查詢操作
$rs = mysql_query("select * from 查詢語句");
while($row = mysql_fetch_array($rs)){
echo "{$row['字段名']}";
echo "{$row['字段名']}";
};
//釋放結(jié)果集
mysql_free_result($rs);
//關(guān)閉數(shù)據(jù)庫
mysql_close($conn);
//手敲代碼,給個(gè)贊唄
方法 bindParam() 和 bindValue() 非常相似。
唯一的區(qū)別就是前者使用一個(gè)PHP變量綁定參數(shù),而后者使用一個(gè)值。
所以使用bindParam是第二個(gè)參數(shù)只能用變量名,而不能用變量值,而bindValue至可以使用具體值。
復(fù)制代碼 代碼如下:
$stm = $pdo-prepare("select * from users where user = :user");
$user = "jack";
//正確
$stm-bindParam(":user",$user);
//錯(cuò)誤
//$stm-bindParam(":user","jack");
//正確
$stm-bindValue(":user",$user);
//正確
$stm-bindValue(":user","jack");
另外在存儲過程中,bindParam可以綁定為input/output變量,如下面:
復(fù)制代碼 代碼如下:
$stm = $pdo-prepare("call func(:param1)");
$param1 = "abcd";
$stm-bindParam(":param1",$param1); //正確
$stm-execute();
存儲過程執(zhí)行過后的結(jié)果可以直接反應(yīng)到變量上。
對于那些內(nèi)存中的大數(shù)據(jù)塊參數(shù),處于性能的考慮,應(yīng)優(yōu)先使用前者。
--------------------------------------------------
參數(shù)化查詢
參數(shù)化查詢(Parameterized Query 或 Parameterized Statement)是指在設(shè)計(jì)與數(shù)據(jù)庫連結(jié)并訪問數(shù)據(jù)時(shí),在需要填入數(shù)值或數(shù)據(jù)的地方,使用參數(shù) (Parameter) 來給值,這個(gè)方法目前已被視為最有效可預(yù)防SQL注入攻擊 (SQL Injection) 的攻擊手法的防御方式。有部份的開發(fā)人員可能會認(rèn)為使用參數(shù)化查詢,會讓程序更不好維護(hù),或者在實(shí)現(xiàn)部份功能上會非常不便[來源請求],然而,使用參數(shù)化查詢造成的額外開發(fā)成本,通常都遠(yuǎn)低于因?yàn)镾QL注入攻擊漏洞被發(fā)現(xiàn)而遭受攻擊,所造成的重大損失。
除了安全因素,相比起拼接字符串的 SQL 語句,參數(shù)化的查詢往往有性能優(yōu)勢。因?yàn)閰?shù)化的查詢能讓不同的數(shù)據(jù)通過參數(shù)到達(dá)數(shù)據(jù)庫,從而公用同一條 SQL 語句。大多數(shù)數(shù)據(jù)庫會緩存解釋 SQL 語句產(chǎn)生的字節(jié)碼而省下重復(fù)解析的開銷。如果采取拼接字符串的 SQL 語句,則會由于操作數(shù)據(jù)是 SQL 語句的一部分而非參數(shù)的一部分,而反復(fù)大量解釋 SQL 語句產(chǎn)生不必要的開銷。
目錄
* 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
[編輯] 原理
在使用參數(shù)化查詢的情況下,數(shù)據(jù)庫服務(wù)器不會將參數(shù)的內(nèi)容視為SQL指令的一部份來處理,而是在數(shù)據(jù)庫完成 SQL 指令的編譯后,才套用參數(shù)運(yùn)行,因此就算參數(shù)中含有具破壞性的指令,也不會被數(shù)據(jù)庫所運(yùn)行。
[編輯] SQL 指令撰寫方法
在撰寫 SQL 指令時(shí),利用參數(shù)來代表需要填入的數(shù)值,例如:
[編輯] Microsoft SQL Server
Microsoft SQL Server 的參數(shù)格式是以 "@" 字符加上參數(shù)名稱而成,SQL Server 亦支持匿名參數(shù) "?"。
SELECT * FROM myTable WHERE myID = @myID
INSERT INTO myTable (c1, c2, c3, c4) VALUES (@c1, @c2, @c3, @c4)
[編輯] Microsoft Access
Microsoft Access 不支持具名參數(shù),只支持匿名參數(shù) "?"。
UPDATE myTable SET c1 = ?, c2 = ?, c3 = ? WHERE c4 = ?
[編輯] MySQL
MySQL 的參數(shù)格式是以 "?" 字符加上參數(shù)名稱而成。
UPDATE myTable SET c1 = ?c1, c2 = ?c2, c3 = ?c3 WHERE c4 = ?c4
[編輯] PostgreSQL/SQLite
PostgreSQL 和 SQLite 的參數(shù)格式是以 “:” 加上參數(shù)名而成。當(dāng)然,也支持類似 Access 的匿名參數(shù)。
UPDATE "myTable" SET "c1" = :c1, "c2" = :c2, "c3" = :c3 WHERE "c4" = :c4
[編輯] 客戶端程序撰寫方法
在客戶端代碼中撰寫使用參數(shù)的代碼,例如:
[編輯] ADO.NET
ADO.NET用于ASP.NET之內(nèi)。
SqlCommand sqlcmd = new SqlCommand("INSERT INTO myTable (c1, c2, c3, c4) VALUES (@c1, @c2, @c3, @c4)", sqlconn);
sqlcmd.Parameters.AddWithValue("@c1", 1); // 設(shè)定參數(shù) @c1 的值。
sqlcmd.Parameters.AddWithValue("@c2", 2); // 設(shè)定參數(shù) @c2 的值。
sqlcmd.Parameters.AddWithValue("@c3", 3); // 設(shè)定參數(shù) @c3 的值。
sqlcmd.Parameters.AddWithValue("@c4", 4); // 設(shè)定參數(shù) @c4 的值。
sqlconn.Open();
sqlcmd.ExecuteNonQuery();
sqlconn.Close();
[編輯] PDO
PDO用于PHP之內(nèi)。 在使用 PDO 驅(qū)動時(shí),參數(shù)查詢的使用方法一般為:
復(fù)制代碼 代碼如下:
// 實(shí)例化數(shù)據(jù)抽象層對象
$db = new PDO('pgsql:host=127.0.0.1;port=5432;dbname=testdb');
// 對 SQL 語句執(zhí)行 prepare,得到 PDOStatement 對象
$stmt = $db-prepare('SELECT * FROM "myTable" WHERE "id" = :id AND "is_valid" = :is_valid');
// 綁定參數(shù)
$stmt-bindValue(':id', $id);
$stmt-bindValue(':is_valid', true);
// 查詢
$stmt-execute();
// 獲取數(shù)據(jù)
foreach($stmt as $row) {
var_dump($row);
}
[code]
對于 MySQL 的特定驅(qū)動,也可以這樣使用:
$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 函數(shù)的轉(zhuǎn)義),但并不是真正的參數(shù)化查詢。其本質(zhì)仍然是拼接字符串的 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之內(nèi)。
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表里有多條數(shù)據(jù)
$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'];
}
}
這是取多個(gè)
取單個(gè)的
$row=$pdo-prepare(select * from A) //A表里有多條數(shù)據(jù)
$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'];
}