【问题标题】:Possible to use named placeholders in DBI's selectcol_arrayref & Co.?可以在 DBI 的 selectcol_arrayref & Co. 中使用命名占位符吗?
【发布时间】:2012-01-27 11:50:51
【问题描述】:

是否可以在 DBI 允许 @bind_values 的情况下使用命名占位符?例如,我想发表如下声明:

my $s = $DB->selectcol_arrayref ("SELECT a FROM b
                                  WHERE c = ? OR d = ? OR e = ?;",
                                  {},
                                  $par1, $par2, $par1) or
        die ($DB->errstr ());

不容易出错。我正在使用 DBD::Pg 和 DBD::SQLite。

【问题讨论】:

  • 占位符支持(以及支持的占位符类型)取决于驱动程序,因此我添加了更多标签。
  • 有什么理由认为你不能? DBI 说$ary_ref = $dbh->selectcol_arrayref($statement, \%attr, @bind_values)。请注意,您可以将 undef 传递给第二个参数,而不是创建一个空哈希。
  • @ikegami:也许您可以解释如何在任何 DBI 方法的 @bind_values 参数中使用 named 占位符。如果您使用的是prepare/bind_param/execute,这很容易,但如果没有大量明确的bind_param 调用,我从来没有想过如何做到这一点。

标签: perl sqlite postgresql dbi


【解决方案1】:

支持哪些类型的占位符(如果有)depends on the driver

占位符和绑定值

一些驱动程序支持占位符和绑定值。
[...]
一些驱动程序还允许使用诸如 :name:N 之类的占位符(例如,:1:2 等on) 除了?,但它们的使用是不可移植的。

但你很幸运,PostgreSQL driver 支持命名或编号参数:

可以在 DBD::Pg 中使用三种类型的占位符。第一种是“问号”类型,其中每个占位符由一个问号字符表示。
[...]
第二种占位符的方法是“美元符号数字”。
[...]
最后的占位符类型是“命名参数”,格式为“:foo”。

SQLite driver 也支持它们:

SQLite 支持多种占位符表达式,包括 ?和:AAAA。

缺点是您最终会在命名参数中大量使用bind_param,因此您将无法使用selectcol_arrayref$sth->execute(1,2,3) 之类的便利(注意:如果有人知道如何将命名占位符与execute 一起使用,我会很感激评论中的一些指示,我从来不知道该怎么做)。但是,您可以使用各种形式的数字占位符(例如 select c from t where x = $1 用于 PostgreSQL 或 select c from t where x = ?1 用于 SQLite)。

还要注意,PostgreSQL 对数组切片使用冒号,对某些运算符使用问号,因此有时标准的 ? 占位符和 :name 命名占位符可能会导致问题。 ? 我从来没有遇到过任何问题,但我也从未使用过geometric operators;我怀疑对空格的合理使用可以避免 ? 的任何问题。如果您不使用 PostgreSQL 数组,那么您可能不必担心 array slices 与您的 :name 命名占位符发生冲突。


执行摘要:您不能将命名占位符用于selectcol_arrayref 或与@bind_params 一起使用的类似方法。但是,对于 SQLite 和 Postgresql,您可以将编号占位符($1$2、... 用于 Postgresql 或 ?1?2、...用于 SQLite)与适用于 @bind_params 的方法一起使用或者你可以使用命名占位符(:name 用于 PostgreSQL 和 SQLite)如果你喜欢使用更长的 prepare/bind_param/execute/fetch 方法序列,你必须小心如果您在查询中使用 PostgreSQL 数组。

【讨论】:

  • 谢谢。在selectcol_arrayref 中使用 "$1" & Co. 并不是万无一失的,所以我可能会在我认为有必要的地方使用 prepare/bind_param/execute/fetch。跨度>
  • @Tim:你总是可以编写自己的实用函数,它接受一个 SQL 字符串和一个哈希引用,然后它可以prepare/bind_param/execute/fetch 并返回总结的结果。这样的事情将是一个合理的妥协。
  • 是的,但这只是我必须“开发”和维护的另一个齿轮。总的来说,我尽可能地坚持其他人的大脑产品,他们通常对可能遇到的任何极端情况的思考比我想象的要多:-)。
猜你喜欢
  • 1970-01-01
  • 2017-05-20
  • 2015-08-07
  • 1970-01-01
  • 1970-01-01
  • 2015-10-03
  • 1970-01-01
  • 1970-01-01
  • 2014-03-14
相关资源
最近更新 更多