Executing procedural queries in perl - mysql

I have a query like this
set #valid_total:=0;
set #invalid_total:=0;
select week as weekno, measured_week,project_id as project,
role_category_id as role_category,
valid_count,valid_tickets,
(#valid_total := #valid_total + valid_count) as valid_total,
invalid_count,invalid_tickets,
(#invalid_total := #invalid_total + invalid_count) as invalid_total
from metric_fault_bug_project
where measured_week = yearweek(curdate())
and role_category_id = 1 and project_id = 11;
it executes fine in heidi (MySQL client) but when it comes to perl, it gives me this error
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 ':=0;
set :=0;
select week as weekno, measured_week,project_id
as project' at line 1 at D:\Mx\scripts\test.pl line 35.
Can't execute SQL statement: You have an error in your SQL syntax; check the man
ual that corresponds to your MySQL server version for the right syntax to use ne
ar ':=0;
set :=0;
select week as weekno, measured_week,project_id
as project' at line 1
The problem seem to be in the set #valid_total := 0; line.
I am fairly new to Perl. Can anyone help?
this is the complete perl code
#!/usr/bin/perl
#use lib '/x01/home/kalpag/libs';
use DBI;
use strict;
use warnings;
my $sid = 'issues';
my $user = 'root';
my $passwd = 'kalpa';
my $connection = "DBI:mysql:database=$sid;host=localhost";
my $dbhh = DBI->connect( $connection, $user, $passwd) ||
die "Database connection not made: $DBI::errstr";
my $sql_query = 'set #valid_total:=0;
set #invalid_total:=0;
select week as weekno, measured_week,project_id,
role_category_id as role_category,
valid_count,valid_tickets,
(#valid_total := #valid_total + valid_count) as valid_total,
invalid_count,invalid_tickets,
(#invalid_total := #invalid_total + invalid_count) as invalid_total
from metric_fault_bug_project
where measured_week = yearweek(curdate())
and role_category_id = 1 and project_id = 11';
my $sth = $dbhh->prepare($sql_query) or die "Can't prepare SQL statement: $DBI::errstr\n";
$sth->execute() or die "Can't execute SQL statement: $DBI::errstr\n";
while ( my #memory = $sth->fetchrow() )
{
print "#memory \n";
}

You are probably using a double quoted string for your query string, in which case perl looks for the variables #valid_total and #invalid_total. This would imply that you are not using
use strict;
use warnings;
Because otherwise you would already know the error. The result is that perl replaces the variables with nothing, which is reflected in your error.
What you need to do is single quote the string:
my $query = 'set #valid_total:=0;
set #invalid_total:=0;
select week as weekno, measured_week,project_id as project,
role_category_id as role_category,
valid_count,valid_tickets,
(#valid_total := #valid_total + valid_count) as valid_total,
invalid_count,invalid_tickets,
(#invalid_total := #invalid_total + invalid_count) as invalid_total
from metric_fault_bug_project
where measured_week = yearweek(curdate())
and role_category_id = 1 and project_id = 11';

Please always use strict and warnings. if you don't have a variable #valid_total, warnings would then warn you
Possible unintended interpolation of #valid_total in string
and strict would even die.
In double quoted strings you must escape # signs:
"set \#valid_total:=0;"
and if you don't need interpolation at all, better use single quotes.
edit: after I can see the perl code:
rather then doing
my $sql_query = 'set #valid_total:=0;
set #invalid_total:=0;
...';
my $sth = $dbhh->prepare($sql_query)
you should do:
my $sql_query = 'set #valid_total:=0';
my $sth = $dbhh->prepare($sql_query);
$sth->execute;
$sth->finish;
$sql_query = 'set #invalid_total:=0'
$sth = $dbhh->prepare($sql_query);
$sth->execute;
$sth->finish;
...
you cannot execute more than one statement in one query.

Related

Multi-line MySQL in Perl

I am trying to pass a command to my database (MariaDB/MySQLi) but Perl's DBI is giving me an error, whatever I try. The thing is that I can execute the MySQL fine in phpMyAdmin without fault. The error that I receive is:
DBD::mysql::st execute failed: You have an error in your SQL syntax;
check the manual that corresponds to your MariaDB server version for
the right syntax to use near SELECT DISTINCT t.bf FROM wrpec t JOIN wrpec r ON t.path LIKE r.path || '%' at line 2 at
retrieve-includes.pl line 20.
DBD::mysql::st fetchrow_array failed:
fetch() without execute() at retrieve-includes.pl line 22.
The full test file (fake database obviously) is as below.
#!/usr/bin/perl
use strict;
use warnings;
use DBI;
use Data::Dumper;
my $dsn = "DBI:mysql:database=mydatabase;host=machine";
my $dbh = DBI->connect($dsn, 'root', '') or die "Couldn't connect to database: " . DBI->errstr;;
my $request_includes = "
SET sql_mode = PIPES_AS_CONCAT;
SELECT DISTINCT t.bf
FROM `wrpec` t
JOIN `wrpec` r
ON t.path LIKE r.path || '%'
WHERE r.bf = 'WRPECsmain\%hd' AND t.has_tree;";
my $sth = $dbh->prepare($request_includes) or die "Couldn't prepare statement: " . $dbh->errstr;
$sth->execute();
while (my #row = $sth->fetchrow_array()) {
print Dumper(\#row);
}
$sth->finish();
I have also tried some ideas I found online: using a clean-up sub that replaces all white-space characters by hard spaces to make sure you're passing a string, and I also tried this notation (I forgot the name) but it doesn't work either (same error).
my $request_includes = <<"REQUEST_INCLUDES";
SET sql_mode = PIPES_AS_CONCAT;
SELECT DISTINCT t.bf
FROM `wrpec` t
JOIN `wrpec` r
ON t.path LIKE r.path || '%'
WHERE r.bf = 'WRPECsmain\%hd' AND t.has_tree;
REQUEST_INCLUDES
You're getting a SQL syntax error because by default, DBD::mysql doesn't allow you to execute multiple statements at once. You should run two separate DBI commands instead:
$dbh->do( q{SET sql_mode = 'PIPES_AS_CONCAT'} );
my $sth = $dbh->prepare(q{
SELECT DISTINCT t.bf
FROM `wrpec` t
JOIN `wrpec` r
ON t.path LIKE r.path || '%'
WHERE r.bf = 'WRPECsmain\%hd' AND t.has_tree
});
I was trying to create a script that works on MySQL as wel as PostgreSQL without changes.
Enable MySQL's ANSI mode and double quote your identifiers:
$dbh->do( q{SET sql_mode = 'ANSI'} ) if $mysql;
my $sth = $dbh->prepare(q{
SELECT DISTINCT t.bf
FROM "wrpec" t
JOIN "wrpec" r
ON t.path LIKE r.path || '%'
WHERE r.bf = 'WRPECsmain\%hd' AND t.has_tree
});
There are a couple other issues, though:
unescaped _ and % in r.path will be interpreted as wildcards
'foo' LIKE 'foo%' is true
To only fetch rows where the t.path is a prefix of r.path, but they're not equal, do:
SELECT DISTINCT t.bf
FROM "wrpec" t
JOIN "wrpec" r
ON POSITION(t.path IN r.path) = 1
AND t.path != r.path
WHERE r.bf = 'WRPECsmain\%hd'
AND t.has_tree

JDBC update database

i have a form and onClick listener i want to update some data on my database exception says that i have a syntax error but when i execute query at mysql console it works here is my code all variables are checked
String temp = itemList.getModel().getElementAt(itemList.getSelectedIndex()).toString();
PreparedStatement pt = supplies.con.prepareStatement("update prods set pquant = pquant + ? where pname = ?");
pt.setInt(1, Integer.parseInt(empsalary.getText()));
pt.setString(2, temp);
supplies.pst.executeQuery(temp);
Error
com.mysql.jdbc.exceptions.MySQLSyntaxErrorException: 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 'DVD Verdatim' at line 1
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:936)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:2985)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1631)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:1723)
at com.mysql.jdbc.Connection.execSQL(Connection.java:3277)
at com.mysql.jdbc.Connection.execSQL(Connection.java:3206)
at com.mysql.jdbc.Statement.executeQuery(Statement.java:1232)
at buy$1.actionPerformed(buy.java:62)
As the compiler mentioned, there is indeed a Syntax error in your SQL query. Try:
String temp = itemList.getModel().getElementAt(itemList.getSelectedIndex()).toString();
PreparedStatement pt = supplies.con.prepareStatement("update prods set pquant = #0 + 21" + "'variableForPquant'" "where pname = #1" + "'variableForPname'");
pt.setInt(1, Integer.parseInt(empsalary.getText()));
pt.setString(2, temp);
supplies.pst.executeQuery(temp);
You need to use quotes when you are using variables in your SQL query. I believe it is either
"'variableName'" or '"variableName'"
I found my error i declare a variable pt and i execute the query from the statement that is empty pst i change to pt.executeUpdate(); and its ok now

fires more then one query in mysql_query

$updateStock = "UPDATE opening SET qtyUsed = 1000 WHERE openingId = 1 ; UPDATE purchase SET qtyUsed = qtyUsed + 25 WHERE purchaseId = 1";
$updateAllStock = mysql_query($updateStock);
This Gives Error : Data Not InsertedYou have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'UPDATE purchase SET qtyUsed = qtyUsed + ' at line 3
mysql_query can only execute one query at a time. You need to execute mysql_query twice.
Instead of the mysql extension use mysqli. With mysqli you can execute multiple queries. http://www.php.net/manual/fr/mysqli.multi-query.php
You can use mysqli_query()
It allows multiple statements. Be careful.
You are sending two queries, so you have to query the databsae twice. There is the support for multiple queries in mysqli, but I strongly advise against using this feature, because you raise the probability of SQL injection attacks.
$updateStock = "UPDATE opening SET qtyUsed = 1000 WHERE openingId = 1";
$updatePurchase = "UPDATE purchase SET qtyUsed = qtyUsed + 25 WHERE purchaseId = 1";
$updateAllStock = mysql_query($updateStock);
$updateAllPurchase = mysql_query($updatePurchase);

mysql: issue with the demonstration of sql injection

according to this tutorial:http://www.tizag.com/mysqlTutorial/mysql-php-sql-injection.php
Below codes will demonstrate SQL Injection:
<?php
// a good user's name
$name = "timmy";
$query = "SELECT * FROM customers WHERE username = '$name'";
echo "Normal: " . $query . "<br />";
// user input that uses SQL Injection
$name_bad = "' OR 1'";
// our MySQL query builder, however, not a very safe one
$query_bad = "SELECT * FROM customers WHERE username = '$name_bad'";
// display what the new query will look like, with injection
echo "Injection: " . $query_bad;
In front end, it shows:
Injection: SELECT * FROM customers WHERE username = '' OR 1''
So I just did a test, in phpmyadmin->sql, I run below codes:
SELECT * FROM users WHERE fname = '' OR 1''
And it shows:
#1064 - 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 ''' LIMIT 0, 30' at line 1
Qustion:
supposed it will show every single entry in the "users" table, but not, why? if I want to demonstrate sql injection, how to do it?
A more typical SQL injection would be: $name_bad = "' OR 1=1 -- ";. This would lead to the following SQL:
SELECT * FROM customers WHERE username = '' OR 1=1 -- '
SELECT * FROM users WHERE fname = '' OR 1 = 1
is likely what they meant
edit just looked
SELECT * FROM users WHERE fname = '' OR 1
1 evaluates to true, so just remove the '' after it
also that link is way out of date, Look at mysqli or pdo instead

Perl DBI select providing wrong values using bind_columns

I have this Perl code:
my $cmd = "
SELECT COUNT(id)
FROM tblUsers
WHERE UPPER(username) = UPPER(?) AND password = ?
";
db_connect();
my $sql = $dbh->prepare($cmd);
my $count = 2;
$sql->execute(
$args{login_username},
crypt($args{login_password}, $args{login_username})
) or die "SQL Error: ".$sql->errstr;
$sql->bind_columns(\$count);
$sql->fetch;
which is returning 0, but should be returning a 1
If I output the following:
$msg = "wrong username/password: $count;$args{login_username};$args{login_password};" . crypt($args{login_password}, $args{login_username});
I get:
wrong username/password: 0;skeniver;password;skh9dtk2bCasY
and the crypt part is exactly what I have in the database. Running the same values in MySQL returns a count of 1.
I really can't figure out what's going wrong here.
Does anyone else see something I'm missing?
Assuming your select returns a non 0 value and assuming that the column password in tblUsers has skh9dtk2bCasY for username=skeniver, Try
$sql->execute($args{login_username}, crypt($args{login_password},$args{login_username}))
or die "SQL Error: ".$sql->errstr;
$count = $sql->fetchrow_array();
Or, if there is a possibility that the query returns multiple rows then-
$sql->execute($args{login_username}, crypt($args{login_password},$args{login_username}))
or die "SQL Error: ".$sql->errstr;
while (($count) = $sql->fetchrow_array()){
print "Count is: $count\n";
}