我正在使用Perl的DBI模块。我使用占位符准备一个语句,然后执行查询。
是否可以打印出执行的最终查询而无需手动转义参数并将其放入占位符?
由于
答案 0 :(得分:16)
见Tracing in DBI。以下工作使用DBD::SQLite
但产生大量输出:
$dbh->trace($dbh->parse_trace_flags('SQL|1|test'));
输出:
<- prepare('SELECT ... FROM ... WHERE ... = ?')= DBI::st=HASH(0x21ee924) at booklet-excel.pl line 213
<- execute('Inhaler')= '0E0' at booklet-excel.pl line 215
等等。
您plug your own filter in to the trace stream只能保留prepare
。
答案 1 :(得分:10)
一般情况下,因为DBI不一定会产生这样的查询。如果您的数据库在其API中支持预准备语句和占位符,则DBI将传递它们并让数据库完成工作,这是使用预准备语句的原因之一。
答案 2 :(得分:9)
您可以使用Statement属性对预准备语句进行调试打印。可以使用“语句句柄”或“数据库句柄”访问它。
print $sth->{Statement} # with a statement handle
print $dbh->{Statement} # with a database handle
答案 3 :(得分:1)
正如masto所说,SQL中的占位符不会直接替换为您的参数。参数化SQL的重点是将带有占位符的SQL传递给数据库引擎进行一次解析,然后只接收参数。
正如idssl所说,您可以从语句或连接句柄中获取SQL,也可以从ParamValues检索参数。如果您不想自己这样做,可以使用DBIx::Log4perl之类的东西来记录SQL和参数。请参阅DBIX_L4P_LOG_DELAYBINDPARAM,它输出如下内容:
DEBUG - prepare(0.1): 'insert into mje values(?,?)'
DEBUG - $execute(0.1) = [{':p1' => 1,':p2' => 'fred'},undef];
当然,因为它使用Log :: Log4perl,你可以省略“DEBUG - ”。有一个使用DBIx :: Log4perl here的小教程。
你应该能够将DBIx :: Log4perl与任何DBD一起使用,如果由于某些原因你不能RT它,我会看看它。
如果您不想使用DBIx :: Log4perl并且DBI跟踪选项不适合您的需求,您可以为DBI的prepare / select * / execute方法编写回调,并收集您喜欢的任何内容。
答案 4 :(得分:1)
这适用于DBD::mysql
,禁用服务器端准备(默认值):
$ DBI_TRACE=2 perl your-script-here
它将打印每个语句两次,一次在绑定参数之前,一次之后。后者将是格式良好的SQL,您可以自己运行。
答案 5 :(得分:0)
如果您不想创建自己的跟踪器模块(如Sinan所建议的那样),最好只是在将参数哈希传递给$sth->execute()
之前尝试打印它。这尤其如此,因为“跟踪”功能依赖于DBMS,$sth->{Statement}
仅返回SQL占位符语句。这就是我所做的。
...
while (my $row = $csv->getline_hr($fh)) {
my $cval = "";
my $tquery = $query;
foreach my $j (@cols) {
$cval = $row->{$j};
$tquery =~ s/\?/\'$cval\'/;
}
print "$tquery\n\n";
$rc = $sth->execute(@{$row}{@cols});
}
我使用过Text :: CSV ... 注意:由于DBMS实现依赖于{'}的处理,这不完全正确。
答案 6 :(得分:0)
对于大多数查询,最简单的调试是使用以下命令...
如果使用do
方法准备并执行一条语句,请使用:
use feature 'say';
say $dbh->{Statement};
如果分别使用prepare
和execute
方法,请使用:
use feature 'say';
use Data::Dumper;
say $sth->{Statement};
say Dumper($sth->{ParamValues});
答案 7 :(得分:0)
对于perl初生植物,我的解决方案是从not2qubit复制并简化/希望使其更加通用/可重用:
sub dump_query {
my $tquery = shift;
my @args = shift;
my $j;
foreach my $j (@args) { $tquery =~ s/\?/\'$j\'/; }
print STDERR "$tquery\n\n";
}