Question

I attempting to take two separate tables, in two separate databases, and compare the fields to each other. I wrote the below code to demonstrate the problem I am having, since I can not copy the code I am using. In the example below I am using one database. Below the code example, I will provide the dump of each table. In any case on with a better description.

reference_table holds the records listed in original_table. I have no control over the contents of original_table. After obtaining these records, the person/s who edit the information in original_table can update any field, or they can downright remove the entry.

My goal is, when going back through original_table, to update the field status to disabled where any of the fields in the original_table no longer match the record I had in reference_table. When looking at the dump you will notice a field called unique_id. This is the id of original_table.

The two main problems that I run into is using the ident of reference_table to update status in reference_table, and properly seeing the tables similarities.

#!/usr/bin/perl
use strict;
use DBI;
use Data::Dumper;

my $dbh = DBI->connect('dbi:mysql:test','user','password',
    {
            RaiseError => 1,
            AutoCommit => 0
    }
) || die "Database connection not made: $DBI::errstr";

my $sql     = "SELECT * FROM original_table";
my $sth     = $dbh->prepare( $sql ) or die $dbh->errstr;
              $sth->execute() or die $sth->errstr;

my @original;
while (my $data = $sth->fetchrow_hashref()){
    push(@original, $data);
}

my $sql     = "SELECT * FROM reference_table";
my $sth     = $dbh->prepare( $sql ) or die $dbh->errstr;
              $sth->execute() or die $sth->errstr;

my @reference;
while (my $data = $sth->fetchrow_hashref()){
    push(@reference, $data);
}

foreach (sort keys @reference){
    unless (exists $original[$_]){
        my $sql     = "UPDATE reference_table SET status = 'd' WHERE ident $reference[ident]";
        my $sth     = $dbh->prepare( $sql ) or die $dbh->errstr;
                      $sth->execute() or die $sth->errstr;

        print "$_: not found in Remote Group\n";
        next; 
    }
    if ($reference[$_] eq $original[$_]){
        print "$_: values are equal\n"
    }else{
        print "$_: values are not equal\n";
    }
}

$dbh->disconnect();

The code produces the following results:

0: values are not equal
1: values are not equal
10: values are not equal
11: not found in Remote Group
2: values are not equal
3: values are not equal
4: values are not equal
5: values are not equal
6: values are not equal
7: values are not equal
8: values are not equal
9: values are not equal

The dump of each table:

@original

$VAR1 = [
          {
            'timezone' => 'tz_001',
            'status' => 'a',
            'full_name' => 'name_001',
            'ident' => '1'
          },
          {
            'timezone' => 'tz_002',
            'status' => 'a',
            'full_name' => 'name_002',
            'ident' => '2'
          },
          {
            'timezone' => 'tz_003',
            'status' => 'a',
            'full_name' => 'name_003',
            'ident' => '3'
          },
          {
            'timezone' => 'tz_004',
            'status' => 'a',
            'full_name' => 'name_004',
            'ident' => '4'
          },
          {
            'timezone' => 'tz_005',
            'status' => 'a',
            'full_name' => 'name_005',
            'ident' => '5'
          },
          {
            'timezone' => 'tz_006',
            'status' => 'a',
            'full_name' => 'name_006',
            'ident' => '6'
          },
          {
            'timezone' => 'tz_007',
            'status' => 'a',
            'full_name' => 'name_007',
            'ident' => '7'
          },
          {
            'timezone' => 'tz_008',
            'status' => 'a',
            'full_name' => 'name_008',
            'ident' => '8'
          },
          {
            'timezone' => 'tz_009',
            'status' => 'a',
            'full_name' => 'name_009',
            'ident' => '9'
          },
          {
            'timezone' => 'tz_010',
            'status' => 'a',
            'full_name' => 'name_010',
            'ident' => '10'
          },
          {
            'timezone' => 'tz_011',
            'status' => 'a',
            'full_name' => 'name_011',
            'ident' => '11'
          }
        ];

