简体   繁体   中英

mysqli statement fails with Commands out of sync; when inserting into database

To be clear I have looked all over stack overflow and php.net docs for help with this before posting.

What I am trying to accomplish:

  • insert a new row of of values
  • return the int/long value of the insert_id
  • use that value to inform the next query

There are FK references between tables, the query that seems to be triggering the error is the initial query (parent table), they are run separately. all use mysqli->free_result().

the query works in phpmyadmin.

            $sqlTPO = "INSERT INTO grc_sandbox_tpos (buyer_name,date_created,item_count,vendor_stid,vendor_name,vendor_address_l1,vendor_address_l2,vendor_city,vendor_state,vendor_zip,vendor_country,vendor_phone)VALUES(?,?,?,?,?,?,?,?,?,?,?,?)";
            $va = [$bn,$dc,$ic,$vstid,$vn,$vl1,$vl2,$vcity,$vstate,$vzip,$vcntry,$vphn];
            $result_tpo = parent::executePreparedWriteingQuery($sqlTPO,$va);
            $this->currentTPOId = $result_tpo["insert_id"];
            $this->Message = $result_tpo["message"];
            $this->Status = $result_tpo["result"];
            if ($this->Status == false){
                return $this;
            }

The following is the database.class.php: write query:

protected function executePreparedWriteingQuery($sql, $bavArray)
{
    if (!is_string($sql) || empty($sql)) {
        return ['result'=>false,"message"=>"SQL statement in an incorrect format or empty.","insert_id"=>null];
    }
    if ($stmnt = $this->dbConn->prepare($sql)) {
        // bind params if they are set
        if (!empty($bavArray)) {
            $types = '';
            foreach ($bavArray as $param) {
                // set param type
                switch ($param) {
                    case is_string($param) == true:
                        $types .= 's';  // strings
                        break;
                    case is_int($param) == true:
                        $types .= 'i';  // integer
                        break;
                    case is_float($param) == true:
                        $types .= 'd';  // double
                        break;
                    default:
                        $types .= 'b';  // default: blob and unknown types
                }
            }

            $bind_names[] = $types;
            for ($i = 0; $i < count($bavArray); $i++) {
                $bind_name = 'bind' . $i;
                $$bind_name = $bavArray[$i];
                $bind_names[] = &$$bind_name;
            }

            call_user_func_array(array($stmnt, 'bind_param'), $bind_names);
        }
        $result = $stmnt->execute();
        if (!$result) {
            $msg = $stmnt->error;
            $stmnt->free_result();
            return ["result"=>false,"message"=>"SQL statement has errors and could not be completed: " . $msg, "insert_id"=>null];
        }else{
            $id = $this->dbConn->insert_id;
            $stmnt->free_result();
            return ["result"=>true,"message"=>"Data has been written to the database with out error.","insert_id"=>(substr(strtolower($sql),0,6)=="insert")?$id:null];
        }
    }else{
        $msg = $this->dbConn->error;
        return ["result"=>false,"message"=>"(Writing) SQL statement could not be prepared: " . $msg, "insert_id"=>null];
    }
}

All the research I have found in this is all on reading data from databases, or running stored procedure, I am not using either of these, but yet it is still failing when attempting to write to database.

Am I missing something? or does any one else have a solution, because at this point I have pretty much exhausted my resources.

I finally found a working solution: The issue was indeed the multi_query causing the hickup: so I present to stack overflow the new multi_query resolution found on the top answer/comment http://php.net/manual/en/mysqli.multi-query.php

    if (!is_string($sql) || empty($sql)) {
        return ['result'=>false,"message"=>"SQL statement in an incorrect format or empty.","insert_id"=>null];
    }
    $result = $this->dbConn->multi_query($sql);
    if (!$result) {
        return ['result'=>false,"message"=>"SQL statement has errors and could not be completed: " . $this->dbConn->error,"insert_id"=>null];
    }else{
        $id = $this->dbConn->insert_id;
        try{
            //use supression to allow completion of action with out folly;
            while (@$this->dbConn->next_result()) {;}
        }
        catch(Exception $e){
            //do nothing
        }
        finally{
            return ['result'=>true,"message"=>"SQL ran successfully.","insert_id"=>(substr(strtolower($sql),0,6)=="insert")?$id:null];
        }
    }

I have opted to suppress the error as this method will only be used for inserts and not reads, the error it throws is more of a warning stating that using the method of choice needs to use a check if there are more results... this works and nothing further will be needed, I want to thank PatrickQ for his input.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM