【发布时间】:2012-09-25 18:19:34
【问题描述】:
我正在构建一个动态 SQL 语句,它将通过准备好的 DBI 语句插入一组或多组 VALUES,我的问题是:
由于我有一个动态数量的VALUES 集,并且我需要添加尽可能多的( ?, ?, ?),( ?, ?, ?) 等来扩展语句INSERT INTO `tblname` ( $columnsString ) VALUES,以便使用占位符和绑定值仅提交一个查询 - 是这是首选方法(最有效等,如果可能的话,效率背后的推理将有助于您的回答)还是我应该将其构建为带有 sprintf 和 dbh->quote() 的查询字符串?
(作为一些额外的信息:我现在实际上正在使用 AnyEvent::DBI,它只公开占位符和绑定值,而不是 quote() 方法,所以如果不创建另一个方法,这对我来说不容易完成直接 DBI $dbh 并使用另一个数据库服务器连接只是为了使用 quote() 方法,或者自己不更改 AnyEvent::DBI 模块。)
通常我只会在必要时执行语句,但在这种繁重的工作负载情况下,我会尝试将插入批处理以提高数据库效率。
另外,如果有人可以回答是否有可能(以及如何)使用占位符和绑定值插入一个 sql DEFAULT 值,那就太棒了。通常,如果我需要这样做,我会直接将 DEFAULTs 附加到字符串中,并仅将 sprintf 和 $dbh->quote() 用于非 DEFAULT 值。
更新:
在快速聊天中解决了误解。用户ikegami 建议不要自己构建查询字符串而不使用占位符,而是将 VALUES 和占位符混合在一起,例如:
$queryString .= '(DEFAULT,?,?),(DEFAULT,DEFAULT,DEFAULT)';
我第一次在 SO 上提出这个问题背后的一些原因是因为我有点反对这种混合,因为我认为它会降低代码的可读性,尽管在确信 sql 'DEFAULT' 不能在占位符绑定值,这是我开始实施的方法。
在可能的情况下使用占位符似乎是更被接受的构建查询的方法,如果您想要 SQL DEFAULT,您只需将其包含在与占位符相同的查询构建中。这不适用于NULL 值,因为可以使用占位符和绑定值undef 插入这些值。
更新 2:
我询问性能的原因、使用 quote() 构建自己的查询与使用占位符构建的“接受度”以及为什么我采用涉及使用 SQL INSERT INTO tblname (cols) 的所有列的解决方案是因为我每天大约有 2-4 百万行进入一个糟糕的数据库服务器,我的代码在同样糟糕的服务器上运行。鉴于我需要DEFAULT sql 值的要求,以及这些可怕的性能限制,我现在选择了一个解决方案。
对于偶然发现此问题的未来开发人员 - 看看@emazep 使用 SQL::Abstract 的解决方案,或者如果出于某种原因您需要构建自己的解决方案,您可以考虑使用 @Schwern 的子程序解决方案或可能合并一些@ikegami 对此的回答,因为这些都是关于 DBI 使用和构建动态查询的“当前状况”的很好回答。
【问题讨论】: