I am trying to set an array containig all required parameters for my PDO queries on a file, and the first of those queries is a SELECT making use of just one parameter.
$data = array(
'us_id' => $_POST['us_id'],
'us_credits' => $_POST['us_credits'],
'us_access' => $_POST['us_access']
);
$selectUsers= "SELECT * FROM ws_users WHERE us_id= :us_id";
$statementSelectUsers = $pdo->prepare($selectUsers);
$statementSelectUsers->execute($data);
$result = $statementSelectUsers->fetch(PDO::FETCH_ASSOC);
$us_fk_ui_id = $result['us_fk_ui_id'];
On executing, a Fatal Error emerges:
Fatal error: Uncaught exception 'PDOException' with message
'SQLSTATE[HY093]: Invalid parameter number: number of bound variables
does not match number of tokens' in
C:\wamp\www\waisap\actions\ad_updateUserInfo.php on line 25
Line 25 is the $statementSelectUsers->execute($data); line
As far as I've learned, a SELECT query on PDO does not need to execute(), but if no query is executed, I can not pass binded data contained on my array to query's placeholders. Is this the reason for the error? How to pass an array to be applied on my SELECT query's placeholders?
Let me repeat what I told you in the other answer 5 minutes ago:
array keys have to match placeholders in the query. If your queries have different sets of placeholders, you will need different arrays as well.
So, that's the reason for this problem.
As far as I've learned, a SELECT query on PDO does not need to execute(),
You've learned it wrong. You have to execute everything that has been prepared.
First, create $data array with only one element and use it for SELECT
$data = array('us_id' => $_POST['us_id']);
$stmt = $pdo->prepare("SELECT us_fk_ui_id FROM ws_users WHERE us_id= :us_id");
$stmt->execute($data);
$us_fk_ui_id = $stmt->fetchColumn();
for the later queries add other items to this array
Related
I'm getting this annoying error and although I have an idea of why I'm getting it, I can't for the life of me find a solution to it.
if ($limit) {
$sth->bindValue(':page', $page - 1, PDO::PARAM_INT);
$sth->bindValue(':entries_per_page', $page * $entries_per_page, PDO::PARAM_INT);
}
$sth->execute($criteria);
Query contains placeholders (:placeholder). But to add those LIMIT placeholders, I need to use the manual method (bindValue) because otherwise the engine will turn them into strings.
I'm not getting the Invalid number of parameters error, so all placeholders have been bound correctly (I assume).
Query:
SELECT `articles`.*, `regional_municipalities`.`name` AS `regional_municipality_name`,
`_atc_codes`.`code` AS `atc_code`, `_atc_codes`.`name` AS `substance`
FROM `articles`
LEFT JOIN `_atc_codes`
ON (`_atc_codes`.`id` = `articles`.`atc_code`)
JOIN `regional_municipalities`
ON (`regional_municipalities`.`id` = `articles`.`regional_municipality`)
WHERE TRUE AND `articles`.`strength` = :strength
GROUP BY `articles`.`id`
ORDER BY `articles`.`id`
LIMIT :page, :entries_per_page
All placeholder values reside in $criteria, except for the last two LIMIT, which I manually bind with bindValue().
This same error 2031 can be issued when one bind two values with the same parameter name, like in:
$sth->bindValue(':colour', 'blue');
$sth->bindValue(':colour', 'red');
..so, beware.
You cannot use ->bind* and ->execute($params). Use either or; if you pass parameters to execute(), those will make PDO forget the parameters already bound via ->bind*.
This exception also appears if you try to run a query with placeholders instead of preparing a statment such as
$stmt = $db->query('SELECT * FROM tbl WHERE ID > ?');
instead of
$stmt = $db->prepare('SELECT * FROM tbl WHERE ID > ?');
From the manual:
public bool PDOStatement::execute ([ array $input_parameters ] )
Execute the prepared statement. If the prepared statement included
parameter markers, you must either:
call PDOStatement::bindParam() to bind PHP variables to the parameter markers: bound variables pass their value as input and
receive the output value, if any, of their associated parameter
markers
or pass an array of input-only parameter values
You need to pick a method. You cannot mix both.
It's not exactly an answer, but this error also happens if you try to use a word with a hyphen as placeholders, for example:
$sth->bindValue(':page-1', $page1);
So better use
$sth->bindValue(':page_1', $page1);
This happens if you have mismatching parameters. For example:
$q = $db->prepare("select :a, :b");
$q->execute([":a"=>"a"]);
The exception also happens (at least in MySQL/PDO) when your SQL tries to UPDATE an AUTO_INCREMENT field.
I am currently looking at ways to use an API to connect and manage queries securely (SQL injection mitigation), while trying to follow DRY guidelines. I use prepared statements to prevent SQL injections, but I am running into warnings when running the function that is called when an HTTP GET request is received:
Warning: mysqli::bind_param(): Number of variables doesn't match number of parameters in prepared statement...
An then my query fails with:
Error: Commands out of sync; you can't run this command now Errno 2014
A simple google search provides me with this answer:
If you get Commands out of sync; you can't run this command now in your client code, you are calling client functions in the wrong order.
The warnings and error message only happens when there is more than one argument in the array.
My mySQL query function is as follows:
//set properties to values given by constructor params,
//open mysqli connection, etc..
public function query_db_stmt($sql, $param)
{
$stmt = $this->connection->prepare($sql);
for ($i = 1; $i < count($param); ++$i)
{
$stmt->bind_param(($param[0][$i - 1]), $param[$i]);
}
$stmt->execute();
$result = $stmt->get_result();
$stmt->close();
return $result;
} // do other stuff here, like close the sql connection in __destruct()...
And then I create the object and then invoke the query function like so:
$sql = 'SELECT ? FROM user WHERE id=?;';
$result = $mysql_db->query_db_stmt($sql, array('si', '*', $this->args[0]));
I am obviously doing something wrong, as I get these warnings, and a Err number 2014, but I cannot figure out what it is. Any help would be appreciated.
EDIT:
I now understand that I cannot use the column or table name as an prepared statement, but I still have a similar problem when using this code except with a HTTP PUT request:
parse_str(file_get_contents("php://input"), $put_vars);
$sql = 'INSERT INTO user (username, password, email, birth, sex) VALUES (?, ?, ?, ?, ?);';
$mysql_db->query_db_stmt($sql, array('sssss', $put_vars['username'], password_hash($put_vars['password'], PASSWORD_DEFAULT),
$put_vars['email'], $put_vars['birth'], $put_vars['sex']));
Using curl, I run curl -X PUT http://localhost/r.php -d username=foo -d password=boo -d email=test#gmail.com -d birthday=2015-08-13 -d sex=m
And I get the same error 5 times:
Warning: mysqli::bind_param(): Number of variables doesn't match number of parameters in prepared statement...
As before, But no DB Query failed error. Any comments?
The problem is that you are trying to bind the table name in PDO. Table and Column name cannot be replaced in PDO.
You don't need to put the column name in a ? and prepare the statement. Instead just take the values of the statement as params and bind the variables to them.
So, the $sql should be-
$sql = 'SELECT * FROM user WHERE id=?';
Then bind the variables accordingly.
Also, don't use SELECT * in your queries, always specify the column names you want output from.
I am attempting to do an UPDATE and a SELECT in the same sql statement. For some reason, the below code is failing.
$sql = "UPDATE mytable SET last_activity=CURRENT_TIMESTAMP,
info1=:info1, info2=:info2 WHERE id = {$id};";
$sql .= "SELECT id, info1, info2 FROM myTable
WHERE info1 >=:valueA AND info2>:valueB;"
$stmt = $conn->prepare($sql);
$stmt->bindParam(":info1", $info1);
$stmt->bindParam(":info2", $info2);
$stmt->bindParam(":valueA", $valueA);
$stmt->bindParam(":valueB", $valueB);
$stmt->execute();
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
echo json_encode($result);
QUESTION: what might I be doing wrong? I have been spending hours on this issue knowing that it's probably a small error right under my nose.
Edited:
I obtained this error message when loading the page that contains the php code:
Uncaught exception 'PDOException' with message 'SQLSTATE[HY000]:
General error' in ajaxCall.php:89 Stack trace: #0 ajaxCall.php(89):
PDOStatement->fetchAll(2) #1 {main} thrown in ajaxCall.php on line 89
I am using ajax to call the php page that contains the above code, and when I load the php page from the browser, I get the above error message.
Line 89 is: $result = $stmt->fetchAll(PDO::FETCH_ASSOC);
Since you are running two queries, you need to call nextRowset to access the results from the second one.
So, do it like this:
// code
$stmt->execute();
$stmt->nextRowset();
// code
When you run two or more queries, you get a multi-rowset result. That means that you get something like this (representation only, not really this):
Array(
[0] => rowset1,
[1] => rowset2,
...
)
Since you want the second set -the result from the SELECT-, you can consume the first one by calling nextRowset. That way, you'll be able to fetch the results from the 'important' set.
(Even though 'consume' might not be the right word for this, it fits for understanding purposes)
Executing two queries with one call is only allowed when you are using mysqlnd. Even then, you must have PDO::ATTR_EMULATE_PREPARES set to 1 when using prepared statements. You can set this using:
$conn->setAttribute(PDO::ATTR_EMULATE_PREPARES, 1);
Alternatively, you can use $conn->exec($sql), which works regardless. However, it will not allow you to bind any data to the executed SQL.
All in all, don't execute multiple queries with one call.
I am Getting Warning Like Warning: PDO::query() expects parameter 1 to be string, object given in C:\xampp\htdoc And Values are not Going to insert in database.
Can anybody please me I am Stuck With Problem From Many Days
Here is code:-
<?php
if(isset($_POST['btn_Add']))
{
// Step 1: Establish a connection
$conn = new PDO("mysql:host=localhost; dbname=DbName", 'root', '');
$MaxId ="2";
$Feild_1 =$_POST['txt_Feild1']; //datatype int
$Feild_2 =$_POST['txt_Feild2']; //datatype varchar
$Feild_3 =$_POST['txt_Feild3']; //varchar
// Step 2: Construct a query
$insert_query=$conn->prepare("Insert INTO Dbname (Max_Id, Feild_1, Feild_2, Feild_3)
values (:Max_Id,:Feild_1, :Feild_2, :Feild_3,");
// Step 3: Send the query
$result=$conn->query($insert_query);
// STEP 4:Bind The Placeholder name to specific Script variables
$insert_query->bindParam(':Max_Id', $Max_Id);
$insert_query->bindParam(':Feild_1', $Field_1);
$insert_query->bindParam(':Feild_2', $Field_1);
$insert_query->bindParam(':Feild_3', $Field_1);
//Step 5 Execute Query
$insert_query->execute();
}//OUTER IF END
?>
PDO Warning :-Warning: PDO::query() expects parameter 1 to be string, object given in C:\xampp\htdocs\BSNL Project\Add_Pin_Unpin_File(Without Auto Increment).php on line 109
[]
Step 1 - Fix your SQL:
So, with the code you've given, you've actually got an SQL error. If we take the SQL out of the PHP, it looks like...
Insert INTO Dbname (Max_Id, Feild_1, Feild_2, Feild_3)
values (:Max_Id,:Feild_1, :Feild_2, :Feild_3,
So the issue with this is that, first, you have a trailing comma that shouldn't be there, and you're missing a trailing ) that closes the values part of the query.
As a side note, you're using Dbname as a table name. Whether this is correct or not, we don't know, that depends on you.
Step 2 - Use PDO correctly:
The warning message you've provided is;
PDO Warning :-Warning: PDO::query() expects parameter 1 to be string, object given in C:\xampp\htdocs\BSNL Project\Add_Pin_Unpin_File(Without Auto Increment).php on line 109
If you look at the documentation the query method expects at least one parameter which has to be a string. This method returns an instance of PDOStatement and runs an execute straight away. As far as I know, it does not support prepared statements.
So the warning comes because you've called prepare with your SQL statement which returns an object of type PDOStatment, and then pass that returned object as the first parameter which as expected throws a warning saying that you've not passed a string.
By simply removing the line $result=$conn->query($insert_query); you will remove the warning message without causing other issues as it's not necessary anyway as you bind and then execute the query manually afterwards.
If there are further issues, then I'd suggest you have a look at setting the exception mode on your PDO connection variable and seeing what comes up.
Step 3 - Fix your binds
The final issue that I can see is with the following...
$insert_query->bindParam(':Max_Id', $Max_Id);
You bind $Max_Id but earlier in your code, you actually create the variable $MaxId.
The same goes for the fields. You bind $Field_1, but your actual variable is $Feild_1.
Finally, you're binding the same variable for multiple placeholders which doesn't seem quite right when you appear to have defined different variables for each one.
You need to call execute for the prepared queries.
http://php.net/manual/en/pdostatement.execute.php
$insert_query->execute();
I have a series of queries to loop through and execute using PDO.
The queries may make use of zero or more of the following 3 bound values, ":valA", ":valB" and ":valC".
At runtime I don't know which of these three parameter a query might use. But the values of these parameters will be the same for each query I loop through.
If I bind all three to a prepared query and the query does not make use of all the parameters, PDO will error.
I.e.
<?php
$stmt = $pdo->prepare('SELECT * FROM table WHERE col = :valA OR col = valB');
$stmt->execute(array(':valA' => 'a', ':valB' => 'b', ':valC' => 'c'); // Results in an error because the query does makes use of :valC.
Is there a method for binding a parameter without making it required to be used by a prepared query?
I thought I wuold be able to catch the exception and allow the code to resume, but the query won't execute regardless of the error mode set for PDO.
Note that this question is different to the suggested duplicate of, Ignore particular WHERE criteria. In that question, the query needed to be crafted to suit optional values supplied by a user. I this case, the values are hardcoded by the application, and the queries are stored in a database. The application does not know which params a query may make use of, so it needs to make them all available.
Obviously I can regex check for params, but it could be tripped up by a string that happen to contain the parameter name.
The queries could also be stored with additional properties to indicate which params it makes use of, but I would prefer to not have to do this.
There is a way to do this with PDO. The methods bindParam() and bindValue() return false or throw an exception if you try to bind to a parameter that doesn't appear in the query.
But it only works if you set:
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
Example:
$stmt = $pdo->prepare("INSERT INTO foo (test, boolcol) VALUES (:valA, :valB)");
if (!$stmt->bindParam("valA", $foo))
{
echo "error, no param 'valA'\n";
}
if (!$stmt->bindParam("valB", $foo))
{
echo "error, no param 'valB'\n";
}
if (!$stmt->bindParam("valC", $foo))
{
echo "error, no param 'valC'\n";
}
Outputs:
PHP Warning: PDOStatement::bindParam(): SQLSTATE[HY093]:
Invalid parameter number: parameter was not defined in /home/billkarwin/pdo.php on line 18
error, no param 'valC'
If you set $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); then it throws an exception instead of a warning, and you could wrap each bindParam() in a try/catch block:
PHP Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[HY093]:
Invalid parameter number: parameter was not defined' in /home/billkarwin/pdo.php:18
Stack trace:
#0 /home/billkarwin/pdo.php(18): PDOStatement->bindParam('valC', 'foo')
#1 {main}
thrown in /home/billkarwin/pdo.php on line 18