Why don't I get output for this DBI/MySQL query? - mysql

I have written the following code in Perl. I have ActivePerl 5.14 for Windows 7.
#!C:\perl64\bin\perl.exe -wT
use strict;
use warnings;
use DBI;
print "Content-type: text/html \n\n";
# MYSQL CONFIG VARIABLES
my $driver = "mysql";
my $database = "test555";
my $tablename3 = "test77";
my $user = "root";
my $pw = "root";
# PERL MYSQL CONNECT()
my $dbh = DBI->connect("DBI:$driver:$database", $user, $pw,);
my $sth = $dbh->prepare("
SELECT *
FROM t6
WHERE paragraph='PWE1234'
");
$sth->execute();
#$dbh->disconnect;
#exit 0;
When the program reaches $dbh->disconnect, the system is throwing an error; hence commented it out. When I comment that out, the system is not throwing any error, but neither do I get output.
There is a result for this query, I checked with MySQL once separately.

There is no output because you have no code to create any output.
After calling execute you need to call one of the fetchsomething methods and do something with the data structure you get back.

Related

DBI->connect working when executed in terminal but not when executed from browser

I am writing a CGI program that prints a database query result in the browser. The script looks like this
#!/usr/bin/perl
use strict;
use warnings;
use DBI;
print "Content-type: text/html\n\n";
my $driver = "mysql";
my $database = "DBname";
my $ip = "127.0.0.1";
my $db = "DBI:$driver:DBNAME:$ip:database=$database";
my $username = "user";
my $password = "pass";
print "Connecting ...";
my $connection = DBI->connect($db, $username, $password)
or print "Couldn't connect to database: " . DBI->errstr . "\n\n";
print "Successful connection\n";
my $query = $connection->prepare("SELECT id FROM table");
$query->execute() or die $DBI::errstr;
while ( my #row = $query->fetchrow_array() ) {
my ($id) = #row;
print "ID = $id \n";
}
$query->finish();
Well, my problem is that when I run it from terminal using
perl test.cgi
it works fine, and I get the print results properly. The CGI script is located in /Library/Webserver/CGI-Executables/ and it is configured by default /cgi-bin/ in /etc/apache2/httpd.conf
If I execute it via the web browser, I just get the first print Connecting and nothing else, not even the or print from DBI->connect. I have been trying to realize what the error is, but I am unable to get a useful solution.
From your final comment it is as I suspected: the perl that the server is using simply doesn't have DBD::mysql installed, whereas your command-line perl does
Simply get that driver module installed on the server and all should be well
Note that is doesn't need to be "configured for Apache", it is simply that the copy of perl that is used by the CGI code doesn't have that module
By the way, the content type should be text/plain, not text/html: you're not generating HTML

Perl module to log in database and do a simple query?

I can't seem to figure out the issue with my .pm file and script. I am fairly new to Perl.
I have a database with name "project" and there is table with name "mailing".
mailing table has 7 entries, which I want to display using module.
So, I have this custom module to log in to database and do a query. This module is names as DB.pm
DB.pm is stored on my FEDORA 20 at /root/mysql/GUI/DB.pm.
DB.pm is defined as follows:
package GUI::DB;
use strict;
use DBI;
use vars qw(#ISA #EXPORT);
use Exporter;
#ISA = qw(Exporter);
#EXPORT = qw(dbConnect query);
#
# dbConnect - connect to the database, get the database handle
#
sub dbConnect {
# Read database settings from config file:
print "Works";
my $dsn = "DBI:mysql:project";
my $dbh = DBI->connect( $dsn,
'root',
'mydatabasepassword',
{ RaiseError => 1 }
);
return $dbh;
}
#
# query - execute a query with parameters
# query($dbh, $sql, #bindValues)
#
sub query {
my $dbh = shift;
my $sql ="SELECT * FROM mailing";
my #bindValues = #_; # 0 or serveral parameters
my #returnData = ();
# issue query
my $sth = $dbh->prepare($sql); //**line number 39 that is giving** error
if ( #bindValues ) {
$sth->execute(#bindValues);
} else {
$sth->execute();
}
if ( $sql =~ m/^select/i ) {
while ( my $row = $sth->fetchrow_hashref ) {
push #returnData, $row;
}
}
# finish the sql statement
$sth->finish();
return #returnData;
}
1;
Now I want to use this module inside my per script. This is what I tried:
#!/usr/bin/perl
use warnings;
use strict;
use lib '/root/mysql/';
use GUI::DB qw(dbConnect query);
dbConnect();
query();
This is the error I'm getting -->
Can't call method "prepare" on an undefined value at /root/mysql/GUI/DB.pm line 39.
Please help me with this. I am not sure how to proceed. I am guessing it has something to do with argument passing. Nothing is wrong with database. It works fine from CLI.
Thanks :)
_x_X_X_X_X_X_X_X_X_X_X_X_X_X_X_X__X_X_X_X_X__X
TILL HERE IT IS RESOLVED
_X_X_X_X_X_X_X_X_X_X_X_X_X_X_X_X_X__X_X_X
FURTHER ISSUE is SQL command is not working.
In the mailing table of my database I have email id with different domains.
For example, some id's are xyz#gmail.com, 12343#gmail.com , bae#yahoo.com as so on and I am assuming new email ids will be added to mailing tables every day with different domains.
I am trying to write a scripts that updates another table which holds a daily count of email addresses by their domain name. This is what I tried:
#!/usr/bin/perl
use warnings;
use strict;
use lib '/root/mysql/';
use 5.016;
use Data::Dumper;
use GUI::DB qw(dbConnect query);
my $data = dbConnect();
my #domain = query($data, "SELECT substr(addr,locate('\#',addr)+1) as maildomain, count (*) as mailcount FROM mailing GROUP BY maildomain ORDER BY mailcount DESC");
for my $key (#domain){
say Dumper ($key);
}
But I am getting an error,
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 '*) as mailcount FROM mailing GROUP BY maildomain ORDER BY mailcount DESC' at line 1 at /root/mysql/GUI/DB.pm line 44.
Same SQL statement works from CLI with no issues.
Any help would be appreciated. :)
1) Your error is saying that $dbh is undefined here:
sub query {
my $dbh = shift;
...
# issue query
my $sth = $dbh->prepare($sql); #<***LOOK HERE***
...which means $dbh must be undefined here:
sub query {
my $dbh = shift; #<***LOOK HERE***
...
# issue query
my $sth = $dbh->prepare($sql);
2) Let's see why. Your dbConnect() method returns $dbh:
sub dbConnect {
# Read database settings from config file:
print "Works";
my $dsn = "DBI:mysql:project";
my $dbh = DBI->connect(
$dsn,
'root',
'mydatabasepassword',
{ RaiseError => 1 }
);
return $dbh; #<***LOOK HERE*****
}
3) But, you call dbConnect() like this:
dbConnect();
Because you never save the return value anywhere, $dbh is discarded.
4) Furthermore, you call query() like this:
query();
Yet, you defined query() like this:
sub query {
my $dbh = shift;
The query() sub believes that the first argument will be the database handle--but you didn't call query() with any arguments.
You need to do this:
my $data_base_handle = dbConnect();
my #results = query($data_base_handle);
#do something with #results
Response to comment:
I printed #results, this is what I see HASH(0x1d05be8)
HASH(0x1d05ba0) HASH(0x1d05b58) HASH(0x1d05b10) HASH(0x1d05ac8)
HASH(0x1d05a80) HASH(0x1d05a38)
You wrote:
my $row = $sth->fetchrow_hashref;
...which asks DBI to return each row as a reference to a hash. Then you wrote:
push #returnData, $row;
...which pushed each hash reference into an array. So query() returns an array of hash references. The notation HASH(0x1d05be8) is what perl outputs when you print a hash reference.
If you want to see what's in those hashes, then do this:
use 5.016; #enable say()
use Data::Dumper;
...
...
for my $href (#results) {
say Dumper($href);
}
To access the data in a hash reference, you can do this:
use strict;
use warnings;
use 5.016;
use Data::Dumper;
my $href = {
c => 3,
a => 1,
b => 2,
};
my %hash = %{$href}; #dereference, {}, the reference into a hash, %
for my $key ( keys %hash ) {
say "$key $hash{$key}";
}
--output:--
c 3
a 1
b 2
Response to next comment:
(Answer posted in comments under op.)
By the way, perl is pretty good at text processing, so if you couldn't figure out the problem with your query, you could process the email addresses with perl:
use strict;
use warnings;
use 5.012;
use Data::Dumper;
use DBI;
use DBD::mysql;
# CONFIG VARIABLES
my $db_type = "mysql";
my $database = "my_db";
my $host = "localhost";
my $port = "3306";
my $user = "root";
my $pword = "";
# DATA SOURCE NAME
my $dsn = "dbi:$db_type:$database:$host:$port";
# PERL DBI CONNECT
my $dbh = DBI->connect($dsn, $user, $pword);
# PREPARE THE QUERY
my $tablename = "mailing";
my $select =<<"END_OF_SELECT";
select addr from $tablename
END_OF_SELECT
my $addr_aref = $dbh->selectcol_arrayref($select); #Returns a reference to a flat array containing all the email addresses
$dbh->disconnect;
my %count_for;
for my $addr (#{$addr_aref}) {
$addr =~ s/.*#//;
$count_for{$addr}++;
}
say Dumper(\%count_for);
--output:--
$VAR1 = {
'google.com' => 2,
'gorilla.com' => 1,
'yahoo.com' => 3
};

Display MySQL Query Results from Perl Script

My Perl script is supposed to print the results from my query. However, at the moment I'm getting the error:
Can't locate object method "fetchrow_array" via package "SELECT * FROM SERVER" (perhaps you forgot to load "SELECT * FROM SERVER"?) at updateDB.pl line 32
I imagine the problem is an easy one to fix.. but my perl / MySQL skills have much to be desired. My script is below:
#!/usr/bin/perl
use DBI;
use DBD::mysql;
use strict;
use warnings;
MySQL("SELECT * FROM SERVER");
# define subroutine to submit MySQL command
sub MySQL
{
# establish connection with 'serverDNA' database
my $connection = DBI->connect("DBI:mysql:database=serverDNA;host=localhost");
my $query = $_[0]; #assign argument to string
my $statement = $connection->prepare($query); #prepare query
$statement->execute(); #execute query
#loop to print MySQL results
while (my #row = $query->fetchrow_array)
{
print "#row\n";
}
}
Thanks so much!
You're calling fetchrow_array on the query string; you want to call it on the statement.
while (my #row = $statement->fetchrow_array)
{
print "#row\n";
}

perl DBI execute statement for LOAD DATA INFILE

I am relatively new to perl and this forum. I am trying to use perl DBI for mySql LOAD DATA INFILE statement to upload a csv file to a mySQL database. However, the execute statement returns an undef value. However if i use a SELECT or DESC statement, it works fine. I suspect that the single quotes and braces in the query is causing the error but don't know how to debug.
#!/usr/bin/perl -w
use strict;
use warnings;
use File::Basename;
use DBI;
use DBD::mySQL;
my $data_path="D:\\NickD\\Project\\StockData\\";
my $db = "TestMMDB";
my $user = "user";
my $pass ="pass";
my $host = "localhost";
my $query ="";
my #row;
my #files = glob("$data_path*.csv");
DBI->trace(1);
my $dbh = DBI->connect("dbi:mysql:$db:$host",$user,$pass);
foreach my $file(#files){
my $filename = basename($file);
my ($db_table,$date) = split("_",$filename);
$query = q{LOAD DATA INFILE ? INTO TABLE ? FIELDS TERMINATED BY ',' (Date,Symbol,Open,High,Low,Close,Volume)};
my $sqlQuery = $dbh->prepare($query);
my $rv = $sqlQuery->execute($file,$db.".".$db_table) or die "Oops!: Can't execute the query :".$sqlQuery->errstr;
while (#row = $sqlQuery->fetchrow_array()) {
print "#row\n";
}
}
my $rc = $dbh->disconnect();
exit(0);
All help will be greatly appreciated.

How do I call MySQL stored procedures from Perl?

How do I call MySQL stored procedures from Perl? Stored procedure functionality is fairly new to MySQL and the MySQL modules for Perl don't seem to have caught up yet.
MySQL stored procedures that produce datasets need you to use Perl DBD::mysql 4.001 or later. (http://www.perlmonks.org/?node_id=609098)
Below is a test program that will work in the newer version:
mysql> delimiter //
mysql> create procedure Foo(x int)
-> begin
-> select x*2;
-> end
-> //
perl -e 'use DBI; DBI->connect("dbi:mysql:database=bonk", "root", "")->prepare("call Foo(?)")->execute(21)'
But if you have too old a version of DBD::mysql, you get results like this:
DBD::mysql::st execute failed: PROCEDURE bonk.Foo can't return a result set in the given context at -e line 1.
You can install the newest DBD using CPAN.
There's an example in the section on Multiple result sets in the DBD::mysql docs.
#!/usr/bin/perl
# Stored Proc - Multiple Values In, Multiple Out
use strict;
use Data::Dumper;
use DBI;
my $dbh = DBI->connect('DBI:mysql:RTPC;host=db.server.com',
'user','password',{ RaiseError => 1 }) || die "$!\n";
my $sth = $dbh->prepare('CALL storedProcedure(?,?,?,?,#a,#b);');
$sth->bind_param(1, 2);
$sth->bind_param(2, 1003);
$sth->bind_param(3, 5000);
$sth->bind_param(4, 100);
$sth->execute();
my $response = $sth->fetchrow_hashref();
print Dumper $response . "\n";
It took me a while to figure it out, but I was able to get what I needed with the above. if you need to get multiple return "lines" I'm guessing you just...
while(my $response = $sth->fetchrow_hashref()) {
print Dumper $response . "\n";
}
I hope it helps.
First of all you should be probably connect through the DBI library and then you should use bind variables. E.g. something like:
#!/usr/bin/perl
#
use strict;
use DBI qw(:sql_types);
my $dbh = DBI->connect(
$ConnStr,
$User,
$Password,
{RaiseError => 1, AutoCommit => 0}
) || die "Database connection not made: $DBI::errstr";
my $sql = qq {CALL someProcedure(1);} }
my $sth = $dbh->prepare($sql);
eval {
$sth->bind_param(1, $argument, SQL_VARCHAR);
};
if ($#) {
warn "Database error: $DBI::errstr\n";
$dbh->rollback(); #just die if rollback is failing
}
$dbh->commit();
Mind you i haven't tested this, you'll have to lookup the exact syntax on CPAN.
Hi, similar to above but using SQL exec. I could not get the CALL command to work. You will need to fill in anything that is within square brackets and remove the square brackets.
use DBI;
#START: SET UP DATABASE AND CONNECT
my $host = '*[server]*\\*[database]*';
my $database = '*[table]*';
my $user = '*[user]*';
my $auth = '*[password]*';
my $dsn = "dbi:ODBC:Driver={SQL Server};Server=$host;Database=$database";
my $dbh = DBI->connect($dsn, $user, $auth, { RaiseError => 1 });
#END : SET UP DATABASE AND CONNECT
$sql = "exec *[stored procedure name]* *[param1]*,*[param2]*,*[param3]*;";
$sth = $dbh->prepare($sql);
$sth->execute or die "SQL Error: $DBI::errstr\n";