PDOStatement::execute(): SQLSTATE[HY093]: Invalid parameter number: parameter was not defined - php

Below is my code, I am not able to resolve this error. Any help is appreciated. I am trying to update a table in my database.
public function updateUnit($params){
$user = 'monil';
$password = 'Masters123';
$dbh = new \PDO('mysql:host=127.0.0.1;dbname=tcsdb', $user, $password);
$task=array(':UnitCode'=>$params['UnitCode'],':UnitDescription'=>$params['UnitDescription'] ,
':UnitName'=>$params['UnitName'], ':UnitID'=>$params['UnitID']);
echo $params['UnitID'];
$sth = $dbh->prepare('UPDATE unit SET UnitCode = :UnitCode,'
. 'UnitDescription = :UnitDescription,UnitName = :UnitName WHERE UnitId=:UnitId');
$sth->execute($task);
return true;
}

Parameter names used in execute()/binding should be exact match for the parameter names used in the SQL query. That's the point of named parameters.
You need to check every placeholder in SQL, whether its name matches the name used in execute(), bindParam() or bindValue().
In your case, :UnitID is not the same as :UnitId, there is a difference in the letter case.
In a rare case, the error can be caused by improper placeholder name. The only characters allowed are [a-zA-Z0-9_].

The same error arise when you missed : colon while creating statement.
ex:
Below statement throws invalid parameter error as password in VALUES is missing : colon.
$stmt = $db->prepare('INSERT INTO members (username,password) VALUES (:username, password)');

same errors may occur if you use a "." dot in bindParam
ex.
$query = "select * from t where t1 = :foo.bar";
$stmt = $pdo->prepare($query);
$stmt->execute([':foo.bar' => 'blah']);

Related

SQLSTATE[HY093]: Invalid parameter number: parameter was not defined (php + pdo)

I have this query that without the inner join it works:
$sql = 'SELECT prodotti.nome, prodotti.prezzo, prodotti.sku, prodotti.produttore, fornitori.nome
FROM prodotti INNER JOIN fornitori
ON prodotti.fornitori_id = fornitori.id
WHERE prodotti.id = :prodotti.id';
$id = 1; // for example
// $this->db-> (is connection)
$stmt = $this->db->prepare($sql);
$stmt->bindParam(':prodotti.id', $id, PDO::PARAM_INT);
$stmt->execute();
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);
$prodlist[$id] = $results;
var_dump($prodlist);
If I run it I get this error:
Fatal error: Uncaught PDOException: SQLSTATE [HY093]: Invalid parameter number: parameter was not defined in ........
It seems that the error lies is in the WHERE and in a particular way, reading online, I discovered that it could be a problem to do this: WHERE prodotti.id = prodotti.id;
suggest to do for example: WHERE prodotti.id =: id '; and then in the bindparam the same thing $stmt->bindParam(': id', $ id, PDO :: PARAM_INT);
in fact, doing so works halfway, in the sense that it gives me back the data called the first 'products' table ignoring the second 'suppliers'.
Can anyone tell me where am I wrong? Thanks
if I run this query on the SQL section of DB it works.
SELECT prodotti.nome, prodotti.prezzo, prodotti.sku, prodotti.produttore, fornitori.nome
FROM prodotti INNER JOIN fornitori
ON prodotti.fornitori_id = fornitori.id
WHERE prodotti.id = 1
as some users have pointed out to me elsewhere, and in fact it partially solves the problem, the point cannot be used in the binding, as reported in the guide at this link:
https://phpdelusions.net/pdo
"Note that PDO supports positional (?) and named (:email) placeholders, the latter always begins from a colon and can be written using letters, digits and underscores only. Also note that no quotes have to be ever used around placeholders."
now it works correctly! Thanks

PHP/Oracle - OCI doesn't like my data type?

