How can I use a query with placeholder inside quotes? (perl / postgresql)
Asked Answered
M

3

5

I'm trying to execute the following script:

#!/usr/bin/perl -w

use strict;
use DBI;

my $db = "Pg";
my $db_database = "whatever";
my $user = "whatever";
my $password = "whatever";

my $dbh = DBI->connect("dbi:$db:dbname=$db_database", $user, $password);

my $query = $dbh->prepare (q{SELECT
                   arrival_date - INTERVAL '? MINUTE'
                   FROM emails LIMIT 1})
  or die ("unable to prepare");
$query->execute(60) or die("unable to execute");

print $query->fetchrow_array, "\n";

(arrival_date has this format: timestamp with time zone NOT NULL default CURRENT_TIMESTAMP)

The problem is that the question mark placeholder is not detected because its inside single quotes:

DBD::Pg::st execute failed: called with 1 bind variables when 0 are needed 

It does not help if I use qq{}, $1 placeholder, and tried a few variations with $dbh->quote. How can I make this work?

Monia answered 18/5, 2012 at 21:4 Comment(0)
M
10

You can't use placeholders inside quotes. You can use SQL string concatenation, but in this case, it's easier to do it by using multiplication:

my $query = $dbh->prepare (q{SELECT
                   arrival_date - ? * INTERVAL '1 MINUTE'
                   FROM emails LIMIT 1});
$query->execute(60);

That way, you don't have to append ' minutes' to the number when you execute the query.

Mettle answered 18/5, 2012 at 21:33 Comment(0)
M
3

I just found a solution here: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=321917

It works using ?::interval instead of 'interval ?':

my $query = $dbh->prepare (q{SELECT
                   arrival_date - ?::interval
                   FROM emails LIMIT 1});

$query->execute('60 MINUTE');
Monia answered 18/5, 2012 at 21:29 Comment(0)
C
2
my $query = $dbh->prepare (<<SQL) or die ("unable to prepare");
SELECT arrival_date - INTERVAL ? FROM emails LIMIT 1
SQL
$query->execute("60 MINUTE");

or

my $query = $dbh->prepare (<<SQL) or die ("unable to prepare");
SELECT arrival_date - INTERVAL CONCAT(?, " MINUTE") FROM emails LIMIT 1
SQL
$query->execute(60);

Chittagong answered 18/5, 2012 at 21:14 Comment(1)
DBD::Pg::st execute failed: ERROR: syntax error at or near "$1", and at or near "(" in the second versionMonia

© 2022 - 2024 — McMap. All rights reserved.