perl DBI 占位符更新 stmt 问题

perl DBI placeholder update stmt issue

dbi 占位符已在以下 sql 'update' 查询中使用,以避免 perl 文档推荐的 sql 注入。在测试时,我注意到新查询无法正常工作。我一直在查看堆栈溢出和其他资源以确定是否缺少任何内容。

#1
$sth = $dbh->do("UPDATE $dbstore SET Classes='" . $c_classes . "', zzzz='" . $c_zzzz . "', Timestamp='" . $timestamp . "' WHERE Host='" . $h_host . "'"); #old - working as expected
#$sth = $dbh->do("UPDATE $dbstore SET Classes=? , zzzz=? , Timestamp=? WHERE Host=? ", undef, $c_classes, $c_zzzz, $timestamp, $h_host); #new

#2
$sth = $dbh->do("UPDATE $dbstore SET Classes='" . $c_classes . "', zzzz='" . $c_zzzz . "', Timestamp='" . $timestamp . "' WHERE Host='" . $h_host . "'"); #old - working as expected
#$sth = $dbh->do("UPDATE $dbstore SET Classes=? , zzzz=? , Timestamp=? WHERE Host=?", undef, $c_classes, $c_zzzz, $timestamp, $h_host); #new

#3
$sth = $dbh->do("UPDATE $dbstore SET Warning='" . $st_warning . "' WHERE IDSID='" . $remote_user . "' AND Host='" . $st_host . "'"); #old - working as expected
#$sth = $dbh->do("UPDATE $dbstore SET Warning=? WHERE IDSID=? AND Host=?", undef, $st_warning, $remote_user, $st_host); #new

#4
$sth = $dbh->do("UPDATE $dbstore SET Warning='" . $st_warning . "' WHERE IDSID='" . $remote_user . "' AND Host='" . $st_host . "'"); #old - working as expected
#$sth =  $dbh->do("UPDATE $dbstore SET Warning=? WHERE IDSID=? AND Host=?", undef, $st_warning, $remote_user, $st_host); #new

#5
$sth = $dbh->do("UPDATE $dbxxxx SET Nodes='Submitted (" . $timestamp . " by " . $remote_user . ")', Configuration='" . $st_configuration . "' WHERE Host='" . $st_host . "'"); #old - working as expected
#$sth =  $dbh->do("UPDATE $dbxxxx SET Nodes='Submitted (? by ?)', Configuration=? WHERE Host=?", undef, $timestamp, $remote_user, $st_configuration, $st_host); #new

#6
$sth = $dbh->do("UPDATE $dbxxxx SET Classes='" . $n_classes_update . "' WHERE Host='" . $st_host . "'");  #old - working as expected
#$sth =  $dbh->do("UPDATE $dbxxxx SET Classes=? WHERE Host=?", undef, $n_classes_update, $st_host); #new

根据我的理解和阅读(可能有误),没有必要用 single/double 引号将变量括起来。这是真的吗?

我最怀疑查询编号 5 'Submitted (? by ?)' 部分。会有吗?在这种情况下,单引号内会导致问题吗?如果是,推荐的解决方案是什么?

您偶然发现其他查询有任何问题吗?

谢谢

你明白了,#5 是问题所在。

$dbh->do("UPDATE $dbxxxx SET Nodes='Submitted (? by ?)'", $timestamp, $remote_user)

上面设置了字符串Submitted (? by ?).

占位符用于单个 SQL 值。您构建字符串并将其传入。

您还需要在 table 名称上使用 quote_identifier。这将引用和转义任何标识符、列和 table 名称,以避免 SQL 注入。

my $q_table = $dbh->quote_identifier($dbxxxx);

$dbh->do("UPDATE $q_table SET Nodes=?", {}, "Submitted ($timestamp by $remote_user)");

请注意,您应该收到有关向语句传递过多参数的警告或错误(我可能是错的,我已经有很长时间没有使用 DBI 了),所以您需要调查一下为什么那没有发生。如果可能的话,打开 RaiseError 以便立即将这些 SQL 失败作为错误。

my $dbh = DBI->connect(
  $data_source, $username, $password, { RaiseError = 1 }
);

SQL 设计说明。避免存储格式化数据。它使搜索变得缓慢而复杂,增加 table 大小,并限制您的输出格式。

出来的时候格式化一下。例如...

update some_table set submitted_at=?, remote_user=?

select concat('Submitted (', submitted_at, ' by ', remote_user, ')')
from some_table;