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

Medicinal Monks,

When you do

$sql = "SELECT field_1, field_2 FROM myTable"; $sth = $dbh->prepare($sql) or die("Could not prepare!" . $dbh->errstr) +; $sth->execute() or die("Could not execute!" . $dbh->errstr); while (($val_1, $val_2) = $sth->fetchrow_array()) { $myhash{$val_1} = $val_2; } $sth->finish; foreach $val_1 (keys %myhash) { print "myhash{$val_1} = $myhash{$val_1}\n"; }
If, for any record, field_2 was empty, then $val_2 is not set, and the "print" statement throws an error "Use of uninitialized value in concatenation...". A clumsy fix would be
if ($val_2) { $myhash{$val_1} = $val_2; } else { $myhash{$val_1} = ''; }
but there HAS to be a better way to go about it. Anyone?

Thanks.




Forget that fear of gravity,
Get a little savagery in your life.

Replies are listed 'Best First'.
Re: Hashing uninitialized values when no value returned from DBI sql select
by kyle (Abbot) on Feb 27, 2008 at 20:11 UTC

    In Perl 5.10, you can say,

    $myhash{$val_1} = $val_2 // '';

    Otherwise, I might say,

    $myhash{$val_1} = defined $val_2 ? $val_2 : '';

    Update: And you can always turn off warnings.

    foreach $val_1 (keys %myhash) { no warnings 'uninitialized'; print "myhash{$val_1} = $myhash{$val_1}\n"; }

    You can selectively and lexically turn off/on warnings as you like. Generally it's a good idea to limit the lack of warnings to the smallest scope possible. See perllexwarn for a list of the warnings categories you can toggle.

      I thought I had 5.1, but I must not, because
      $myhash{$val_1} = $val_2 // '';
      produces
      Illegal division by zero
      on my system.
        I thought I had 5.1, but I must not, because
        5.10?

        Well, what does perl -v say?

        With Perl 5.8.8:

        $ perl -e '$v2=undef;$v1 = $v2 // "";' Search pattern not terminated at -e line 1. $ perl -e '$v2=undef;$v1 = $v2 / "";' Illegal division by zero at -e line 1.
Re: Hashing uninitialized values when no value returned from DBI sql select
by runrig (Abbot) on Feb 27, 2008 at 20:17 UTC
    $val_2 = '' unless defined $val_2
    but sometimes I'll just say:
    defined or $_ = '' for @list_of_values;
    e.g.:
    defined or $_ = '' for $val_1, $val_2;
Re: Hashing uninitialized values when no value returned from DBI sql select
by chrism01 (Friar) on Feb 28, 2008 at 07:22 UTC
    You need to decide if your prog (or user) cares about the difference (in the DB) between NULL and the empty string ''.

    If not, use kyle's suggestion:

    $myhash{$val_1} = defined $val_2 ? $val_2 : '';

    If your prog does care, you'll just have to explicitly check for definedness at each subsequent usage of the value, or use an SQL fn like ifnull(col1, val1, val2) or the local equiv, to cvt it to an unused value eg '~'.

Re: Hashing uninitialized values when no value returned from DBI sql select
by punch_card_don (Curate) on Feb 28, 2008 at 16:17 UTC
    Well, in the end, I really like Kyle's

    $myhash{$val_1} = defined $val_2 ? $val_2 : '';

    compact if-then-else suggested notation. It's really exactly the If-Else structure I proposed in the OP, just a nice compact notation. Haven't used it much - tend to be more verbose - but this is a good application for it.

    Is there a name for this kind of notation?

      Is there a name for this kind of notation?

      I usually hear it called the ternary operator, but it's documented in perlop under "Conditional Operator" so that's probably a better name.