Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?
 
PerlMonks  

MySQL logic

by sulfericacid (Deacon)
on May 27, 2005 at 20:01 UTC ( [id://461218]=perlquestion: print w/replies, xml ) Need Help??

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

I started to learn MySQL a few months back but got back tracked but now I'm ready to give it another try.

Can someone assist me with the logic of how to go about setting this up? I'm converting my link tracker over to a MySQL backend to make the data more sortable.

What it's doing here is checking a url_param for the referring URL and checking whether or not it was in the id row already. If it wasn't, it'll setup the current data (the ip address, the time it was clicked and will start with 1 view).

If the url was already setup, it will autoincrement "views", store the current IP address in last_ip (overwriting original value) and store it with ALL ips in all_ip.

I'm to the point where I bind the variables to the columns but from here I don't know what to do.

Any assistance would be much appreciated.

###### # Connecting to our database ###### my $dbh = DBI->connect("DBI:mysql:$dbase", $mysql_user, $mysql_pass) o +r print DBI=>"errstr"; my $url = url_param("url"); ###### # Was the referring URL in the database? or not ###### my $data = qq(SELECT id, views, last_ip, last_time, all_ip FROM track +where id = "$url"); my $sth = $dbh->prepare($data); $sth->execute() or die $dbh->errstr; if ($sth->rows < 1) { my ($id, $views, $last_ip, $last_time, $all_ip); $sth->bind_columns(\$id, \$views, \$last_ip, \$last_time, \$all_ip) +; # nothing was here so we'll setup the values starting with 1 view } else { my ($id, $views, $last_ip, $last_time, $all_ip); $sth->bind_columns(\$id, \$views, \$last_ip, \$last_time, \$all_ip) +; # this URL was tracked previously, we have to autoincrement $views +and store all our info }


"Age is nothing more than an inaccurate number bestowed upon us at birth as just another means for others to judge and classify us"

sulfericacid

Replies are listed 'Best First'.
Re: MySQL logic
by jZed (Prior) on May 27, 2005 at 20:08 UTC
    First, use RaiseError since you are not consistent about checking errstr (and in fact are checking a $dbh errstr on a $sth call).

    Second, USE PLACEHOLDERS! (I yell because it's been said so many times on perlmonks it's hard to believe you haven't seen it).

    Third, read the DBI docs about the rows() method - it rarely does what you want with a select statement. Instead, test the return value of the execute statement (but read the DBI docs about what execute returns).

    update and bind_columns should come before an execute, not after (my bad) (thought it's hard to tell what you are wanting to do with it). Also look up MySQL's replace command if you are going to be updating a row (no need to check first).

    I really recommend you read the docs and some tutorials on DBI since your mistakes are DBI mistakes, not SQL or MySQL mistakes (in this case)
Re: MySQL logic
by samtregar (Abbot) on May 27, 2005 at 20:30 UTC
    I recommend you pick up a copy of Programming the Perl DBI. It's a much better guide to using DBI than Perlmonks. Of course, you could just read the manual (DBI) but the book is probably friendlier.

    -sam

Re: MySQL logic
by johnnywang (Priest) on May 27, 2005 at 21:19 UTC
    First, it seems you're lacking some basic understanding of database/sql (e.g., you only have a select query, but you want to bind to a "insert" or an "update"), this really has nothing to do with perl. So I'd suggest do some searching/reading on that, probably before DBI.

    Second, it seesm you're doing this in real-time (i.e., while the request comes in), I'd say that's not necessary in general, you could just run a perl script periodically against your access log, which will make your web site faster.

Re: MySQL logic
by monarch (Priest) on May 28, 2005 at 06:08 UTC
    A couple of general comments on my approach to databases. Note it should all be taken with a grain of salt because I'm no DBA.

    First and most importantly I think about the database schema (or layout of the tables in my database) because if I don't do this right then the whole point of the project is lost.

    Draw a diagram with rectangles.. each rectangle is a TABLE containing the FIELDS within that constitute one row in the table. In this case you have:

    |-USER------| | id | (a unique identifier for the row) | views | (count of how many pages user has viewed) | last_ip | (the last IP address user used) | last_time | (the last time we saw the user) | url | (the user's URL) |-----------|

    I suggest the all_ip function is performed in a different table:

    |-ALLIP-----| | id | (a unique identifier for the row) | user_id | (the id of the user that used this IP) | ip | (the IP address) | time | (the time it was seen) |-----------|

    Now, whenever you want to query the ALLIP table you can use a WHERE clause to bind the two tables together so you can reference the customer involved.

    e.g. what IP addresses has a customer used?

    my $sql = <<SQLCODE; SELECT a.ip FROM ALLIP a, USER u WHERE a.user_id = u.id AND u.id = ? GROUP BY a.ip SQLCODE my $sth = $dbh->prepare( $sql ); if ( $sth && $sth->execute( $user_id ) ) { while ( my $row = $sth->fetchrow_arrayref() ) { print( "IP address " . $row->[0] . "\n" ); } $sth->finish(); } else { die( "Database error " . $dbh->errstr . "\n" ); }

    Now onto your question. How do you check for something and update it if it already exists or add it if it doesn't.. good question, it will be more verbose than you were hoping..

    my $found_id = undef; my $sql = <<SQLCODE SELECT id FROM track WHERE url = ? SQLCODE my $sth = $dbh->prepare( $sql ); if ( $sth && $sth->execute( $url ) ) { if ( my $row = $sth->fetchrow_arrayref() ) { $found_id = $row->[0]; } } else { die( "Database error " . $dbh->errstr . "\n" ); } if ( $found_id ) { # perform update $sql = <<SQLCODE; UPDATE user SET view = view + 1, last_ip = ?, last_time = ? WHERE id = ? SQLCODE my $sth = $dbh->prepare( $sql ); if ( $sth && $sth->execute( $last_ip, time(), $found_id ) ) { if ( my $row = $sth->fetchrow_arrayref() ) { $found_id = $row->[0]; } } else { die( "Database error " . $dbh->errstr . "\n" ); } } else { # perform insert # code left to read as an exercise }
Re: MySQL logic
by trammell (Priest) on May 27, 2005 at 22:44 UTC
    In addition to the other suggestions above, I see you have:
    my $dbh = DBI->connect("DBI:mysql:$dbase", $mysql_user, $mysql_pass) or print DBI=>"errstr";
    where you probably mean
    my $dbh = DBI->connect("DBI:mysql:$dbase", $mysql_user, $mysql_pass) or print DBI->errstr;

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others about the Monastery: (5)
As of 2024-04-25 13:49 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found