in reply to Re: Problem passing date to SQL
in thread Problem passing date to SQL

Thanks. I just tried but still have the same problem. :( Also, since I'm using single quotes do I need to escape the % sign?

Replies are listed 'Best First'.
Re^3: Problem passing date to SQL
by ravi45722 (Pilgrim) on Aug 19, 2015 at 04:48 UTC

    I am working in mysql. If i want previous month data i write code like this. Dont know whether works in sql

    $month=`date --date='1 month ago' +%B`; . . . my $sth = $dbh->prepare("SELECT * from $table where monthname(Date)='$ +month'" ); . . .
      $month=`date --date='1 month ago' +%B`; my $sth = $dbh->prepare("SELECT * from $table where monthname(Date)='$ +month'" );

      This is a really bad example:

      • `date ...` returns a line break, as you can see by running perl -e '$month=`date --date="1 month ago" +%B`; print "[$month]"'. Your code does nothing to remove the line break (chomp missing), so it is passed to MySQL. I guess that MySQL will see a difference between "Foo" and "Foo<line break>" and wrongly return no results.
      • date ... +%B returns the month name in the current locale of the operating system of the computer the perl script runs on. Something like "Août", "August", or "Agosto". MySQL's monthname() returns the month name in the locale that was selected in the MySQL configuration, possibly on a different machine. Something like "Aguste", "Agustus", or "Aguste". A locale mismatch will wrongly give you no results. MySQL's month() returns numbers in the usual range 1..12, no mismatch possible. It may also return 0 for "strange" dates, see MySQL documentation.
      • "date --date='1 month ago' +%B" is not portable. Guess what happens when you execute it on Windows. Right, it does not work. It waits for input, because it does not understand GNU parameters:
        Microsoft Windows [Version 6.1.7601] Copyright (c) 2009 Microsoft Corporation. All rights reserved. C:\Users\alex>date --date='1 month ago' +%B The system cannot accept the date entered. Enter the new date: (dd-mm-yy)
        Don't ask me what happens on other systems without GNU's date. I would expect to see errors, unexpected output, or both.
      • You don't need external tools to get the current month, perl has gmtime and localtime. Both return the month a number in the range 0..11. Add 1 to get the usual range 1..12.
      • Using string interpolation to fill values into SQL statements is extremely dangerous (http://bobby-tables.com/) and it actively prevents any caching done by DBI, DBD::*, and the database. Always use placeholders; they prevent SQL injection, automatically handle all required quoting, and allow caching.

      To clean up:

      my $month=(localtime())[4]+1; ... my $sth=$dbh->prepare("SELECT * from $table where month(Date)=?"); $sth->execute($month); ...

      Except that this still misses the "last month" logic. Quite easy to handle. The previous month number is current month number minus 1. If that is 0, replace it with 12.

      my $month=(localtime())[4]+1; # last month: $month--; $month||=12; ... my $sth=$dbh->prepare("SELECT * from $table where month(Date)=?"); $sth->execute($month); ...

      This still can be simplifed because localtime already returns current month number minus 1. And while we are at it, rename $month to $lastmonth.

      my $lastmonth=(localtime())[4]||12; ... my $sth=$dbh->prepare("SELECT * from $table where month(Date)=?"); $sth->execute($lastmonth); ...

      And the final bit to get rid of little bobby tables: $table may come from an untrusted source, or may just be a reserved word. DBI can handle this, too, for any database:

      ... my $sth=$dbh->prepare('SELECT * from '.$dbh->quote_identifier($table). +' where month(Date)=?'); ...

      Alexander

      --
      Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)

      Alexander's post doesn't even mention that you seem not to care about the year.

      And your solution is somewhat inflexible because it can't be simply changed from month to week or 14 days or whatever.

      I did upvote anyway, because of Tim Toady: Taking the month name makes it completely clear you want the data of the complete month.