PHP PDO bindValue fails on ODBC to SQL Server - php

I want to bind Values to a SQL Statement using a PDO connection to an SQL Server via ODBC.
If I execute the statement without a parameter I get a result but if I want to bind a parameter to that sql I get a "Function sequence error" thrown back.
$fromDate = strval(date('Y-d-m'))." 00:00:00.000";
//works
$sql = "SELECT a.FromDate FROM Absence a WHERE a.FromDate > '".$fromDate."'";
$arrParams = [];
runStatement($sql, $arrParams);
//don't work
$sql = "SELECT a.FromDate FROM Absence a WHERE a.FromDate > :fromdate1";
$arrParams = [':fromdate1' => $fromDate];
runStatement($sql, $arrParams);
//thats how I bind the parameters
function runStatement($sql, $arrParams)
{
$stmt = $this->conn->prepare($sql);
foreach($arrParams as $key => $value)
{
$stmt -> bindValue($key, $value);
}
$stmt -> execute();
return $stmt -> fetchAll(PDO::FETCH_ASSOC);
}
I tried to bind the values with bindParam() but the error remains the same. On Sqlite and Ingres Database the bindValue() works fine for me.
I am using PHP 8.x and SQL Server 2012. Installing the php drivers for SQL doesn't work here.
Edit: I could narrow down the error to the date type. Because in the where clause I want to compare two dates.
When I try other statements without dates as binded params the statement works fine.
So the comparison of the datetype is the error here.

Related

PHP SQL Injection bind dynamic variables in statement for UPDATE

I am trying to be safe from Sql Injection by doing prepared statements + binding on all Database save/update/query actions.
But I got stuck in the moment in which the table name + user_id are variables. code:
// ALL USUAL $dbc MySqli DATABASE CONNECTION - then code statement prepare:
$stmt = $dbc->prepare("UPDATE ".$tablex." SET logo=?, last_mod=? WHERE ".$table_id."=?");
// or: $stmt = $dbc->prepare("UPDATE $tablex SET logo=?, last_mod=? WHERE $table_id=?"); same thing
$stmt->bind_param('ssi', $log_logo, $last_mod, $user_id);
// execute and do some checking
$status_save = $stmt->execute();
if ($status_save === false) {trigger_error($stmt->error, E_USER_ERROR);}
It has worked fine so far as long as $tablex and $table_id were known. Now they can have different names, and using a variable sets things wrong. What am I doing wrong here? Tx.

What's the correct syntax for returning a single value using PDO and mySQL?

I'm trying to switch my sql to PDO but I'm having trouble getting even this simple query to return a value. Surely it can't be this difficult. I've done the same query the old fashioned way and it works perfectly as expected. The PDO version returns nothing. What's the trick here?
This first version returns the value I expect.
$customfieldid = 676;
$entityid = 9784549;
$entitytype = 'familyoverview';
$sql = "select value
from customfieldvalues
where customfieldid = ".$customfieldid."
and entityid = ".$entityid."
and entitytype = '".$entitytype."'";
$result = mysql_query($sql);
if($row = mysql_fetch_array($result)) {
$mysqlvalue = $row["value"];
echo "<br>mysql value: ".$mysqlvalue;
}
This PDO version returns nothing.
$sql = "select value
from customfieldvalues
where customfieldid = :customfieldid
and entityid = :entityid
and entitytype = :entitytype";
$stmt = $pdo->prepare($sql);
//$stmt->bindValue(':customfieldid', $customfieldid, PDO::PARAM_INT);
//$stmt->bindValue(':entityid', $entityid, PDO::PARAM_INT);
//$stmt->bindValue(':entitytype', $entitytype, PDO::PARAM_STR);
$stmt->bindValue(':customfieldid', 676, PDO::PARAM_INT);
$stmt->bindValue(':entityid', 9784549, PDO::PARAM_INT);
$stmt->bindValue(':entitytype', 'familyoverview', PDO::PARAM_STR);
$pdovalue = $stmt->fetchColumn();
echo "<br>pdo value: ".$pdovalue;
I've confirmed that I have a pdo database connection. I've tried using the third parameter and omitting the third parameter in the bindValue calls. I've also tried hardcoding the values in the bindValue calls vs passing them in but none of that makes any difference.
Your PDO code is missing a call to $stmt->execute(), so the query is never sent to the MySQL server and executed. Without executing the query, there can't be any results.

