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

Hi, I have a situation where our site sends out email alerts. I didn't write the scripts but am trying to adjust. When someone signs up for email alerts in a certain category, their email gets stuffed in a field in the database, and it's separated by ~~~. So the email field in the alerts database could have multiple emails in there.

I've setup a bademails table that we can store bounced emails. I want to check that table, then remove any emails from the alerts table. Here's what I have, but something is wrong with my loop. It stops after finding one record.

###### $SQL = "Select * from bademails ORDER BY ID DESC"; &Do_SQL; while ($pointer = $sth->fetchrow_hashref) { $bademail = $pointer->{'email'}; $SQL2 = "Select * from $alertstable where email LIKE '%$bademail%' +"; &Do_SQL2; $item = $pointer2->{'type'}; $alertype = $pointer2->{'alertype'}; $emaillist = $pointer2->{'email'}; $ID = $pointer2->{'ID'}; @emails = split /~~~/,$emaillist; foreach $address (@emails) { print "$ID<Br>\n"; $elist = ""; if ($address eq $bademail) { $elist = $elist . $address . "~~~"; } } $SQL3 = "UPDATE $alertstable SET email='$elist' WHERE type='$item' +and alerttype='$alerttype'"; &Do_SQL3; print "Updated $ID<Br>\n"; } # end while #######################

Replies are listed 'Best First'.
Re: Comparing 2 databases
by helphand (Pilgrim) on Mar 12, 2006 at 05:23 UTC

    Well, there are still pieces of your script missing, so I'm not sure I've captured all of the functionality, but try this...

    #!/usr/bin/perl use strict; use warnings; use DBI; my $alertstable = $ARGV[0] || 'alertstable'; my $dbh = DBI->connect("DBI:mysql:database=dbname;host=sqlhost", 'username','password', {'RaiseError'=>1}); my $sth=&Do_SQL("Select * from bademails ORDER BY ID DESC"); while (my $pointer = $sth->fetchrow_hashref) { my $bademail = $pointer->{'email'}; my $sth2=&Do_SQL2("Select * from $alertstable where email LIKE '% +$bademail%'"); while (my $pointer2 = $sth2->fetchrow_hashref) { my $item = $pointer2->{'type'}; my $alertype = $pointer2->{'alertype'}; my $emaillist = $pointer2->{'email'}; my $ID = $pointer2->{'ID'}; my @emails = split /~~~/,$emaillist; my @goodmails = (); foreach my $address (@emails) { print "$ID<Br>\n"; if ($address ne $bademail) { push @goodmails,$address; } } if (scalar(@goodmails)) { my $newlist=join('~~~',@goodmails); $dbh->do("UPDATE $alertstable SET email='$newlist' WHERE t +ype='$item' and alerttype='$alertype';") || die $dbh->errstr; print "Updated $ID<Br>\n"; } } } # end while $dbh->disconnect; sub Do_SQL{ my ($SQL)=@_; my $sth; eval { $sth = $dbh->prepare($SQL); }; # check for errors if($@){ $dbh->disconnect; print "Content-type: text/html\n\n"; print "An ERROR occurred! $@\n"; exit; } else { $sth->execute; } return ($sth); }

    You'll need to fix up the connect code to reflect your username and password for the database, and it was not clear what $alertable ever got set to, so make sure it is right.

    Scott

Re: Comparing 2 databases
by helphand (Pilgrim) on Mar 12, 2006 at 00:27 UTC

    What do those Do_SQL, Do_SQL2 and Do_SQL3 routines do?

    Scott

      They are all the same but they do this...
      sub Do_SQL{ eval { $sth = $dbh->prepare($SQL); }; # end of eval # check for errors if($@){ $dbh->disconnect; print "Content-type: text/html\n\n"; print "An ERROR occurred! $@\n"; exit; } else { $sth->execute; } # end of if/else return ($sth); } ## End

        Guess I'm confused then. Why have three identical subroutines with three different names?

        Also, The subroutines return a statement handle, yet you are not capturing any return value. That means your first fetch is fetching what? And your second fetch literally doesn't exist, how are you retrieving anything from the db for the second select statement?

        You say you didn't write the script, but are trying to adjust it. I can't see where the script ever worked at all, did you leave something out?

        Scott