How can I print the SQL query executed after Perl's DBI fills in the placeholders?

前端 未结 8 655
梦毁少年i
梦毁少年i 2021-02-05 09:36

I\'m using Perl\'s DBI module. I prepare a statement using placeholders, then execute the query.

Is it possible to print out the final query that was executed without ma

相关标签:
8条回答
  • 2021-02-05 09:41

    See Tracing in DBI. The following works using DBD::SQLite but produces a lot of output:

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

    Output:

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

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

    etc etc.

    You could plug your own filter in to the trace stream to only keep prepares.

    0 讨论(0)
  • 2021-02-05 09:50

    You can do a debug print of a prepared statement using the Statement attribute. This can be accessed either with a "statement handle" or a "database handle".

    print $sth->{Statement} # with a statement handle
    
    print $dbh->{Statement} # with a database handle
    
    0 讨论(0)
  • 2021-02-05 09:53

    Not in general, because DBI doesn't necessarily produce such a query. If your database supports prepared statements and placeholders in its API, DBI will pass them through and let the database do the work, which is one of the reasons to use prepared statements.

    0 讨论(0)
  • 2021-02-05 09:53

    For perl neophytes, my solution, copied from not2qubit and simplified/hopefully made a bit more generic/reuseable:

    sub dump_query {
      my $tquery = shift;
      my @args = shift;
      my $j;
        foreach my $j (@args) { $tquery =~ s/\?/\'$j\'/; }
        print STDERR "$tquery\n\n";
    }
    
    0 讨论(0)
  • 2021-02-05 09:57

    If you don't want to create your own tracer module (as suggested by Sinan), you are better off just trying to print the argument hash before it is passed to $sth->execute(). This is especially true, since the "Trace" functionality is DBMS dependent and $sth->{Statement} only returns the SQL placeholder statement. Here's what I did.

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

    Where I have used Text::CSV... NOTE: This is not exact, due to DBMS implementation dependent handling of {'}s.

    0 讨论(0)
  • 2021-02-05 10:00

    This works for DBD::mysql with server-side prepare disabled (the default):

    $ DBI_TRACE=2 perl your-script-here
    

    It will print each statement twice, once before binding parameters and once after. The latter will be well-formed SQL that you can run yourself.

    There is also a module, DBI::Log, which only prints SQL statements (no other debug noise), and optional timing information and caller stacktraces. It's really useful.

    0 讨论(0)
提交回复
热议问题