1. 程式人生 > >談下mysql預處理基礎

談下mysql預處理基礎

意思 fault pre 連接 發現 myisam 定量 ont 預編譯

傳統的操作數據庫方法有兩種:

  1. 先寫一條sql語句,然後通過mysqli->query($sql)去操作數據庫(此處使用的是mysqli擴展庫)。這樣操作並不會有什麽大的錯誤,但是當要插入上千條上萬條數據呢?難道也還是要這樣寫一條sql語句然後再操作一下數據庫?這裏我說下mysqli自帶的操作多條sql語句的方法,即第二種方法。
  2. mysqli->multi_query($sql),這是操作多條sql語句的方法,如下:
    insert into student(name,age,sex,studentNo,grade) values(馬特,14,,20170809,六年級
    ),(凱文,15,,20170810,七年級)

    如果你認為這樣就可以完全解決問題,那麽你就錯了,接下來讓我們來看一看MySQL數據庫執行sql語句的原理!
    技術分享

    從上圖可以看出,無論我們是發送一條sql語句還是發送多條sql語句,數據庫都要對其一一的進行編譯,那麽當數據達到一定量之後,數據庫的開銷就必然很大。那究竟怎樣解決這個問題呢?此時就引入了預處理技術的概念。

    下面我們來看一段預處理技術的代碼:
    student表結構如下:

    CREATE TABLE `student` (
      `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
      `age` 
    int(11) DEFAULT NULL COMMENT 年齡, `name` varchar(20) CHARACTER SET utf8 DEFAULT NULL COMMENT 姓名, `sex` varchar(2) CHARACTER SET utf8 DEFAULT NULL COMMENT 性別, `studentNo` varchar(20) DEFAULT NULL, `grade` varchar(20) CHARACTER SET utf8 DEFAULT NULL COMMENT 班級, PRIMARY KEY (`id`) ) ENGINE
    =MyISAM AUTO_INCREMENT=4 DEFAULT CHARSET=latin1;
    <?php
    /**
     * Created by PhpStorm.
     * User: Administrator
     * Date: 2017/7/22
     * Time: 10:52
     */
    $mysqli = new mysqli("localhost", "root", "root", "test");
    if ($mysqli->connect_error) {
        die("連接失敗" . $mysqli->error);
    }
    $mysqli->query("set names utf8");//設置編碼格式為utf-8,這樣數據庫展示中文的時候才不會出錯
    $sql = "insert into student(name,age,sex,studentNo,grade) values (?,?,?,?,?)";
    //向數據庫發送sql語句,讓數據庫對該sql語句先進行編譯
    $mysqli_stmt = $mysqli->prepare($sql);
    if( !$mysqli_stmt ) {
        die( $mysqli->error );
    }
    //綁定參數
    $name = "珀利";
    $age = 13;
    $sex = ‘男‘;
    $stuNo = "201501225";
    $grade = ‘四年級‘;
    
    $mysqli_stmt->bind_param("siisd", $name, $age, $sex, $stuNo, $grade);
    $mysqli_stmt->execute();//執行
    $mysqli->close();//關閉連接

    首先我們來看

    $sql = "insert into student(name,age,sex,studentNo,grade) values (?,?,?,?,?)";
    ?這裏的問號相當於一個占位符,之後只要向數據庫發送數據就能夠自動把數據對應的填充進去
    
    這就是預編譯技術的精髓之處,我們通過$mysqli_stmt = $mysqli->prepare($sql);向數據庫發送sql語句,然後數據庫對該sql語句進行編譯,
    並且數據庫不會立即釋放掉編譯的結果。 $mysqli_stmt
    ->bind_param("siisd", $name, $age, $sex, $stuNo, $grade);bind_param,顧名思義,就是綁定參數的意思,那麽,它給誰綁定參數呢?
    看看上面的values (?,?,?,?,?),bind_param裏面的參數一一對應著values的每一個參數。那麽bind_param裏面的siisd又是什麽意思呢?別急,請看下方:

    參數有以下四種類型: 
      i - integer(整型) 
      d - double(雙精度浮點型) 
      s - string(字符串) 
      b - BLOB(布爾值) 
      每個參數都需要指定類型。 
      通過告訴數據庫參數的數據類型,可以降低 SQL 註入的風險.
      $mysqli_stmt->execute();這句代碼就是將數據傳遞給數據庫了。

    我們來用預處理查詢數據庫:
    技術分享

    <?php
    
    $mysqli = new mysqli("localhost","root","root","test");
    if($mysqli->connect_error){
        die("連接失敗".$mysqli->error);
    }
    $mysqli->query("set names utf8");
    
    $sql="select name,sex,age from student where id>?";
    
    $mysqli_stmt=$mysqli->prepare($sql);
    if( !$mysqli_stmt ) {
        die( $mysqli->error );
    }
    $id=1;
    $mysqli_stmt->bind_param("i",$id);
    $mysqli_stmt->execute();
    
    $mysqli_stmt->bind_result($name,$sex,$age);//綁定結果集,傳遞的是引用
    while($mysqli_stmt->fetch()){
        echo "$name:$sex:$age"."<br>";
    }
    
    $mysqli_stmt->free_result();//關閉資源
    $mysqli_stmt->close();//關閉預編譯語句,否則數據庫會一直保存
    $mysqli->close();//關閉連接
    輸出:
    馬特:男:14
    凱文:女:15 

    我們看到有這麽一句:

    $sql="select name,sex,age from student where id>?";

    看看這句sql語句,你會發現bind_result裏面的參數一一對應於sql語句當中你要查詢的字段(name,sex,age),當然,bind_result裏面的參數可以不與sql語句的字段名字相同,但是通常推薦這樣做。

談下mysql預處理基礎