PDO not executing bound variables correctly [duplicate] - php

This question already has answers here:
Can PHP PDO Statements accept the table or column name as parameter?
(8 answers)
Closed 8 years ago.
So I am having this strange issue with PDO, in that queries with bound variables are not executing properly for some reason. Let me show some code:
$conn = new PDO("mysql:host=$db_host;dbname=$db_name", $db_user, $db_pwd);
$sth=$conn->prepare("select count(*) from article");
$sth->execute();
var_dump($sth->fetchColumn());
This will print out the correct number of entries in the table "article".
However, if we change it slightly, by making the table a named parameter instead of a constant:
$conn = new PDO("mysql:host=$db_host;dbname=$db_name", $db_user, $db_pwd);
$sth=$conn->prepare("select count(*) from :article");
$sth->execute(array(":article"=>"article"));
var_dump($sth->fetchColumn());
This will print a boolean false. Both statements should return the same result, but I have no idea why the second one is not working. I suspect I have a typo somewhere, but I checked several times, and I don't see any issue. Anyone have any idea?

Not possible. You're trying to use a placeholder for a tablename. This is not permitted. placeholders can only replace values.
SELECT count(*) FROM :table WHERE field=:article
^^^^^^--illegal ^^^^^^^^--legal
For this, you'll have to use old-fashion string building:
$table = "article";
$sth=$conn->prepare("select count(*) from $table");
which then re-opens the SQL injection attack vulnerability, because you're now directly inserting external data into an SQL string.

Related

Why does this prepared statement binding fail? [duplicate]

This question already has answers here:
Use bound parameter multiple times
(5 answers)
Closed 3 years ago.
I'm having an issue with the PDO statements for ODBC.
I'm using SQL SERVER 7 in Windows Server 2003 and PHP 5.4.x
For eg:
I have the query:
(this is not the actual query but it serves right for the example)
$query = SELECT * FROM table WHERE number = :number OR number = :number
in my php i have:
$conn = new PDO($connectionString);
$conn->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$statement = $conn->prepare($query);
$statement->bindParam(':number', $someNumber);
$statement->execute();
This throws error
COUNT field incorrect or syntax error
The thing is, bindParam is only binding the FIRST occurrence of :number ... AND trying to bind it again doesn't work either.
Is there a way to bind multiple named params with the same name?
I'm trying not to use positional params using the ? instead
Theoretical you could turn on emulation of prepared statements.
You must include a unique parameter marker for each value you wish to
pass in to the statement when you call PDOStatement::execute(). You
cannot use a named parameter marker of the same name more than once in
a prepared statement, unless emulation mode is on.
http://www.php.net/manual/en/pdo.prepare.php
I don't know too much about MsSQL to be honest, but I am quite sure there is some equivalent to User Defined Variables in MySQL. You could use those instead of parameters like I described in this answer:
https://stackoverflow.com/a/31068865/3391783
Just turn emulation on, changing this setting from false to true:
$conn->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);

Updating sql table using php [duplicate]

This question already has answers here:
How can I prevent SQL injection in PHP?
(27 answers)
Closed 6 years ago.
I have a table (core_customer_information) and I want to create a SQL query in php that uses the variable $code and updates the activated field in my table.
$code = mysqli_real_escape_string($conn, $_GET['code']);
$check = mysqli_query("SELECT * FROM core_customer_information WHERE activation_code='$code' AND activated='1' ");
if ( mysqli_num_rows($check) == 1)
{
die ('The account has already been activated');
}
else
{
$activate = mysqli_query("UPDATE core_customer_information SET activated='1' WHERE activation_code='$code'");
echo ('Your account has know been activated <br>');
echo $code;
}
First of all, I check whether the activated is equal to 1, in which case the account is classed as activated, and if not, I then create an UPDATE query to update the activated field of this class.
My problem is that the query isn't updating my table and I'm unsure where the problem is at.
I would appreciate if someone could take a look for me please.
I would recommend you use mysqli_real_escape_string as it escapes the string taking into account the current connection charset as stated by the page:
This function is used to create a legal SQL string that you can use in an SQL statement. The given string is encoded to an escaped SQL string, taking into account the current character set of the connection.
To prevent most mysql injection methods you should do the following:
$code = mysqli_real_escape_string($link, $_GET['code']);
If you should ever use an adapter like ADODB or some other, I'd recommend you use prepared statements and their methods of preventing SQL injection.
It's not totally clear from your question what language you will be using to launch the SQL queries (since the only tags are sql and mysql at the moment...)
But if the language is similar to Java then you can use something similar to Java's PreparedStatement. (See https://docs.oracle.com/javase/7/docs/api/java/sql/PreparedStatement.html)
A PreparedStatement is safer than simple concatenation of dynamic variables into sql Strings.

How to update database using PHP variables? [duplicate]

