PHP + MySQL簡易操作教學

前置作業:


流程:
  1. 連線到資料庫
  2. 執行SELECT SQL
  3. 取出一列列的資料
  4. 其他注意事項和小撇步

PHP的MySQL相關function操作其實不難,但是新手們一開始在使用時卻會很不習慣,以下僅以在下的認知做出簡易示範(應該不是最好的方法,事實上我自己目前已經不是這樣做,但我相信本文應該會是很好理解的流程)
連線到資料庫

連線到資料庫通常都很好解決(如果MySQL Server有設定好的話):mysql_connect('localhost', 'username', 'password');
mysql_select_db('myDB');

這段程式碼通常會寫在一個給所有頁面引入的檔,假設上面兩行被我們存檔為"database.php",那麼遇到需要對資料庫連線的時候只要PHP呼叫:require_once 'database.php';就可以了。這個方法也可以應用在其他想要在每個頁面上做的事情(像是紀錄IP、檢查是否已登入之類的)。

不過只是這樣子有時會有點風險,比方說如果資料庫不是自己設定的,但我們又必須指定編碼(目前的趨勢是使用UTF-8)的話,就得加上一句"SET NAMES 'UTF8'"的SQL,以防止一些亂碼的狀況發生,當然這個前提是你的網頁也是用UTF-8編碼。連線的設定可能就會變成: $db_server = 'db.mycom.com';
$db_user = 'kong0107';
$db_password = '********';
$db_name = 'test';

mysql_connect($db_server, $db_user, $db_password);
mysql_select_db($db_name);
mysql_query("SET NAMES 'UTF8'");
你可能會覺得先把帳號密碼寫在變數裡這件是有點多餘,不過實務面上我們很有可能還會把「帳號資料」和「連線」這兩個區塊分開--通常是做很大的站台的時候。比方說我可能某個頁面同時要跟Google、Yahoo!和FaceBook做連線,那麼我就會分開寫兩個檔:/* 這個檔叫做config.php */
$db_server = 'db.mycom.com';
$db_user = 'kong0107';
$db_password = '********';
$db_name = 'test';

$google_user = 'kong0107';
$google_password = 'hahaha';

$yahoo_user = 'kong_crazykid';
$yahoo_password = 'oh my god';

$fb_user = 'kong0107@gmail.com';
$fb_password = 'this is longer';

/* 這個檔叫做service_connection.php */
require 'config.php'; /*就會把上面那個檔案叫進來*/

mysql_connect($db_server, $db_user, $db_password);
mysql_select_db($db_name);
mysql_query("SET NAMES 'UTF8'");

require_once 'google_api.php'; /*把google的API(最重要的是連線function)叫進來*/
$google = new GoogleAPI();
$google->connect($google_user, $google_password);

require_once 'yahoo_api.php';
$yahoo = new yahooAPI();
$yahoo->connect($yahoo_user, $yahoo_password);

require_once 'facebook_api.php';
$fb = new facebookAPI();
$fb->connect($fb_user, $fb_password);
看吧,只是連線而已就已經開始讓人頭昏眼花,而且我們根本還沒有開始真正操作什麼呢!所以還是把一些設定(諸如帳號、密碼)通通寫在同一區,這樣子之後要改才比較方便。(註:那些API的實際使用方法應該不是這樣子,我只是隨便舉個例子。但總之通常只會更複雜)

執行SELECT SQL
希望你不會覺得光是連線就亂七八糟的,因為下面才要開始操作...orz
在這邊我們先考慮把資料從資料庫中取出來就好,寫入的方法之後會再介紹。
如果你還記得最簡單的SQL:SELECT id, name FROM student
這就是取出student資料表中的id和name兩個欄位。請注意資料庫的SELECT指令只會「取出資料」而不會「排序」--除非你要求他要排序:SELECT * FROM student
ORDER BY id ASC
其中"ASC"是表示遞增排序(遞減排序則是DESC)

