SQL 的扩展占位符,例如 WHERE id IN (??)

Extended placeholders for SQL, e.g. WHERE id IN (??)

提问人:mario 提问时间:9/13/2010 最后编辑:mario 更新时间:10/1/2010 访问量:4065

问:

赏金更新:已经从马克那里得到了很好的答案。将 := 改编为 :,如下。但是,除了 DBIx 之外,我仍在寻找类似的方案。我只是对兼容任何东西感兴趣。


我需要关于我在参数化 SQL 语句中为“扩展”占位符选择的语法的建议。因为构建一些结构(IN子句)很困扰我,所以我决定使用一些语法快捷方式,这些快捷方式会自动扩展到普通?占位符。
我喜欢他们。但我想把它打包分发,并问自己它们是否容易理解。

基本上,我的新占位符是 and(枚举参数)和 and and and(对于命名占位符),用例如下:??:?:&:,:|::

-> db("  SELECT * FROM all WHERE id IN (??)  ", [$a, $b, $c, $d, $e])

根据对我的 db() 函数的$args数,扩展为。这个很清楚,它的语法已经有点标准化了。Perls DBIx::Simple 也使用它。所以我很确定这是一个可以接受的想法。???,?,?,?,?,...

-> db("  SELECT :? FROM any WHERE id>0   ",  ["title", "frog", "id"]);
// Note: not actually parameterized attr, needs cleanup regex

承认吧。我只是喜欢笑脸。基本上,此占位符将关联$args扩展为普通列名称。事实上,它抛弃了任何$args值。它实际上对 INSERT 与 ??, 结合使用很有用,有时对 IN 子句也很有用。但在这里我已经想知道这种新语法是否合理,或者不仅仅是一个用词不当,因为它混合了 : 和 ?字符。但不知何故,它似乎与语法方案很好地匹配。:?

-> db("  UPDATE some SET :, WHERE :& AND (:|)   ", $row, $keys, $or);

在这里,助记符扩展为用逗号分隔的对列表。而 the 是由 s 连接的 column=:column 列表。为了平价,我添加了.不过,:& 在 UPDATE 命令之外还有其他用例。
但我的问题不是关于有用性,而是 :, 和 :& 似乎可以记住吗?
:,name=:name,:&AND:|

 -> db("  SELECT * FROM all WHERE name IN (::)  ", $assoc);

经过一段时间后,我还添加了插值,非常喜欢扩展到 .类似的用例,并且具有均匀性是明智的。:::named,:value,:list???,?,?

无论如何,有没有人实施过这样的计划?不同的占位符?或者为了简单起见,您会推荐哪一个?更新:我知道PHP Oracle OCI接口也可以绑定数组参数,但不使用特定的占位符。我正在寻找可比较的占位符语法。

PHP SQL的

评论

0赞 OMG Ponies 9/13/2010
我想你在这方面花了很多心思,但是 、 、 子句和子查询呢?自定义格式呢,例如当您需要按日期分组而不包含时间部分时?需要额外配置的函数,如 COALESCE 或使用 OVER 子句的任何函数(假设支持)怎么办?GROUP BYHAVINGORDER BY
0赞 mario 9/13/2010
@OMG没有,没有花太多心思。我专注于我最常用的用例。而特定的动态 SQL 仍然需要手动工作。尤其是表情。但例如:?可用于 ORDER 和 GROUP BY 子句。对于一些构造,我已经有 {TOKEN} 支持(这本质上是 SQL 串联)。
0赞 mario 9/27/2010
@stereofrog:确实如此。尽管后端目标不同,但我更关心在 SQL 上抛出数组。占位符方法具有可比性。

答:

2赞 Chris Laplante 9/13/2010 #1

非常整洁!我认为占位符很好,只要你很好地记录它们并在分发时提供大量示例。你发明了自己的占位符是可以的;毕竟,总得有人考虑用。?

3赞 Mark Byers 9/13/2010 #2

您可能希望避免用作占位符,因为它已经在例如 MySQL 中具有用法:=

例如,请参阅此答案以了解实际使用情况。

评论

0赞 OMG Ponies 9/13/2010
此外,在 Oracle(可能还有 Postgres,也许是其他)中是 BIND 变量语法。Oracle 还用于值分配。::=
0赞 mario 9/13/2010
好渔获!没怎么考虑存储过程。
4赞 NikiC 9/27/2010 #3