Difficulty linking proper $var values and db rows in this PHP foreach statement

I'm trying to insert a PHP function into a foreach loop in order to generate values for each row fetched from the db for the variable $Match.
The db query itself works properly, and the function which assigns values to variable $Match works properly when I test it with hard-coded values, but when I try combining it with the rest of the code in order to use db values it stops working properly. Specifically: 1) It only runs the first IF statement; and 2) If that statement is true, it's adding the same value for every row.
I've uploaded a functional example with hard-coded values to this sandbox http://sandbox.onlinephpfunctions.com/code
Declaring values for test case:
$User_Waist = "26";
$User_Hip = "38";
$Match = Null;
$waistMatch = Null;
$hipMatch = Null;
Query database & fetchAll
$stmt = $conn - > prepare("SELECT * FROM SizeChart WHERE FIND_IN_SET($User_Waist, Waist_Measurement) > 0 OR FIND_IN_SET($User_Hip, Hip_Measurement) > 0;");
$stmt - > bindValue(':Waist_Measurement', $Waist_Measurement, PDO::PARAM_STR);
$stmt - > bindValue(':Hip_Measurement', $Hip_Measurement, PDO::PARAM_STR);
$stmt - > execute();
$rows = $stmt - > fetchAll(PDO::FETCH_ASSOC);
Loop through results
$count = 0;
foreach($rows as $row) {
$count++;
Adds value to variable $Match
if (strpos($row['Waist_Measurement'], $User_Waist) !== false) {
$waistMatch = 'waistFit';
}
if (strpos($Hip_Measurement, $User_Hip) !== false) {
$hipMatch = 'hipFit';
}
$Match = $waistMatch.', '.$hipMatch;
Display Results
echo "Size #: ".$row['Size']."; Fit Matches: ".' '.$Match."; Waist: ".$row['Waist_Measurement'], "; Hip: ".$row['Hip_Measurement'], ".<br />";
The SQL text doesn't contain bind placeholders :Waist_Measurement or :Hip_Measurement.
The bindValue calls aren't going to work, since there's no placeholder of the specified name to bind a value to.
Here's an example that uses a bind placeholder named :fum. Note that this string appears both in the SQL text and as an argument to bindValue or bindParam.
$foo = "bar";
$sql = "SELECT fee FROM fi WHERE fo = :fum ";
// ^^^^
$sth = $dbh->prepare($sql);
$sth->bindValue(":fum", $foo, PDO::PARAM_STR);
// ^^^^
$sth->execute();
FOLLOWUP
This is the SQL text in your prepare.
(I notice that there's a semicolon at the end of the SQL text, and that may be causing an error; I normally don't include a trailing semicolon in my SQL text.)
SELECT *
FROM SizeChart
WHERE FIND_IN_SET($User_Waist, Waist_Measurement) > 0
OR FIND_IN_SET($User_Hip, Hip_Measurement) > 0
But the point is that there aren't any bind placeholders in that SQL text. When you do a:
->bindValue(":Waist_Measurement",...
^^^^^^^^^^^^^^^^^^
That's essentially saying "Hey! There's a string literal ':Waist_Measurement' in the SQL text of the prepared statement", and saying "in place of that string literal, use this value...".
But the thing is, that string literal does not appear in your SQL text. There's no bind placeholder in the statement. (There's not even a placeholder of a different name, I don't see any colon characters anywhere in the SQL.)
I'm surprised that PDO isn't throwing an error. Actually, PDO probably is throwing an error, but your code is ignoring it. If your code isn't going to check the return from prepare, execute, et al. then you can have PDO do the check and throw the exception for you, by specifying an attribute on the connection.
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
Also...
The inclusion of PHP variables $User_Waist and $User_Hip is a little unusual in a prepared statement. One of the benefits of prepared statements is that variables representing values can be replaced with bind placeholders.
(I'm confused by what you are trying to do, I can't tell you how to fix it.)

How to use a quoted string variable in a MySqli prepared statement?

Sorry if this seems a really stupid question, but I'm struggling to get to grips with changing from Mysql to Mysqli and prepared statements.
So in mysql, I would have done this:
$q=('SELECT * FROM table WHERE field="'.$variable.'"');
$result = mysql_query($q);
I now know this is not good. So I now have the below:
$stmt = $mysqli->prepare('SELECT * FROM table WHERE field=? LIMIT 1');
$stmt->bind_param('s', $variable);
$stmt->execute();
Problem is that the query doesn't work. Say the ? is actually "tree". So the query becomes:
'SELECT * FROM table WHERE field=tree LIMIT 1'
If I tried to run that query in say phpmyadmin I get "Unknown column tree in where clause". Obviously if I put quotes around it then it works, hence the original query. So how can I get this to work if I can't use quotes, since then you are looking for the literal question mark?
For reference I am then using this code:
$meta = $stmt->result_metadata();
while ($field = $meta->fetch_field()) {
$parameters[] = &$row[$field->name];
}
call_user_func_array(array($stmt, 'bind_result'), $parameters);
while ($stmt->fetch()) {
foreach($row as $key => $val) {
$x[$key] = $val;
}
$results[] = $x;
}
As I can't use get_result() which is very annoying. I have PHP version 5.4, and even the mysqlnd driver, but can't enable it as I'm on a VPS and my host says it might affect other sites on that server. Consequently what is actually just two lines in MySql is actually now something like 15 lines in the 'improved' mysqli. Great.
Any help would be appreciated!
This:
$stmt = $mysqli->prepare('SELECT * FROM table WHERE field=? LIMIT 1');
$stmt->bind_param('s', $variable);
is not equivalent to this:
SELECT * FROM table WHERE field=tree LIMIT 1
Prepared statement placeholders are not the same as copy and pasting in values. You are binding the value "tree" as a string here, the database will actually understand this. The ? is not simply being replaced by the bound value, the database understands the difference between your query structure with its placeholders and the values you're binding into them. Binding the parameter this way is equivalent to running:
SELECT * FROM table WHERE field='tree' LIMIT 1
Consequently what is actually just two lines in MySql is actually now something like 15 lines in the 'improved' mysqli. Great.
Mysqli is not intended to be used as is. It is but a building material for the higher level library. When used wisely, it can give you data in one line:
$data = $db->getAll('SELECT * FROM table WHERE field=?s', $variable);
(BTW, the same goes for the old mysql ext as well)

PHP PDO interface with MS SQL Server

I am having trouble with using PHP PDO interface with Microsoft SQL Server. The problem is with converting PHP number values to use in functions of MS SQL Server. I use the following statement to delete certain records:
$sql = "DELETE FROM table WHERE SUBSTRING(attribute, 1, ?) = ?";
I prepare and execute this statement with code (a little shrinked):
$query = $pdo->prepare ($sql);
$query->execute (array (strlen ('Text'), 'Text'));
But the query always fails. The error is:
SQLSTATE[42000]: [Microsoft][SQL Server Native Client 11.0][SQL Server]Argument data type nvarchar is invalid for argument 3 of substring function.
I am assuming the number from strlen is not parsed into a number, but I don't know how to fix this (except to manually add into the query).
I have found these links, however not very helpful.
http://social.msdn.microsoft.com/Forums/en-US/sqldriverforphp/thread/0f09ac5e-62cd-4ccf-b2cb-848aad23811e
http://drupal.org/node/1169202
The guys on Drupal had same error, but they fixed it with recreating function with casts. Is there any other way to fix this?
Thanks.
Not sure if this will solve it, but try something like this
$length = strlen('Text');
$text = "Text";
$sql = "DELETE FROM table WHERE SUBSTRING(attribute, 1, :len) = :text";
$query = $pdo->prepare ($sql);
$query->bindParam(':len', $length, PDO::PARAM_INT);
$query->bindParam(':text', $text, PDO::PARAM_STR);
$query->execute();
Try:
$query = $pdo->prepare ($sql);
$query->execute (array ((int) strlen ('Text'), 'Text'));

Categories