在這邊要注意幾點事情:

  • SQL指令可以換行,所以我建議你在寫比較長的指令時,擅用換行來讓指令比較好理解
  • SQL的關鍵字不限大小寫,所以你也可以寫成"select * from student"。但是我個人覺得把關鍵字都大寫比較容易懂
  • "select *"的星號是特殊用法,意思是「取得所有欄位」。通常我會建議這麼做,因為你不一定知道待會可能會想用到哪些欄位
  • 通常資料庫名稱、資料表名稱、欄位名稱是不需要用引號框起來的,不過你可以為了區別他們和關鍵字而特別這麼做。但是要注意的是在MySQL中,把這類名稱框起來的引號並不是單引號或雙引號,而是鍵盤上左上角Esc鍵下面的那個「`」(請小心不要打成全型字),像是:SELECT `id`, `name`
    FROM `student`
    WHERE `id` < 10
    ORDER BY `id` DESC
  • 如果有字串的話,一定要用單引號(不能用雙引號)。舉例來說:SELECT * FROM student WHERE name = '高睿甫'
    如果字串之中有單引號的話,就要用跳脫字元「\」,像是如果要取出留言板中的特定留言:SELECT *
    FROM message
    WHERE content = '野村克也說\'要讓一個選手墮落很簡單啊,只要稱讚他就行了!\'他說的真是太忠肯了'
其實還有其他要注意的,不過先到此為止吧,我們還得回來看PHP呢....

PHP執行SQL的指令是mysql_query()(注意:當然要先對資料庫連線,再執行mysql_query()才有意義),有時我們會把SQL直接寫在裡面:$res = mysql_query("SELECT * FROM student");
不過如果是像上面有比較長的SQL,我倒是比較建議先另外丟進變數裡:$sql = "SELECT `id`, `name`
FROM `student`
WHERE `id` < 10
ORDER BY `id` DESC";
$res = mysql_query($sql);
也別忘了PHP的字串裡面是可以直接換行的(題外話:如果你有在寫JavaScript的話,請注意JavaScript並不能直接這樣做喔)

有注意到我都把mysql_query()回傳的東西丟給$res變數嗎?那就是我們接下來要操作的東西囉

取出一列列的資料
好,這一個區塊其實才是我寫本文的主要目的....(不過上面講SQL好像花了太多篇幅)
mysql_query()回傳的$res變數是PHP的某種資料結構,沒辦法直接取得所有資料,不過可以「一筆一筆」的取出來(在這裡我是用mysql_fetch_assoc(),你也可以用mysql_fetch_row(),後面會再介紹他們的不同): $res = mysql_query("SELECT * FROM student");
$row1 = mysql_fetch_assoc($res); /*第一列*/
$row2 = mysql_fetch_assoc($res); /*第二列*/
$row3 = mysql_fetch_assoc($res); /*第三列*/
注意我們其實是在執行同一個function,但是每次卻回傳不同的結果喔!當然你應該不會想這麼呆呆的把整張資料表取完,這種時候就得用上迴圈啦。但是面對不知道SQL回傳的結果有幾筆資料的時候,回圈應該要在什麼時候停止呢?
其實mysql_fetch_assoc()(和mysql_fetch_row())都會在「已經沒有資料」的時候回傳false,所以我們只要把取出來的東西丟給while判斷就好啦: $res = mysql_query('SELECT * FROM student');
while($row = mysql_fetch_assoc($res)) {
/* 這裡就看你想對這一筆資料幹嘛*/
echo $row['id']; /*像這樣就可以印出該學生的學號*/
}

流程大概都清楚了,我們就來試試用HTML的表格來顯示出所有學生的學號和姓名吧: $res = mysql_query('SELECT `id`, `name` FROM `student`');
echo '<table>';
while($student = mysql_fetch_assoc($res)) {
echo '<tr>';
echo '<td>';
echo $student['id'];
echo '</td>';
echo '<td>';
echo $student['name'];
echo '</td>';
echo '</tr>';
}
echo '</table>';
像是這樣,不過輸出的部份我自己比較喜歡另一個方式:<table>
<?php
while($student = mysql_fetch_assoc($res)) {
?>
<tr>
<td><?=$student['id']?></td>
<td><?=$student['name']?></td>
</tr>
<?php
}
?>
<table>
就是這樣囉,或是看你想怎麼顯示都可以。
其他注意事項和小撇步
  • 如果你只想取得一筆資料(比方說想用學號來查名字),那就不需要用while回圈了,比方說:$id = 9646515;
    $res = mysql_query("SELECT * FROM student WHERE id = $id");
    $kong = mysql_fetch_assoc($res);
    $name = $kong['name'];
    echo "學號$id 的學生,他的名字是$name";
  • mysql_fetch_assoc()指令只是我自己慣用,如果資料表是你自己設計的,也可以使用mysql_fetch_row()。差別在於回傳回來的array結構: $res = mysql_query("SELECT id FROM student");

    $row1 = mysql_fetch_assoc($res);
    echo $row1['id'];

    $row2 = mysql_fetch_row($res);
    echo $row2[0];

    $row3 = mysql_fetch_array($res);
    echo $row3['id'];
    echo $row3[0];

    mysql_fetch_assoc()的好處是你不用記得欄位順序,但缺點是你必須記得欄位名稱;mysql_fetch_row()則相反。當然你也可以用mysql_fetch_array(),這樣就兩種方式都可以取得想要的資料。
    小提醒:上面的例子中,請注意$row1、$row2、$row3是會取得「不同筆」的資料喔。
  • 實務面上我們常常需要藉由使用者表單來湊出SQL指令,比方說前面舉過的搜尋留言板:$txt = $_GET['search'];
    $sql = "SELECT * FROM message WHERE content = '$txt'";
    // 還記得字串要加上單引號吧..
    不過以這個例子來說,我們又必須小心使用者輸入的東西本身就有單引號。比方說使用者輸入了"我好傷心喔 T_T'",那麼整個SQL丟給MySQL的時候就會變成SELECT * FROM message WHERE content = '我好傷心喔 T_T''然後就發生錯誤啦(因為MySQL看不懂那些引號是怎麼回事)
    這種時候就必須另外用程式把那個單引號解決掉:$txt = str_replace("'", "\\'", $_GET['search']);
    /* 如果你看不懂那個"\\'",就先照做吧....*/
    $sql = "SELECT * FROM message WHERE content = '$txt'";

    通常我只處理單引號,不過你可能也想把其他東西代換掉,就依樣畫葫蘆囉。
  • 承上,如果是用留言的流水號(數字)來查的話,直覺上程式碼應該是:$id = $_GET['id'];
    $sql = "SELECT * FROM message WHERE id = $id";
    可是,如果使用者在表單中,根本不是打數字的話(比方說使用者什麼都沒打),SQL就會變成SELECT * FROM message WHERE id = 於是就產生錯誤了(因為等號後面不是數字)。
    要解決這個狀況有兩個方法,一個是無論該欄位是不是數字都加上引號:$id = str_replace("'", "\\'", $_GET['id']);
    $sql = "SELECT * FROM message WHERE id = '$id'";

    另一個就是使用sprintf()函數,這也是我比較偏好的方法:$sql = "SELECT * FROM message WHERE id = %d";
    $sql = sprintf($sql, $_GET['id']);
    以上兩個方法都可以應付使用者亂打的狀況
善用sprintf()
承上,我們有時會需要比較長的SQL,像是:SELECT * FROM car
WHERE brand = 'BMW'
AND oilCart > 2000
AND price < 700000
如果我們是使用sprintf()的話,就可以用比較容易懂得簡短程式碼來執行(簡潔易懂的程式碼可以幫助自己或他人後續的除錯和更新):$sql = "
SELECT * FROM car
WHERE brand = '%s'
AND oilCart > %d
AND price < %d
";
$sql = sprintf($sql, $_GET['brand'], $_GET['oilCart'], $_GET['price']);
這只是個比較簡單的例子,但如果是遇到像是需要報表、統計這一類需要跨多的資料表的SQL,使用sprintf()的替代方式可以讓你快速的編輯和除錯。

先到此為止吧,我手痠了
......
... read more

久違的台中

不知怎地,各個case在這兩週幾乎都有更新要求
於是最近總沒能成功讓自己好好放鬆
前天經前輩提醒才驚覺台中爵士音樂節已經開始了

是位最近在台中看房地產的前輩
聽他提到台中市的街道狀況和生活習慣
總覺得自己跟台中已經整個脫節了啊
該找時間回家了吧

說到爵士音樂節
去年拿亞軍的那隻可愛大熊學弟好像有說要教我鋼琴
原本還說我今年要參賽的勒

....似乎也不需要動用到「人事已非」來描述
雖然確實是名副其實啦
......
... read more

應該遵照本質嗎?

我從小時候就不喜歡龍應台,大概是因為她總堅持著要別人也接受她所認定的那些「應該」的事物。於是就連她所創立的清華思沙龍(其實我印象中剛創立時的名字是「思想沙龍」,如果我待會打成「廝殺龍」的話好像也很不錯)都不喜歡。
今天在交大看到了清華思沙龍的活動海報,主題是[共築社區夢想藍圖-從清大宵夜街談起],又讓我一整個反感。以下先節錄海報的部分內容:

天橋下的人潮
從湍急的車潮裡穿出
喧鬧的夜市
卻是被漠視的暗巷

清大一直在這裡
那,大學生在哪裡?

主持人:
王俊秀 清大通識中心教授

與談人:
曾光宗 中原大學建築系系主任
陳天佑 中華大學建築系系主任
劉俊秀 交大教授 新竹市長候選人

地點:清華大學 合勤演藝廳

姑且不論劉俊秀是不是來拉票,我看著海報時就一直在嘲笑龍應台長久以來一直想要灌輸社會大眾的本質問題。她好像總以「某某東西不該是某某樣子」之類的論點來引起注意,但是似乎她自己也只在自己在乎的地方實行這些想法而已....
合勤演藝廳-清大內唯一一個觀眾容納量是100~200人的有室內場地,但是由於合勤公司當初是將該廳的設備、燈光、裝潢、聲響設計成表演藝術的展演空間,使得許多想以之作為活動場地的小單位們一直被合勤的管理單位(我忘了是誰了)婉拒。而清華思沙龍也不知道是不是挾著龍應台的氣魄,從成立之初就常常使用該場地...(但我沒有要說合勤演藝廳不應該用做演講場地。)
回到活動的宣傳文字。清夜是不是跟大學生有關係,這我不予置評,不過海報上把官方網站打成nthuthinkers@blogspot.com,說實話讓我啼笑皆非,不像是一個自我要求的人創辦的自我要求的團體該發生的事件。
......
... read more