Home » Php » php – Mistake in SQL syntax.. (bindValue?)

php – Mistake in SQL syntax.. (bindValue?)

Posted by: admin February 25, 2020 Leave a comment

Questions:

I am trying to create an update query and I am looping in some set stuff to a var called $str and I cant seem to get it to work.

       if (is_numeric($id)) {
           if (!empty($values) && !empty($table_name)) {
               $str = '';
               $sql = "UPDATE `$table_name` SET :update_values WHERE `$column_name` = :id";

               // Its one because we dont use ID like that
               $i = 1;

               foreach ($values as $key => $value) {
                   if ($key != $column_name) {
                       // Exclude the last one from having a comma at the end
                       if ($i == count($values) - 1) {
                           $str .= "$key='" . $value . "'";
                       } else {
                           $str .= "$key='" . $value . "', ";
                           $i++;
                       }
                   }
               }
               $query = $this->dbh->prepare($sql);
               $query->bindValue('update_values', $str, PDO::PARAM_STR);
               $query->bindValue(':id', $id, PDO::PARAM_INT);
               $query->execute();
               return true;  
           } else {
               return false;
           }
       } else{
           return false;
       }
   }

Output:

Fatal error: Uncaught PDOException: SQLSTATE[42000]: Syntax error or
access violation: 1064 You have an error in your SQL syntax; check the
manual that corresponds to your MariaDB server version for the right
syntax to use near ”note_name=\’yeet\’, note_date=\’2020-02-20\’,
note_desc=\’asdasdasdasdadsasdads’ at line 1

Am I making any obvious mistakes?

Also for the life of me I don’t know what the backslashes in front of the values mean.

How to&Answers:

In MySQL, identifiers cannot be provided as values.

References to columns must appear in the text of the SQL statement, they cannot be provided through bind parameters. This holds true for table names, column names, function names.

There is no workaround; this is a by-design restriction. There’s several reasons for this. One of the most straightforward reasons is understanding how a SQL statement gets prepared, the information that is needed to come up with an execution plan, the tables and columns have to be known at prepare time (for the semantic check and privilege check. The actual values can be deferred to execution time.

Bind placeholders are for providing values, not identifiers.

With the code given, what MySQL is seeing something along the lines of

 UPDATE `mytable` SET 'a string value' WHERE `id_col` = 42

And MySQL is balking at the 'a string value'.


We can (and should) use bind parameters for values.

We could dynamically generate SQL text that looks like this:

    UPDATE `mytable`
       SET `col_one` = :val1
         , `col_two` = :val2
     WHERE `id_col` = :id 

and after the SQL text is prepared into statement, we can bind values:

         $sth->bindValue(':val1', $value_one , PDO::PARAM_STR );
         $sth->bindValue(':val2', $value_two , PDO::PARAM_STR );
         $sth->bindValue(':id'  , $id        , PDO::PARAM_INT );

and then execute