Please I am having problem tracking down the problem with this code I have been trying for hours . it gives me the error DBD::mysql::st fetchrow_hashref failed: fetch() without execute() at line 15
sub Split_Into_Words
{
#### Connection parameters ############################
my $dsn = "dbi:mysql:malware:localhost:3306";
my $user = 'root';
my $passwd = 'sxxxs';
########################################################
my $domain ;
my $countDir = 0 ;
my $file = shift ;
my $labelID = (split(/[.]/ , $file))[1] ; ### Split and get the middle value since format is temporay.
#### Query String ############################################################################
my $InsertIntoHostTable_QS = "INSERT INTO TB_host(HostName , UrlID , ExtID) Values (? , ? , ? ) ; ";
my $InsertIntoDomainTable_QS = "INSERT IGNORE INTO TB_Domain(Domain) values (?) ;" ;
my $InsertIntoArgVal_QS = "INSERT INTO TB_Arg_Value(Arg, URL_ID) VALUES (? , ? ) ; " ;
my $InsertIntoDirectory_QS = "INSERT INTO TB_Directory(DIRNAME , DEPTH , URLID) VALUES (? , ? , ? )" ;
my $InsertIntoExtension_QS = "INSERT IGNORE INTO TB_Extension (Extension) values ( ? ) ; ";
my $InsertIntoExtensionNULL_QS = "INSERT IGNORE INTO TB_Extension (ID , Extension) values (? , ? ) ; ";
my $SelectString = " Select URL , ID from TB_URL where LabelID = '" . $labelID."';";
my $InsertIntoFileName_QS = "INSERT IGNORE INTO TB_FileName( filename) VALUES (?) ; " ;
###################################################################################################
my $DBIConnect = DBI->connect($dsn , $user , $passwd) or die("Cannot connect to datadbase $DBI::errstr\n");
print ("Splitting Into Words \n");
######Initialization of a default DB value #################
my $sth = $DBIConnect->prepare( $InsertIntoExtensionNULL_QS);
$sth->execute(1 , 'null') or die("Error Executing the Insertion" . $sth->errstr );
$sth->finish();
#############################################################
$sth = $DBIConnect ->prepare($SelectString);
sleep(10);
open (FH , '<' , $file); # Open file to be read from disk
my $i = 0;
$sth->execute() or die("Error Executing the Insertion" . $sth->errstr );
->line 15 while(my $hash_ref = $sth->fetchrow_hashref )
{
my $extensionID = "1";
my $intialURL = $hash_ref->{URL} ;
my $initialID = $hash_ref->{ID};
}
}
I'm not sure if this is the issue, but you may not need the finish after the insert. From the DBI doc:
Indicate that no more data will be fetched from this statement handle
before it is either executed again or destroyed. You almost certainly
do not need to call this method.
Adding calls to finish after loop that fetches all rows is a common
mistake, don't do it, it can mask genuine problems like uncaught fetch
errors.
If that is the problem, you may want to create a second statement handler for the select call.
Apart from the annoyingly long SQL variable names, $SelectString should contain a "?", in case $labelID contains something that could break the query or cause an injection.
prepare() doesn't absolutely require a "?", but if execute has parameters, then there must be a matching number of "?" in the query string.
First $sth->finish() is not needed because the query is an insert and doesn't return any rows.
Second 'die' should be "Error executing query", because it executing $SelectString
Note SQL convention is to write all in uppercase, and for extra safety enclose field names in backticks. Queries do not end with semicolon. Also note that "my" variables are local to that between braces, { } so that my variables in the while loop will be unavailable afterwards.
Suggest formatting thus:
sub Split_Into_Words {
#### Connection parameters ############################
my $dsn = "dbi:mysql:malware:localhost:3306";
my $user = 'root';
my $passwd = 'sxxxs';
########################################################
my $domain ;
my $countDir = 0 ;
my $file = shift ;
my $labelID = (split(/[.]/ , $file))[1] ; ### Split and get the middle value since format is temporary.
#### Query String ############################################################################
my $InsertIntoHostTable_QS = "INSERT INTO `TB_host` (`HostName`,`UrlID`,`ExtID`) VALUES (?,?,?)";
my $InsertIntoDomainTable_QS = "INSERT IGNORE INTO `TB_Domain` (`Domain`) VALUES (?)";
my $InsertIntoArgVal_QS = "INSERT INTO `TB_Arg_Value` (`Arg`,`URL_ID`) VALUES (?,?)";.
my $InsertIntoDirectory_QS = "INSERT INTO `TB_Directory` (`DIRNAME`,`DEPTH`,`URLID`) VALUES (?,?,?)";
my $InsertIntoExtension_QS = "INSERT IGNORE INTO `TB_Extension` (`Extension`) VALUES (?)";
my $InsertIntoExtensionNULL_QS= "INSERT IGNORE INTO `TB_Extension` (`ID`,`Extension`) VALUES (?,?)";
my $SelectString = "SELECT `URL`,`ID` FROM `TB_URL` WHERE `LabelID`=?";
my $InsertIntoFileName_QS = "INSERT IGNORE INTO `TB_FileName` (`filename`) VALUES (?)";
###################################################################################################
my $DBIConnect = DBI->connect($dsn , $user , $passwd) or die("Cannot connect to datadbase $DBI::errstr\n");
print ("Splitting Into Words \n");
######Initialization of a default DB value #################
my $sth = $DBIConnect->prepare( $InsertIntoExtensionNULL_QS);
$sth->execute(1 , 'null') or die("Error executing the Insertion: " . $sth->errstr );
# $sth->finish(); # not needed because it's an insert
#############################################################
$sth = $DBIConnect->prepare($SelectString);
sleep(10);
open (FH , "<$file"); # Open file to be read from disk
my $i = 0;
$sth->execute($labelID) or die("Error executing query: " . $sth->errstr );
while(my $hash_ref = $sth->fetchrow_hashref ) {
my $extensionID = "1";
my $intialURL = $hash_ref->{URL};
my $initialID = $hash_ref->{ID};
}
Related
Why are trailing blanks chopped off from the column value even though ChopBlanks is not enabled?
use DBI;
my $value = ' string ';
my $db = 'my_mysql_db';
my $dbh = DBI->connect( "dbi:mysql:db=$db", 'user', '*', { RaiseError => 1, ChopBlanks => 0 } ) or die DBI->errstr;
my $table = 'test_mysql';
$dbh->do( "CREATE TABLE IF NOT EXISTS $table (col_1 CHAR(64))" );
my $sth = $dbh->prepare( "DELETE FROM $table WHERE col_1 = ?" );
$sth->execute( $value );
$sth = $dbh->prepare( "INSERT INTO $table (col_1) VALUES( ? )" );
$sth->execute( $value );
$sth = $dbh->prepare( "SELECT * FROM $table" );
$sth->execute();
$sth->dump_results;
' string'
1 rows
I believe this is a MySQL thing and not a DBI thing. From 11.3.2 The CHAR and VARCHAR Types:
When CHAR values are stored, they are right-padded with spaces to the specified length. When CHAR values are retrieved, trailing spaces are removed unless the PAD_CHAR_TO_FULL_LENGTH SQL mode is enabled.
I'm baffled, when I use the terminal (mysql) and insert into username,account_password columns, user_id AUTO_INCREMENTS just as it should.
my table:
CREATE TABLE users (
user_id int NOT NULL AUTO_INCREMENT,
user_type VARCHAR(20) NULL,
creation_date TIMESTAMP NOT NULL,
username VARCHAR(100) NOT NULL,
account_password VARCHAR(255) NOT NULL,
PRIMARY KEY (user_id)
);
yet when I use this script:
use strict;
use warnings FATAL => 'all';# good for debugging, FATAL kills program so warnings are more identifiable
use CGI qw/:standard/;
use CGI::Carp qw(fatalsToBrowser); # good for debugging, sends info to browser
use DBI;
use DBD::mysql;
use Digest::SHA qw(sha256);
print header, start_html;
my $fName = param('firstName');
my $lName = param('lastName');
my $compName = param('compName');
my $email = param('email');
my $pswrd = param('password');
my $cnfPswrd = param('confPassword');
my $encpswrd = "";
#check passwords match, if not display error, and exit script
if ($pswrd eq $cnfPswrd) {
$encpswrd = sha256($pswrd);
} else {
print "Passwords did not match! refresh form!";
exit;
}
#database credentials, to be changed accordingly
my $database = "intsystest";
my $host = "localhost";
my $user = "root";
my $pw = "password";
my $dsn = "dbi:mysql:$database:localhost:3306";
#connect to database
my $dbh = DBI->connect($dsn, $user, $pw,
{ RaiseError => 1 }) or die "unable to connect:$DBI::errstr\n"; # <- this line good for debugging
#create, prepare, execute query, disconnect from DB
my $personsQuery = "INSERT INTO persons (first_name, last_name) VALUES (?,?)";
my $compQuery = "INSERT INTO company (company_name) VALUES (?)";
my $usersQuery = "INSERT INTO users (username, account_password) VALUES (?,?)";
my $sth = $dbh->prepare($personsQuery);
$sth->execute($fName, $lName);
$sth = $dbh->prepare($compQuery);
$sth->execute($compName);
$sth = $dbh->prepare($usersQuery);
$sth->execute($email, $encpswrd);
$dbh -> disconnect;
# additional processing as needed ...
print end_html;
I get this error:
DBD::mysql::st execute failed: Field 'user_id' doesn't have a default value at /usr/lib/cgi-bin/compSignUpDBCGI.pl line 44.
I'm assuming it's likely something wrong with the handler. What am I missing??
If your persons table has a foreign key to the users table then you need insert the users record first, then get the id of the new users record and add that to the SQL to insert the persons record.
Something like this:
my $usersQuery = "INSERT INTO users (username, account_password) VALUES (?,?)";
$sth = $dbh->prepare($usersQuery);
$sth->execute($email, $encpswrd);
$sth = $dbh->prepare('SELECT user_id FROM users WHERE username = ?');
$sth->execute($email);
my $user_id = $sth->fetch->[0];
my $personsQuery = "INSERT INTO persons (user_id ,first_name, last_name) VALUES (?,?,?)";
$sth = $dbh->prepare($personsQuery);
$sth->execute($user_id, $fName, $lName);
This is an area where DBIx::Class will definitely make your life easier.
what i need to fetch data from stored procedures
syntax in sql developer
select abc_web_demo.wwv_json_data.dashboards('abc','7','tt',1211) from dual
returns json string
{"data":[{"logs":7,"to_abc":88,"to_cl":12,"to_me":0}]}
code
$tns = "
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST =ABC)(PORT = 1521))
)
(CONNECT_DATA = (SID = AAA))
)
";
try {
$conn = new PDO("oci:dbname=".$tns, '**', '**');
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
echo 'Connected to database';
} catch(PDOException $e) {
echo 'ERROR: ' . $e->getMessage();
}
$sql = "CALL abc_web_demo.wwv_json_data.dashboards('ABC','79','Y',121221) ";
$stmt = $conn->prepare($sql);
$te=$stmt->execute();
//$stmt = $connection->query("SELECT #NEW_ID");
//$id = $stmt->fetchColumn();
print_r($te);
Problem
i have google & found i need to pass in string in query
like $stmt = $connection->query("SELECT #NEW_ID");
here in my my case i need to pass 4 parameters in procedure.
i new in stored procedures i need help how to pass 4 arguments in procedure .
how to access json response using fetch statement.
i need json repsonse from fetch data.
any help much appreciated
Solution i tried
$output = $conn->query("select 'abc', '7' ")->fetch(PDO::FETCH_ASSOC);
var_dump($output);
Error
SQLSTATE[HY000]: General error: 923 OCIStmtExecute: ORA-00923: FROM keyword not found where expected
when i tried test query it works
$stmt = $conn->prepare("select * from customers");
$st=$stmt->execute();
$result = $stmt->fetch(PDO::FETCH_ASSOC);
print_r($result);
Write your query as follows. The FROM clause is mandatory in Oracle dialect of SQL.
select 'abc', '7' from dual
I have a table with no primary key.
I need to execute the following:
UPDATE t1
SET tstamp = now()
WHERE `col1` = 1
AND `col2` = 'this';
In Workbench it throws Error 1175 until I execute this line before the update:
SET SQL_SAFE_UPDATES = 0;
With this line it works just fine.
But when I try to do this in perl it doesn't work. I tried both
$dbh->do("SET SQL_SAFE_UPDATES = 0");
and
my $dbh = DBI->connect("DBI:mysql:$db:$host:$port",$user,$password, { RaiseError => 1, AutoCommit => 0, sql_safe_updates => 0 })
but it still doesn't work.
How can I get this work in perl?
UPD.
I updated the code with ##sql_safe_updates check and commit.
The code:
$sth = $dbh->prepare("SELECT #\#sql_safe_updates"); $sth->execute; while(my #row = $sth->fetchrow_array) { print "sql_safe_updates before: ". $row[0] . "\n"; }
$dbh->do("SET SQL_SAFE_UPDATES = 0") or die $dbh->errstr;
$sth = $dbh->prepare("SELECT #\#sql_safe_updates"); $sth->execute; while(my #row = $sth->fetchrow_array) { print "sql_safe_updates after: " . $row[0] . "\n"; }
$query = "UPDATE t1 SET tstamp = now() WHERE `col1` = 1 AND `col2` = 'this'";
$sth = $dbh->prepare($query);
$rv = $sth->execute or die $sth->err();
$dbh->commit;
if ("$rv" ne "1") {
$query =~ s/\n/ /g; $query =~ s/ / /g;
print "Failed to run query: $query\n";
exit;
}
Output:
sql_safe_updates before: 0
sql_safe_updates after: 0
Failed to run query: UPDATE t1 SET tstamp = now() WHERE `col1` = 1 AND `col2` = 'this'
UPD2. I checked the table - everything works after I commited. It is confusing thought, that $rv is 1 on successful select and 2 on successful update
It was a return code check error, and a missing commit.
Regarding the return code check, for a non-SELECT statement, execute returns the number of rows affected, if known.. Zero rows affected (as opposed to an error) is represented as the special "zero but true" value "0E0". In the OP's case, the statement was returning 2.
Afternoon everyone,
I'm currently trying to insert or update form field values via params into a mysql after some simple validation. The form submits, but does not actually execute any of the operations and does not raise a syntax or database connection error. I know my connection string works because I fetched values from it to compare to in the code prior to the nested evaluation blocks shown below. The foreach loops were inserted as an alternate means of validating that the values have indeed been altered in the table. Your help is greatly appreciated, as always:
my $dbusr = param("dbuser");
my $dbpw = param("dbpass");
my $dbmail = param("dbemail");
my $dbtel = param("dbphone");
my $postflag = param("Submit");
if ($dbusr ne "") {
$sth = $dbh->prepare("SELECT * FROM USER WHERE username LIKE ?");
$sth->execute('$dbusr');
warn( $DBI::errstr ) if ( $DBI::err );
my #results = $sth->fetchall_arrayref();
foreach(#results){
if ($dbusr eq $_){
$loopval = 1;
}
}
unless($loopval){
$sth = $dbh->prepare("INSERT INTO USER
(username, password, phone, email)
values
(?,?,?,?)");
$sth->execute($dbusr, $dbpw, $dbtel, $dbmail);
warn( $DBI::errstr ) if ( $DBI::err );
$sth = $dbh->prepare("SELECT * FROM USER WHERE username LIKE ?");
$sth->execute('$dbusr');
#results = $sth->fetchall_arrayref();
foreach(#results){
if ($dbusr eq $_){
$successflag = 1;
}
}
}
else{
$sth = $dbh->prepare("UPDATE USER
SET (password = ?, phone = ?, email = ?)
WHERE username = ?");
$sth->execute($dbpw, $dbtel, $dbmail, $dbusr);
warn( $DBI::errstr ) if ( $DBI::err );
$sth = $dbh->prepare("SELECT * FROM USER WHERE username LIKE ?");
$sth->execute('$dbusr');
#results = $sth->fetchall_arrayref();
foreach(#results){
if ($dbusr eq $_){
$successflag = 1;
}
}
}
}
Basic Perl: '-quoted strings do NOT interpolate variables:
$sth->execute('$dbusr');
^-- ^---
You're literally passing $, d, b, etc... to your query as the placeholder value.
Try
$sth->execute($dbusr); // note the lack of ' quotes
instead.
You are searching for entire rows with the SELECT * FROM USER WHERE username LIKE ? statement, and are then fetching all the rows in one go with
my #results = $sth->fetchall_arrayref();
That method "returns a reference to an array that contains one reference per row.", but you are treating the returned value as an list of usernames:
foreach(#results){
if ($dbusr eq $_){
$loopval = 1;
}
}
To make this work you should just fetch the username column, and treat the returned rows as references of references. And as you look for exact matches in the database replace LIKE with =:
$sth = $dbh->prepare("SELECT username FROM USER WHERE username = ?");
$sth->execute($dbusr); # no quoting
die( $DBI::errstr ) if ( $DBI::err ); # what else to do if the execute fails?
my $results = $sth->fetchall_arrayref(); # an arrayref is returned
foreach(#$results){ # de-reference the array
if ($dbusr eq $_->[0]){ # each row is an arrayref, look in first element
$loopval = 1;
}
}
(Of course the same applies to the second search.)