perl, dbi with sql statement with a like condition - sql

in my code i must do a simple sql query with a like condition.
i've do in this way
my $out = "/Users/zero/out.log";
my $filename = "/Users/zero/data.txt";
my $dbh = DBI->connect("DBI:Oracle:sid=$sid;host=$host;port=$port", $user, $pwd) or die "Couldn't connect to database: " . DBI->errstr;
my $query = "select SOMETHING from SOMETHING_1 where SOMETHING like ?||'%' ";
my $sth = $dbh->prepare($query) or die "Connection Error: " . $dbh->errstr;
open (IN,"< $filename") or die("Unable to open $filename");
my #righe = <IN>;
close IN;
open (OUT,">$out") or die "Unable to open $out";
foreach my $riga (#righe) {
chomp $riga;
(my $valore) = split (/\n/, $riga);
$sth->execute($valore) ||print "Impossibile eseguire la query $query";
while (my $real = $sth->fetchrow_array) {
print OUT "\"$real\"\n";
}
}
$sth->finish;
$dbh->disconnect();
but the query return all the rows, ignoring the like condition.
Where's my fault?
Thank's

You have to concat the % char to the variable you search for.
my $query = "select SOMETHING from SOMETHING_1 where SOMETHING like ?";
...
$sth->execute($valore.'%') ||print "Impossibile eseguire la query $query";

Related

Oracle SQL query returns some data when it should be empty-PowerShell

I am writing a script in PowerShell Core 7.2. I get a list of files from a folder that I check against Oracle db. I need the data of Description, and NC_Name column if the file is in db.
The issue is that even when the file is not in db it still returns the data but of some other file.
For example: I have a list of files, File#1, File#2,File#3. If File#2 is not in the db it still returns the data of File#1.
I have tried counting the number of rows and putting it as a condition. As in
$rowNum = $connection.count
The issue with this is that $rowNum is never zero because it returns data for some other file; because the variable $fileName is never empty.
I also tried checking for the file name in the query itself but it gave a lot of errors. The query was
$query="DECLARE record_exists INTEGER; BEGIN SELECT COUNT(*) INTO record_exists FROM NC_PROGRAMS WHERE NC_PROGRAMS.NC_NAME = '$fileName' AND ROWNUM = 1; IF record_exists = 1 THEN Select DESCRIPTION, NC_NAME"
The code is:
#Get all files
$result = $start.EnumerateDirectories() | ForEach-Object -Parallel {
$_.GetFiles('*.EIA', $using:enum)
}
$result | Format-Table -AutoSize
foreach($item in $result){
$fileName = $item.BaseName
#Oracle connection
Add-Type -Path C:\lib\netstandard2.1\Oracle.ManagedDataAccess.dll
$query = "Select DESCRIPTION, NC_NAME From NC_PROGRAMS WHERE
NC_PROGRAMS.NC_NAME = '$fileName' "
$connectionString = "connectionString"
$connection = New-Object Oracle.ManagedDataAccess.Client.OracleConnection($connectionString)
$connection.Open()
$command = $connection.CreateCommand()
$command.CommandText = $query
$reader = $command.ExecuteReader()
$rowNum = $connection.count
Write-host "Number of rows-"$rowNum
while($reader.Read()) {
$description=$reader.GetString(0)
$fastemsFileName = $reader.GetString(1)
}
$connection.Close()
}

Phalcon: specific column on joined PHQL

The below PHQL generates a complex resultset like it should:
$phql = "SELECT User.*, ProductUser.* "
. "FROM ProductUser "
. "INNER JOIN User "
. "WHERE ProductUser.product_id = 5";
Replacing ProductUser.* with an existing column like ProductUser.id causes an error:
MESSAGE: The index does not exist in the row
FILE: phalcon/mvc/model/row.zep
LINE: 67
This is version 2.0.6. Is this a bug or am I making a mistake somewhere? According to the documentation it should be fine.
It was my mistake (expecting the row to always be an object).
I hope this helps someone because looping complex resultsets is not in the documentation.
$result = $this->modelsManager->createQuery($phql)->execute();
if ($result instanceof \Phalcon\Mvc\Model\Resultset\Complex) {
foreach ($result as $rows) {
foreach ($rows as $row) {
if (is_object($row)) {
$modelData = $row->toArray());
// this is what I needed
} else {
$id = $row;
}
}
}
}
First of all you're missing the ON clause in your query.
Anyways, it's easier and more error prone to use Phalcon's query builder for querying:
<?php
// modelManager is avaiable in the default DI
$queryBuilder = $this->modelsManager->createBuilder();
$queryBuilder->from(["product" => 'Path\To\ProductUser']);
// Inner join params are: the model class path, the condition for the 'ON' clause, and optionally an alias for the table
$queryBuilder->innerJoin('Path\To\User', "product.user_id = user.id", "user");
$queryBuilder->columns([
"product.*",
"user.*"
]);
$queryBuilder->where("product.id = 5");
// You can use this line to debug what was generated
// $generatedQuery = $queryBuilder->getPhql();
// var_dump($generatedQuery);
// Finish the query building
$query = $queryBuilder->getQuery();
// Execute it and get the results
$result = $query->execute();
// Now use var_dump to see how the result was fetched
var_dump($result);
exit;

How can I get a query result in perl?

