pdo prepared statements exit with invalid parameter number - mysql

I have the following query:
$sql="INSERT INTO form_6 SET
Project-name=:Project-name,
Project-manager-gruppo-CDT=:Project-manager-gruppo-CDT,
Short-description=:Short-description,
Status=:Status,
Dependency-with-BB-Pj=:Dependency-with-BB-Pj,
Critical-issues=:Critical-issues"
and the following array of data to be inserted:
Array (
[:Project-name] => test
[:Project-manager-gruppo-CDT] => jack
[:Short-description] => simple project
[:Status] => on going
[:Dependency-with-BB-Pj] => yes
[:Critical-issues] => problems trying to insert data
)
and this is the code that I am using to run the query:
try{
$stmt = $pdo->prepare($sql);
$stmt->execute($values_array);
}
catch(PDOException $Exception){
$message=$Exception->getMessage();
$status=500;
//ho avuto un problema e mi fermo
die(json_encode(array('status'=>$status,'message' => $message)));
}
I really am not able to see why this terminates with the following exception:
Invalid parameter number: parameter was not defined
usually this comes from typos between the query and the array or using the same placeholder two times. But typos are excluded since I build the query and the array together using a foreach:
$values_array=array();
$sql = "INSERT INTO $tabella SET ";
foreach ($_POST as $key=>$value){
$sql .= $key.'=:'.$key.',';
$values_array[":$key"]=$value;
}
$sql=rtrim($sql,',');
echo $sql; //this echoes the query at the beginning of the question
print_r($values_array); //this echoes the array at the beginning of the question
What am I missing?

You can't use - in parameter names. When you write :Project-name it's equivalent to :Profile - name, so it's expecting a parameter named :Profile, and then trying to subtract the column name from that.
Replace the - with _ in the placeholder.
Also, if a column name contains -, you need to put the name in backticks. See When to use single quotes, double quotes, and backticks in MySQL
$values_array=array();
$sql = "INSERT INTO $tabella SET ";
foreach ($_POST as $key=>$value){
$placeholder = str_replace('-', '_', $key);
$sql .= "`$key` = :$placeholder,";
$values_array[":$placeholder"]=$value;
}

Related

Insert/Update MySQL into longtext Column

