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;
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;