查詢mysql總結和預處理

任務:進一步深刻mysqli_multi_query()用法.php

1、鏈接到mysql:mysql

$dbc = mysqli_connect(host,user,password,databasename);
等價於:
$dbc = mysqli_connect(host,user,pwd);
mysqli_select_db($dbc,db_name);


若是發生錯誤,能夠調用:mysqli_connect_error() 返回錯誤信息,不帶參數
$dbc = @mysqli_connect(host,user,pwd,db) or die('沒法鏈接到mysql:'.mysqli_connect_error());

@是錯誤控制運算符,防止在web瀏覽器顯示php錯誤。此外,@也能夠放在mysqli_query前面。上面是一種首選作法,由於錯誤將由or die處理。die()會終止腳本執行。

能夠將鏈接文件放在路徑外。

設置編碼:mysqli_query("set names gb2312");

2、執行查詢:
不論是select, delete, update,insert 查詢都是用:
$result=mysqli_query($dbc,SQL);
對於insert ,delete,update等查詢不會返回結果,$result將返回true或false,所以能夠用這個來判斷下一步:
$result = mysqli_query($dbc,sql);
if($result) {//susses}

若是查詢沒有成功,一定發生某種mysql錯誤,可能調用
mysqli_error($dbc)    //注意和mysqli_connect_error()區別

3、關閉鏈接:
mysqli_close($dbc) 這不是必須要的,php會在腳本最後自動關閉,但最好寫上。

4、多條查詢:
mysqli_multi_query()容許同時執行多條查詢。但語法更復雜一點。特別是當返回結果時。

5、檢索select查詢結果:
mysqli_fetch_array($result [, type])
是最經常使用的,以數組格式一次返回一行數據。由它來配合while()來遍歷返回數據。帶有一個可選參數type,用於指定返回的數組類型:關聯的仍是索引的,或兩者都可。參數類型以下:
MYSQLI_ASSOC   示例:$rows['columnName']
MYSQLI_NUM 示例:$rows[0] ,這一種效率較高一點。
MYSQLI_BOTH 示例:$rows[0]或$rows['columnName']

當使用mysqli_fetch_array($result [, type])後,能夠採起一個可選步聚的是:一旦查詢結果完成了工做,便可釋放這些信息,來消除$result佔用的系統內存開銷。這一步是可選的,PHP一樣也在會結果時自動清理:
mysqli_free_result($result)   //注意參數是否是$rows!
流程以下:
while($rows=mysqli_fetch_array($result))   //或while($rows=mysqli_fetch_array($result,MYSQLI_ASSOC))
{//遍歷
   .......code do something.......
   echo $rows[0]
   mysqli_free_result($result)
}
注意:
mysqli_fetch_array()和mysqli_fetch_array($result,MYSQLI_NUM)等價
mysqli_fetch_assoc()和mysqli_fetch_array($result,MYSQLI_ASSOC)等價


6、確保sql安全,使用轉義函數:
mysqli_real_escape_string($dbc,para)
該函數用於檢驗用戶提交的並將組合到sql查詢語句的變量值,它將轉義那些有可能無心或帶惡意的字符。如單引號,在外國人的姓名有可能會包含該符號(如O'Toole),這時就須要用它。
案例:
$name = $_POST['name'];
$name = mysqli_real_escape_string($dbc,$name);
$query = "Select ... From tb where name='$name'"; //這樣能夠確保帶入sql 時參數的安全。
注意:若是在使用php6以前的版本,若啓用MAGIC QUOTES魔法引用時,那麼在使用mysqli_real_escape_string前,須要用stripslashes(para)刪除魔法引用添加的任何斜槓,以下:
$fn = mysqli_real_escape_string($dbc,trim(stripslashes($_POST['firstName'])));


7、統計select返回的記錄數:
使用mysqli_num_rows($result)統計select 返回的結果行數。$num=mysqli_num_rows($r),對於上面所說的while流程,能夠更改爲如下更嚴謹的寫法,而不僅是分析查詢是否成功,由於若是數據庫爲空的話,就不會出錯。
$sql = "select * from tb where id=$id";
$r = @mysqli_query($dbc,$sql);
$num = mysqli_num_rows($r);
if($num>0){ //這樣比if($r)更準確。不是僅僅分析是否成功運行。

     // Do something;
     
     mysqli_free_result($r)
}
mysqli_close($dbc);

8、返回insert ,update,delete受影響行數:
和上面不一樣的是,若是查詢不是select則用mysqli_affected_rows()函數返回受影響行數。用法以下:
$num = mysqli_affected_rows($dbc); //注意參數是$dbc;
如:
$q = "update tb set pass=SHA1('$newpassword') where id=$row[0]";
$r = @myslqi_query($dbc,$q);
if(mysqli_affected_rows($dbc)==1){
      //Do something
}else{
     echo mysqli_error($dbc);
     exit(); //終止腳本。
}

注意:
一、若是使用truncate tb清空表時,則mysqli_affected_rows()會返回0,即便查詢成功執行而且刪除了每一行。
二、若是用update查詢時,但實質上沒有更改任何列的值,好比用相同的密碼代替一箇舊密碼,則也會返回0web

9、批量查詢:預處理語句(第12章第4節:P311)
版本:MYSQL 4.1開始添加預處理。php5可使用。
預處理的好處:
一、更大安全性。二、更好性能。三、批量查詢。
對於預處理語句,只會把查詢自己發送給mysql,而且只會解析一次,而後單獨把值發送給mysql。
$q = 'Insert into tb(num) values (?)';
$stmt = mysqli_prepare($dbc,$q);
mysqli_stmt_bind_param($stmt,'i',$n);
for($n=1;$n<=100;$n++)
{
    mysqli_stmt_execute($stmt);
}
能夠經過insert , update , delete , select 查詢建立預處理,步驟:
一、定義查詢:
$q = "select firstname,lastname from users where uid = ?";   //(正常則是uid=$id)
二、將查詢傳給mysql預處理:
$stmt = mysqli_prepare($dbc,$q);   //此時mysql會解析查詢,但不會執行。
三、將變量綁定到查詢佔位符"?",以下:
mysqli_stmt_bind_param($stmt,'i',$id);
其中'i'的含義是mysql_stmt_bind_param函數指望接收到的值爲int類型,共有如下幾種:
--------------------------------------------------------------------------------
字母                    表示綁定的值類型
                            Decimal
                              Integer
                             Blob (二進制類型)
                              全部其它類型

----------------------------------------------------------------------------------
若是查詢語句有多個變量,如:
$q = "select uid,firstname from users where email=? AND pass=SHA1(?)"; //注意這裏都沒有對?問號加單引號,即便是字符型。這是和標準查詢的區別。
多個變量直接在綁定時按順序在引號內列出便可。以下:
$stmt = mysqli_prepare($dbc,$q);
mysqli_stmt_bind_param($stmt,'ss',$e,$p);
還須要注意的時,在調用綁定函數前,能夠不須要先對變量定義設置,如上面的$e,$p在下面才設置,這不會出錯。
四、完成綁定後,能夠給php變量賦值(若是尚未值的話)。而後執行語句。
$id=15;
mysqli_stmt_execute($stmt);
五、關閉預處理:
mysqli_stmt_close($stmt);
六、關閉鏈接
mysqli_close($dbc);
執行預處理時,若有出錯則用mysqli_stmt_error($stmt)調用sql

示例:
$dbc =mysqli_connect('localhost','username','pwd','forum');
$q = 'insert into messages(forumid,parentid,userid,subject,body,forumdate) values(?,?,?,?,?,NOW())';
$stmt = mysqli_prepare($dbc,$q);
mysqli_stmt_bind_param($stmt,'iiiss',$forumid,$parentid,$userid,$subject,$body);

$forumid = (int)$_POST['forumid'];
$parentid=(int) $_POST['parentid'];
$user_id =3;
$subject = strip_tags($_POST['subject']); //strip_tags
$body = strip_tags($_POST['body']);
mysqli_stmt_execute($stmt);
if(mysqli_stmt_affected_rows($stmt)==1)
{
      //do ....
}else{
     echo mysqli_stmt_error($stmt);
}
mysqli_stmt_close($stmt);
mysqli_close($dbc);數據庫

以上演示了預處理的一種語句,實際上預處理有兩種語句:
一、綁定參數(bound parameter):如上面的示例
二、綁定結果(bound result):將查詢結果綁定到php變量。數組

10、阻止sql注入:(第12章第4節:P311)
一、驗證在查詢中要使用的數據,若是有可能,就可執行類型強制轉換。如:
$forumid = (int)$_POST['forumid'];
if($forumid>0) ....   //若是強制轉換成int完=0時,則不符數據型要求。
二、使用mysqli_real_escape_string($dbc,para)
三、使用mysqli_real_escape_string($dbc,para)替×××法:預處理,參上面。瀏覽器

11、早先的php和mysql鏈接方式:
mysql_connect,在寫法上只差上面一個字母i,但用法差很少。如下簡單示例:
$conn = mysql_connect("127.0.0.1","mysqltest","123456");
mysql_select_db("shop"); //若是用$selectdb = mysql_select_db("shop");則$selectdb=1安全

mysql_query("set names gb2312"); //mysql_query("set names utf8");
$exec="select * from product";
$result=mysql_query($exec,$conn); //或:$result=mysql_query($exec);ide

while($rs=mysql_fetch_object($result))
{
echo "品名:[".$rs->pname . "] &nbsp;&nbsp;";
echo "價格:".
   $rs->price . "&nbsp;&nbsp;";
echo "入庫時間:".$rs->addTime . "&nbsp;&nbsp;";
echo "<br />";
}
echo $result;函數

若是要進行結果判斷有無再輸出,則能夠用:
$conn = mysql_connect("127.0.0.1","mysqltest","123456");
mysql_select_db("shop");

mysql_query("set names gb2312"); //mysql_query("set names utf8");
$exec="select * from product";
if($result=mysql_query($exec,$conn)){
while($rs=mysql_fetch_object($result))
{
   echo "品名:[".$rs->pname . "] &nbsp;&nbsp;";
   echo "價格:".
    $rs->price . "&nbsp;&nbsp;";
   echo "入庫時間:".$rs->addTime . "&nbsp;&nbsp;";
   echo "<br />";
}
}

附:
A、在insert後取得最後一條記錄:2種方法:
一、使用mysql的:last_insert_id() 函數。「insert into ....;select last_insert_id()」
二、使用php 的 mysql_insert_id() 或mysqli_insert_id() 返回一樣的值:
PHP的 mysql_insert_id ( [resource $link_identifier] ) 函數能夠返回你須要的ID。 可選參數是php鏈接mysql的句柄。 每一個鏈接都有不一樣的句柄。如:
    mysql_query("INSERT INTO mytable (product) values ('kossu')");
    printf ("Last inserted record has id %d\n", mysql_insert_id());



B、幾個函數:
trim() , ltrim(), rtrim()
exit(),

strip_tags()去掉字符串中包含的任何 HTML 及 PHP 的標記字符串。如果字符串的 HTML 及 PHP 標籤原來就有錯,例如少了大於的符號,則也會返回錯誤。而本函數和 fgetss() 有着相同的功能。 $text = '<p>Test paragraph.</p><!-- Comment --> <a href="#fragment">Other text</a>'; echo strip_tags($text); //結果:Test paragraph. Other text // 許可用 <p> and <a> echo strip_tags($text, '<p><a>'); //結果:<p>Test paragraph.</p> <a href="#fragment">Other text</a>

相關文章
相關標籤/搜索