Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change
 
PerlMonks  

Using CGI.pm params to make a DBI MySQL query

by George_Sherston (Vicar)
on Oct 09, 2001 at 19:43 UTC ( [id://117771]=perlquestion: print w/replies, xml ) Need Help??

George_Sherston has asked for the wisdom of the Perl Monks concerning the following question:

Back in the bad old days before I started using CGI, I always had my parameters in the form of a hash. That made interpolating into strings easy. Now they come in the form of function calls. So there are lots of different ways to get them into strings, none of them quite right. Here are my least un-favourite three:
(1) my $dbh->do("INSERT INTO tbl VALUES (".param('Col1').",".param('Col2') +.",".param('Col3').")"); (2) my $Col1 = param('Col1'); my $Col2 = param('Col2'); my $Col3 = param('Col3'); my $dbh->do("INSERT INTO tbl VALUES ($Col1,$Col2,$Col3)"); (3) my %params = Vars; my $dbh->do("INSERT INTO tbl VALUES ($params{'Col1'},$params{'Col2'},$ +params{'Col3'}')");
I feel that none of these is the canonical way. (1) is too messy and buggable, whilst (2) and (3) involve seemingly needless proliferation of variables. I'd be very glad to see how the mighty ones do it.

§ George Sherston

Replies are listed 'Best First'.
Re: Using CGI.pm params to make a DBI MySQL query
by tommyw (Hermit) on Oct 09, 2001 at 19:54 UTC

    Placeholders, as frequently mentioned, are your friends:

    my $sth=$dbh->prepare("INSERT INTO tbl VALUES(?, ?, ?)"); $sth->execute(param('Col1'), param('Col2'), param('Col3'));
    Yes, this is an extra statement, but it does make life easier for the SQL parser.

      You'll want scalar there, lest you be burned the day someone gives you none or two parameters for Col1 and friends.
      my $result = $dbh->do("INSERT INTO tbl VALUES(?,?,?)", undef, map scalar param($_), qw(Col1 Col2 Col3));

      -- Randal L. Schwartz, Perl hacker

Re: Using CGI.pm params to make a DBI MySQL query
by arturo (Vicar) on Oct 09, 2001 at 19:59 UTC

    I like to use prepare and all that gunk, even for INSERTs, but you can still use placeholders with do :

    $dbh->do("INSERT INTO tbl VALUES (?,?,?)", undef, @params{qw(Col1 Col2 + Col3)});

    This gives you quoting of the values (nice from a security point of view). And the hash slice is just icing on the cake.HTH!

    perl -e 'print "How sweet does a rose smell? "; chomp ($n = <STDIN>); +$rose = "smells sweet to degree $n"; *other_name = *rose; print "$oth +er_name\n"'
Re: Using CGI.pm params to make a DBI MySQL query
by projekt21 (Friar) on Oct 09, 2001 at 20:04 UTC

    If you do that:

    my $sth = $dbh->prepare("INSERT INTO tbl VALUES (?,?,?)"); $sth->execute(@values) or die $dbh->errstr;

    you should win twice:

    1. You get your values quoted.
    2. You can use an array.

    Hope that helps.

    alex pleiner <alex@zeitform.de>
    zeitform Internet Dienste

      Hmm, that's particularly good in my case because when I'm not making my query with CGI params I'm making it with the output of a SELECT query, and that output is in the form of an arrayref. Using an array avoids the intermediate step of breaking out the array into its elements.

      § George Sherston
Re: Using CGI.pm params to make a DBI MySQL query
by cLive ;-) (Prior) on Oct 09, 2001 at 19:50 UTC
    Whenever I need to interpolate a lot, I create a hash - just like the good ol' days:
    my %field; for ( param() ) { $field{$_} = param($_); }
    but I've also found that the more I use CGI.pm, the more my coding moves away from that method towards template thingies.

    cLive ;-)

      And just to be on the safe side
      my %field; for ( qw/foo bar baz/ ) { $field{ $_ } = param( $_ ); }
      This way we are explicitly allowing the things we want, and can even build in error handling if the things we need aren't there.
Re: Using CGI.pm params to make a DBI MySQL query
by Anarion (Hermit) on Oct 09, 2001 at 22:11 UTC
    If you are using CGI.pm and want a hash, theres a method that return one:

    my %form=$query->Vars();

    man CGI

    $anarion=\$anarion;

    s==q^QBY_^=,$_^=$[x7,print

(dkubb) Re: (1) Using CGI.pm params to make a DBI MySQL query
by dkubb (Deacon) on Oct 10, 2001 at 06:57 UTC

    I have one comment that hasn't been addressed yet, is slightly OT, but still important.

    In your SQL query you may want to explicitly specify the columns you are inserting into. This has a large benefit: if you add a column to the table or the column ordering changes, your code is less likely to break. A good rule of thumb I use is to:

    • never assume the order of columns in an SQL query
    • always explicitly define the columns

    I've found this to be especially helpful in SELECT and INSERT -type statements.

    Here's an example that demonstrates what I mean and answers your question:

    $dbh->do( 'INSERT INTO table (Col1, Col2, Col3) VALUES (?, ?, ?)', {}, map scalar param($_), qw(Col1 Col2 Col3), );

    I began doing this after thinking about the issues raised in Topics in Perl Programming: Table-Mutation Tolerant Database Fetches with DBI, and realizing the way I was doing SQL does not lend itself to change very well.

Re: Using CGI.pm params to make a DBI MySQL query
by shotgunefx (Parson) on Oct 09, 2001 at 23:47 UTC
    In addition to some of these suggestions, you could also use CGI's import_names function instead of a hash to import your cgi values into a namespace.

    -Lee

    "To be civilized is to deny one's nature."
Re: Using CGI.pm params to make a DBI MySQL query
by tcf22 (Priest) on Oct 10, 2001 at 03:53 UTC
    I always like to use
    use CGI; my $cgi = new CGI; my %MYDATA = $cgi->Vars;
    -Tom

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://117771]
Approved by root
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others learning in the Monastery: (3)
As of 2024-04-24 20:18 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found