2009-11-06 14 views
13

Sto usando il modulo DBI di Perl. Preparo una dichiarazione usando segnaposto, quindi eseguo la query.Come posso stampare la query SQL eseguita dopo che DBI di Perl riempie i segnaposti?

E 'possibile stampare la query finale che è stato eseguito senza sfuggire manualmente i parametri e rilasciandoli nelle segnaposto?

Grazie

+1

possibile duplicato di [Come posso fare a DBI registrare tutte le query compresi i parametri?] (Http://stackoverflow.com/questions/19703521/how-can-i-make-dbi-log-all-queries-including- params) – Jake

+0

@Jake questa domanda è stata posta 4 anni prima dell'altra domanda, anche questa domanda ha risposte migliori, (secondo me). Ecco perché ho segnato l'altra domanda come duplicato e candidato alla chiusura. – aidan

risposta

16

Vedere Tracing in DBI. Le seguenti opere con DBD::SQLite ma produce un sacco di uscita:

$dbh->trace($dbh->parse_trace_flags('SQL|1|test')); 

uscita:

<- prepare('SELECT ... FROM ... WHERE ... = ?')= DBI::st=HASH(0x21ee924) at booklet-excel.pl line 213

<- execute('Inhaler')= '0E0' at booklet-excel.pl line 215

ecc ecc

Si potrebbe plug your own filter in to the trace stream per mantenere solo prepare s .

+1

Invisito per avermi insegnato sulla traccia, anche se non risponde alla domanda (perché, come altri hanno sottolineato, è impossibile). E questo commento è qui solo perché mi sento in colpa per aver upvoting una risposta che so non risponde alla domanda. lol: $ – msb

10

Non in generale, perché DBI non produce necessariamente una query. Se il database supporta dichiarazioni preparate e segnaposto nella sua API, DBI le passerà attraverso e lascerà che il database faccia il lavoro, che è uno dei motivi per usare le istruzioni preparate.

8

Si può fare una stampa di debug di una dichiarazione preparata utilizzando l'attributo Statement. È possibile accedere a questo con un "handle di istruzioni" o un "handle di database".

+1

Ciò restituisce semplicemente la stringa passata all'ultimo 'prepare' o' do', quindi i segnaposto non vengono compilati come l'OP richiesto. – ThisSuitIsBlackNot

+1

Potrebbe usare 'print Dumper ($ statement_handle -> {'ParamValues'});' per stampare separatamente i parametri di bind - Potrebbe essere sufficiente per eseguire il debug della maggior parte delle query. – user1027562

1

Come dice masto in generale, i segnaposto in SQL non vengono sostituiti direttamente con i parametri. L'intero punto di SQL parametrizzato è l'SQL con i segnaposto viene passato al motore di database per analizzare una volta e quindi riceve solo i parametri.

Come note di idssl è possibile ottenere il codice SQL dall'istruzione o dall'handle di connessione ed è inoltre possibile recuperare i parametri da ParamValues. Se non vuoi farlo da solo, puoi usare qualcosa come DBIx::Log4perl per registrare solo SQL e parametri. Vedere DBIX_L4P_LOG_DELAYBINDPARAM che emette qualcosa di simile:

DEBUG - prepare(0.1): 'insert into mje values(?,?)' 
DEBUG - $execute(0.1) = [{':p1' => 1,':p2' => 'fred'},undef]; 

Naturalmente in quanto utilizza Log :: log4perl è possibile omettere il "DEBUG -" se si vuole. C'è un piccolo tutorial per l'uso di DBIx :: Log4perl here.

Si dovrebbe essere in grado di utilizzare DBIx :: log4perl con qualsiasi DBD e se non è possibile per qualche motivo RT e mi guarderà a questo.

Se non si desidera utilizzare DBIx :: Log4perl e le opzioni di traccia DBI non soddisfano le proprie esigenze, è possibile scrivere callback per i metodi DBA di preparazione/selezione */esecuzione e raccogliere tutto ciò che si desidera.

0

Se non si desidera creare il proprio modulo di tracciamento (come suggerito da Sinan), è meglio provare a stampare l'hash dell'argomento prima che venga passato a $sth->execute(). Ciò è particolarmente vero, poiché la funzionalità "Traccia" dipende dal DBMS e $sth->{Statement} restituisce solo l'istruzione segnaposto SQL. Ecco cosa ho fatto.

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

Dove ho usato Text :: CSV ... NOTA: Questo non è esatto, a causa di implementazione DBMS movimentazione dipendente della { '} s.

1

Questo funziona per DBD::mysql con lato server preparare disabilitata (impostazione predefinita):

$ DBI_TRACE=2 perl your-script-here 

Si stamperà ogni dichiarazione due volte, una prima di parametri vincolanti e una volta dopo. Quest'ultimo sarà un SQL ben formato che puoi gestire da solo.

Problemi correlati