Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery
 
PerlMonks  

Using Perl and MySQL for Activity Log

by PyrexKidd (Monk)
on Apr 27, 2011 at 05:55 UTC ( [id://901472]=perlquestion: print w/replies, xml ) Need Help??

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

I am using Perl and MySQL to create a customer catalog. What I would like to do is create a change log, so when I update the primary table I have a record of it.

I have created my tables as such:

CREATE TABLE catalog ( phone_number VARCHAR(10) PRIMARY KEY NOT NULL, name VARCHAR(255), address VARCHAR(255), notes VARCHAR(255) ); CREATE TABLE change_log ( transaction_id INT(10) PRIMARY KEY NOT NULL AUTO INCREMENT, timestamp TIMESTAMP, number_record VARCHAR(255), action VARCHAR(255) );

So I update the DB pragmatically like so:

#!/usr/bin/perl use strict; use warnings; use DBI; use DBD::mysql; #this is my config module use DBase::MySQL::Config qw(DB_CUSTOMER_CATALOG DB_USER DB_PW); my $dbh = DBI->connect(DB_CUSTOMER_CATALOG, DB_USER, DB_PW); my $query = "INSERT INTO catalog (phone_number) VALUES ('5555555555'), + ('1111111111');"; $dbh->do($query); $dbh->disconnect();

What I would like to do is: if a record exists, update the record with name, address, etc. and insert a new record into the change log, with number affected and action performed. If a record doesn't exist, insert the new record into the customer catalog (along with name, address, and any notes where applicable) and add a new record to the change log noting the addition.

Thanks in advance for any assistance. This one has had me stuck.

Replies are listed 'Best First'.
Re: Using Perl and MySQL for Activity Log
by davido (Cardinal) on Apr 27, 2011 at 06:30 UTC

    Well, the general logic/flow could look like this:

    # $person is an object holding a record with getters for each field. if( record_exists( $person->id() ) ) { log_change( update_record( $person ) ); } else { log_new( add_record( $person ) ); }

    The rest is sort of fill-in-the-blanks, but you seem to already know how to handle DB work, so I don't think that's where you're having trouble. If that's the issue, you'll have to be more specific as to what kind of help you were after.

    You should be using placeholders though, with your DB access. See the documentation for DBI for more info. Placeholders improve security as well as providing for easier code maintenance.

    By the way: Are you sure that keying off of a person's phone number is a good idea? You're sure to get multiple entries for the same individual. People never can recall what number they used when they first interacted with an organization. Was it my cell? My home? My office? My Google Voice? My Skype? My wife's cell? Was it my old AT&T cell, or my new Verizon one? Addresses aren't exactly ideal either; people move more than you might guess. Email addresses change too. It's really hard to ensure that you don't end up with duplicates regardless of how you maintain the database, but phone numbers are a weak starting point. If human interaction is a possibility, the person at the front line could always ask, "Are you Mr Spacey from Los Angeles, or Mr Spacey from Detroit?"


    Dave

Re: Using Perl and MySQL for Activity Log
by moritz (Cardinal) on Apr 27, 2011 at 08:17 UTC

    Use a database-level trigger for creating the change_log entries. That way the integrity and completeness of the log is enforced at a database layer, and works fine even if someboy uses something else than your perl script to make changes to the catalog table.

      That's the best way, in theory.

      However, he is using MySQL. Does his version of Mysql support triggers? I think the newer versions do, but he doesn't say what version of Mysql he is using. (Yes, triggers have been added in 5.0.2.)

      There's a reason why Mysql is traditionally considered a toy database, and this is one of them.

Re: Using Perl and MySQL for Activity Log
by wind (Priest) on Apr 27, 2011 at 06:45 UTC

    It's been ages since I've written direct database queries, but something like the following could be what you use.

    Using prepared statements and placeholders are the biggest things I'd recommend:

    #!/usr/bin/perl use strict; use warnings; use DBI; use DBD::mysql; #this is my config module use DBase::MySQL::Config qw(DB_CUSTOMER_CATALOG DB_USER DB_PW); my $dbh = DBI->connect(DB_CUSTOMER_CATALOG, DB_USER, DB_PW); my $catalog_u = $dbh->prepare(q{UPDATE catalog SET name=?, address=?, +notes=? WHERE phone_number=?}); my $catalog_i = $dbh->prepare(q{INSERT INTO catalog SET phone_number=? +, name=?, address=?, notes=?}); my $catalog_c = $dbh->prepare(q{SELECT COUNT(*) FROM catalog WHERE pho +ne_number=?}); my $change_i = $dbh->prepare(q{INSERT INTO change_log SET timestamp=NO +W(), number_record=?, action=?}); while(<DATA>) { chomp; my ($phone, $name, $address, $notes) = split "\t"; my $catalog_c->execute($phone) or die $dbh->errstr; my ($exists) = $catalog_c->fetchrow_array; if ($exists) { my $changed = $catalog_u->execute($name, $address, $notes, $ph +one) or die $dbh->errstr; if ($changed) { $change_i->execute($phone, 'update') or die $dbh->errstr; } } else { $catalog_i->execute($phone, $name, $address, $notes) or die $d +bh->errstr; $change_i->execute($phone, 'insert') or die $dbh->errstr; } } $catalog_u->finish; $catalog_i->finish; $catalog_c->finish; $change_i->finish; $dbh->disconnect(); __END__
Re: Using Perl and MySQL for Activity Log
by anonymized user 468275 (Curate) on Apr 27, 2011 at 13:11 UTC
    I would have suggested using triggers as well but for bart's valid point and because the version in question of MySQL is barely a year old.

    However, stored procedures have been around in MySQL for 8 years. So it seems reasonable to write access stored procedures that have the logging to log tables built in. Calling these from Perl instead of coding SQL in the Perl code is usually preferable anyway. There are overheads to dragging data out of the database, processing it and putting it back. As a rule it is better to let Perl pre- or post-process database data but to use stored procedures where possible, especially if the database is on a different machine from where the Perl will run. A trigger is anyway a special case of a stored procedure.

    One world, one people

Re: Using Perl and MySQL for Activity Log
by eff_i_g (Curate) on Apr 27, 2011 at 14:32 UTC
    ...if a record exists, update the record... If a record doesn't exist, insert the new record
    You can use INSERT...ON DUPLICATE KEY UPDATE for this and set up a trigger for the record keeping. I assume these will play nicely.
Re: Using Perl and MySQL for Activity Log
by Anonymous Monk on Apr 27, 2011 at 13:01 UTC
    Also do not forget to use transactions.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://901472]
Approved by Corion
Front-paged by moritz
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others browsing the Monastery: (3)
As of 2024-04-18 03:32 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found