PHP and PDO prepared statments - Column not found - php

I have a problem with a "unknown" column.
This is the error I get back in firebug.
ERROR: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'admin' in 'where clause'UPDATE users SET session_key = 1234567890 WHERE username = 'admin'
this is the parameters and call statement
$table = 'users';
$fields_vals = array( 'session_key' => $session_key );
$where = array('username' => $username);
$dbResult = $this->DB->sql_update($fields_vals, $table, $where);
/*
* UPDATE
* $data -> assoc array containing (field => value) to be UPDATED.
* $where -> Where clause (only a single argument)
* $table -> to be updated
*/
public function sql_update($fieldsVals, $table, $where)
{
try {
//Values to be updated in in a assoc array
//Extract values and fields and concatenate with '=' ( field = value )
$upd_string = '';
foreach($fieldsVals as $name => $value){
$upd_string .= $name .' = :'. $name .' ,';
}
//Trim last comma that was appended
$upd_string = rtrim($upd_string, ',');
// Formulate the where clause
$where_str = '';
foreach($where as $wName => $wValue){
$where_str .= "$wName = $wValue";
}
//Set Query
//$query = "UPDATE {$table} SET {$upd_string} WHERE $where_str";
// THIS IS WHERE I EXPLICITLY RAN THE QUERY, BUT GOT EXACTLY THE SAME ERROR.
$query = "UPDATE users SET session_key = 1234567890 WHERE username = 'admin'";
$stmt = $this->conn->prepare($query);
//Exec
foreach($fieldsVals as $k => &$v){
$stmt->bindParam(":{$k}", $v);
}
$stmt->execute();
return true;
} catch(PDOException $e) {
echo 'ERROR: ' . $e->getMessage();
return false;
}
}
Here is proof that the column does exist.
PLEASE NOTE -> where username = 'admin'

Try passing your WHERE attribute in as a prepared variable:
$query = "UPDATE users SET session_key = 1234567890 WHERE username = :username";
$fieldsVals[":username"] = "admin";

$where_str .= "$wName = '$wValue'";
Otherwise your query comes as "WHERE username = admin"

What you should do to use prepared statements for the whole query, so you should change your function from the current one into:
function sql_update($fieldsVals, $table, $where)
{
//Values to be updated in in a assoc array
//Extract values and fields and concatenate with '=' ( field = value )
$upd_string = '';
foreach ($fieldsVals as $name => $value) {
$upd_string .= $name . ' = :set_' . $name . ' ,';
}
//Trim last comma that was appended
$upd_string = rtrim($upd_string, ',');
// Formulate the where clause
$where_str = '';
foreach ($where as $wName => $wValue) {
$where_str .= $wName . ' = :wh_' . $wName . ' ,';
}
//Trim last comma that was appended
$where_str = rtrim($where_str, ',');
//Set Query
$query = "UPDATE {$table} SET {$upd_string} WHERE $where_str";
$stmt = $this->conn->prepare($query);
//Exec
foreach ($fieldsVals as $k => &$v) {
$stmt->bindParam(":set_{$k}", $v);
}
foreach ($where as $k => &$v) {
$stmt->bindParam(":wh_{$k}", $v);
}
$stmt->execute();
return true;
}

The correct usage would be:
$stmt = $this->conn->prepare('UPDATE users SET session_key = :session WHERE username = :username');
$stmt->bindParam(':session', session_id(), PDO::PARAM_STR);
$stmt->bindParam(':username', $username, PDO::PARAM_STR);
Then execute.
I think your variable $fieldsVals is wrong due to the foreach's you do. Maybe you switching key und val by accident, resulting in WHERE admin=username.
Update:
#MarcinNabiaƂek is right of course you are missing quotes.
But it seems like the error is coming from a different part of the script.

It seems you don't use ' in your query in PHP. Either you don't use it or use other symbol that look similar.
If I run in phpmyAdmin query:
UPDATE users SET session_key = 1234567890 WHERE username = admin
I also get error message:
#1054 - Unknown column 'admin' in 'where clause'
but when I have
UPDATE users SET session_key = 1234567890 WHERE username = 'admin'
it works fine
In your code you should definitelly change:
$where_str .= "$wName = $wValue";
into
$where_str .= "$wName = '$wValue'";

session_key is a varchar
You have to use the query like the below,
$query = "UPDATE users SET session_key = '1234567890' WHERE username = 'admin'";

column admin doesn't exist! column administrator exists though.
I don't see any admin column in your mysql table in the screenshot that you provided.
You can simply change the name of the administrator column in your mysql table to admin and everything will work.

Related

Update Row Fields if POST['submitted_field'] Is Not Null MariaDB , MySQL

