如何打印Perl的DBI填充占位符后执行的SQL查询?

hxzsmxv2  于 2022-11-15  发布在  Perl
关注(0)|答案(8)|浏览(172)

我使用Perl的DBI模块,使用占位符准备一条语句,然后执行查询。
是否可以打印出执行的最终查询,而无需手动转义参数并将其放入占位符中?
谢谢

kxkpmulp

kxkpmulp1#

这适用于禁用服务器端准备的DBD::mysql(缺省设置):

$ DBI_TRACE=2 perl your-script-here

它会将每条语句打印两次,一次在绑定参数之前,一次在绑定参数之后。
还有一个模块DBI::Log,它只打印SQL语句(没有其他调试噪音),以及可选的定时信息和调用者堆栈跟踪。

wgx48brx

wgx48brx2#

如果您不想创建自己的跟踪器模块(如希南所建议的),最好尝试在将参数哈希传递给$sth->execute()之前打印它。这一点尤其正确,因为“Trace”功能依赖于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});
}

我使用文本的地方::CSV...注意:由于DBMS实现依赖于对{'}的处理,因此这并不精确。

gojuced7

gojuced73#

正如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::Log 4perl时,如果你愿意,你可以省略“DEBUG -“。这里有一个使用DBIx::Log 4perl的小教程。
您应该能够将DBIx::Log 4perl与任何DBD一起使用,如果您由于某种原因不能RT它,我将查看它。
如果您不想使用DBIx::Log 4perl,并且DBI跟踪选项不符合您的需要,则可以为DBI的prepare/select*/execute方法编写回调,并在其中收集您喜欢的任何内容。

v6ylcynt

v6ylcynt4#

对于大多数查询,最简单的调试是使用以下代码...

  • 如果使用do方法准备并执行单个语句,请用途:
use feature 'say';
 say $dbh->{Statement};
  • 如果您分别使用prepareexecute方法,请用途:
use feature 'say';
 use Data::Dumper;
 $Data::Dumper::Sortkeys = 1;
 say $sth->{Statement};
 say Dumper($sth->{ParamValues});
u5rb5r59

u5rb5r595#

对于perl新手,我的解决方案是从not 2 qubit复制过来的,并进行了简化/希望变得更通用/更可重用:

sub dump_query {
  my $tquery = shift;
  my @args = shift;
  my $j;
    foreach my $j (@args) { $tquery =~ s/\?/\'$j\'/; }
    print STDERR "$tquery\n\n";
}
gwo2fgha

gwo2fgha6#

请参阅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
等等等等。
您可以将自己的筛选器插入跟踪流,以便只保留prepare

nhjlsmyf

nhjlsmyf7#

您可以使用Statement属性对预处理语句进行调试打印。这可以通过“语句句柄”或“数据库句柄”来访问。

print $sth->{Statement} # with a statement handle

print $dbh->{Statement} # with a database handle
fhity93d

fhity93d8#

一般情况下不会,因为DBI不一定会生成这样的查询。如果您的数据库在其API中支持预处理语句和占位符,则DBI会将它们传递给数据库,让数据库执行这些工作,这也是使用预处理语句的原因之一。

相关问题