Error when using placeholder in prepared statement - php

I got this error when using the code below (everything is in a try catch block):
SQLSTATE[HY093]: Invalid parameter number: number of bound variables
does not match number of tokens
$item_q = 4;
$item_no = 12;
$update = $db->prepare("UPDATE stock
SET quantity = quantity - :item_q
WHERE item_number = :item_no");
$update->execute([':item_q' => $item_q]);
$update->execute([':item_no' => $item_no]);
It is something with the :item_q that is causing problem and i do not what it is. It works when I replace the :item_q in the sql query with a number. I am happy for some help! :)

Issue
Currently you're executing twice with one parameter bound each time.
Solution
You want to either bind the parameters first then execute, or execute with both parameters bound.
Executing with both bound values in PDOStatement::execute() function
$update->execute([":item_q" => $item_q, ":item_num" => $item_no]);
Executing after binding parameters with PDOStatement::bindParam() function
$update->bindParam(":item_q", $item_q, PDO::PARAM_INT);
$update->bindParam(":item_num", $item_no, PDO::PARAM_STR);
$update->execute();

Problem is with executing your statement two times.
$update->execute([':item_q' => $item_q]);
$update->execute([':item_no' => $item_no]);
Combine it into one as
$update->execute([':item_q' => $item_q,':item_no' => $item_no]);

Try this and let me know if it doesn't work
$update->execute([':item_q' => $item_q,':item_no' => $item_no]);

Related

Why does this PDO prepared statement not update the record?

