Adding backticks to a variable in perl - mysql

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;
}

Related

pdo prepared statements exit with invalid parameter number

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;
}

Perl MySQL INSERT error

I'm trying to parse a few references from a file and load them into a MySQL table, but I keep on getting this error everytime I run the script
DBD::mysql::st execute failed: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ' Njuguna, M.I., Yusuf, J. A., Akama, V.,2013,Animal husbandry in the developed w' at line 1 at manuscripts3.pl line 51, <$fh> line 1.
Uncaught exception from user code
See my code below.
I'm at my wits end. What am I doing wrong?
#!/usr/bin/perl
use strict;
use warnings;
use diagnostics;
use DBI;
my $driver = "mysql";
my $database = "test";
my $user = "root";
my $password = "";
my $dbh = DBI->connect(
"DBI:$driver:$database",
$user,
$password, {
RaiseError => 1,
PrintError => 1,
AutoCommit => 0,
}
) or die $DBI::errstr;
my $file = "/var/www/manuscripts.txt";
open my $fh, "<", $file;
my #manuscripts;
while (my $lines = <$fh>) {
$lines =~ s/\, \(/\t/g;
$lines =~ s/\) \“/\t/g;
$lines =~ s/\” /\t/g;
my ($authors, $year, $title, $journal) = split(/\t/, $lines);
push #manuscripts, {
authors => $authors,
year => $year,
title => $title,
journal => $journal
};
#print "$title\n";
my $sql = "insert into manuscript($authors,$year,$title,$journal) values (?,?,?,?)";
$dbh->commit();
my $stmt = $dbh->prepare($sql);
$stmt->execute($authors, $year, $title, $journal);
# disconnect from the MySQL database
$dbh->disconnect();
}
#print $manuscripts[0][2];
text file:
Kamau, M.A., Njuguna, M.I., Yusuf, J. A., Akama, V., (2013) “Animal husbandry in the developed world” Journal of Hospital Infenction
Kamau, M.A., Njuguna, M.I., Yusuf, J. A., Akama, V., (2013) “Agriculture and global warming” PLOS Medicine Kamau, M.A., Njuguna,
M.I., Yusuf, J. A., Akama, V., (2013) “Rotational farming as a business” The Journal of Infectious Diseases
The problem is here:
my $sql = "insert into manuscript($authors,$year,$title,$journal)
values (?,?,?,?)";
You are putting the contents of the variables as the field names. I assume you mean:
my $sql = "insert into manuscript(authors,year,title,journal)
values (?,?,?,?)";
You have to use $stmt->bind_param(); to bind the parameter and use $stmt->execute() without parameter
my $sql = "insert into manuscript(authors,year,title,journal)
values (?,?,?,?)";
my $stmt = $dbh->prepare($sql);
$stmt->bind_param(1,$authors);
$stmt->bind_param(2,$year);
$stmt->bind_param(3,$title);
$stmt->bind_param(4,$journal);
$stmt->execute();

Mysql insert query failed

