Using sql server 2008 I am getting and invalid precision value error in the following perl script:
use DBI;
$idx = '12345';
$query = 'if exists (select * from tbl where idx = ?) select top 10 * from tbl';
my $h = $dbh->prepare($query) or die "Couldn't prepare query: " . $dbh->errstr;
$h->execute($idx) or die "Couldn't execute statement: " . $h->errstr;
Note however that if I try this instead
use DBI;
$query = 'if exists (select * from tbl where idx = \'12345\') select top 10 * from tbl';
my $h = $dbh->prepare($query) or die "Couldn't prepare query: " . $dbh->errstr;
$h->execute() or die "Couldn't execute statement: " . $h->errstr;
then it works. I am really confused at how the ? in the query could possibly be causing an invalid precision error.
Thanks for any help anyone can provide.
Based on this article, please try the following:
You need to import the SQL type constants from DBI
and specify that SQL_LONGVARCHAR as the type of the data to be added to the memo field.
To do that you do:
$dbh->bind_param(1, $idx, SQL_LONGVARCHAR);
Binding with a specific type overrides what DBD::ODBC decides. DBD::ODBC will bind the parameter based on what comes back from SQLDescribeParam. Sometimes SQL Server's SQLDescribeParam fails, especially in cases where you are using functions or subselects. The SQL Server ODBC driver takes your SQL and rearranges it to attempt to end up with something like "select idx from tbl" then it looks at the columns to answer SQLDescribeParam calls. I'm betting the SQL Server ODBC driver fails to rearrange your SQL in this case and either SQLDescribeParam failed or returned the wrong information. If you enable tracing in DBD::ODBC we could probably see this happening.
Related
I'm using PHP7 (with Droctrine 2.5.13) on Ubuntu 16.04 x64.
I'm trying to do a prepared statment to a Microsoft SQL database using a named variable like so:
$sql = 'SELECT DISTINCT
"PRODUCT"."NUMBER"
FROM
"PRODDB"."PRODUCT"
WHERE
"PRODUCT"."NUMBER" LIKE :productNumber
ORDER BY
"PRODUCT"."NUMBER" DESC';
$query = $this->db->prepare($sql);
$query ->bindParam(':productNumber' , $ofSearch);
$status = $query->execute();
$result = $query->fetchAll();
But SQL tell me that I need to use question mask instead of the named parameter
Error : sqlsrv does not support named parameters to queries, use question mark (?)
If I replace the named variable by a question mark it work fine.
The example below work fine:
$sql = 'SELECT DISTINCT
"PRODUCT"."NUMBER"
FROM
"PRODDB"."PRODUCT"
WHERE
"PRODUCT"."NUMBER" LIKE ?
ORDER BY
"PRODUCT"."NUMBER" DESC';
$query = $this->db->prepare($sql);
$query ->bindParam(1 , $ofSearch);
$status = $query->execute();
$result = $query->fetchAll();
Using question mark is a terrible way to do prepared statement as when you have very complex query with over 20 parameters it become a nightmare to maintain.
Do you have any idea if there is a solution to this problem or at least a workaround?
I'm trying to use groovy.sql.Sql to create databases in an MSSQL (Microsoft SQL Server) server. It seem like the prepared statement adds additional quotes around the last parameter breaking the query.
This test code:
import groovy.sql.Sql
import com.microsoft.sqlserver.jdbc.SQLServerDataSource
def host = 'myhost'
def port = '1433'
def database = 'mydatabasename'
def usernameName = 'myusername'
def password = 'mypassword'
def dataSource = new SQLServerDataSource()
dataSource.setURL("jdbc:sqlserver://$host:$port")
dataSource.setUser(username)
dataSource.setPassword(password)
def connection new Sql(dataSource)
connection.execute(
'IF EXISTS (SELECT * FROM master.dbo.sysdatabases WHERE name = ?) DROP DATABASE ?',
[ databaseName, databaseName ]
)
Gives the error:
Failed to execute: IF EXISTS (SELECT * FROM master.dbo.sysdatabases WHERE name = ?) DROP DATABASE ? because: Incorrect syntax near '#P1'.
How can I use prepared statements without having it add single quotes around parameter one (DROP DATABASE ? seem to be rewritten as DROP DATABASE '?') or can I write the query in a different way so that the added single quotes does not produce a syntax error?
I would also be fine with other frameworks, if anyone could give me a working example.
Can you try:
connection.execute(
"IF EXISTS (SELECT * FROM master.dbo.sysdatabases WHERE name = $databaseName) DROP DATABASE ${Sql.expand(databseName)}"
)
I have attempted to transfer one txt file into a SQL Server from Perl, but I now need to create a DB in SQL that combines hundreds of txt files. Is there an automated way of doing this to save manually transferring all the txt files? I will insert my attempt of coding one txt file. I believe I need to use Bulk Insert to achieve this but I am unsure what code to use. Any advice on the problem would be really appreciated, and if there is anymore code you wish to see or a specific thing I forgot to mention then please comment and I will edit. Thank you.
#!/usr/bin/perl -w
use strict;
use DBI;
use Carp;
# Connect to the data source and get a handle for that connection.
my $dbh = DBI->connect('dbi:ODBC:RegressionDBS') ||
confess "Connection Failed: $DBI::errstr";
# This query generates a result set with one record in it.
my $sql = "SELECT 1 AS test_col";
my $tablename = "RegressionTable";
open(FH, "newregression.txt") || die "cant open file";
my $Sqlh = $dbh->prepare("INSERT INTO RegressionTable (Ticker, TradeDate, HighPrice, LowPrice, TradePrice, TotalVolume, TotalValue) VALUES (?,?,?,?,?,?,?);") || confess $DBI::errstr;
while (my $line = <FH> )
{
$line =~/^(.*)(..)(..)$/;
my ($curTicker, $wTradeDate, $wHighPrice, $wLowPrice, $wTradePrice, $wTotalVolume, $wTotalValue);
$curTicker=$1
#$wTradeDate=
$wHighPrice=$2;
$wLowPrice=$1;
#$wTradePrice=$1;
#$wTotalVolume=$1;
#$wTotalValue=$4;
$Sqlh->execute($curTicker, $wTradeDate, $wHighPrice, $wLowPrice, $wTradePrice, $wTotalVolume, $wTotalValue) || confess $DBI::errstr;
}
$Sqlh->finish();
$dbh->disconnect();
Ok, so you run
INSERT INTO RegressionTable (
Ticker, TradeDate, HighPrice, LowPrice, TradePrice, TotalVolume, TotalValue
)
VALUES (?, ?, ?, ?, ?, ?, ?)
for every line in newregression.txt, and now you want to do it for multiple files. Why not wrap your code above in a subroutine, say insert_file(), then call it per file in a loop...
my #files = qw(red.txt green.txt blue.txt);
for my $file (#files) {
insert_file($file);
}
Or if the target table varies per file, define a hash:
my %files = (
'red.txt' => 'RedTable',
'blue.txt' => 'BlueTable'
);
while ( my ($file, $table) = each %files ) {
insert_file($file, $table);
};
Not sure how you'd use Bulk Insert given the field separator in your data file seems to be indeterminate (i.e. the regex /(.*)(..)(..)/ defines field boundaries). You may need to use the FORMATFILE option. Also, if you generate a BULK INSERT statement using DBI, be aware that the user your SQL Server runs as must be able to read your data files over the filesystem (networked, local or otherwise).
I am facing this problem perl DBD::ODBC rollback ineffective with AutoCommit enabled at and while looking at the problem , I found that a very basic thing is failing with Perl::DBI using DBD::ODBC on sql server. But i am not sure if this wont happen with any other driver.
The problem is that when I create a #temp table using $dbh->do and when i try to access the same #temp table using another $dbh->do , i am getting the below error. Also this does not happen all the time , but only intermittently.
Invalid object name '#temp'
$dbh->do("SELECT ... INTO #temp FROM ...");
$dbh->do("INSERT INTO ... SELECT ... FROM #temp");
The second do fails with 'Invalid object name '#temp''
Kindly help me with the problem.
Not that it answers your question but it might help. The following works for me.
#
# To access temporary tables in MS SQL Server they need to be created via
# SQLExecDirect
#
use strict;
use warnings;
use DBI;
my $h = DBI->connect();
eval {
$h->do(q{drop table martin});
$h->do(q{drop table martin2});
};
$h->do(q{create table martin (a int)});
$h->do(q{create table martin2 (a int)});
$h->do('insert into martin values(1)');
my $s;
# this long winded way works:
#$s = $h->prepare('select * into #tmp from martin',
# { odbc_exec_direct => 1}
#);
#$s->execute;
# and this works too:
$h->do('select * into #tmp from martin');
# but a prepare without odbc_exec_direct would not work
print "NUM_OF_FIELDS: " . DBI::neat($s->{NUM_OF_FIELDS}), "\n";
$s = $h->selectall_arrayref(q{select * from #tmp});
use Data::Dumper;
print Dumper($s), "\n";
$h->do(q/insert into martin2 select * from #tmp/);
$s = $h->selectall_arrayref(q{select * from martin2});
print Dumper($s), "\n";
I was having this problem as well. I tried all of the above but it didnt matter. I stumbled upon this http://bytes.com/topic/sql-server/answers/80443-creating-temporary-table-select-into which solved my problem.
What's happening is that ADO is opening a second connection behind
your back. This has really not anything to do with how you created the
table.
The reason that ADO opens an extra connection, is because there are
rows waiting to be fetched on the first connection, so ADO cannot
submit a query on that connection.
I assume that Perl DBI is doing the same, so based on this assumption, here's what I did and it worked perfectly fine:
my $sth = $dbh->prepare('Select name into #temp from NameTable');
$sth->execute();
$sth->fetchall_arrayref();
$sth = $dbh->prepare('Select a.name, b.age from #temp a, AgeTable b where a.name = name');
$sth->execute();
my ($name,$age)
$sth->bind_columns(\$name,\$age);
while ( $sth->fetch())
{
# processing
}
I know there is a similar question: Connect to SQL Server 2005 from Perl and do a SELECT , but I tried the accepted answer and am unable to get it to work.
Assuming I have a db named test, and would love to do a select from mytable
(select id, name from mytable)
Code is from the link above with updated dsn:
use strict;
use warnings;
use DBI;
# Insert your DSN's name here.
my $dsn = 'database=test'
# Change username and password to something more meaningful
my $dbh = DBI->connect("DBI::ODBC::$dsn", 'username', 'password')
# Prepare your sql statement (perldoc DBI for much more info).
my $sth = $dbh->prepare('select id, name from mytable');
# Execute the statement.
if ($sth->execute)
{
# This will keep returning until you run out of rows.
while (my $row = $sth->fetchrow_hashref)
{
print "ID = $row->{id}, Name = $row->{name}\n";
}
}
# Done. Close the connection.
$dbh->disconnect;
This is what I got when running the script:
Can't connect to data source 'ODBC::database=test' because I can't work out what
driver to use (it doesn't seem to contain a 'dbi:driver:' prefix and the DBI_DR
IVER env var is not set) at script.pl line 9
Looks like the problem is in the dsn but I have no idea how to fix it (I am on sql 2005, active perl 5.10 and windows xp).
Edit:
I used the following code to verified whether ODBC is installed.
use DBI;
print join (", ", DBI->installed_versions);
Output:
It looks like ODBC is indeed in the list.
ADO, CSV, DBM, ExampleP, File, Gofer, ODBC, SQLite, Sponge, mysql
What am I missing?
I got the same error with SQLite just now, and it looks like you did the same thing wrong as me. Note the number of colons in the first argument - this is the wrong format:
my $db = DBI->connect('DBI::SQLite::dbname=testing.db', '', '', {RaiseError => 1, AutoCommit => 1});
There should actually only be two colons, not two pairs of colons in the first argument:
my $db = DBI->connect('DBI:SQLite:dbname=testing.db', '', '', {RaiseError => 1, AutoCommit => 1});
Question answered despite its age because it's still top of the results in Google for this particular error message
Try setting your DSN to something like:
my $dbh = DBI->connect("dbi:ODBC:test", 'username', 'password')
If that doesn't work, ensure you have DBD::ODBC installed by running:
perl -MDBI -e 'DBI->installed_versions;'
Assume SQL server is located on local server, connection below can be right:
my $DSN = "driver={SQL Server};Server=127.0.0.1;Database=test;UID=sa;PWD=123456";
my $dbh = DBI->connect("dbi:ODBC:$DSN");