How to insert text into mysql having quotes using perl - mysql

How to insert text into mysql having quotes using perl ?
It seems difficult to insert text containing ' & ".
I'm using Perl DBI module & DB is mysql.
UPDATE:
here is my query
my $s = "INSERT INTO comment(guid,review_id) VALUES ('$guid','$review_id')";

You should read section 'Placeholders and Bind Values' in man DBI
EDIT: added example
my $s = "insert into comment(guid,review_id) values (?, ?)";
$dbh->do( $s, undef, $guid, $review_id) or die $dbh->errstr;

Your old query would have been something like this:
my $s = "insert into comment(guid,review_id) values ('$guid','$review_id')";
$dbh->do($s);
The better way, using placeholders and bind values as per #AlexD's answer, would look like this:
my $sth = $dbh->prepare("insert into comment(guid,review_id) values (?, ?)";);
$sth->execute($guid, $review_id);
To learn about the security risks of your first approach, have a look at SQL injection attacks on Wikipedia.

Related

Why is MySQL giving me a syntax error?

so I am pretty much a big newbie in coding and I am kinda learning by Trial and error, this time I am trying to work with a DB with Perl, actually it works well when I just use 3 table headers (Terminal, Zeitstempel, Ergebnisnummer) but when I try to add more headers (Ergebnistext, Transart, Belegnummer, Trace, Betrag, Kartenart, Kartennummer, Entrymode) it is always giving me a Syntax-error and I checked for half an hour but couldnt find the error. If anyone knows why I would appreciate your help! this part of my code Looks like this:
foreach $file (#file)
{
$currentfile = "$currentdir\\$file";
open(zloop, "<", $currentfile) or die "Failed to open file: $!\n";
while ( <zloop> ) {
my %row;
chomp;
#row{#headers} = split /;/;
my $tid = $row{'tid'};
my $zeit = $row{'zeit'};
my $ergebnisnummer = $row{'ergebnisnummer'};
my $ergebnistext = $row{'ergebnistext'};
my $transart = $row{'transart'};
my $belegnummer = $row{'belegnummer'};
my $trace = $row{'trace'};
my $betrag = $row{'betrag'};
my $kartenart = $row{'kartenart'};
my $kartennummer = $row{'kartennummer'};
my $entrymode = $row{'entrymode'};
my $sth = $dbh->prepare("INSERT INTO `teso`( Terminal, Zeitstempel, Ergebnisnummer, Ergebnistext, Transart, Belegnummer, Trace, Betrag, Kartenart, Kartennummer, Entrymode )
values ( $tid, $zeit, $ergebnisnummer, $ergebnistext, $transart, $belegnummer, $trace, $betrag, $kartenart, $kartennummer, $entrymode )");
$sth->execute() or die $DBI::errstr;
$sth->finish();
i didnt Change the variable names to english because maybe they are causing the Syntax error. This is the error message:
DBD::mysql::st execute failed: You have an error in your SQL syntax;
check the m anual that corresponds to your MySQL server version for
the right syntax to use near '' )' at line 2 at
C:\Users\Desktop\findlogstamp\sqlneu.pl lin e 50, line 1. 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 '' )' at
line 2 at C:\User s\Desktop\findlogstamp\sqlneu.pl line 50,
line 1.
You are possibly getting quotation errors arising from passing your variables in as a string. You should instead use placeholders.
Try doing something like this instead:
my $sth = $dbh->prepare('INSERT INTO `teso`( Terminal, Zeitstempel, Ergebnisnummer, Ergebnistext,
Transart, Belegnummer, `Trace`, Betrag, Kartenart, Kartennummer, Entrymode )
values ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )');
$sth->execute($tid, $zeit, $ergebnisnummer, $ergebnistext,
$transart, $belegnummer, $trace, $betrag, $kartenart,
$kartennummer, $entrymode) or die $DBI::errstr;
I've also included mwp's answer too.
It is also worth time reading Borodins Answer for a more thorough way to approach placeholders and SQL inside perl.
I believe "trace" is a reserved word in MySQL. Try adding backticks around the column name(s).
Values in an SQL expression must be quoted correctly. Simple numeric values don't need quoting, and I imagine the first three columns that you used -- terminal ID, timestamp, and result number -- are all numbers, which is why they worked without quotes
The DBI module provides functions database handle method quote which will do this for you (as well as quote_identifier which does the same thing for identifiers, such as table and column names). However it is always much safer to prepare an SQL statement with placeholders instead of trying to interpolate the values into the string yourself. Then the actual values can be provided in the execute call, wehen DBI will implicitly call $dbh->quote on all of the values before inserting them into the statement
It is also best to prepare a statement just once, as the handle may then be used repeatedly. And there is no need to extract a series of scalar variables from your %row hash -- a hash slice can be used to fetch the correct fields straight from the hash into the execute call. It is best, however, to keep a list of the field names in an array as you have done with #headers; in fact your #headers may be the same as my #items, in which case there is no need to define both
I have used a here document for the SQL string. If you want to do the same thing then be careful that there must be no white space either before or after the end tag END_SQL otherwise it won't be found
Note that I've used join together with the list repetition operator x to produce exactly the right number of question mark placeholders in the QSL. It's much safer to do things this way so as to avoid miscounting, and to allow the number of fields to be changed without altering the SQL statement. You can print "$sql\n" to see the SQL that has been built if you wish
I hope this helps
my #items = qw/
tid zeit ergebnisnummer ergebnistext transart
belegnummer trace betrag kartenart kartennummer entrymode
/;
my $sql = sprintf <<END_SQL, join ', ', ('?') x #items;
INSERT INTO teso (
Terminal, Zeitstempel, Ergebnisnummer, Ergebnistext, Transart,
Belegnummer, Trace, Betrag, Kartenart, Kartennummer, Entrymode
)
VALUES (%s)
END_SQL
my $insert = $dbh->prepare($sql);
for my $file ( #file ) {
my $current_file = "$currentdir\\$file";
open my $fh, '<', $current_file or die qq{Unable to open "$current_file" for input: $!};
while ( <$fh> ) {
my %row;
#row{#headers} = split /;/;
$insert->execute(#row{#items}) or die $sth->errstr;
}
}
I think, error is because backticks around teso is interpolated by perl.
Anyway, interpolating values into a query string is a really bad idea.
You can replace quotation marks around your query with a single quotes (to eliminate undesired interpolation) and replace values to be inserted with a placeholders. Then you should pass actual values to execute() method. Like this:
my $sth = $dbh->prepare('INSERT INTO teso( Terminal, Zeitstempel, Ergebnisnummer, Ergebnistext, Transart, Belegnummer, Trace, Betrag, Kartenart, Kartennummer, Entrymode )
values ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )');
$sth->execute($tid, $zeit, $ergebnisnummer, $ergebnistext, $transart, $belegnummer, $trace, $betrag, $kartenart, $kartennummer, $entrymode) or die $DBI::errstr;
$sth->finish();
or, if you wish to insert just a single row, you can replace all this with a single do():
$dbh->do('INSERT INTO teso( Terminal, Zeitstempel, Ergebnisnummer, Ergebnistext, Transart, Belegnummer, Trace, Betrag, Kartenart, Kartennummer, Entrymode ) values ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )', undef,
$tid, $zeit, $ergebnisnummer, $ergebnistext, $transart, $belegnummer, $trace, $betrag, $kartenart, $kartennummer, $entrymode ) or die $DBI::errstr;

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($_);
}
`

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

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

how to bind values INSERT INTO mysql perl

I've got the code below that works but I need to know how to bind them for security. If I just replace $new_row with ? and put it in execute I get an error. Thanks for your help.
foreach my $field (#account_field_order) {
$new_row .= "'" . param($field) . "', ";
}#foreach
$new_row .= "'$status'";
my $dsn = "DBI:mysql:$database";
my $dbh = DBI->connect($dsn, $MYSQLuserid, $MYSQLpassword )
or die $DBI::errstr;
my $sth = $dbh->prepare(qq(INSERT INTO $table VALUES ($new_row) )) or die $DBI::errstr;
$sth->execute() or die $DBI::errstr;
You will want to use placeholders, and never interpolate variables in strings. You should probably use taint mode and de-taint your param values before using them, if safety is important to you. Documentation on placeholders here.
Try something like:
my #values = map param($_), #account_field_order; # add values to array
push #values, $status; # for simplicity
$new_row = join ", ", ("?") x #values; # add ? for each value
... # basically same code as before, except the execute statement:
$sth->execute(#values); # arguments given will be inserted at placeholders
If your values were in a hash, there's the insert_hash example in the docs (under prepare_cached). Adjust as appropriate if not using an array.