I have a login system and I am currently converting it to PDO, but I think there is something wrong with my code as whenever I run the original code it works and when I run the PDO it doesn't (there are no errors in the console).
This is my original code:
$update_otp = "UPDATE classadmin SET code = $code, status = $status WHERE code = $fetch_code";
$update_res = mysqli_query($con, $update_otp);
This is my PDO converted code:
$update_otp = $conn->prepare("UPDATE classadmin SET code = :code, status = :status WHERE code = :code");
$update_res = $update_otp->execute(['code' => $code, 'status' => $status, 'code' => $fetch_code]);
code occurs twice as a named argument in the given statement, with two different values. This won't work, unless $code === $fetch_code.
This might help you out, using distinct names for the named arguments (you are completely free to choose them, they don't need to match the column name):
$update_otp = $conn->prepare("UPDATE classadmin SET code = :newCode, status = :status WHERE code = :oldCode");
$update_res = $update_otp->execute(['newCode' => $code, 'status' => $status, 'oldCode' => $fetch_code]);
When using emulated prepared statements (this is the default with PDO), the same placeholder can appear multiple times in the SQL. You have :code twice in the SQL. The value that you provide for :code in the execute will be put in place of the two placeholders named :code.
In PHP, associative arrays cannot have the same value with the same key. The one that comes later will overwrite the value with the same key.
$update_otp = $conn->prepare("
UPDATE classadmin
SET
code = :code,
status = :status
WHERE code = :code
");
$update_res = $update_otp->execute([
'code' => $code,
'status' => $status,
'code' => $fetch_code // <-- This one will overwrite the first $code
]);
To fix the problem use distinctly named placeholders or use positional arguments instead.

PDO Object: Invalid parameter number: number of bound variables does not match number of tokens

$queryString = 'SELECT * FROM n8593370.items AND Suburb = :suburb AND Name LIKE \'%:name%\'';
$stmt = $pdo->prepare($queryString);
$stmt->bindValue(':suburb', $suburb);
$stmt->bindValue(':name', $name);
$stmt->execute();
$results = $stmt->fetchAll();
I am getting the above mentioned error can not for the life of my figure out why.
I am certain I only have 2 variables to bind and that I indeed bind both.
When I perform this with each conditional on their own i.e. WHERE 1 = 1 AND Suburb = :suburb or WHERE 1 = 1 AND Name LIKE \'%:name%\' I do not have any errors.
ALTHOUGH the latter of the two conditionals does not return any results, however when I test it in MySQL Workbench it works as I expect it.
Can anybody shed some light on the issue?
When using placeholder values it's important to leave any and all escaping out of the query. The value itself should be bare, PDO will take care of the escaping for you if you're disciplined about using placeholder values.
Specify it this way:
"...name LIKE :name..."
Then you bind this way:
$stmt->bindValue(':name', "%$name%");

PHP-PDO_PGSQL - SQLSTATE[HY093]: Invalid parameter number

It's all the day that I'm stuck with this simple prepared statement:
// $conn it's my PDO Object
// and $intervention my params'array
$s = $conn->prepare("INSERT INTO intervention(firm_id,category,subject,amount,start_date,end_date) VALUES(:firm_id,':category',':subject',:amount,':start_date',':end_date')");
$result = $s->execute(array(
'firm_id' => $firm_id ,
'category' => $intervention["category"] ,
'subject' => $intervention["subject"] ,
'amount'=> $intervention["amount"] ,
'start_date'=> $intervention["start_date"],
'end_date'=>$intervention["end_date"]
));
The execute will give me:
Warning: PDOStatement::execute(): SQLSTATE[HY093]: Invalid parameter number: :category
Can someone help me understand what is wrong with this simple code?
In this part of the query:
VALUES(:firm_id,':category',
:category is taken as a literal string and not as a parameter name, because of the quotes enclosing it.
There should be no quotes around parameter names, as in:
...VALUES(:firm_id, :category,...
There is the same mistake for the other non-numeric parameters of the rest of the query.
Parameters name should not have a quotes. The prepared statement will do the replacement properly. Pay attention too at the number of parameters you write in the query and what will you bind on execute method.

PDOException SQLSTATE[HY093]: yii-2 where and between Query

After long research I could not find a exact solution for the PDOException SQLSTATE[HY093]
I am using yii 2 frame work and i have problem when using between condition.
$query = SalesOrder::find()->where(['between','created_date', ':fromDate', ':toDate']);
$query->addParams([':fromDate' => $salesReport->fromDate,':toDate' => $salesReport->toDate]);
$query->all();
tried differently same problem.
$qString1=':fromDate';
$qString2=':toDate';
$query = SalesOrder::find()->where(['between','created_date',$qString1,$qString2]);
$query->addParams([':fromDate' => $salesReport->fromDate],[':toDate' => $salesReport->toDate]);
$query->all();
Caused by: PDOException
SQLSTATE[HY093]: Invalid parameter number: number of bound variables does not match number of tokens
You can not pass parameter name in this case. try :
$query = SalesOrder::find()->where(['between','created_date', $salesReport->fromDate, $salesReport->toDate]);
$query->all();
Or, If you'd like to use parameter, try :
$query = SalesOrder::find()->where('created_date BETWEEN :fromDate AND :toDate');
$query->addParams([':fromDate' => $salesReport->fromDate],[':toDate' => $salesReport->toDate]);
$query->all();

Function doesn´t work with more parameters

This is my function:
function countRows($sql, $parameters){
$db = new PDO("mysql:host=localhost;dbname=cms","root");
$result = $db->prepare($sql);
foreach ($parameters as $key => $parameter) {
$result->bindParam($key, $parameter);
}
$result->execute();
$number_of_rows = $result->fetchAll();
return count($number_of_rows);
}
With $parameters array like this it works just fine:
$parameters=array("key"=>"parameter");
But when the array has more keys and variables it just will give result 0
For example with array like this it gives me 0 rows, when it should be 3
$parameters=array("key"=>"parameter", "key2"=>"parameter2");
Edit:
Example of an query:
"SELECT * FROM users WHERE username=:username AND password=:password"
Example of an $parameters for this query:
$parameters = array(":username"=>$username, ":password"=>$password);
When i run it with one column (like only username or only password) it runs fine, with both it returns always 0.
The problem is that you're using bindParam() for a variable that changes its value:
foreach ($parameters as $key => $parameter) {
$result->bindParam($key, $parameter);
}
You have to understand that bindParam() binds the variable by reference, not the value the variable has at the time you do the bind.
You're binding the variable $parameter to both parameters in your query. The value isn't sent until you call execute(). So it sends the value that the variable has after the loop is finished, which is the password.
I tested this by enabling the general query log on my MySQL server, and observing what gets logged:
140905 10:09:45 49 Connect root#192.168.56.1 on test
49 Prepare SELECT * FROM users WHERE username=? AND password=?
49 Execute SELECT * FROM users WHERE username='password' AND password='password'
49 Close stmt
49 Quit
You can solve this in either of two ways:
Use bindValue() instead of bindParam(). This copies the value of $parameter at the time you do the bind.
Alternatively, you don't need to do a loop for binding parameters one at a time all, just pass the array to execute():
$result->execute($parameters);
I don't know why so many developers believe they're required to write code to bind parameters one at a time. It's easier to pass the array of parameters directly to execute().
Your parameters should look like array
$parameters = [
"key" => "parameter",
"key2 " => "parameter2"
];
Then You missed the password
$db = new PDO("mysql:host=localhost;dbname=cms","root","your_password");
My idea take a look on PDOStatement::bindParam Docs

Categories