最近在學習資料庫的應用看到這段程式碼
<?php
if(isset($_POST["action"]) and ($_POST["action"]=="add")){
include("connMysql.php");
if (!@mysql_select_db("test")) die("資料庫選擇失敗!");
$sql_query = "INSERT INTO `students` (`cName` ,`cSex` ,`cBirthday` ,`cEmail` ,`cPhone` ,`cAddr`) VALUES (";
$sql_query .= "'".$_POST["cName"]."',";
$sql_query .= "'".$_POST["cSex"]."',";
$sql_query .= "'".$_POST["cBirthday"]."',";
$sql_query .= "'".$_POST["cEmail"]."',";
$sql_query .= "'".$_POST["cPhone"]."',";
$sql_query .= "'".$_POST["cAddr"]."')";
//重新導向回到主畫面
header("Location: data.php");
}
其中SQL的INSERT語法我一直不清楚為何會那樣撰寫
在我的印象中INSERT是
insert into 資料表
(欄位1
,欄位2
) value ('值1','值2');
所以會認為加上POST傳輸的話是
insert into 資料表
(欄位1
,欄位2
) value ('$_POST[值1]','$_POST[值2]');
這樣!
想請問各位 上面範例的INSERT為什麼會那樣寫呢?
簡單地說,你不要把PHP跟SQL搞混了。你貼的程式碼,用意是在PHP中組出SQL statement字串,然後傳給相關的函數或物件方法做查詢。你要知道組出的SQL statement是否正確,只需要把$sql_query變數用echo印出來看看就知道了。
複雜一點說,你貼的程式可能讓你無法直覺了解SQL statement。其實在PHP中透過雙引號或是heredoc語法組出字串時,有更好的作法,並不一定要用這樣的字串串接。例如:
define('domine', 'what?');
$arr = array('name' => 'fillano');
echo "Hello '$arr[name]'";//印出 Hello 'fillano'
echo "Hello '${arr['name']}'";//同上
echo "Hello '{$arr['name']}'";//同上
echo "Hello '{$arr[name]}'";//印出 Hello 'what?'
/* (如果沒定義domine這個常數,應該會出現錯誤) */
這樣可以讓組出字串的語法更容易閱讀。(請參閱Strings文件的說明,後面Variable Parsing的部份別忘了)
另外,你貼的程式,直接把$_POST傳進來的東西內嵌到SQL Statement字串中,這是最危險的作法,幾乎可以保證會發生SQL Injection攻擊。如果你使用mysqli,那請使用mysqli_real_escape_string()函數處理過。另外,為了避免XSS攻擊,最好也用htmlspecialchars()或是htmlentities()處理過,才組進SQL Statement字串。
補充一下,程式改這樣可能比較容易看($_POST要記得處理,我省略了)
$sql_query = "INSERT INTO `students` (`cName` ,`cSex` ,`cBirthday` ,`cEmail` ,`cPhone` ,`cAddr`) VALUES ('{$_POST["cName"]}', '{$_POST["cSex"]}', '{$_POST["cBirthday"]}', '{$_POST["cEmail"]}', '{$_POST["cPhone"]}', '{$_POST["cAddr"]}')";
不好意思,我想請問這段的意思,因為run出來與您說的不同,是否能說明一下或是筆誤@@?謝謝
echo "Hello '{$arr[name]}'";//印出 Hello 'what?' /* (如果沒定義domine這個常數,應該會出現錯誤) */
因為有錯...前兩行要改一下:
define('name', 'domine');
$arr = array('name' => 'fillano', 'domine' => 'what?');
上面的寫法其實跟 insert into 資料表 (欄位1,欄位2) value ('$_POST[值1]','$_POST[值2]'); 是一模一樣的
只是他先把SQL語法當遲了字串處理最後再統一丟給mysql去做處理,其實兩者寫法沒什麼不同
$sql .= 與 $sql= 可以看到第二行開始多了. 符號,在PHP裡面表示字串連接,也就是$sql 變數裡面的內容由上到下一個個組合連接起來,形成最後的SQL字串,不過你那段程式裡面,我並沒有看到SQL最後有被執行,就被導向到另一支程式了
那一段的SQL INSERT的語法,是標準正規寫法,省略寫的話如下:
$sql_query = "INSERT INTO `students` VALUES (";
$sql_query .= "'".$_POST["cName"]."',";
$sql_query .= "'".$_POST["cSex"]."',";
$sql_query .= "'".$_POST["cBirthday"]."',";
$sql_query .= "'".$_POST["cEmail"]."',";
$sql_query .= "'".$_POST["cPhone"]."',";
$sql_query .= "'".$_POST["cAddr"]."')";
缺點是欄位的順序必須對
要是我我不會那樣寫,我的方式如下:
sql_query = "INSERT INTO `students` SET ".
"cName='".$_POST["cName"]."',".
"cSex='".$_POST["cSex"]."',".
"cBirthday='".$_POST["cBirthday"]."',".
"cEmail='".$_POST["cEmail"]."' ";
欄位順利隨便,因為已經指定欄位名稱對應變數值了,如果你可能只是要更新二個欄位,就很簡單,如下:
sql_query = "UPDATE students SET ".
"cName='".$_POST["cName"]."',".
"cSex='".$_POST["cSex"]."',".
"cBirthday='".$_POST["cBirthday"]."',".
" WHERE cEmail='".$_POST["cEmail"]."' ";
其實你的寫法跟你PO的寫法都是可以用的。
會這樣寫的原因,其一是要將其更正規化。也就是不想利用雙引號自動代變數的規則。
(這可防止變數帶錯,雖然機會不大,除非有用到特殊字)
其二就是欄位改變會比較方便。(因為可以整行移除或是移位)
只是~~~~目前來說最好還是不要用這樣的寫法啦。
因為直接用POST值的話。是很容易有問題的。