skip to Main Content

While trying to insert data into the database using prepared statement the prepared statement always returns false and not complete the connection.

I’m using this connection on cpanel (not sure if that’s related) tried to change the order tried to change the data type.

$conn = mysqli_connect($servername,$username,$password,$database);

// $sql=$conn->prepare("insert into asset 'assetName'=?, 'grp' ='?'  ,'Descrip' = '?'  , 'enteredValue' = '?',  'depreciationRate' = '?','entrydate'='?' 'availability'= '?'  ,'enteredBy' = '?' , 'updatedOn' = '?' , 'isPeriodic' = '?' , 'assetType' = '?','Frequency'='?','ExitDate'='?'");

if($sql = $conn->prepare("INSERT INTO `asset`(`id`, `assetName`, `grp`, `Descrip`, `enteredValue`, `depreciationRate`, `entrydate`, `availability`, `enteredBy`, `updatedOn`, `isPeriodic`, `assetType`, `Frequency`, `ExitDate`) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)")){

$sql->bind_param("sssssssssss",$name,$group,$value,$depreciation,$entryDate,$availability,$enteredBy,$updatedOn,$isPeriodic,$type,$frequency,$exitDate);

$sql->execute();
always return false and nothing has been inserted in the database.

3

Answers


  1. You have to execute the statement once you’ve bound the data.

    $sql->execute();
    

    The number of parameters are also inconsistent as pointed out by the comments.

    Login or Signup to reply.
  2. I think you don’t execute your query calling the execute method :

    $conn = mysqli_connect($servername,$username,$password,$database);
    
    // $sql=$conn->prepare("insert into asset 'assetName'=?, 'grp' ='?'  ,'Descrip' = '?'  , 'enteredValue' = '?',  'depreciationRate' = '?','entrydate'='?' 'availability'= '?'  ,'enteredBy' = '?' , 'updatedOn' = '?' , 'isPeriodic' = '?' , 'assetType' = '?','Frequency'='?','ExitDate'='?'");
    
    if($sql = $conn->prepare("INSERT INTO `asset`(`id`, `assetName`, `grp`, `Descrip`, `enteredValue`, `depreciationRate`, `entrydate`, `availability`, `enteredBy`, `updatedOn`, `isPeriodic`, `assetType`, `Frequency`, `ExitDate`) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)")){
    
    $sql->bind_param("sssssssssss",$name,$group,$value,$depreciation,$entryDate,$availability,$enteredBy,$updatedOn,$isPeriodic,$type,$frequency,$exitDate);
    sql->execute();
    sql->close(); // close connection 
    
    Login or Signup to reply.
  3. As I said in the comments:

    Well you have 14 ? and 11 s by my count. OR sssssssssss and ?????????????? Which as most of us know, is gonna throw an error as your placeholder count doesn’t match your values

    If you can put your data in an array you can use that array to build your query.

    if($sql = $conn->prepare("INSERT INTO `asset`(`id`, `assetName`, `grp`, `Descrip`, `enteredValue`, `depreciationRate`, `entrydate`, `availability`, `enteredBy`, `updatedOn`, `isPeriodic`, `assetType`, `Frequency`, `ExitDate`) VALUES (".implode(',', array_fill(0,count($data), '?')).")")){
       $sql->bind_param(str_repeat('s', count($data)),...$data);
    

    Lets walk thought this a bit

    Basically you can create your arguments with the same length as the $data with these 2 pieces of code:

      implode(',', array_fill(0,count($data), '?')) //implode "?" with ","  equal to the length of data
      str_repeat('s', count($data)) //create 's' equal to the length of data
    

    Then the real magic happens here with the ... “variadic” (variable length arguments):

     $sql->bind_param(str_repeat('s', count($data)),...$data);
    

    In PHP v5.6+ you can just inject the data using ... in and it will unwind it for you. Or in other words, put each array item in as a new argument.


    For the fields (columns)

    If you want to do the fields too, that is a bit more tricky. You have to be careful of what is in those if you put that data directly into the SQL. For example a User could edit the keys used in a $_POST request in such a way as to do SQLInjection if you just concatenate the Post Keys into the SQL.

    One of the simplest ways to solve this is to have a whitelist of fields like so (matched to the column names):

     //all allowed column names for this query (case sensitive)
     $whitelist = ["id", "assetName", ...];
    

    You can use array_intersect_key to retain only the data you want for the query (assuming the data has matched keys). The keys will be safe to use now in the query as they must match what is in the $whitelist.

     //remove unknown keys form input data (~ retain only known ones)
     //array_flip($whitelist) = ["id"=>0, "assetName"=>1, ...];
     $data = array_intersect_key($_POST, array_flip($whitelist));
    
     if($sql = $conn->prepare("INSERT INTO `asset`(`".implode("`,`", array_keys($data))."`)VALUES(".implode(',', array_fill(0,count($data), '?')).")".)){
        $sql->bind_param(str_repeat('s', count($data)),...$data);
    

    Other things

    The only thing this doesn’t cover is if you want all the fields in $whitelist to always be present. You can solve this with validation of the incoming data or you can merge in some empty fields to insure that all the data is present.

      $default =  array_fill_keys($whitelist, ''); //["id"=>"", "assetName"=>"", ...] ~ create empty "default" row
    
      //$default['updatedOn'] = date('Y-m-d'); //you can also manually set a value
    
      $data =  array_intersect_key(
                     array_merge(
                            $default,
                            $_POST  //["id"=>"1", ...] ~ missing assetName
                     ), array_flip($whitelist)); //-> ["id"=>"1","assetName"=>""]
    

    Array fill keys (similar to array fill from before) takes a list of keys, and adds a value in for each. So that gives us an array who’s keys are the the values of $whitelist and an empty string for each items value. I call this a default row.

    Then we merge this with our original data. Data in the first array will be overwritten by any data with matched keys for the second array ($_POST in my example). So if a key is present like id in the example above, it overwrite the empty one.

    Anything not overwritten keeps the empty value from the default row we made. Then the array intersect key removes anything extra like before.

    *PS I didn’t test any of this so please forgive any syntax errors.

    Enjoy!

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search