I'm not crazy about positional parameters in DBI, but I don't want to use a heavy-duty module like Tangram or Alzabo* to get away from them.
What I decided was to use simple SQL templates with placeholders like $foo
instead of ?
, then write a simple module to expand the template given a hash of placeholder names and values.
my $str = 'SELECT id FROM People' . 'WHERE age >= $min AND age <= $max'; my $template = SQL::Template->new($str); my ($sql, @args) = $template->process( 'min' => 20, 'max' => 29 ); # $sql = 'SELECT id FROM People' # . 'WHERE age >= ? AND age <= ?' # @args = (20, 29) $dbh->prepare_cached($sql, @args);
my $str = 'SELECT id FROM People' . 'WHERE { name ILIKE $name }:AND'; my $template = SQL::Template->new($str); my ($sql, @args) = $template->process( 'name' => 'tolk% %chris%' ); # $sql = 'SELECT id FROM People' # . 'WHERE name ILIKE ? AND name ILIKE ?' # @args = ('tolk%', '%chris%') $dbh->prepare_cached($sql, @args);
SQL::Template
is the most obvious choice, but to me that sounds like a big, fancy module whereas mine is very simple (and likely to remain that way).You might want to have a look at Tim Bunce's Advanced DBI talk
-Dom
Re:Positional Parameters are a good idea
nkuitse on 2003-08-08T12:45:06
Not using them means that you have to recreate the query execution plan each time.
Actually, my code generates SQL with positional parameters. It takes a pseudo-SQL template like this:And turns it into this:SELECT foo
FROM bar
WHERE baz = $baz
AND qux = $quxSimultaneously taking the name-based parameters that you provide (in a hash, i.e., unordered) and lining their values up in the correct order in a params array:SELECT foo
FROM bar
WHERE baz = ?
AND qux = ?The result is:$tmpl = SQL::Template->new($template_string);
($sql, @params) = $tmpl->process(
'qux' => 'quaint',
'baz' => 'baboon'
);Which you can then use normally:$sql =...as above...
@params = ('baboon', 'quaint')Oh, and thanks for the tip on Tim Bunce's slides!$sth = $dbh->prepare[_cached]($sql);
$sth->execute(@params);
Re:need testers?
nkuitse on 2003-08-20T14:47:28
I'd be happy to help test this with MySQL if you'd like.
Sure, thanks. (Though it doesn't really matter which RDBMS is used, since SQL::Template simply spits out SQL and a correctly ordered list of values.)
You can download version 0.01 here (ca. 3KB) for now. Do the usual to install:It sounds a lot like it would be useful for me with an upcoming project I'm working on.perl Makefile.PL
make
make test
[sudo] make install
Glad to hear it!