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

Dear Monks, I'm putting together a form to enter data in MySQL but when I look at the data inside the database, I'm getting hash references such as HASH(0x1875380) instead of the expected names.

#!c:\perl\bin\perl use strict; use warnings; use CGI; use DBI; my $q = new CGI; if($q->param("addrecord")){ my %cols = ( servicename => "Name", description => "description", url => "url", help => "helpdesk", group => "grp", hbi => "hbi", riskregister => "register", serviceman => "service_manager", servemail => "man_email", servtel => "man_phone", deputy => "deputy_manager", depemail => "dep_email", deptel => "dep_phone" ); my $keystring = (); my $valuestring = (); my $db = DBI->connect('foo', 'bar', 'baz') or die "Can't connect"; foreach ( qw/ servicename description url help group hbi riskregis +ter serviceman servemail servtel deputy depemail deptel /) { if ({$_}) { $keystring .= $cols{$_} .","; $valuestring .= $db->quote({$_}) .","; } } #remove last comma $keystring =~ s/,$//; $valuestring =~ s/,$//; my $statement = qq( INSERT INTO service_metrics ($keystring) VALUES ($valuestring) ); my $sth = $db->prepare($statement); if (! $sth) { die(sprintf('[FATAL] Could not prepare statement: %s\n\n + ERRSTR: %s\n', $db->errstr())); } $sth->execute(); if (! $sth) { die(sprintf('[FATAL] Could not execute statement: %s\n\n + ERRSTR: %s\n', $db->errstr())); } $sth->finish; $db->disconnect(); } print $q->header(); print $q->start_html(-title=>'New Service'); print "You have added a service";

It is probably the case that I have managed to do something rather silly but I cannot see what it is at the moment and it is driving me nuts. I'm fairly new to Perl and would be grateful if somebody could help me learn what I am doing incorrectly. Thanks.

Replies are listed 'Best First'.
Re: Receinving hash where expecting a string
by Joost (Canon) on Aug 15, 2007 at 12:34 UTC
    $valuestring .= $db->quote({$_}) .",";
    that should give a warning
    Odd number of elements in anonymous hash at...
    Since {$_} in this instance creates a hash with a single key "$_" and no value.

    You want quote($_) instead, though you're probably a lot better off using placeholders.

    I.e. something like:

    $db->prepare("INSERT INTO bla col=?, othercol=? ..."); $db->execute($value1,$value2 ...);
    Update: I see that you're using the {$_} in more places, usually where you seem to want $cols{$_} instead. Maybe you should take more notice of the webserver's error log. Or use CGI::Carp 'fatalsToBrowser'; use warnings FATAL=>'all'; or something similar.

Re: Receinving hash where expecting a string
by moritz (Cardinal) on Aug 15, 2007 at 13:36 UTC
    Assuming you want to insert all values from the hash into your database, you could use the following code:

    my @keys = sort keys %cols; my $keystring = join ', ', @keys; my $valstring = join ', ', ('?') x scalar @keys; my $statement = qq{ INSERT INTO service_metrics ($keystring) VALUES ($valuestring) }; my @values = map { $cols{$_} } @keys; my $sth = $dbh->prepare($statement); if (! $sth) { die(sprintf('[FATAL] Could not prepare statement: %s\n\n + ERRSTR: %s\n', $db->errstr())); } $sth->execute(@values); if (! $sth) { die(sprintf('[FATAL] Could not execute statement: %s\n\n + ERRSTR: %s\n', $db->errstr())); } $sth->finish; $db->disconnect();

    This is a bit less code and, by using placeholders, guards you against SQL injection.

    You can learn more about placeholders in the DBI documentation.

    The sorting of the keys eliminates the need to add supply an order manually.

    If you have possibly undefined values, change the first line to

    my @keys = grep { defined $cols{$_} } sort keys %cols;

      Many thanks for these responses. Using the $cols($_) and CGI:Vars has got the data into the db correctly. However, I'll also try the other method suggested by moritz and play with that.
Re: Receinving hash where expecting a string
by FunkyMonk (Bishop) on Aug 15, 2007 at 12:36 UTC
    I'm getting hash references such as HASH(0x1875380) instead of the expected names
    Where? It would be helpful if you were to tell us which line(s)

    However, your code contains:

    if ({$_}) {

    This is definately wrong and should have got have got you a "Odd number of elements in anonymous hash" warning. Should it be

    if ($cols{$_}) {

    ?