Why is MySQL giving me a syntax error? - mysql

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;

Related

Update db row with perl cgi

I am trying to update my sql table with some new values entered into the user. For some reason the sql command is not updating my db. I am getting the correct values I verified. Here is my code
#!/usr/bin/perl
#This is going to be the user login check and will set a cookie
use DBI;
use CGI qw(:standard);
use strict;
#Connection error
sub showErrorMsgAndExit {
print header(), start_html(-title=>shift);
print (shift);
print end_html();
exit;
}
#Connecting to the database
my $dbUsername = "root";
my $dbPassword = "password";
my $dsn = "DBI:mysql:f18final:localhost";
my $dbh = DBI->connect($dsn, $dbUsername, $dbPassword, {PrintError => 0});
#error checking
if(!$dbh) {
print header(), start_html(-title=>"Error connecting to DB");
print ("Unable to connec to the database");
print end_html();
exit;
}
print header;
print start_html(-title=>'Add Classes');
#Get the information the user entered
my $id = param('classid');
my $className = param('classname');
my $department = param('department');
my $classnum = param('classnum');
my $grade = param('grade');
my $credits = param('credit');
print "$id $className, $department, $classnum, $grade, $credits";
#first sql check to see if username is already taken
my $check = "UPDATE tblclasses(classname, department, classnum, grade, credits) VALUES (?, ?, ?, ?, ?) WHERE classID = $id";
my $sth = $dbh->prepare($check);
$sth->execute($className, $department, $classnum, $grade,$credits);
print "<h1>Success</h1>";
print "<form action=http://localhost/cgi-bin/edit.pl method = 'post'>";
print "<input type = 'submit' name = 'submit' value = 'Update Another'>";
print "</form>";
print "<form action=http://localhost/cgi-bin/actions.pl method = 'post'>";
print "<input type = 'submit' name = 'submit' value = 'Back to actions'>";
print "</form>";
print end_html();
exit;
When I try to run the sql command in mysql workbench it successfuly updates the row. What is my issue?
There is an error in the syntax of your SQL statement :
UPDATE tblclasses(classname, department, classnum, grade, credits)
VALUES (?, ?, ?, ?, ?)
WHERE classID = $id
Should be written :
UPDATE tblclasses
SET classname = ?,
department = ?,
classnum = ?,
grade = ?,
credits = ?
WHERE classID = ?
See the mysql docs.
Side notes (as commented also by #Grinnz) :
you should always « use strict »
you should set DBI attribute « RaiseError » to 1 on your database or statement handle(s) ; hence all DBI errors become fatal ; disabling both « RaiseError » and « PrintErrror » results in DBI neither dying on errors nor reporting them, hence you must manually check the return code of each and every DBI call to make sure that it worked - see the DBI docs
you should bind all variables in your SQL statement to void SQL injection (you did not bind $id, I changed that in the above query)
Without knowing the DBMS I can't be 100% certain, but it appears as though you blended the syntax for an insert and an update command. The correct syntax for an update should be:
UPDATE tblclasses
set
classname = ?,
department = ?,
classum = ?,
grade = ?,
credits = ?
WHERE classID = $id
Also, for what it's worth, you should also be able to pass the $id variable as a parameter also rather than interpolating it. This, in theory, will be kinder to the database as it will be compiling once and executing the same SQL statement over and over, only with different bind variable values:
my $check = qq{
UPDATE tblclasses
set
classname = ?,
department = ?,
classum = ?,
grade = ?,
credits = ?
WHERE classID = ?
};
my $sth = $dbh->prepare($check);
$sth->execute($className, $department, $classnum, $grade,$credits, $id);

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

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

Update MySQL within Perl loop failing (fetchrow_array)

I've created a Perl script which is meant to loop through an array (a shortlist of customers who meet certain criteria), execute an external command using system() , then update a field within each row once the operation has completed.
It works on the first record (ie external command executes, customer record updates), however when it gets to the second record I receive this error:
DBD::mysql::st fetchrow_array failed: fetch() without execute() at customer_update.pl
Through some googling I added the $sth->finish(); command, however whether I include it or not (either inside the loop as shown, or straight afterward) I still get the same error.
Can anyone shed any light for me as to what I am doing wrong here?
Here's an extract:
# PERL MYSQL CONNECT()
$dbh = DBI->connect('dbi:mysql:signups', $user, $pw)
or die "Connection Error: $DBI::errstr\n";
# DEFINE A MySQL QUERY
$myquery = "SELECT * FROM accounts WHERE field3 = false";
$sth = $dbh->prepare($myquery);
# EXECUTE THE QUERY
$sth->execute
or die "SQL Error: $DBI::errstr\n";
#records = $sth->rows;
print "Amount of new customers: #records\n\n";
while ( my ($field1, $field2, $field3) = $sth->fetchrow_array() ) {
#execute external command via system();
$update_customer_status = "UPDATE accounts SET field3=true WHERE id=$id";
$sth = $dbh->prepare($update_customer_status);
$sth->execute
or die "SQL Error: $DBI::errstr\n";
print "Customer record modified & MySQL updated accordingly\n\n";
$sth->finish();
}
Building a SQL statement with variables and then prepare()ing it defeats the purpose of the prepare. You should build the SQL statement with a placeholder ? instead of $id, prepare() it, and then execute($id) it. As it is, you are leaving yourself open to SQL injection attacks.
Also, it seems that you are not using the warnings and strict pragmas. These two lines should be at the top of every program you write:
use warnings;
use strict;
They will save you much heartache and frustration in the future.
In your loop, you overwrite the handle over from which you are fetching. Use a different variable. (Changing $sth = ...; to my $sth = ...; will do.) While we're at it, let's move the prepare out of the loop.
my $sth_get = $dbh->prepare("SELECT * FROM accounts WHERE field3 = false");
my $sth_upd = $dbh->prepare("UPDATE accounts SET field3=true WHERE id = ?");
$sth_get->execute();
while ( my ($field1, $field2, $field3) = $sth_get->fetchrow_array() ) {
...
$sth_upd->execute($id);
}
You are stomping on your $sth variable when you execute this line ...
$sth = $dbh->prepare($update_customer_status);
Why not save off the result of $sth->fetchrow_array() to an array variable.
Something like ...
my #select_results_AoA = $sth->fetchrow_array();
... and then iterate over the array ...
for my #row ( #select_resilts_AoA ) {
... instead of ...
while ( my ($field1, $field2, $field3) = $sth->fetchrow_array() ) {

How to insert text into mysql having quotes using perl

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.