How do I insert the following string into MySQL:
$myValue ouputs: [Hey, this is a multi text file that has special characters like this ' and this '' and this ,,"", and this ''' and this '''' and this !#$ and whatever]
But the following will not work because of special characters:
$sql = "UPDATE `mytable` SET NEWS=('$myValue') WHERE _id='1'";
I do not want to manually escape every character (like adding an ' before every ')
Update/Insert should should start at [ and end at ] (as seen in $myValue)
EDIT (mysqli)
$_myValue = mysqli_real_escape_string($myValue);
$conn = new mysqli($servername, $username, $password, $dbname);
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
$sql = "UPDATE `mytable` SET NEWS='$_myValue' WHERE _id='1'";
if ($conn->query($sql) === TRUE) {
echo "Record updated successfully";
} else {
echo "Error updating record: " . $conn->error;
}
From the syntax of your code I assume that php is used to submit the queries to mysql.
If you just want to escape special characters in a string variable passed to a field, then use
PDO::quote() (if you use PDO)
mysqli_real_escape_string() (if you use mysqli)
mysql_real_escape_string() (if you use mysql, although you should not)
If you are looking for a more generic solution gainst sql injection, then consider using prepared statements. See this landmark SO topic on how to prevent SQL injection in php-mysql environment.
If your using php you could look at using PDO;
$conn = new PDO( DB_DSN, DB_USERNAME, DB_PASSWORD );
$sql = "UPDATE `mytable` SET NEWS=:myValue WHERE _id=1";
$st = $conn->prepare( $sql );
$st->bindValue(":myValue", $myValue, PDO::PARAM_STR);
$st->execute();
This will input all the data stored in $myValue. I would look at sanatising the input too.

Perl: Breaking out of foreach loop when last array element is encountered

Perl noob here. I have a small script (see below) that I'm using to build a MySQL INSERT statement.
use strict;
my #records = qw/Record1 Record2 Record3/;
my $insert = "
INSERT INTO table
VALUES
";
foreach my $record (#records) {
$insert .= "('" . $record . "'),\n ";
}
print "$insert\n";
Current Output
INSERT INTO table
VALUES
('Record1'),
('Record2'),
('Record3'),
I need to know how to break at the last element of the #records array and append a ; instead of ,
Desired Output
INSERT INTO table
VALUES
('Record1'),
('Record2'),
('Record3');
You can do that with map and join.
my #records = qw/Record1 Record2 Record3/;
my $insert = "
INSERT INTO table
VALUES
";
$insert .= join ',', map { '(' . $dbh->quote($_) . ')' } #records;
$insert .= ';'; # this line is not needed
The quote method of $dbh is better than just putting the stuff into quotes because it handles bad stuff for you. The map is not much different from a foreach loop, and the join will take care of putting the commas in between the elements, and not the last one.
On a related matter, I always try to avoid putting data and sql statements on the same line, thus minimize the risk of sql injection. In perl you have a prepare/execute mechanism available for this:
my #records = qw/Record1 Record2 Record3/;
$sth = $dbh->prepare("INSERT INTO table VALUES ?");
foreach my $record (#records) {
$sth->execute($record);
}
http://bobby-tables.com/perl.html

Fetching data from database in php file

I am trying to fetch data from table. Table contains the data and query is true. Even why following query says $u and $t are not define. While condition becoming false.
I manually checked in database, it was showing results.
$url = "http://paulgraham.com/";
$user_id = "123";
$con = mysqli_connect('127.0.0.1', 'root', '', 'mysql');
if (mysqli_connect_errno())
{
echo "Failed to connect to MySQL: " . mysqli_connect_error();
return;
}
$result = mysqli_query($con,"SELECT * FROM post_data WHERE userid =".$url." and url=".$user_id."");
while ($row = #mysqli_fetch_array($result))
{
echo "hi";
$t = $row['title'];
$u = $row['url'];
}
echo "title is : $t";
echo "url is : $u";
Giving your SQL query :
"SELECT * FROM post_data WHERE userid =".$url." and url=".$user_id.""
You can see you are mixing url and userid... Change to :
"SELECT * FROM post_data WHERE userid =".$user_id." and url=".$url.""
Also define your $t and $u variables before your loop in case you have no record.
Next time, try to var_dump your generated query to test it.
If you were able to see the errors the DBMS is reporting back to PHP then you'd probably be able to work out what's wrong with the code.
Before the 'while' loop try...
print mysql_error();
(the obvious reason it's failing is that strings mut be quoted in SQL, and you've got the parameters the wrong way around)

Adding backticks to a variable in perl

I have MYSQL database that has field names containing hyphens. Trying to insert data from XML to database using Perl.I have XML in %HEAD
The keys are the column header and values are the corresponding data.
my %HEAD= ('REGISTRATION-NUMBER' => 'AAACT2727QXM003',
'RETURN-YEAR' => '2013',
'MONTH' => 'July',
'LTU' => 'Yes',
'NIL-RETURN' => 'No',
'ASSESSEE-NAME' => 'TATA MOTORS LIMITED');
my #HEADER_keys= keys %HEAD;
foreach $key(#HEADER_keys) {
$value= $HEAD{$key};
my $sth = $dbh->prepare("INSERT INTO indirect_taxes($key) VALUES ($value)");
$sth->execute() or die $sth->errstr;
}
or instead of foreach
my #HEADER_values= values %HEAD;
my $sth = $dbh->prepare("INSERT INTO indirect_taxes(?) VALUES (?)");
$sth->execute_array(\#HEADER_keys, \#HEADER_values) or die "the failure cause: $DBI::errstr";
As the keys are containing hyphens i am getting MYSQL syntax error. From Can a table field contain a hyphen?
got the syntax but using perl not able to add backtick to the variable $key or #HEADER_keys.
Please suggest a way to add backticks to $keys.
Try back sticks around $key and use sql placeholder ? to avoid sql injection
foreach my $key(keys %HEAD) {
my $sql = sprintf("INSERT INTO indirect_taxes (%s) VALUES (?)",
$dbh->quote_identifier($key));
my $sth = $dbh->prepare($sql);
$sth->execute($HEAD{$key})
or die $sth->errstr;
}

What's failing in my Perl script? MySQL/getopt

I wrote a script where I'm passing (optional, I hope!) command line arguments and sending them to a MySQL query. If any are omitted I want the query to basically ignore that argument. If I pass all 3, my query is working. If I pass the second (an integer) and the third (a letter) the script also works. But if I omit either the int or the letter I get no results.
I tried to fix this by using ISNULL and Coalesce in my MySQL query as I'm not sure if the declared variable is null or empty if I don't explictly pass them in my commandline argument.
Currently it works if I pass "Perl Script.pl -s Hockey -i 10 -l h, or
"Perl Script.pl -i 20 -l z", but fails under any other iteration of the 3 arguments.
What I want to know is
1. Did I make the arguments optional as I intended? Should I be using getopts instead of getopt?
2. What do I need to change in my MySQL query to get it to work as I intended? Why aren't ISNULL or Coalesce working?
3. Is anything else incorrect with the way I'm passing or passing the data?
#!/usr/bin/perl -w
use warnings;
use DBI;
use Getopt::Std;
use strict;
getopt('s:il');
our ($opt_s);
our ($opt_i);
our ($opt_l);
my $sport_search;
if ($opt_s) ($sport_search=$opt_s);
my $integer_search;
if ($opt_i=~m/\d+/) {$integer_search=$opt_i};
my $letter_search;
if ($opt_l =~m/^[a-zA-Z]$/) {$letter_search=$opt_l};
my $g_hash = function1($sport_search,$integer_search,$letter_search);
my $string = "Just a string!";
if (&function2($g_hash,$string) != 0) {
print "No values found for '$sport_search'","\n";
};
sub function1 {
my ($lsport_search,$linteger_search,$lletter_search) = #_;
our $dbh = DBI->connect{"dbi:mysql:dbname=database", "root", "password")
or die $DBI::errstr;
my $sql = "SELECT * from Players_Sport where Sport like '$lsport_search' AND length(Player)<=ISNULL('$linteger_search',20) AND Player between 'a' and ISNULL('lletter_search",'z')";
my $hash_ref = $dbh->selectall_hashref($sql, 'Player')
or die $DBI::errstr;
$dbh->disconnect
or warn "Disconnection failed: $DBI::errstr\n";
return $hash_ref;
}
sub function2 {
my ($l_hash,$variable_two) = #_;
my $hashvalue=();
if(keys $l_hash == 0) {
$hashvalue = -1;
}
else {$hashvalue = 0;
print "$_\n" for (keys %$l_hash);
};
return $hashvalue;
}
There are some problems in your query:
my $sql = "SELECT * from Players_Sport where Sport like '$lsport_search'
AND length(Player)<=ISNULL('$linteger_search',20)
AND Player between 'a' and ISNULL('lletter_search",'z')";
Even if $linteger_search and $lletter_search are undefined in Perl, they will never be NULL in SQL because you have put quotes around them. In MySQL, '' is not the same as NULL.
You also have some typos: 'lletter_search" should be '$lletter_search' Note you must end the quoted string with the same type of quotes that you started it with, but you started with single-quote and ended it with double-quote (actually, I'm surprised it didn't throw an SQL error).
You also forgot the $ variable prefix before lletter_search.
It's more common to build the SQL string dynamically, including search terms only when your search criteria are non-null.
my $sql = "SELECT * from Players_Sport where true ";
if ($lsport_search) {
$sql .= " AND Sport like '$lsport_search' ";
}
if ($linteger_search) {
$sql .= " AND length(Player) <= $linteger_search";
}
if ($lletter_search) {
$sql .= " AND Player between 'a' and '$lletter_search'";
}