I'm new to OCI, but just trying to do a basic oci_bind_by_name in PHP to get it working. But even with a simple select statement and a dummy variable, it rejects the variable type.
Here's the code:
$conn = oci_connect($username, $password, $database);
$dummy = "dummy#dummy.com";
$u = oci_parse($conn, "select ca_email from pwv_google_group");
oci_bind_by_name($u, ':ca_email', $dummy);
But it just returns:
Warning: oci_bind_by_name(): ORA-01036: illegal variable name/number
Since this is a very simple query/parameter, I can only assume my syntax is wrong or something might be off on the Oracle side (ca_email really should be a varchar, but I'm using Datagrip which doesn't allow DESC command, so I don't know how to validate that). Is something else wrong?
oci_bind_by_name() is expecting you to bind a value for some form of input to the SQL statement - from the manual
bv_name The colon-prefixed bind variable placeholder used in the
statement. The colon is optional in bv_name. Oracle does not use
question marks for placeholders.
So for your example, it would be more like
$u = oci_parse($conn, "select * from pwv_google_group where ca_email = :ca_email");
oci_bind_by_name($u, ':ca_email', $dummy);
As you are trying to retrieve the values from the data you just need to fetch the data as in (hacked from example #3 in manual)
$u = oci_parse($conn, 'select ca_email from pwv_google_group');
oci_execute($u);
$row = oci_fetch_array($u, OCI_ASSOC+OCI_RETURN_NULLS);
foreach ($row as $item) {
print $item."<br>\n";
}

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.)

MySql database query not working when I use _GET inside

I am a php beginner.
I have the following script which works if I do not use _GET['version'] in the query, but works if I remove it. There is no error; I am not sure why it is not working.
<?php
// Specify your table name
$hostname = 'localhost';
$dbname = 'stats';
$table_name = 'st_stats';
$username = 'test';
$password = 'test';
try
{
$conn = new PDO("mysql:host=$hostname;dbname=$dbname",$username,$password);
//By default mode is silent and exception is not thrown. So I it to throw ex
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// If the query is like this no error is given but page shows up blank
$stmt = $conn->query("SELECT * FROM $table_name where version = $_GET['version']", PDO::FETCH_ASSOC);
// This works if uncomment below line instead and comment line above
//$stmt = $conn->query("SELECT * FROM $table_name", PDO::FETCH_ASSOC);
$count = $stmt->rowCount();
echo("<h1>currently $count records</h1>");
}
catch(PDOException $e)
{
echo 'ERROR: ' . $e->getMessage();
}
?>
I want to access the page like this
http://www.mydomain/records.php?version=1.2
Note that version column does exit in the table
You could try to avoid a bit of sql injection here by preparing the statement properly:
$v_term = $_GET['version'];
$query = "SELECT * FROM $table_name where version = :term";
$result = $conn->prepare($query);
$result->bindValue(":term",$v_term);
$result->execute();
Also, run the statement straight from the db if you can to make sure you are getting records back. Other than that, there is no other way to debug this for you from what you given us.
Maybe version is not an integer therefore need quotes ?
"SELECT * FROM $table_name where verion = '".$_GET['version']."'",
Anyway you are vulnerable to sql injection and also misusing PDO
You should at least bindParam/bindValue
Or use execute() and past the $_GET value
As documented under Variable parsing:
There are two types of syntax: a simple one and a complex one.
[ deletia ]
Example #8 Simple syntax example
[ deletia ]
echo "He drank some $juices[koolaid1] juice.".PHP_EOL;
[ deletia ]
Complex (curly) syntax
This isn't called complex because the syntax is complex, but because it allows for the use of complex expressions.
[ deletia ]
// Works, quoted keys only work using the curly brace syntax
echo "This works: {$arr['key']}";
That is, you can reference associative arrays from within a double-quoted string in one of two ways:
// simple - don't quote your keys
"... $_GET[version] ..."
// complex - you may quote your keys, but must surround the expression in braces
"... {$_GET['version']} ..."
HOWEVER, you shouldn't be doing either here. You should instead be using a parameterised statement in order to prevent SQL injection attacks:
$stmt = $conn->prepare("SELECT * FROM $table_name WHERE verion = ?");
$stmt->execute([$_GET['version']]);
This doesnt work because you're trying to access $_GET['version'] an array variable within a string here
"SELECT * FROM $table_name where version = $_GET['version']", PDO::FETCH_ASSOC
placing {} around the variable will fix this one issue
$stmt = $conn->query("SELECT * FROM $table_name where verion = {$_GET['version']}", PDO::FETCH_ASSOC);
But you should also sanitize this value before you put it right int a sql statement
You have verion rather than version in your query. You're also not passing the value of $_GET['version'], you're passing the string "$_GET['version']" right into the query. Update your query to this:
$stmt = $conn->query("SELECT * FROM $table_name where version = {$_GET['version']}", PDO::FETCH_ASSOC);
Wrapping a variable that's inside a double quoted string ("") in curly braces ({}) evaluates to the value of the variable.
If you do this you will be wide open to SQL injection attacks. Be sure to sanitize the variable before you run the query, or better yet consider prepared statements.

SQLSTATE[HY000]: General error with PHP and PDO

I have a little login script.
function login($sql) {
try {
$fbhost = "localhost";
$fbname = "foodbank";
$fbusername = "root";
$fbpassword = "";
$DBH = new PDO("mysql:host=$fbhost;dbname=$fbname",$fbusername,$fbpassword);
$DBH->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$STH = $DBH->query($sql);
$STH->setFetchMode(PDO::FETCH_ASSOC);
session_start();
if ($row = $STH->fetch()) {
$_SESSION['username'] = "$row[username]";
header("Location:index.php");
}
} catch(PDOException $e) {
echo $e->getMessage();
}
}
EDITS:
index.php
$sql = "SELECT username from users where username = ". $_POST['username'] ." AND password = ". $_POST['password'] ."";
login($sql);
Changed above from insert to select query. Now I get new error:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'pvtpyro' in 'where clause'
Based on your latest edit: You can't fetch results with PDO after executing an INSERT query. See here: http://www.php.net/manual/en/pdostatement.fetch.php#105682
Edit: I suppose, since the function's called "login", you want to have something like this as $sql: "SELECT password FROM users WHERE username = :username", and then iterate over the results with the while loop, and then log in the user if the password matches?
Edit2: Based on your edit to provide a SELECT query: DO NOT USE THIS QUERY. What you are doing is NOT SQL injection proof. Never ever use variables from user input (i.e. $_POST, $_GET et al) and put them unfiltered into an SQL query. Please look up the term "prepared statements" here at SO or Google.
As you can see, since you forgot to put single ticks (apostrophes) before and after the double quotes, MySQL thinks that your input refers to another column ("pvtpyro") instead of comparing the value in the column against a string. ALWAYS use the ":username", ":password" syntax (the one with prepended colons) or your queries will be unsafe and enormously dangerous to your application.
The constructor of PDO uses 2 variables which are not defined in the code you supplied - $fbhost and $fbname.
EDIT:
You're calling session_start() inside the while loop, which can cause errors. Take it out of the loop.
EDIT 2:
You should really debug the code. Either via putting die in different parts of the code, outputting some helpful information just before (which is the less preferred way) OR by using xdebug and an IDE, which will allow you to run line by line, and see the exact state of each variable and such.
If I undestand correctly, $data $STH->execute($data); should be an array, even if value is one. So, you may try replacing that query with $STH->execute(array($data));
edited:
Change your lines to this:
$data = array($_POST["username"], $_POST["password"]);
$sql = "INSERT INTO users (username, password) value (?, ?)";
$STH = $DBH->prepare($sql);
$STH->execute($data);
Seems to me that you're not connected to your database properly... I had this error earlier today and it was for that reason. Either that or you have an incorrect string

Categories