Hi I'm trying to update user information on valid submit
in my query it's possible to update multiple columns only if it's relevant $_POST[ ] is not null
how i can do that ? used tool php , MariaDB or mysql I. I tried something like this but it returns syntax error corresponding to MariaDB
$query = " UPDATE `users`
SET name = COALESCE($name, name),
title = COALESCE($title, title),
email = COALESCE($email, email),
gender = COALESCE($gender, gender)
WHERE `id` = '" . $_SESSION['id'] . "' LIMIT 1";
You can have a helper for doing that
function getUserUpdateQuery(array $data, $userId)
{
$condition = 'WHERE id = '.$userId;
$query = 'UPDATE `users` SET ';
$updates = [];
foreach ($data as $columnName => $columnValue) {
if( !is_null($columnValue) )
{
$updates[] = sprintf('`%s` = \'%s\'', $columnName, $columnValue);
}
}
$query .= implode(' AND ', $updates).' ';
$query .= $condition;
return $query;
}
$query = getUserUpdateQuery(['title' => $title, 'email' => $email], $_SESSION['id']);
// updating codes here
Note: in production environment it is better practice to bind data. PDO is a good tool for doing that.

php function to mysqli update

Trying to create a function that would be used to update any row of any table, but I'm getting trouble getting into it.
Data sent in array where the array index is the field name in table and the value is the new value for that index.
For examplpe:
$args["name"] = "NewName";
$args["city"] = "NewCity";
$args["id"] = 4; // row ID to update
What I got:
function create_update_query($table, $keys){
$keys = array_map('escape_mysql_identifier', $keys);
$table = escape_mysql_identifier($table);
$updates = "";
$count = 0;
foreach($keys as $index => $value){
if($index != "id"){
$count++;
if($count == count($keys)-1){
$updates = $updates . "$index = ?";
}else{
$updates = $updates . "$index = ?,";
}
}
}
return "UPDATE $table SET $updates WHERE id = ? LIMIT 1";
}
After that, I have the function to really do the query:
function crud_update($conn, $table, $data){
$sql = create_update_query($table, array_keys($data));
if(prepared_query($conn, $sql, array_values($data))){
$errors [] = "OK";
}else{
$errors [] = "Something weird happened...";
}
}
The function that makes the prepared statement itself:
function prepared_query($mysqli, $sql, $params, $types = ""){
$types = $types ?: str_repeat("s", count($params));
if($stmt = $mysqli->prepare($sql)) {
$stmt->bind_param($types, ...$params);
$stmt->execute();
return $stmt;
} else {
$error = $mysqli->errno . ' ' . $mysqli->error;
echo "<br/>".$error;
}
}
When trying to submit the data with the following criteria:
$args['name'] = "Novo Nome";
$args['field'] = "New Field";
$args['numaro'] = 10101010;
$args['id'] = 4;
//create_update_query("teste_table", $args);
crud_update($link, "teste_table", $args);
Have an error:
1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '1 = ?,2 = ?,3 = ? WHERE id = ? LIMIT 1' at line 1
But if I echo the query created by create_update_query it seems ok:
UPDATE `teste_table` SET name = ?,field = ?,numaro = ? WHERE id = ? LIMIT 1
Any help would be appreciated.
Thanks.
The problem is that as you pass the keys to create_update_query() as
create_update_query($table, array_keys($data));
Using array_keys() will just take the key names, so the $keys parameter is just a list of the field names as something like ...
Array(
0=> 'name',
1 =>'field',
2 =>'numaro'
)
You then extract the data using
foreach($keys as $index => $value){
and build your SQL with
$updates = $updates . "$index = ?";
so at this point, the indexes are the numeric value, so change these lines to...
$updates = $updates . "$value = ?";
which is the name of the field.
With the various other changes, I would suggest the code should be...
foreach($keys as $value){
if($value != "id"){
$updates = $updates . "$index = ?,";
}
}
$updates = rtrim($updates, ",");
return "UPDATE $table SET $updates WHERE id = ? LIMIT 1";

Pass parameter with a space in prepared statement

The prepared statement that gets generated dynamically from my PHP (as an example) looks like this:
SELECT COUNT(exuid) as result_count FROM full_db3 WHERE `Age Range` = :Age Range
Age Range is one of my column names.
The problem here is that having the space in between "Age" and "Range" in my parameter, but I'm not sure how to handle this. The query is generated dynamically like so (only relevant code shown):
$all_attributes = $_POST['attris'];
$sql = "SELECT COUNT(exuid) as result_count FROM {$table}";
$any_condition = false;
foreach($all_attributes as $key=>$val) {
if (!empty($val) && in_array($key,$validKeys)) {
if ($any_condition) {
$sql .= ' AND `'.$key.'` = :'.$key;
} else {
$sql .= ' WHERE `'.$key.'` = :'.$key;
$any_condition = true;
}
}
}
$stmt = $dbh->prepare($sql);
foreach($all_attributes as $key=>$val) {
if (!empty($val) && in_array($key,$validKeys)) {
$stmt ->bindValue(':'.$key, $val, PDO::PARAM_STR);
}
}
$stmt->execute();
If I change my column name in the DB to Age_Range everything works perfectly fine. For a number of reasons, I'd like to be able to exclude that underscore, as I display my column names in a select and all the underscores look terrible.
Using my idea, and copying syntax from u_mulder's comment, this should work?
$all_attributes = $_POST['attris'];
$sql = "SELECT COUNT(exuid) as result_count FROM {$table}";
$any_condition = false;
foreach($all_attributes as $key=>$val) {
if (!empty($val) && in_array($key,$validKeys)) {
if ($any_condition) {
$sql .= ' AND `'.$key.'` = :'.str_replace(' ', '_', $key);
} else {
$sql .= ' WHERE `'.$key.'` = :'.str_replace(' ', '_', $key);
$any_condition = true;
}
}
}
It leaves the field names as is, and only changes the parameter names.
But this
$stmt ->bindValue(':'.$key, $val, PDO::PARAM_STR)
will probably need changed to this as well
$stmt ->bindValue(':'.str_replace(' ', '_', $key), $val, PDO::PARAM_STR)

Dynamic prepared statement, PHP

I've checked almost all questions that produce the same error but all of these questions bind parameters in some wrong way. Perhaps and most probably I too am binding params incorrectly though my case is different because I've dynamic query.
I am creating query dynamically from input which is being created perfectly. But problem comes from $stmt->bind_param statement within foreach loop. Here is my Code snippet that is erronous:
$query = "UPDATE users SET";
foreach($updationFields as $field => $value){
if($value != "-"){
$query = $query. " " . $field . " = :".$field.",";
}
}
$query = rtrim($query, ",");
$query = $query . " WHERE UserId = :UserId";
$stmt = $this->conn->prepare($query);
foreach($updationFields as $field => $value){
echo $field;
if($value != "-"){
$input = ":".$field;
$stmt->bind_param($input, $value); // This line produces error
}
}
$stmt->bind_param(":UserId", $userId);
$stmt->execute();
Here is produced dynamic "string query" for one field:
UPDATE users SET fullName = :fullName WHERE UserId = :UserId
Error says: Fatal error: Call to a member function bind_param() on a non-object in
Any Idea what i am doing wrong?
As pointed out by #Fred-ii- and #commorrissey :Placeholder is supported by PDO not mysqli so so I had to:
Replace :Placeholders with ?
Call bind_param with call_user_func_array feeding dynamic references as expected by mysqli_stmt.
Here is the code that creates dynamic binding:
$params = array();//
$params[] = $type;
$i=0;
foreach($updationFields as $field => $value){
if($value != "-"){
$bind_name = 'bind' . $i;
$$bind_name = $value;
$params[] = &$$bind_name;
$i++;
}
}
$bind_name = 'bind' . $i;
$$bind_name = $userId;
$params[] = &$$bind_name;
$return = call_user_func_array(array($stmt,'bind_param'), $params);

building db query with a for loop

I've made a function to query the database. This function takes an array, the id of the user I want to update
and a query operation.
if the query operation is UPDATE
if you look at the code below, would this be a good coding practice or is this bad code?
public function query($column, $search_value, $query_operation = "SELECT"){
if(strtoupper($query_operation == "UPDATE")){
$query = "UPDATE users SET ";
if(is_array($column)){
$counter = 1;
foreach($column as $key => $value){
if($counter < count($column)){
$query .= $key . ' = ?, ';
}else{
$query .= $key . ' = ? ';
}
$counter++;
}
$query .= "WHERE id = ?";
$stmt = $this->database->prepare($query);
$counter = 1;
foreach($column as $key => &$value){
$stmt->bindParam($counter, $value);
$counter++;
}
$stmt->bindParam($counter, $search_value);
if($stmt->execute()){
$stmt = $this->database->prepare("SELECT* FROM
users WHERE id = ?");
$stmt->bindParam(1, $search_value, PDO::PARAM_INT);
$stmt->execute();
return $this->build_array($stmt);
}
}
}
}
would love to hear some feedback.
I would NOT mix SELECT and UPDATE in the same function.
The following update function uses arrays for column names and values $columnNames & $values using unnamed parameters.
function update($tableName,$columnNames,$values,$fieldName,$fieldValue){
$sql = "UPDATE `$tableName` SET ";
foreach($columnNames as $field){
$sql .= $field ." = ?,";
}
$sql = substr($sql, 0, -1);//remove trailing ,
$sql .= " WHERE `$fieldName` = ?";
return $sql;
}
As table and column names cannot be passed as parameters in PDO I have demonstrated whitelistng of table names.
$tables = array("client", "Table1", "Table2");// Array of allowed table names.
Also array_push()to add value for last parameter (WHERE) into $values array
Use
if (in_array($tableName, $tables)) {
$sql = update($tableName,$columnNames,$values,$fieldName,$fieldValue);
array_push($values,$fieldValue);
$STH = $DBH->prepare($sql);
$STH->execute($values);
}
You can use similar technique for SELECT

Categories