This question already has answers here:
How to include a PHP variable inside a MySQL statement
(5 answers)
Closed 3 years ago.
$Createdby=$_SESSION['adminlog'];
$total =$_POST['total'];
$due =$_POST['due'];
$date =$_POST['issedate'];
$invoiceno =$_POST['invno'];
$CmpnyName =$_POST['CmpnyName'];
$itemdetails =$_POST['item_details'];
$itemname =$_POST['itemname'];
$amtpaid =$_POST['paid'];
$query = "UPDATE billdata SET Total='$total' Due='$due' WHERE InvoiceNo=$invoiceno";
$result = mysql_query($query);
This is the code I am using to get HTML values to variable and update particular invoice number with new data.
First off, never use the deprecated mysql_* API.
Switch to either PDO or mysqli, both have prepared statements, which would make your code a tad bit more safe when it comes to SQL-Injections (which your code is very open for).
When a query fails, the mysql_error() global function will return the latest mysql error.
The easiest way to get information about a failing query is by adding or die(mysql_error()); after the query execution.
Example with your code:
$result = mysql_query($query) or die(mysql_error());
This will report your error and stop execute the script.
Your sql code is slightly wrong (as RST mentions), you are missing a comma between the values you are trying to set.
Using mysqli and prepared statements, your code could look something like:
// Using the mysqli object oriented style.
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = new mysqli('localhost', 'username', 'password', 'database');
// Prepare the statement.
$statement = $mysqli->prepare('UPDATE billdata SET Total=?, Due=? WHERE InvoiceNo=?');
// The question marks is placeholders for the input that will be added in a while.
// Bind your parameters (ssi tells mysqli what type of params it is, s = string, i = int).
$statement->bind_param('ssi', $total, $due, $invoceno);
// Execute the statement.
$statement->execute();
// Cleanup.
$statement->close();
$mysqli->close();
$query = "UPDATE billdata SET Total='$total', Due='$due' WHERE InvoiceNo=$invoiceno";
There should be a comma between the sets of values.
It is not a good idea to use the value from $_POST() as they are, better perform some validation checks.

PHP PDO bindParam/bindValue Multiple times [duplicate]

This question already has answers here:
Use bound parameter multiple times
(5 answers)
Closed 3 years ago.
I'm having an issue with the PDO statements for ODBC.
I'm using SQL SERVER 7 in Windows Server 2003 and PHP 5.4.x
For eg:
I have the query:
(this is not the actual query but it serves right for the example)
$query = SELECT * FROM table WHERE number = :number OR number = :number
in my php i have:
$conn = new PDO($connectionString);
$conn->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$statement = $conn->prepare($query);
$statement->bindParam(':number', $someNumber);
$statement->execute();
This throws error
COUNT field incorrect or syntax error
The thing is, bindParam is only binding the FIRST occurrence of :number ... AND trying to bind it again doesn't work either.
Is there a way to bind multiple named params with the same name?
I'm trying not to use positional params using the ? instead
Theoretical you could turn on emulation of prepared statements.
You must include a unique parameter marker for each value you wish to
pass in to the statement when you call PDOStatement::execute(). You
cannot use a named parameter marker of the same name more than once in
a prepared statement, unless emulation mode is on.
http://www.php.net/manual/en/pdo.prepare.php
I don't know too much about MsSQL to be honest, but I am quite sure there is some equivalent to User Defined Variables in MySQL. You could use those instead of parameters like I described in this answer:
https://stackoverflow.com/a/31068865/3391783
Just turn emulation on, changing this setting from false to true:
$conn->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);

How do you use IN clauses with mysqli prepared statements [duplicate]

This question already has answers here:
How can I bind an array of strings with a mysqli prepared statement?
(7 answers)
Closed 3 years ago.
I’m moving some old code over to the new msqli interface using prepared statements, I’m having trouble with SQL statements containing the IN clause. I would just normally do this:
$ids = '123,535,345,567,878'
$sql = "SELECT * FROM table WHERE id IN ($ids)";
$res = mysql_query($sql);
Converting this to mysqli and prepared statements I have tried a number of solutions:
$ids = '123,535,345,567,878'
$ids = implode($ids,',');
$result = $msqli->prepare("SELECT foo,blar FROM table WHERE id IN (?));
$result->bind_param("i", $ids);
$result->execute();
The above fails and calculating the number of elements in the array and altering number of question marks in the SQL string and calling bind_parm for each element in the array also fails. Just using the comma separated string also fails.
I can find no good documentation in Google on this, so how have you solved the problem?
It's not possible to bind a list of variable length to a single bound variable.
Similarly, if you were to bind the string $ids you'll actually end up with:
SELECT foo,blar FROM table WHERE id IN ('123,535,345,567,878')
(Note the quotes around the list of IDs).
Creating your own query with the right number of question marks and bound parameters should have actually worked - you may need to try that again and report on the actual error.
Alternatively, this may be one of those occasions where it's unfortunately necessary to hand-craft your own SQL and not use bound parameters.
Look at the answer to a similar question that has been asked here before (second code sample):
I have an array of integers, how do I use each one in a mysql query (in php)?
It boils down to:
create the SQL string with the right amount of question marks
use call_user_func_array() to bind your array to the query string
I thought the point of prepared statements was so in this situation you could just do:
$stmt = $this->mysqli->prepare("UPDATE radcheck SET attribute = ?, value = ? WHERE username = ? AND attribute LIKE 'CS-Total-Octets%'");
foreach ($usernames as $username)
{
$stmt->bind_param('sss', $bandwidth_types[$bandwidth_type], $bandwidth_bytes, $username);
$stmt->execute();
}
$stmt->close();

Categories