@reference

$VAR1 = [
          {
            'timezone' => 'tz_001',
            'status' => 'a',
            'full_name' => 'name_001',
            'ident' => '1',
            'unique_id' => '1'
          },
          {
            'timezone' => 'tz_002',
            'status' => 'a',
            'full_name' => 'name_002',
            'ident' => '2',
            'unique_id' => '2'
          },
          {
            'timezone' => 'tz_003',
            'status' => 'a',
            'full_name' => 'name_003',
            'ident' => '3',
            'unique_id' => '3'
          },
          {
            'timezone' => 'tz_004',
            'status' => 'a',
            'full_name' => 'name_004',
            'ident' => '4',
            'unique_id' => '4'
          },
          {
            'timezone' => 'tz_005',
            'status' => 'a',
            'full_name' => 'name_122',
            'ident' => '5',
            'unique_id' => '5'
          },
          {
            'timezone' => 'tz_006',
            'status' => 'a',
            'full_name' => 'name_006',
            'ident' => '6',
            'unique_id' => '6'
          },
          {
            'timezone' => 'tz_007',
            'status' => 'a',
            'full_name' => 'name_007',
            'ident' => '7',
            'unique_id' => '7'
          },
          {
            'timezone' => 'tz_008',
            'status' => 'a',
            'full_name' => 'name_008',
            'ident' => '8',
            'unique_id' => '8'
          },
          {
            'timezone' => 'tz_009',
            'status' => 'a',
            'full_name' => 'name_009',
            'ident' => '9',
            'unique_id' => '9'
          },
          {
            'timezone' => 'tz_010',
            'status' => 'a',
            'full_name' => 'name_010',
            'ident' => '10',
            'unique_id' => '10'
          },
          {
            'timezone' => 'tz_011',
            'status' => 'a',
            'full_name' => 'name_011',
            'ident' => '11',
            'unique_id' => '11'
          },
          {
            'timezone' => 'tz_012',
            'status' => 'a',
            'full_name' => 'name_012',
            'ident' => '12',
            'unique_id' => '12'
          }
        ];

Please let me know if you have additional questions. Any help is greatly appreciated.

Was it helpful?

Solution 2

You are using the string comparison operator eq to try to compare to hash references.

$reference[$_] eq $original[$_]

The "stringification" of a hash reference is a string like HASH(0xdeadbeef), so this will always be false unless $reference[$_] and $original[$_] refer to the exact same memory.

Even comparing all keys and values will not give you what you want, because the $reference[$_] hash reference contains the key unique_id and $original[$_] does not.

A more customized solution would be something like:

if (equivalent($reference[$_],$original[$_]) {
    print "$_: values are equal\n"
} else {
    print "$_: values are not equal\n";
}

sub equivalent {
    my ($hash1, $hash2) = @_;
    return $hash1->{timezone} eq $hash2->{timezone} &&
        $hash1->{status} eq $hash2->{status} &&
        $hash1->{full_name} eq $hash2->{full_name} &&
        $hash1->{ident} eq $hash2->{ident} &&
}

OTHER TIPS

"UPDATE reference_table SET status = 'd' WHERE ident $reference[ident]"

The problem is this $reference[ident]. You are trying to access an array element indexed by the bareword ident, but that does not work.

To correct this, use an appropriate index like $_. The next problem is that @reference is an array of hashrefs. I assume you want to use the ident field in that hashref. Then: $reference[$_]{ident}.

I also suggest you use placeholders to avoid possible issues with escaping:

    my $sql     = "UPDATE reference_table SET status = 'd' WHERE ident ?";
    my $sth     = $dbh->prepare($sql) or die $dbh->errstr;
                  $sth->execute($reference[$_]{ident}) or die $sth->errstr;

There are some remaining style issues with your code, but this should get you going.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top