我喜欢你的提案背后的基本思想,但不喜欢占位符的“命名”。我基本上有两个反对意见:

  • 占位符以 或 开头。您应该选择一种形式,以便可以立即识别占位符。我会选择它,因为它与 SQL 发生冲突的可能性较小,并且更常见于表示占位符。:??
  • 占位符很难理解,也很难记住。 在我看来似乎是合理的,但区分,而且相当困难。:&:|??:?:

我更改了我的数据库类以支持更多的占位符并更加智能:DB_intelligent.php(自述文件中关于占位符的部分不适用于此类。它仅适用于普通班级。

DB 类有两种类型的占位符:多功能占位符和关联数组占位符(可以是 或 )。??xx,&|

位符:此占位符根据参数的类型确定插入的类型:

null                => 'NULL'
'string'            => 'string'
array('foo', 'bar') => ('foo','bar')

?x 占位符:数组中的每个元素都转换为结构并用分隔符内爆。分隔符由组件指定:用逗号、by 和 by 分隔。`field`='value'x,&AND|OR

示例代码:

DB::x(
    'UPDATE table SET ?, WHERE value IN ? AND ?&',
    array('foo' => 'bar'),
    array('foo', 'bar'),
    array('hallo' => 'world', 'hi' => 'back')
);

// Results in this query:
// UPDATE table SET `foo`='bar' WHERE value IN ('foo','bar') AND `hallo`='world' AND `hi`='back'

在设计这个版本的 DB 类时,我有一些想法:

可能会出现一个明显的想法:为什么不用于所有类型的数据,甚至是关联数组。仅添加和添加。在关联数组上使用与在当前设计中使用相同。我没有这样做的原因是安全性。您经常希望将 中的数据插入到查询 () 中。但是,由于 HTML 允许数组 () 表单控件,因此也可以提交具有相同名称的关联数组。因此,我的查询合成器会将其识别为字段 => 值列表。尽管这可能不会损害安全性,但它会导致 SQL 错误,这是很糟糕的。??&?|??,<select multiple>IN ?form[array]

评论

0赞 mario 9/27/2010
很有意思。但是,不应使用添加斜杠。它类似于 stereofrog 的,类型说明符不同,并且 u 总是从 php 类型中推断出 sql。我喜欢 DB::x() 接口,看起来很省时。(- 我与 和的混淆是由于 ?enumerated 和 :named 参数占位符的差异。“:?”是两者兼而有之。还有一个笑脸。??*:*
0赞 NikiC 9/27/2010
为什么我不应该使用?那么它不太安全吗?如果是这样,我会改变它。addslashesself::$instance->quote
0赞 mario 9/27/2010
这是一个非常假设的问题,但 ->quote 考虑了 UTF-8,而替代的 ' 编码序列可能会漏掉添加斜杠。取决于字符集和数据库。例如,对于SQLite来说,这并不重要。
0赞 NikiC 9/27/2010
你是完全正确的。此外,某些数据库可能不使用转义,而只使用转义。我会改变这一点。\'''
2赞 ITroubs 10/1/2010 #4

如果你愿意花一些时间学习教义,那么你可以做一些令人惊奇的事情,比如:

$q = Doctrine_Query::create()
    ->select('u.id')
    ->from('User u')
    ->whereIn('u.id', array(1, 3, 4, 5));

echo $q->getSqlQuery();

什么会产生这样的查询:

SELECT 
u.id AS u__id 
FROM user u 
WHERE u.id IN (?, 
?, 
?, 
?)

此示例摘自:doctrine dql documentation

评论

0赞 mario 10/1/2010
谢谢你的建议。然而,教义对我的使用产生了太多的开销。ORM 对于许多用例来说都很好,但基本上相当于“非存储过程”。Doctrine 查询构建器既需要学习 SQL 之上的另一种领域语言,也需要预定义架构 (YAML)。我认为它大大简化了复杂的数据库。对于单数表,这有点矫枉过正。尽管它在某种程度上具有我正在寻找的数组处理。
0赞 ITroubs 10/1/2010
实际上并不需要 YAML。你可以在没有它的情况下完美地生活,并自己编写你的模型类。YAML 只是用于自动创建模型的简单工具。
0赞 ITroubs 10/1/2010
如果你像 implode(',',$array) 这样的数组传递给你的函数会怎样?类似于该数组(“first”,“second”,“third”)的数组将转换为“first,second,third”