OSWikiHK: 請協力 GPLv3 的中文翻譯工作。

PEAR::DB SQL statement

OSWikiHK,自由中文開源知識庫

大家都應該知道什麼是 SQL,我也不想花時間在這類基本慨念問題 ,有興趣的可以到 http://www.onlamp.com/mysql/onlamp/general/mysql.csp ,裡面一些 SQL 的淺介。

SELECT 命令可算是 SQL 中最重要的命令,其他命令如 INSERTUPDATE 和 DELETE 主要都是用作修改資料庫上的資料, 傳回結果也只是成功或失敗兩種。而 SELECT 命令就會傳回查詢得到的資料, 而這些資料可能佔用很大的資源,所以處理兩類命令亦有點分別。

目录

query 及 simpleQuery

前面的例子都顯示了要求資料庫執行 SQL 命令的動作是由 $dbh->query() 去做的,但其實還有個 $dbh->simpleQuery() 。事實上, $dbh->query() 本身都是透過 $dbh->simpleQuery() 去向資料庫發出執行 SQL 的要求。 $dbh->simpleQuery() 執行成功, 如執行的 SELECT 命令則會傳回有關資料庫的 result handle , 其他則傳回 DB_OK 。 $dbh->query 的作用是把 simpleQuery() 傳回的 result handle 變成 DB_result 物件。在一般情況下 ,我都建議大家用 $dbh->query

$dbh->quoteString($str)

quoteString 的作用是將和 addslashes 一樣,處理 $str 中引數 (', ") 這類可能會做成 SQL 命令語法錯誤的字元。例如:

$dbh->query("SELECT * FROM posts WHERE subj = '$subj'")

如果 $subj 的值是 "peter's box" , 中間含單引號,整個 SQL 命令就變成:

 "SELECT * FROM posts WHERE subj = 'peter's box'"

做成語法錯誤。如果您事前經 quoteString 處理,問題就可以解法了:

$subj = $dbh->quoteString($subj);

$subj 如在 PostgreSQL 或 MySQL 就會變成 "peter\'s box" ,在 Oracle 則變成 "peter''s box" 。

要留意現時 PEAR 的 cvs 中,新增了一個方法 quote ,和 quoteString 的分別是 quote 還會在字串的前後加單引號。

prepare 、 execute 及 executeMultiple

其實有些資料庫管埋系統有提供預先編譯 SQL 命令的功能,可以加快查詢 的速度。

 $sql = $dbh->prepare("INSERT INTO test_table (name) VALUES('test')");

 for( $i = 0; $i < 10; $i++ ) {
     $dbh->execute($sql);
 }

以上例子和重覆執行十次同一句 INSERT 命令的結果一樣,但在一些資料庫管埋系統 ,因為 INSERT 命令已預先被編譯,所以速度會較快。被編譯的 SQL 命令 亦可以有參數。

 $data = array('mary', 'peter', 'john', 'robert');

 $sql = $dbh->prepare("INSERT INTO test_table (id, name) VALUES(?, ?)");

 for( $i = 0; $i < count($array); $i++ ) {
    $dbh->execute($sql, array( $i, $name) );
 }


 $data = array(
   array('mary', 'mary@foo.com'),
   array('peter', 'peterl@bar.com'),
   array('john', 'john@foo.com'),
   array('robert', 'robert@baz.net')
 );

 $sql = $dbh->prepare("INSERT INTO test_table (name, mail) VALUES(?, ?)");

 $dbh->executeMultiple($sql, $data);

prepare 等會自動幫您將參數用 quoteString 處理,所以您不用擔心 參數中的引號。但要留意 ? 只可以是實際的資料,您不可以以 table 名或欄名作為參數,以以下的用法都是錯誤的:

SELECT ?, name FROM test_table
DELETE FROM ? WHERE id = ?

現時只有 InterBase 及 Oracle 支援 prepare 等方法, 未有支援的則由 PEAR::DB 模擬出來。

$dbh->limitQuery($query, $from, $count)

$dbh->limitQuery 的作用是只讀取查詢中的部份 結果,這對編寫網站程式很有作用。

 <?php
 $p = intVal($p);
 $dbh = DB::connect('mysql://jrandom:@localhost/forum');
 $dbh->setFetchMode(DB_FETCHMODE_ASSOC);
 $sql = 'SELECT subj, author, posttime FROM posts ORDER BY posttime DESC';
 $result = $dbh->limitQuery($sql, $p * 10, 10);
 ?>
 <table>
   <tr><td>Subject</td><td>Author</td><td>Time</td></tr>
 <?php while ( $row = $result->resultRow() ) : ?>
   <tr>
     <td><?=$row['subj']?></td>
     <td><?=$row['author']?></td>
     <td><?=$row['posttime']?></td>
   </tr>
 <?php endwhile; ?>
 </table>
 <p>
 <a href="<?=$PHP_SELF?>?p=<?=$p - 1?>">Prev</a> |
 <a href="<?=$PHP_SELF?>?p=<?=$p + 1?>">Next</a>
 </p>

作者: 來醫

Personal tools
廣告橫額