LuisC329
LuisC329

Reputation: 135

How can I detect empty fields in a hash in Perl?

I am pulling complete rows from MySQL table into hashes using DBI and cannot figure out how to detect those fields that are empty.

The code below is a little sloppy because I have tried different ways to find a solution to my problem. Essentially the loop below prints out the content of the first row from MySQL. Some fields have data, some do not. But regardless of whether any key in the hash points to data or not, this loop states that each of them is defined, but empty. I would assume, I am missing something so simple, but cannot find it.

my %currec; 
foreach my $row (@{$data_all})
{
    say $row;
    %currec = %{$row};
    foreach my $columns (keys %currec) {
      my $text = $currec{$columns};
      say $text;
      if(undef($text))
      {
        say "$columns is NOT DEFINED";
      }
      elsif (length($text) < 1)
      {
        say "$columns DEFINED, but empty";
      }
    }
    exit;

}

Upvotes: 2

Views: 696

Answers (2)

brian d foy
brian d foy

Reputation: 132918

Also see my answer to In Perl, how can I concisely check if a $variable is defined and contains a non zero length string?.

Your problem is that you used the wrong thing to check. You wanted defined instead of undef. I typically find these situations with a couple of debugging statements:

print "Before check, text is <$text>\n";
if(undef($text))   # you wanted defined() here
  {
    say "$columns is NOT DEFINED";
  }
print "After check, text is <$text>\n";

But, other people may have the same question for a different reason, so here's their answer.

In Perl, there are two ways that something can be "empty". Your database has various ways too, and then how you treat data (such as using the empty string to mean NULL) is yet another way. In these issues, I usually go through the entire data path to see how the value is treated. If things should be NULL, nothing should be deciding to make it otherwise. All of this is a much longer answer:

  • The table and column definitions
  • Input to program that will insert or update value
  • The query that inserts the value
  • The program that reads the values

Back to Perl values.

First, a Perl "value" can have no value (think about that a moment!). You say your values are defined, so this probably isn't your situation. The undef is the default "value" before you use something meaningful. Check for that with defined:

 if( not defined($n) ) { ... }

Second, your value might be the empty (zero-width) string. It's a string with no characters, which is as good a string as any other. Some things don't like undef and convert it to the empty string. Sometimes this happens because something along the data path treated the value as a string and the undef was converted to the empty string. Checking length can check those:

 if( ! length($n) ) { ... }

And, starting with Perl v5.12, length returns undef for the undef value, where it returned 0 before.

Had something along the data path treated undef as a number, the value would be 0 (the default numeric value, which is the additive identity). Curiously, having a numeric value then converting to a string gives you a non-zero length string.

But you also ask about hashes. A hash value can be any of the values that I just mentioned, but the key might not exist in the hash. For any key that doesn't exist, Perl returns the undef value when you use that key. You can use this as a guard condition before you use that key:

if( exists $hash{$key} ) { ... }

Upvotes: 3

sticky bit
sticky bit

Reputation: 37507

undef() undefines the variable and always returns the undefined value...

Try:

...
if(!defined($text))
...

Upvotes: 6

Related Questions