I tried this script to obtain some info from DB:
use strict;
use warnings;
use DBI;
my $dbh;
my $query= "SELECT table_name FROM user_tables";
my $queryH;
my #tables_names;
my $i;
my $db_pass2 = "*****";
my $db_user2 = "*****";
print "DB connection...\n\n";
#DB connection
$dbh = DBI->connect('DBI:Oracle:host=***********;sid=*****;port=***', $db_user2, $db_pass2);
$queryH = $dbh->prepare($query);
print " ".$queryH->execute()."\n";
print "\n\n";
$queryH->finish();
$dbh->disconnect();
print "\n\n End!!!\n";
Why $queryH->execute() return me 0E0? How can I get a string as result?
I need to get the table name from the db... How can I get it with this script?
execute only executes the query. To retrieve the results you have to use one of the many retrieval methods documented under Statement Handle Methods. For example:
$queryH->execute;
my ( $table_name ) = $queryH->fetchrow_array;
print "result = $table_name\n";

SELECT issue moving from PG_query to PDO

I have a select statement see below. Using PDO how would I recreate this same Select statement, as I want to grab two values from it and combine them into the $geomstring. I can figure out the combine, but not the first 3 lines.
$sql1 = "SELECT easting_value, northing_value FROM gridreference_tbl WHERE gridref_id='$_POST[gridref_id]'";
$result1 = pg_query($sql1);
$row1 = pg_fetch_array($result1);
$geomstring = $row1['easting_value']. $_POST['grid_eastings']." ".$row1['northing_value'].$_POST['grid_northings'];
*php website for prepared statements says *
$stmt = $dbh->prepare("SELECT * FROM REGISTRY where name = ?");
if ($stmt->execute(array($_GET['name']))) {
while ($row = $stmt->fetch()) {
print_r($row);
}
}
I have something similar working for populating a dropdown that partly uses this
$stmt = $conn->prepare("SELECT easting_value, northing_value FROM gridreference_tbl WHERE gridref_id=$gridref_id");
$stmt->setFetchMode(PDO::FETCH_OBJ);
Found it on php.net, I was googling the wrong stuff:
$stmt4 = $conn->prepare("SELECT easting_value, northing_value from gridreference_tbl WHERE gridref_id = 4");
$stmt4->execute();
print("PDO::FETCH_ASSOC: ");
print("Return next row as an array indexed by column name\n");
$result = $stmt4->fetch(PDO::FETCH_ASSOC);
print_r($result);
print("\n");

How can I avoid the program quitting when Perl's DBI encounters an error preparing a statement?

I'm making a script that goes through a table that contains all the other table names on the database. As it parses each row, it checks to see if the table is empty by
select count(*) cnt from $table_name
Some tables don't exist in the schema anymore and if I do that
select count(*)
directly into the command prompt, it returns the error:
206: The specified table (adm_rpt_rec) is not in the database.
When I run it from inside Perl, it appends this to the beginning:
DBD::Informix::db prepare failed: SQL: -
How can I avoid the program quitting when it tries to prepare this SQL statement?
One option is not to use RaiseError => 1 when constructing $dbh. The other is to wrap the prepare in an eval block.
Just put the calls that may fail in an eval block like this:
for my $table (#tables) {
my $count;
eval {
($count) = $dbi->selectrow_array("select count(*) from $table");
1; #this is here so the block returns true if it succeeds
} or do {
warn $#;
next;
}
print "$table has $count rows\n";
}
Although, in this case, since you are using Informix, you have a much better option: the system catalog tables. Informix keeps metadata like this in a set of system catalog tables. In this case you want systables:
my $sth = $dbh->prepare("select nrows from systables where tabname = ?");
for my $table (#tables) {
$sth->execute($table);
my ($count) = $sth->fetchrow_array;
$sth->finish;
unless (defined $count) {
print "$table does not exist\n";
next;
}
print "$table has $count rows\n";
}
This is faster and safer than count(*) against the table. Full documentation of the system catalog tables can be found in IBM Informix Guide to SQL (warning this is a PDF).
Working code - assuming you have a 'stores' database.
#!/bin/perl -w
use strict;
use DBI;
my $dbh = DBI->connect('dbi:Informix:stores','','',
{RaiseError=>0,PrintError=>1}) or die;
$dbh->do("create temp table tlist(tname varchar(128) not null) with no log");
$dbh->do("insert into tlist values('systables')");
$dbh->do("insert into tlist values('syzygy')");
my $sth = $dbh->prepare("select tname from tlist");
$sth->execute;
while (my($tabname) = $sth->fetchrow_array)
{
my $sql = "select count(*) cnt from $tabname";
my $st2 = $dbh->prepare($sql);
if ($st2)
{
$st2->execute;
if (my($num) = $st2->fetchrow_array)
{
print "$tabname: $num\n";
}
else
{
print "$tabname: error - missing?\n";
}
}
}
$sth->finish;
$dbh->disconnect;
print "Done - finished under control.\n";
Output from running the code above.
systables: 72
DBD::Informix::db prepare failed: SQL: -206: The specified table (syzygy) is not in the database.
ISAM: -111: ISAM error: no record found. at xx.pl line 14.
Done - finished under control.
This printed the error (PrintError=>1), but continued. Change the 1 to 0 and no error appears. The parentheses in the declarations of $tabname and $num are crucial - array context vs scalar context.