How do I ensure I caught all errors from MySQLi::multi_query?

前端 未结 3 930
清酒与你
清酒与你 2020-12-03 15:11

The docs for multi_query say:

Returns FALSE if the first statement failed. To retrieve subsequent errors from other statements you have to call mysqli

相关标签:
3条回答
  • 2020-12-03 15:18

    Despite the code example in the docs, perhaps the better method would be something like this:

    if ($mysqli->multi_query(...)) {
      do {
        // fetch results
    
        if (!$mysqli->more_results()) {
          break;
        }
        if (!$mysqli->next_result()) {
          // report error
          break;
        }
      } while (true);
    }
    
    0 讨论(0)
  • 2020-12-03 15:21

    There is no way to caught all errors, check out the example you use (which is from here)

    This example has only "select" statements in it, which is not common for multi-statement scripts.

    If you will put "insert", "update", "delete" or at least "set" - it will work differently.

    "multi_query" - Returns FALSE if the first statement failed. FIRST STATEMENT - this is all we can control. All subsequent statement are mystery. If it is not a "select" statement - it will give an error on "$mysqli->store_result();" and we never know was it successful or not.

    BUT

    If you will have your SQL script in "START TRANSACTION; ... commit;" wrapper, you can be sure - if something fails, everything fails. This is good, this is helping us to see if "all fails".

    To do this, just add in the end of you "insert - update" script a little "select", if last statement returns data - all script completed successfully.

    Use SQL like:

    START TRANSACTION;    
      set @q=1;
      select "success" as response from dual;
    commit;
    

    The PHP function:

    function last_of_multi_query ($mysqli, $query) {
        mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT); //After that all mysql errors will be transferred into PHP exceptions.
        $mysqli->multi_query($query);               
        do { null; } while($mysqli->next_result());
        $result = $mysqli->store_result();
        if (!$result){
            throw new Exception('multi_query failed');
        }
        return $result;
    }// end function
    
    0 讨论(0)
  • 2020-12-03 15:27

    Bill Karwin's answer doesn't look very eloquent to me. It seems strange to write separate conditional breaks when the do while loop is already setup to handle breakpoints.

    I haven't tested the following snippet, but you should be able to access the necessary results and errors from it:

    $queries["CURRENT_USER"]="SELECT CURRENT_USER()";
    $queries["CITY_NAME"]="SELECT Name FROM City ORDER BY ID LIMIT 20, 5";
    
    if(mysqli_multi_query($mysqli,implode(';',$queries))){
        do{
            list($current_table,$current_query)=each($queries);
            if($current_table!="CURRENT_USER"){
                printf("-----------------\n");
            }
            if($result=mysqli_store_result($mysqli)){
                if(mysqli_num_rows($result)<1){
                    echo "<p>Logic Error @ $current_table Query<br>$current_query</p>";
                }else{
                    while($row=mysqli_fetch_row($result)){
                        printf("%s\n",$row[0]);
                    }
                }
                mysqli_free_result($result);
            }
        } while(mysqli_more_results($mysqli) && mysqli_next_result($mysqli));
    }else{
        list($current_table,$current_query)=each($queries);
    }
    if($error=mysqli_error($mysqli)){
        echo "<p>Syntax Error @ $current_table Query<br>$current_query<br>Error: $error</p>";
    }
    
    0 讨论(0)
提交回复
热议问题