Download chap10b

Survey
yes no Was this document useful for you?
   Thank you for your participation!

* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project

Document related concepts

DBase wikipedia , lookup

Relational algebra wikipedia , lookup

Microsoft Access wikipedia , lookup

Oracle Database wikipedia , lookup

Concurrency control wikipedia , lookup

Btrieve wikipedia , lookup

Extensible Storage Engine wikipedia , lookup

Entity–attribute–value model wikipedia , lookup

Ingres (database) wikipedia , lookup

Database wikipedia , lookup

Microsoft Jet Database Engine wikipedia , lookup

Open Database Connectivity wikipedia , lookup

Microsoft SQL Server wikipedia , lookup

Clusterpoint wikipedia , lookup

Versant Object Database wikipedia , lookup

SQL wikipedia , lookup

Relational model wikipedia , lookup

Database model wikipedia , lookup

PL/SQL wikipedia , lookup

Transcript
(Chapter 10 continued)
• Our examples feature MySQL as the database engine.
• It's open source and free.
• It's fully featured.
• And it's platform independent for the most part.
• These examples and concepts carry over to other database
systems.
• The DBI (database Interface) module provides the
objects used in the program to connect to, prepare, and
deliver SQL statements to the database engine.
• The DBD::mysql module handles the details of the
connection behind the scenes.
• Connecting to a different database requires only a
different DBD (Database Driver) module be installed.
Overview of Perl<--->MySQL interface
• You construct SQL queries with the DBI module in a Perl
program.
• The driver handles the connection details.
• Raw SQL is delivered to the database engine.
• Returned data is stored in a DBI object, which has methods
for extracting the data.
Overview of objects provided by the DBI module.
Database object: This is the object that holds the connection
to the desired database. It works kind of like a file handle
since it references the open database connection. For that
reason, we will call this object the database handle.
Query object: This object is created by calling a method of
the database handle. It is through methods of this object that
we are able to send SQL statements to the database system.
Driver object: This object is seldom used. It is only used for
performing administrative tasks, such as creating or destroying
an entire database, which has nothing to do with SQL. Note
that we are not talking about creating or destroying tables;
which is done through SQL statements. We include this for
completeness, and will not have occasion to use this object.
The following discussion assumes we have already imported
the DBI module into the Perl program:
use DBI;
Connecting to a database:
$dbhandle =
DBI->connect("DBI:driver:databaseName",
user, password);
• $dbhandle is reference to the database object created by
this constructor.
• This statement assumes the MySQL daemon is running on
the same computer as the Web server. Otherwise, more
information such as the server address and port number is sent
to the constructor.
Example: Connect to a MySQL database named store, where
storeuser is the user name and pass is the password.
$dbhandle = DBI->
connect("DBI:mysql:store","storeuser", "pass")
or &errorPage(DBI->errstr());
The errstr() method returns a string containing useful
error messages on failed connection attempts.
Closing an open database connection is very similar in concept
to closing an open file.
$dbhandle -> disconnect();
Now assume we have an open $dbhandle.
Using the query object:
There are 4 steps in executing a SQL query using DBI.
1. Prepare the SQL statement.
2. Execute the SQL statement.
3. Fetch any returned results from the query object. This step
is only necessary for SELECT queries. CREATE, INSERT,
DELETE, and DROP queries don't return useful data.
4. Clear the query object.
1. Preparing an SQL statement.
$qObj =
$dbhandle->prepare("SQL_statement_as_string");
• $qObj is reference to a new query object.
• It it usually requires some work to build an SQL statement in
a Perl program, so we typically store the SQL statement in a
Perl variable such as $sql.
$sql = [work to put together an SQL statement];
$qObj=$dbhandle->prepare($sql)
or &errorPage($dbhandle->errstr());
• Also, it is important to send descriptive preparation
messages where you can see them during development.
• One important issue when building SQL statements is that
special characters like (' and %) are properly escaped in the
data.
• The database object has a quote() method to handle that
job for you.
$sql = $dbhandle->quote("somestring");
Example: Building an SQL statement where the data comes
from user input. This adds a row to some_table, which has
only one column.
$sql = "INSERT INTO some_table VALUES ("
. $dbhandle->quote($formHash{"someName"})
. ")";
If you look at the resulting string, it is an SQL statement
squashed into one line.
"INSERT INTO some_table VALUES (someValue)"
Here someValue would be the data submitted by the user and
properly quoted using the quote() method.
2. Executing the SQL statement.
• The result of the prepare() method of the database object
is that the query object is constructed and the SQL statement is
stored in the query object in some format.
• The execute() method of the query object takes that
internally stored SQL statement and sends it to the database
engine (with the help of the proper driver).
$qObj->execute() or &errorPage($qObj->errstr());
• Upon a successful execution, the query object contains data
returned from the database query. Again, we are usually only
concerned with the returned data when it is the result of a
SELECT query which returns a sub-table of data..
3. Fetching the results from the query object.
• The fetchrow_array() method returns one row at a
time out of the query object, with the columns already split
into an array.
@first_row = $qObj->fetchrow_array();
• You can fetch out one row at a time like this.
• But, often you need to iterate over the rows.
while(@row = $qObj->fetchrow_array()) {
do something with @row;
}
• A row can also be fetched as a hash using the
fetchrow_hashref() method.
$rowhashref = $qObj->fetchrow_hashref();
%row = %$rowhashref;
• As its name indicates, this method returns a scalar reference
to a hash which is de-referenced into a hash variable.
• The hash contains one row of the returned sub-table.
• The keys are the column names (table keys).
• For SQL statements that only change the table, such as
UPDATE and DELETE, you can get a count of how many rows
were affected using the rows() method.
$number_changed = $qObj->rows();
• When $qObj contains a sub-table returned from a SQL
SELECT statement, the rows method works a bit differently.
The query object only knows how many rows have been
returned after all rows have been fetched out of the object.
Presumably, the query object counts the rows as they are
fetched out of the object. Fortunately, there is a simple trick to
enable you to quickly determine the number of returned rows.
$qObj->fetchall_arrayref();
$number_of_rows = $qObj->rows();
• The fetchall_arrayref() method returns a scalar
reference to a two dimensional array that contains the whole
table, fetched out of the object. But that is not important,
because we do not intend to use the array!! The important
thing is that now the query object knows how many rows were
returned. Note that if you want to re-fetch the rows, starting
from the first, after the above code has executed, you must reexecute (step 2) thereby refreshing the query object with a
newly returned sub-table.
4. Clear the query object.
$qObj->finish();
• Omitting this step is usually not fatal. We will endeavor to
remember this step as a matter of good programming
practice.
Database Example: state table
Like other state-keeping tools we have seen (our toolkit
functions and the CGI::SecureState module), database
utilities to handle state-keeping needs should:
• Generate long session IDs.
• Create state records (formerly state files) identified by a long
ID.
• Police the state table (formerly file cache) so that it doesn't
accumulate records without bound.
• Be able to read a state record (into a hash or hash-like
format).
• Be able to overwrite (update) a state record.
• Be able to provide session timeouts.
Example state table keeping state records for the online quiz
example from Chapter 7.
• Will use Perl's time function to set the age of a state record.
• The difference between the current value returned by
time and the value in the state record will be the age of
the record.
• The difference will be in seconds, due to the way time
works.
• The states table would need to exist in advance and the Web
application merely adds (and deletes) state records.
Signature for the database version of get_long_id:
sub get_long_id_db {
my ($dbhandle, $table_name, $cache_limit,
$file_life_span) = @_;
• The $dbhandle (connection to the database)needs to exist
in advance.
• The $table_name is analogous to the name of a state file
directory.
• The $cache_limit works as before.
• We still give the $file_life_span is given in days. (We
convert to seconds as needed in the function.)
Logic of get_long_id_db:
See source file toolkit_db.pl
• Count the number of records in the table: SELECT an entire
column and count the rows.
• If the number of rows exceeds the $cache_limit
• DELETE FROM $table_name WHERE …
• Again, count the number of records in the table.
• If the $cache_limit is still exceeded
• Deny session / warn server administrator
• Create a new state record with an ID and time stamp
• Return the ID
Note: Before we created a state file with a call to
write_state. Here, the state record needs to exist before
we can do an SQL UPDATE to it with the new
write_state_db function.