【问题标题】:Perl DBI placeholders other than ?s?s 以外的 Perl DBI 占位符
【发布时间】:2015-08-07 13:50:09
【问题描述】:

我正在尝试为插入 SQL 编写准备语句,它有很多行要一次插入。所以当前的准备语句如下所示,

my $sth = $dbh->prepare("INSERT INTO queues_details (id,keyword,data,flags) VALUES 
                             (?,'penaltymemberslimit','0','0'),
                             (?,'answered_elsewhere','0','0'),
                             (?,'timeoutpriority','app','0'),
                             (?,'timeoutrestart','no','0'),
                             (?,'memberdelay','0','0'),
                             (?,'servicelevel','60','0'),
                             (?,'reportholdtime','no','0'),
                             (?,'ringinuse','yes','0'),
                             (?,'weight','0','0'),
                             (?,'autofill','no','0'),
                             (?,'eventmemberstatus','no','0'),
                             (?,'eventwhencalled','no','0'),
                             (?,'monitor-join','yes','0'),
                             (?,'monitor-format','','0'),
                             (?,'periodic-announce-frequency','0','0'),
                             (?,'queue-thankyou','queue-thankyou','0'),
                             (?,'queue-callswaiting','queue-callswaiting','0'),
                             (?,'queue-thereare','queue-thereare','0'),
                             (?,'maxlen','0','0'),
                             (?,'joinempty','yes','0'),
                             (?,'leavewhenempty','no','0'),
                             (?,'strategy','ringall','0'),
                             (?,'timeout','15','0'),
                             (?,'retry','5','0'),
                             (?,'wrapuptime','0','0'),
                             (?,'announce-frequency','60','0'),
                             (?,'announce-holdtime','no','0'),
                             (?,'announce-position','yes','0'),
                             (?,'queue-youarenext','queue-youarenext','0');");

请注意,所有 ? 值都将是相同的 id。

这维护起来很复杂,并且很难在 prepare 和 execute 中添加/删除行。 这些占位符 (?s) 是否有任何编号方法,以便我可以轻松找到需要更改的行。

谢谢!

【问题讨论】:

  • 即使没有占位符,INSERT 也会非常笨拙。您是否真的在脚本中使用不同的 ID 值集多次执行此查询?
  • 目前一次只有一个 ID 值。

标签: sql perl placeholder dbi


【解决方案1】:

仅使用占位符

my $sql = "INSERT INTO queues_detail (id,keyword,data,flags) VALUES ";
$sql .= join ', ', ("(?,?,?,?)") x @data;

$dbh->do($sql, $undef, map { $id, @$_ } @data);

或者根本不使用任何东西

my $sql = "INSERT INTO queues_detail (id,keyword,data,flags) VALUES ";
$sql .= join(', ', map { "(" . join(', ', map $dbh->quote($_), $id, @$_) . ")" } @data);

$dbh->do($sql);

以上使用如下:

my @data = (
   [ 'penaltymemberslimit',         '0',                  0 ],
   [ 'answered_elsewhere',          '0',                  0 ],
   [ 'timeoutpriority',             'app',                0 ],
   [ 'timeoutrestart',              'no',                 0 ],
   [ 'memberdelay',                 '0',                  0 ],
   [ 'servicelevel',                '60',                 0 ],
   [ 'reportholdtime',              'no',                 0 ],
   [ 'ringinuse',                   'yes',                0 ],
   [ 'weight',                      '0',                  0 ],
   [ 'autofill',                    'no',                 0 ],
   [ 'eventmemberstatus',           'no',                 0 ],
   [ 'eventwhencalled',             'no',                 0 ],
   [ 'monitor-join',                'yes',                0 ],
   [ 'monitor-format',              '',                   0 ],
   [ 'periodic-announce-frequency', '0',                  0 ],
   [ 'queue-thankyou',              'queue-thankyou',     0 ],
   [ 'queue-callswaiting',          'queue-callswaiting', 0 ],
   [ 'queue-thereare',              'queue-thereare',     0 ],
   [ 'maxlen',                      '0',                  0 ],
   [ 'joinempty',                   'yes',                0 ],
   [ 'leavewhenempty',              'no',                 0 ],
   [ 'strategy',                    'ringall',            0 ],
   [ 'timeout',                     '15',                 0 ],
   [ 'retry',                       '5',                  0 ],
   [ 'wrapuptime',                  '0',                  0 ],
   [ 'announce-frequency',          '60',                 0 ],
   [ 'announce-holdtime',           'no',                 0 ],
   [ 'announce-position',           'yes',                0 ],
   [ 'queue-youarenext',            'queue-youarenext',   0 ],
);

【讨论】:

  • 很好的解决方案,谢谢!实际上一次会有一个id,忘了在问题中提及。我也为此阅读了 bind_ 参数。
  • 这可以简化解决方案,尽管只是一点点。更新了答案。
【解决方案2】:

这取决于数据库驱动程序。其中一些支持其他占位符格式,但大多数不支持。您可以查看自己的文档(例如 DBD::Pg、DBD::mysql)并查看可用的文档。

您更好的选择是:

1:编写代码以生成 SQL。你最好使用 all 占位符;那么你可以从一个类似的结构开始

my @data = (
    [ $foo, 'penaltymemberslimit', 0, 0],
    [ $bar, 'answered_elsewhere', 0, 0],
    # ... a bunch more rows
);

然后用类似的东西跟进它:

my $sql = "INSERT INTO queues_details (id,keyword,data,flags) VALUES";
my @binds;
for my $row (@data) {
    $sql .= " (?,?,?,?)";
    push @binds, @$row;
}

my $sth = $dbh->prepare($sql);
$dbh->execute(@binds);

2:使用DBIx::Class。如果您为queues_details 表创建一个带有类的模式,那么您只需创建一个大的散列数组,其中列名作为键,值作为值,并将其传递给populate,DBIC 将为你。它甚至可以使用更有效的方式插入批量数据,例如使用特殊的 API 或延迟约束。您还可以选择创建对象并在其上调用create。

【讨论】:

  • 您构建的 SQL 语句缺少很多逗号。
猜你喜欢
  • 2015-06-22
  • 1970-01-01
  • 2010-12-24
  • 1970-01-01
  • 2017-05-20
  • 2012-12-22
  • 1970-01-01
  • 1970-01-01
  • 2010-12-13
相关资源
最近更新 更多