I'd first like to extend a hearty thank-you to the Monks' help with my last project. Thank you for helping to make my life easier!

I've moved to a new database project using DBI and DBD::ODBC. I'm in the design phase now, and I've run up against an odd requirement. I'm well aware of the value of abstracting SQL from the Perl that calls it -- but I now have the requirement not to use Stored Procedures. I'm not allowed to change this requirement.

So, what I can't figure out is: what's the best way, barring stored procedure use, to abstract the SQL as much as possible away from my perl code?

Update 2004-09.Sep-30:
I have solved the problem using ideas given by repliers combined with some of my own. I thought the Monastery might be interested.

The methodology is simple:

  1. Put SQL into separate files, named with query_name.sql.
  2. Run this:
    use strict; use warnings; my %queries; for (@ARGV) { open my $FH, '<', $_ or die("failed opening $_ :$!"); s'\.sql$''; while (chomp($queries{$_}.=<$FH>)) {} } # the PERLINST env var holds the location of our private # Perl Module store open my $MODULE, '>', "$ENV{PERLINST}/MyProject/SQL.pm" or die("Unable to open SQL module"); print $MODULE q( package Private::MyProject::SQL; require Exporter; use vars (@ISA, @EXPORT); ); print $MODULE '@EXPORT = qw(',join(' ',keys %queries),");\n"; for (keys %queries) { print $MODULE 'use constant '.$_.' => q('.$queries{$_}.");\n"; } print $MODULE '1;\n'; close $MODULE;
  3. Pack code using PAR
The end result is that the SQL files get drafted into a module, which can be included in the solid .exe that PAR generates. The SQL maintainer updates the .sql files and runs a batch file which calls the above script, then packs with PAR. No perl is ever apparent to the SQL maintainer.

Things to consider:

I'm currently thinking of putting it in our in-house Private:: module namespace with something like Private::ProjectName::SQL containing something like:

package Private::ProjectName::SQL; require Exporter; use warnings; use strict; use vars qw($VERSION @ISA @EXPORT); $VERSION = 0.01; @ISA = qw(Exporter); @EXPORT = qw(sql_queryname1 sql_queryname2 ...); use constant sql_queryname1 = qq( SELECT RecordID FROM Management WHERE IQ > 40 AND Salary < (SELECT UngodlyAmount FROM References) ); #don't trim this line! use constant sql_queryname2 =.... 1;

Will something like the above work? Is there a better way? Is that enough abstraction?

Thank you, wise monks, for bestowing wisdom upon me.

require General::Disclaimer;

All code, unless otherwise noted, is untested

"All it will give you though, are headaches after headaches as it misinterprets your instructions in the most innovative yet useless ways." - Maypole and I - Tales from the Frontier of a Relationship (by Corion)


In reply to Abstracting SQL without Stored Procedures by radiantmatrix

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.