Hello i am trying to insert some data into mysql using perl.
i have an array that i want insert into a table. but problem is that the array has a " ' "
.when i try to insert it got an error mysql query failed.
#!/usr/bin/perl
use DBI;
#abc = "FUJI-XEROX CO. LTD. ADVANCED TECH & ENG'G CENTER 9-50 CHUO 2-CHOME, EBINA-SHI KANAGAWA 24 JAPAN";
$dbh = DBI->connect('dbi:mysql:remotegenius;host=localhost', 'root', 'active123') or die "Connection Error: $DBI::errstr\n";
$dbh->do("insert into OUI set `oui`='$abc'");
when i execute code i got
DBD::mysql::db do failed: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'G CENTER 9-50 CHUO 2-CHOME, EBINA-SHI KANAGAWA 24 JAPAN'' at line 1 at ./test.pl line 9.
I need someone help from mysql and perl expertise.
First of all it is essential to use strict and use warnings at the top of every program. It saves a huge amount of time by revealing simple mistakes, and would have alerted you to the fact that you put a string into array #abc and then use the scalar $abc in your SQL statement. I assume here that you intended to use $abc throughout.
Your error is because that's not what an INSERT statement looks like. You also need to escape and quote the string in $abc properly as it contains single quotes, so you must write
$dbh->do(sprintf 'INSERT INTO oui (oui) VALUES (%s)', $dbh->quote($abc))
But it is best to prepare the statement first and then execute it
my $insert = $dbh->prepare('INSERT INTO oui (oui) VALUES (?)');
and later
$insert->execute($abc);
Or perhaps you mean "UPDATE oui SET oui = ?"? But that will set the oui field to the same value on every row of the table.
If you need to insert array of values, first make sure you have values in array variable.
#vals = ('One', 'Two', 'Three');
Error is because INSERT query syntax is wrong, here is the INSERT syntax
INSERT INTO <table> (col1, col2) VALUES ('val1', 'val2)
Here is the snippet that should work for you
use DBI;
my #vals = ('One', 'Two', 'Three');
$dbh = DBI->connect('dbi:mysql:remotegenius;host=localhost', 'root', 'active123') or die "Connection Error: $DBI::errstr\n";
my $in = $dbh->prepare('INSERT INTO oui (oui) VALUES (?)');
foreach (#vals) {
$in->execute($_);
}
`

Unable to insert a record into MySQL database using DBI

I am trying to insert a record into a MySQL database using Perl DBI. I am not getting any errors but the insert is not working. However, I am able to successfully fetch records from the database using DBI.
Here is the code that does the insert:
#!"C:\xampp\perl\bin\perl.exe"
use diagnostics;
use DBI;
use strict;
use warnings;
my $driver = "mysql";
my $database = "mysql";
my $dsn = "DBI:$driver:database=$database";
my $userid = "root";
my $password = "password";
my $buffer;
my #pairs;
my $pair;
my $name;
my $value;
my %FORM;
# Read in text
my $ENV;
$ENV{'REQUEST_METHOD'} =~ tr/a-z/A-Z/;
if ($ENV{'REQUEST_METHOD'} eq "GET")
{
$buffer = $ENV{'QUERY_STRING'};
}
# Split information into name/value pairs
#pairs = split(/&/, $buffer);
foreach $pair (#pairs)
{
($name, $value) = split(/=/, $pair);
$value =~ tr/+/ /;
$value =~ s/%(..)/pack("C", hex($1))/eg;
$FORM{$name} = $value;
}
my $first_name= $FORM{name};
my $address = $FORM{address};
my $city = $FORM{city};
my $occupation = $FORM{occupation};
my $age = $FORM{age};
my $dbh = DBI->connect("dbi:mysql:dbname=mysql", "root", "password",{ AutoCommit => 0,RaiseError => 1}, ) or die ("Couldn't connect to database: ") , $DBI::errstr;
# my $sth = $dbh->prepare("INSERT INTO persons
# (FirstName, LastName,Address,City)
# values
# ($first_name, $last_name,$address,$city)");
my $query = "insert into userrecords(Address,Age,City,Name,Occupation)
values (?, ?, ?, ?, ?) ";
my $statement = $dbh->prepare($query) or die ("Couldn't connect to database: "), $DBI::errstr;
$statement->execute($address,$age,$city,$name,$occupation) or die ("Couldn't connect to database: "), $DBI::errstr;
$dbh->disconnect();
my $URL = "http://.....:81/cgi-bin/showdata.cgi";
print "Location: $URL\n\n";
exit(0);
When I run my code in the Padre IDE, I get the following errors:
****Error*********
Useless use of a variable in void context at InsertRecord.cgi line 50 (#1)
(W void) You did something without a side effect in a context that does
nothing with the return value, such as a statement that doesn't return a
value from a block, or the left side of a scalar comma operator. Very
often this points not to stupidity on your part, but a failure of Perl
to parse your program the way you thought it would. For example, you'd
get this if you mixed up your C precedence with Python precedence and
said
$one, $two = 1, 2;
when you meant to say
($one, $two) = (1, 2);
Another common error is to use ordinary parentheses to construct a list
reference when you should be using square or curly brackets, for
example, if you say
$array = (1,2);
when you should have said
$array = [1,2];
The square brackets explicitly turn a list value into a scalar value,
while parentheses do not. So when a parenthesized list is evaluated in
a scalar context, the comma is treated like C's comma operator, which
throws away the left argument, which is not what you want. See
perlref for more on this.
This warning will not be issued for numerical constants equal to 0 or 1
since they are often used in statements like
1 while sub_with_side_effects();
String constants that would normally evaluate to 0 or 1 are warned
about.
Useless use of a variable in void context at InsertRecord.cgi line 59 (#1)
Useless use of a variable in void context at InsertRecord.cgi line 60 (#1)
Use of uninitialized value in transliteration (tr///) at InsertRecord.cgi line
23 (#2)
(W uninitialized) An undefined value was used as if it were already
defined. It was interpreted as a "" or a 0, but maybe it was a mistake.
To suppress this warning assign a defined value to your variables.
To help you figure out what was undefined, perl will try to tell you the
name of the variable (if any) that was undefined. In some cases it cannot
do this, so it also tells you what operation you used the undefined value
in. Note, however, that perl optimizes your program and the operation
displayed in the warning may not necessarily appear literally in your
program. For example, "that $foo" is usually optimized into "that "
. $foo, and the warning will refer to the concatenation (.) operator,
even though there is no . in your program.
Use of uninitialized value $ENV{"REQUEST_METHOD"} in string eq at
InsertRecord.cgi line 24 (#2)
Use of uninitialized value $buffer in split at InsertRecord.cgi line 29 (#2)
Location: http://.......:81/cgi-bin/showdata.cgi
Press any key to continue . . .
***********END***********************
What is the issue?
When I was editing your code so that it was more readable, I stumbled upon what I assume is the solution:
You are using $name when inserting into the database, but you use $first_name when getting the value $FORM{name}. So since you used $name above, it has the value of the last name used, whatever that might be. The relevant code snippets:
($name, $value) = split(/=/, $pair);
...
$FORM{$name} = $value;
...
my $first_name = $FORM{name};
...
$statement->execute($address,$age,$city,$name,$occupation)
# ^^^^^--- should be $first_name
Your problem would have been solved if you had used proper scope on your variables, namely something like this:
foreach my $pair (#pairs) {
my ($name, $value) = split(/=/, $pair);
$value =~ tr/+/ /;
$value =~ s/%(..)/pack("C", hex($1))/eg;
$FORM{$name} = $value;
}
Then when you later would try to use $name, you would get the error
Global variable "$name" requires explicit package name ...
Which would alert you to your mistake and save you hours in debugging time. When you declare variables at the top of the script, instead of in the smallest possible scope, you effectively disable the protection that use strict 'vars' offers. So don't do that.
Also, you should probably use the CGI module instead of trying to handle it manually. It will make things easier, and safer. Don't forget to perform sanity checks on your data to prevent database injection attacks.
Your script when cleaned up and properly formatted looks like this.
What happens when you replace your code with this:
#!"C:\xampp\perl\bin\perl.exe"
use strict;
use warnings;
use diagnostics;
use DBI;
use CGI qw[param redirect];
my $driver = "mysql";
my $database = "mysql";
my $dsn = "DBI:$driver:database=$database";
my $userid = "root";
my $password = "password";
my $dbh = DBI->connect("dbi:mysql:dbname=mysql", "root", "password",
{ AutoCommit => 0,RaiseError => 1}, )
or die "Couldn't connect to database: ", $DBI::errstr;
my $query = "insert into userrecords(Address,Age,City,Name,Occupation)
values (?, ?, ?, ?, ?) ";
my $statement = $dbh->prepare($query)
or die "Couldn't connect to database: " , $DBI::errstr;
$statement->execute(param('address'), param('age'), param('city'),
param('name'), param('occupation'))
or die "Couldn't connect to database: " , $DBI::errstr;
$dbh->disconnect();
my $URL = "http://.....:81/cgi-bin/showdata.cgi";
print redirect($URL);
I've basically made two changes:
Use the CGI.pm module to handle the CGI interaction (getting the parameters and printing the redirection header).
Fixed your "void context" errors by removing the misplaced parentheses in all of your calls to die.
I'm made no substantive changes to the code, but at least we now have a clean version to go with.
Update: D'oh. It's obvious now the code is cleaned up a bit. If you have "Autocommit" turned off, then you need to commit your changes. Add $dbh->commit between the calls to execute() and disconnect().
The warning comes from this:
or die ("Couldn't connect to database: ") , $DBI::errstr;
The , $DBI::errstr is outside of the die and nothing is done with it, thus being in void context. You want something like this:
or die ("Couldn't connect to database: $DBI::errstr");
Also, your form handling code has some issues. If you're writing CGI scripts, you may as well use the CGI module. Here's a quick cleanup of your code:
#!"C:\xampp\perl\bin\perl.exe"
use diagnostics;
use CGI ':standard';
use DBI;
use strict;
use warnings;
my $driver = "mysql";
my $database = "mysql";
my $dsn = "DBI:$driver:database=$database";
my $userid = "root";
my $password = "password";
my $name = param('name');
my $address = param('address');
my $city = param('city');
my $occupation = param('occupation');
my $age = param('age');
my $dbh = DBI->connect( $dsn, $userid, $password,
{ AutoCommit => 1, RaiseError => 1 },
) or die("Couldn't connect to database: $DBI::errstr");
my $query = <<'END';
INSERT INTO userrecords(Address,Age,City,Name,Occupation)
VALUES ( ?, ?, ?, ?, ?)
END
my $statement = $dbh->prepare($query);
$statement->execute( $address, $age, $city, $name, $occupation );
$dbh->disconnect();
my $URL = "http://.....:81/cgi-bin/showdata.cgi";
print "Location: $URL\n\n";
Note that I've removed many or die statements because you already have RaiseError set to a true value.
For simplicity's sake, I've also (reluctantly) turned on AutoCommit.

DBI/DBD::mysql/mysql_type_name: How to distinguish between Blob and Text?

This example outputs two times "blob". How could I find out, if the datatype of a column is TEXT?
#!/usr/bin/env perl
use warnings;
use strict;
use DBI;
use Data::Dumper;
my$dbh = DBI->connect( "DBI:mysql:dbname=test", 'user', 'passwd', {
RaiseError => 1,
AutoCommit => 1,
} ) or die DBI->errstr;
my $table = 'my_test_table';
$dbh->do( "DROP TABLE IF EXISTS $table" );
$dbh->do( "CREATE TABLE $table ( Foo TEXT, Bar BLOB )" );
my $sth = $dbh->prepare( "INSERT INTO $table ( Foo, Bar ) VALUES( ?, ? )" );
$sth->execute( 'a', 'a' );
$sth = $dbh->prepare( "SELECT * FROM $table" );
$sth->execute();
my $col_types = $sth->{mysql_type_name};
print Dumper $col_types;
Output:
$VAR1 = [
'blob',
'blob'
];
Generally when you work with Database you know what the data fields are and you use fetch_hashref or fetch_arrayref functions and get the required data(in your case fields Foo(Text) and Bar(Blob)) , I didn't get what are you trying to achieve here? , If you need to get the data from Foo/Bar you should use fetch_arrayref or hashref functions, I also see that with 'use strict' you still managed to pass bareword 'mysql_type_name' to statement handle $sth.
This is because BLOB and TEXT are (nearly) the same thing in mysql: The BLOB and TEXT Types.
I am not sure why DBD::mysql can not distinguish the two. You may want to use VARCHAR instead of TEXT.