Show Contents Previous Page Next Page Chapter 5 - Maintaining State / Storing State Information in SQL Databases The DBI interface provides methods for opening SQL databases, sending queries to the opened database, and reading the answers returned by those queries. To open a database, you call DBI->connect() with the "data source name," a string that tells the database driver where the database is located. If the database requires a username and password for access, you can pass that information in the connect() call as well. The format of the data source name is DBMS-specific. For a MySQL database, it looks like this: "dbi:mysql:$database:$hostname:$port"
All MySQL data sources begin with "dbi:mysql" $dbh = DBI->connect('dbi:mysql:www', 'games', 'grok');
If successful, connect() returns a database handle, The database handle has several methods, the most important of which are do(), prepare(), and errstr(). do() is used to execute SQL statements which do not return a list of records, such as INSERT, DELETE, UPDATE, or CREATE. If the operation is successful, do() returns a count of the number of rows modified. For example, the following query sets the GAMENO field of all sessions to 1 and returns the number of rows affected: $count = $dbh->do('UPDATE hangman SET GAMENO=1'); die $dbh->errstr unless defined $count; If the database encountered an error while processing the statement (for example, the SQL contained a syntax error), it will return undef. The errstr() method can be used to retrieve an informative error message from the driver. SELECT queries can return a potentially large number of records, often more than will fit into memory at once. For this reason, the results from SELECT queries are returned in the form of statement handle objects. You then call the statement handle's fetch() method repeatedly to retrieve each row of the result. Here's an example of retrieving the session_id and WORD fields from each session in the hangman database: $sth = $dbh->prepare('SELECT session_id,WORD FROM hangman') || die $dbh->errstr; $sth->execute() || die $sth->errstr; while (my $row = $sth->fetch) { my($session, $word) = @$row; print "session => $session, word => $word\n"; } $sth->finish;
The example starts with a call to the database handle's prepare() method with the text of the SQL SELECT statement. prepare() parses the SQL and checks it for syntactic correctness but does not actually execute it. The query is returned as a statement handler which we store into the variable
Next we call the statement handler's execute() method. This performs the query and returns either the number of rows retrieved or undef if an error occurred. In the case of a syntactically correct query that happens to return no rows (because the table is empty or because no records satisfied the criteria in the WHERE clause), execute() returns the value Now we enter a loop in which we call the statement handler's fetch() method. Each time it's called, fetch() returns the requested columns in the form of an array reference. To retrieve the values themselves, we just dereference the value into a list. Because we requested the columns session_id and WORD, we get a reference to a two-item array back from fetch(). When there are no more rows left, fetch() returns undef. DBI actually offers a family of fetch functions. fetchrow_array() is like fetch(), but it dereferences the row first and returns an array corresponding to the list of requested columns. Another function, fetchrow_hashref(), turns the current row into a hash of the column names and their values and returns the hash's reference to the caller. This allows us to make the example above more readable at the cost of making it somewhat less efficient: $sth = $dbh->prepare('SELECT session_id,WORD FROM hangman') || die $dbh->errstr; $sth->execute || die $sth->errstr; while (my $row = $sth->fetchrow_hashref) { print "session => $row->{session_id}, word => $row->{WORD}\n"; } $sth->finish; DBI also provides a fetchrow_arrayref() method for fetching the row as an array reference. It is identical in every respect to fetch(). When you are finished with a statement handler, you should call its finish() method in order to free up the resources it uses.
The last thing you need to know about statement handlers is that many DBI drivers allow you to put placeholders, indicated by the $sth = $dbh->prepare('SELECT * FROM hangman WHERE session_id=?');
Now we can fetch information on session $sth->execute('fd2c95dd'); The same statement handler can later be used to fetch information from other named sessions. You should still call finish() at the end of each series of fetches, even though you are going to reuse the statement handler. Failure to do so can lead to memory leaks. When you are completely finished with a database handle, you should call its disconnect() method in order to sever the connection and clean up. Show Contents Go to Top Previous Page Next Page
One of the problems with using DBI databases from conventional CGI scripts is that there's often a significant amount of overhead associated with opening a database connection. When you run a $DBH ||= DBI->connect($data_source, $user, $password); Apache::DBI, a module written by Edmund Mergl, makes handling persistent database connections even easier. It replaces DBI's connect() and disconnect() methods with versions that handle persistent connections behind the scenes. connect() maintains a cache of database handles and returns one of them in response to attempts to open the same database multiple times. It also checks that the database handle is still "live" (some databases have a nasty habit of timing out inactive sessions) and reconnects if necessary. disconnect() is replaced by a no-op so that database handles are not inadvertently closed.
To activate Apache::DBI, you need only # perl startup file
use Apache::DBI ();
use Apache::Registry ();
use CGI::Cookie ();
. . . etc.
If you don't have a Perl startup file, you can also load the module at server startup time by adding this directive to one of the server configuration files: PerlModule Apache::DBI
You will now have persistent database connections when using Copyright © 1999 by O'Reilly & Associates, Inc. |
HIVE: All information for read only. Please respect copyright! |