我使用Perl的DBI模块,使用占位符准备一条语句,然后执行查询。是否可以打印出执行的最终查询,而无需手动转义参数并将其放入占位符中?谢谢
kxkpmulp1#
这适用于禁用服务器端准备的DBD::mysql(缺省设置):
DBD::mysql
$ DBI_TRACE=2 perl your-script-here
它会将每条语句打印两次,一次在绑定参数之前,一次在绑定参数之后。还有一个模块DBI::Log,它只打印SQL语句(没有其他调试噪音),以及可选的定时信息和调用者堆栈跟踪。
wgx48brx2#
如果您不想创建自己的跟踪器模块(如希南所建议的),最好尝试在将参数哈希传递给$sth->execute()之前打印它。这一点尤其正确,因为“Trace”功能依赖于DBMS,而$sth->{Statement}只返回SQL占位符语句。下面是我所做的。
$sth->execute()
$sth->{Statement}
... 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实现依赖于对{'}的处理,因此这并不精确。
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方法编写回调,并在其中收集您喜欢的任何内容。
v6ylcynt4#
对于大多数查询,最简单的调试是使用以下代码...
do
use feature 'say'; say $dbh->{Statement};
prepare
execute
use feature 'say'; use Data::Dumper; $Data::Dumper::Sortkeys = 1; say $sth->{Statement}; say Dumper($sth->{ParamValues});
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"; }
gwo2fgha6#
请参阅DBI中的追踪。下列程式使用DBD::SQLite运作,但会产生大量输出:
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。
<- prepare('SELECT ... FROM ... WHERE ... = ?')= DBI::st=HASH(0x21ee924) at booklet-excel.pl line 213
<- execute('Inhaler')= '0E0' at booklet-excel.pl line 215
nhjlsmyf7#
您可以使用Statement属性对预处理语句进行调试打印。这可以通过“语句句柄”或“数据库句柄”来访问。
print $sth->{Statement} # with a statement handle print $dbh->{Statement} # with a database handle
fhity93d8#
一般情况下不会,因为DBI不一定会生成这样的查询。如果您的数据库在其API中支持预处理语句和占位符,则DBI会将它们传递给数据库,让数据库执行这些工作,这也是使用预处理语句的原因之一。
8条答案
按热度按时间kxkpmulp1#
这适用于禁用服务器端准备的
DBD::mysql
(缺省设置):它会将每条语句打印两次,一次在绑定参数之前,一次在绑定参数之后。
还有一个模块DBI::Log,它只打印SQL语句(没有其他调试噪音),以及可选的定时信息和调用者堆栈跟踪。
wgx48brx2#
如果您不想创建自己的跟踪器模块(如希南所建议的),最好尝试在将参数哈希传递给
$sth->execute()
之前打印它。这一点尤其正确,因为“Trace”功能依赖于DBMS,而$sth->{Statement}
只返回SQL占位符语句。下面是我所做的。我使用文本的地方::CSV...注意:由于DBMS实现依赖于对{'}的处理,因此这并不精确。
gojuced73#
正如masto所说,一般来说,SQL中的占位符不会直接被参数替换。参数化SQL的要点是,带有占位符的SQL被传递给数据库引擎进行一次解析,然后它只接收参数。
正如idssl所指出的,你可以从语句或连接句柄中获取SQL,也可以从ParamValues中检索参数。如果你不想自己做这些,你可以使用类似DBIx::Log4perl的命令只记录SQL和参数。请参见DBIX_L4P_LOG_DELAYBINDPARAM,它输出类似如下的内容:
当然,当它使用Log::Log 4perl时,如果你愿意,你可以省略“DEBUG -“。这里有一个使用DBIx::Log 4perl的小教程。
您应该能够将DBIx::Log 4perl与任何DBD一起使用,如果您由于某种原因不能RT它,我将查看它。
如果您不想使用DBIx::Log 4perl,并且DBI跟踪选项不符合您的需要,则可以为DBI的prepare/select*/execute方法编写回调,并在其中收集您喜欢的任何内容。
v6ylcynt4#
对于大多数查询,最简单的调试是使用以下代码...
do
方法准备并执行单个语句,请用途:prepare
和execute
方法,请用途:u5rb5r595#
对于perl新手,我的解决方案是从not 2 qubit复制过来的,并进行了简化/希望变得更通用/更可重用:
gwo2fgha6#
请参阅DBI中的追踪。下列程式使用
DBD::SQLite
运作,但会产生大量输出:输出量:
<- prepare('SELECT ... FROM ... WHERE ... = ?')= DBI::st=HASH(0x21ee924) at booklet-excel.pl line 213
<- execute('Inhaler')= '0E0' at booklet-excel.pl line 215
等等等等。
您可以将自己的筛选器插入跟踪流,以便只保留
prepare
。nhjlsmyf7#
您可以使用Statement属性对预处理语句进行调试打印。这可以通过“语句句柄”或“数据库句柄”来访问。
fhity93d8#
一般情况下不会,因为DBI不一定会生成这样的查询。如果您的数据库在其API中支持预处理语句和占位符,则DBI会将它们传递给数据库,让数据库执行这些工作,这也是使用预处理语句的原因之一。