2009-11-06 26 views
13

我正在使用Perl的DBI模塊。我使用佔位符準備語句,然後執行查詢。如何在Perl的DBI填充佔位符後打印執行的SQL查詢?

是否可以打印出已執行的最終查詢,而無需手動轉義參數並將其放入佔位符中?

謝謝

+1

可能的重複[如何使DBI記錄包括params在內的所有查詢?](http://stackoverflow.com/questions/19703521/how-can-i-make-dbi-log-all-queries-including- params) – Jake 2015-09-14 19:43:13

+0

@Jake這個問題在另一個問題出現前4年被問到了,這個問題也有更好的答案,(在我看來)。這就是爲什麼我把另一個問題標記爲重複和候選人關閉。 – aidan 2015-09-15 06:10:42

回答

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

Upvoted教我跟蹤,儘管它沒有回答這個問題(因爲正如其他人指出的那樣,這是不可能的)。這個評論在這裏只是因爲我覺得內疚,因爲我知道這個答案並沒有回答這個問題。 lol:$ – msb 2017-01-04 00:03:01

10

不一般,因爲DBI不一定產生這樣的查詢。如果您的數據庫在其API中支持準備好的語句和佔位符,則DBI將傳遞它們並讓數據庫執行此操作,這是使用準備語句的原因之一。

8

您可以使用Statement屬性來執行準備語句的調試打印。這可以通過「語句句柄」或「數據庫句柄」來訪問。

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

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

這只是返回傳遞給上一個'prepare'或'do'的字符串,所以佔位符沒有按照OP請求填充。 – ThisSuitIsBlackNot 2015-05-28 22:03:04

+1

可以使用'print Dumper($ statement_handle - > {'ParamValues'});' 分別打印綁定參數 - 可能足以調試大多數查詢。 – user1027562 2015-12-23 12:02:53

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

當然,因爲它使用日誌:: Log4perl可以省略「DEBUG - 」如果你想要的。有一個使用DBIx :: Log4perl here的小教程。

您應該可以將DBIx :: Log4perl與任何DBD一起使用,並且如果由於某種原因RT無法正常工作,我會查看它。

如果您不想使用DBIx :: Log4perl並且DBI跟蹤選項不適合您的需要,您可以爲DBI的prepare/select */execute方法編寫回調並收集您喜歡的任何內容。

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

當我用文字:: CSV ... 注意:這是不完全一樣,由於{'} S的DBMS實現相關處理。

1

這適用於DBD::mysql與服務器端準備disabled(默認值):

$ DBI_TRACE=2 perl your-script-here 

它將打印每個語句兩次,綁定參數和一次後前一次。後者將是可以自行運行的格式良好的SQL。