'DBD::SQLite Placeholder for integer value in HAVING clause
Since similar statements using DBD::mysql seem to work fine, where is my mistake in using a placeholder for an integer in a HAVING clause, when using DBD::SQLite as DBI driver?
#!/usr/bin/perl
use 5.012;
use warnings;
use DBI;
my $dbh = DBI->connect("dbi:SQLite:dbname=/tmp/test.sqlite","","", {
RaiseError => 1,
sqlite_allow_multiple_statements => 1,
});
$dbh->do( <<'EOT' );
CREATE TABLE cd (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT
);
CREATE TABLE artist (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT,
cd INTEGER,
FOREIGN KEY (cd) REFERENCES cd (id)
);
INSERT INTO cd (title) VALUES ('foo');
INSERT INTO cd (title) VALUES ('bar');
INSERT INTO artist (name, cd) VALUES ('max fob', 1);
INSERT INTO artist (name, cd) VALUES ('max baz', 1);
EOT
my $sth1 = $dbh->prepare(<<'EOT');
SELECT cd.title
FROM cd
LEFT JOIN artist ON artist.cd = cd.id
WHERE artist.name LIKE ?
GROUP BY cd.title
HAVING count( artist.cd ) = 2
EOT
my $sth2 = $dbh->prepare(<<'EOT');
SELECT cd.title
FROM cd
LEFT JOIN artist ON artist.cd = cd.id
WHERE artist.name LIKE ?
GROUP BY cd.title
HAVING count( artist.cd ) = ?
EOT
$sth1->execute('max%');
# says 'hit'
say 'sth1: hit' if $sth1->fetch;
$sth2->execute('max%', 2);
# stays silent
say 'sth2: hit' if $sth2->fetch;
Thank you, DDL.
Solution 1:[1]
I don't know why the placeholder is treated as a string[1], but you can get the code to work by making SQLite treat the value as an integer. Both of the following solutions are means of achieving this:
my $sth2 = $dbh->prepare(<<'EOT');
SELECT cd.title
FROM cd
LEFT JOIN artist ON artist.cd = cd.id
WHERE artist.name LIKE ?
GROUP BY cd.title
HAVING count( artist.cd ) = ?
EOT
$sth2->bind_param(1, 'max%');
$sth2->bind_param(2, 2, DBI::SQL_INTEGER);
$sth2->execute();
my $sth2 = $dbh->prepare(<<'EOT');
SELECT cd.title
FROM cd
LEFT JOIN artist ON artist.cd = cd.id
WHERE artist.name LIKE ?
GROUP BY cd.title
HAVING count( artist.cd ) = CAST( ? AS INTEGER )
EOT
$sth2->execute('max%', 2);
- The other answer claims that placeholders are always treated as strings. Not only is this not an explanation, it's not even true. This unbacked claim of theirs is obviously false since
bind_paramcan cause placeholders to be treated as something other than a string.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
