Web based applications often need to access information that is stored in some kind of a database, the information needed includes everything from user account information to product lists. Although it is possible to create simple "flat-file" databases using the Perl I/O functions, there are numerous advantages to using a real database system to store data. In this section we will explore the Win32:ODBC Perl module which provides access to nearly any database stored on a Windows based PC from a Perl program. Although we will focus on the interface between Perl and a MS Access database, the concepts extend to many other operating system/database system combinations.
We will examine the steps necessary to develop and install a sample Perl CGI program that accesses user account information that is stored in a MS Access Database. Although we develop a working CGI program that uses a database to store information, a complete discussion of database connectivity, SQL, and Perl ODBC module are beyond the scope of this course. Links are provided to sources of more complete information on these topics.
Microsoft Access is a fairly simple database system intended to support small databases for individual use, or use by small workgroups. Although Access is not the best choice for supporting the needs of a large web-based application, we use it because it's easy to get started (you don't need to be a database expert to do simple things) and because we all already have it. There are many other commercial database systems that are more powerful and would generally be used to support real web-based applications (for example, Oracle is used by many large web-sites).
In Access you can create a database that includes multiple tables. Each table is composed of a list of fields, each field has a name, type and value (there are many other attributes that can be associated with fields as well). The fields correspond to the columns in a table.
The rows in a table correspond to records, so the number of rows in a table corresponds to the number of records. (The number of columns in a table is the number of fields.).
For our sample CGI system we need a single table that holds user ids and passwords, we will use this database to verify logins that are sent by a browser when a user fills in a login form and presses submit. The Perl CGI program will compare the name and password entered by the user against the records (rows) in the database to see if the user account exists and the password is correct.
Our database needs a single table that contains all the user-id/passwrod records. To create this table you should start up Access and create a new database (I named my database "eiwdb"). When you create a new database you need to tell Access where the file should exist - make sure you remember where you told Access to put the file. At this point your Access window should look like this:

Now we need to create the table that will hold the userids and passwords. Press on "Create Table in Design view", this will bring up a screen that allows you to enter the names (and types) of the individual fields (columns) you want in the table. For this sample, I've named the fields "Name" and "Password". The data type for each of these fields is the default type "text" - this means that the fields can hold any kind of textual data, there are other field type for numbers, dates, etc. At this point the Access window looks like this:

Each table in an Access Database needs to include a primary key, which is a field whose value will be unique for each record. For our example the field named "Name" will be unique for each record (each user will need to have a different userid). To tell Access to use the field named "Name" as the primary key, you right-click on the Name field and select "Primary Key". If you don't select a primary key Access will automatically create a new field that will become the primary key (this is also fine for our application).
Now close the table you have just created, when you do this Access will ask you if you want to save changes and will allow you to specify the name of the table - your table should be named "password". Your Access window should now look like this:

You can now add some records to your database. For the sample application we are developing (a simple login/user account creation CGI) we will be creating records in the database from Perl (when a user creates a new account we will add the name and password to the database), but for now you might want to add a few records while in Access. Doubleclick on the password table icon to open the table and begin entering values. The table will appear in a form just like a spreadsheet, and you can type in values directly. Here is what my table looks like after adding 2 user accounts: one for "Bush" and one for "Gore":

Now the database we need is complete, you can close the Access program. In a real web application there are other fields you may want to put in a table that holds user account information, for example you might want to store a session-key in the database, or include personal information like the full name, address, credit card numbers, etc. A real application would also typically require other tables in the database, for example an online store might have a table that holds product information (fields like product name, product number, price, the name of a file that holds a picture, etc).
To access your database from a Perl program you use the
Win32::ODBC Perl module. Before looking at the mechanics of
how to so this from Perl, we should talk about what ODBC is and why it's used.
ODBC stands for "Open Database Connectivity". This is a Microsoft technology that provides access to many relational database systems with one single programming interface. This simplifies the writing of programs that use relational databases, since you don't need to worry about the specifics of which database is used (Access vs. Orcale vs. whatever...), the program is the same no matter what database system is used. To use ODBC you register your specific database with the ODBC manager - this associates a name (called a "Data Source Name") with the specific database you have on your PC. Any program that wants to access your database needs to know the "Data Source Name", but nothing else (the program doesn't need to know if the database is actually part of an Oracle database or a Microsoft Access database).
When we use the Win32::ODBC Perl module to access our
password database we will need to first register the database with the
ODBC manager installed on the PC. If you don't have an ODBC manager
installed on your PC you will need to get one (from Microsoft). The
ODBC manager is available via the Control Panel - you should bring up
the control panel and double click on "ODBC Data Sources (32bit)". You
should see something like this:

To register your Access database with the manager you should select the "User DSN" tab and press the "Add" button. This should give you a list of data source drivers you can choose from, you want to select "Microsoft Access Driver".

Now press "Finish" and you should get a dialog that asks for a Data Source Name and Description. You must provide a name, this name will be used by your Perl program to identify the database. You also need to press the "Select" button to select the MS Access file you just created. Here is what my dialog looks like after I've typed in a name and description and selected the Access database file:

Close the dialog by pressing "OK" and your new DSN should now show up in the list of User Data Sources in the ODBC control panel:

Now any program that uses the ODBC interface can access your new database
using the DSN you specified. The next step is to create a Perl program that
uses Win32::ODBC to access the database.
Win32::ODBC is the name of a Perl module that
provides connectivity to ODBC databases. To tell Perl about a module that
you want to use in your Perl program you use the use command
like this (at the top of your perl program):
|
The Win32::ODBC module is based on a Perl object
interface, we have not talked about Perl objects at all. The general
idea is just like C++: there are objects that have methods and data
associated with them, and to use an object you need to know how to
create the object, and what methods and data members are available. You can
get complete information about the Perl Win32::ODBC module at
http://www.roth.net/perl/odbc/, we will just cover what we need
for our sample application.
Creating a Win32:ODBC object requires that you provide the "DSN" that you created when you registered your Access database file with the ODBC control panel. In my example I used the name "eiw", and here is the Perl code that would create an ODBC object that will be used to access this database:
|
The Perl variable $db created above corresponds to
a Win32::ODBC object that can now be used to access the database.
To call a method associated with this object we use a syntax similar to
the C++ method calling syntax, although we need to treat the
$db variable as an object reference. The following code
calls the TableList() method - this method returns an
array, each element in the array is the name of a table in the
database (there can be many tables in one database):
|
NOTE: Since we already know the name of the
table in our database we don't actually need to call
TableList(), this is just an example of the syntax used
when calling a object method in Perl.
The methods use to extract information from the database first require that we establish the subset of the data we wish to deal with. For our application we can simply select the table "password", in general we can select specific fields in a table (and much more complex subsets involving multiple tables). Before we can show how to tell the database obejct what table we want to deal with, we need to talk about the language used to communicate with the database: SQL.
SQL is "Structured Query Language", a popular language used to communicate with database systems. SQL is quite complex, although the subset of this language we need to know to use databases in our CGI programs is very simple. For the sample CGI program we are developing the operations we need are to extract name/password pairs from the database and to add new name,password pairs to the database. We will look at the commands to accomplish each of these tasks, for a complete reference to SQL you should look at the following:
SELECT commandThe SELECT SQL command establishes the subset of the
database that we want to deal with. For our application we would like
to access the fields "Name" and "Password" from the table named
"password", here is the SELECT command that will do
this:
SELECT Name, Password FROM password
The general form of the SELECT command looks like this:
SELECT column1, column2, ..., columnN FROM table1, table2, ..., tableN [WHERE clause]
As you can see, any number of fields (columns) can be selected from
and number of tables. The [WHERE clause] is
optional and can be used to specify a subset of rows in the table. For
example, if you had a product list in a database you could create a
SELECT command that would select only those rows that had
a field named Price with a value less than $100. We don't need the
WHERE for our simple application.
To send the database our SELECT command that extracts
all the names and passwords from the password table, we use the
Sql method of our database object:
|
Once you have sent the SELECT command to the database,
you can extract the resulting rows one at a time by using the
FetchRow method. This tells the database to grab the next
row of the selected database, the method returns TRUE as long as there
are rows remaining (false means the end of the table has been reached).
To get the data in to perl variables, we use the Data method,
there are other Win32:ODBC database object methods that will allow us
to get at the data in other ways, this is just the simplest.
The following Perl code will print out all the names and passwords
in the password table, note that we now do some error checking when
sending the SELECT command to the database:
|
INSERT commandOur login handling program will also allow users to create
accounts - this means we need to add a new row (record) to the
password database. We use the SQL INSERT command
to accomplish this, here is the general syntax for the INSERT
SQL command:
INSERT INTO table (column1, column2, ... columnN) VALUES (value1, value2, ..., valueN)
column1, column2, are the field names and
value1, value2, are the field values. For field values
that are numbers you can use the value directly, for field values that
are text strings (like names and passwords) you should put each field
value inside single quotes.
Here is the perl code that will add a new name,password pair to the
database. This code assumes the name to be added is in the perl
variable $n and the password is in $p:
|
The above command used the SQL INSERT command to add
a new row into the password table, the field named
Name gets the value $n and the field named
Password gets the value $p. Note that the
Sql method returns TRUE if there is some kind of error, so
we would always check for errors like this:
|
We now have enough Win32:ODBC code to support our simple login/account creation application. Before we look at the entire system, we will create some perl subroutines that do most of the database work. This allows the rest of the Perl code to operate using simepl perl variables, and makes it much easier to write (and read) the code that deals with the specifics of our application.
Here are two Perl subroutines that can handle most of the
database operations we need. Both of these subroutines must be
passed a Win32::ODBC database object reference, so the database
must be opened before calling the subroutines. The subroutine
named read_passwords reads all the name,password
pairs from the database and returns these as an associative
array (index by name):
|
You may notice that this code uses the fatal_error subroutine
that is part of the eiw-cgi.pl library. Remember that this
subroutine prints an error message as HTML and then exits. The next subroutine
takes care of adding a new name,password to the database. This subroutine
expects to get a database object reference, a name and a password as
parameters:
|
Below is the HTML form that will be used with our simple application. There are 2 different forms, one for returning users (they supply a name and password only), and one use by new users to create an account. When a submission is made to our CGI, the name/value pair of the submit button is used to distinguish between the 2 different forms. Both submit buttons are named "operation", the value of the login button is "Login" and the value of the new account button is "Create". Our CGI first checks the value of the field named "operation" to decide whether the user is logging in or creating a new account.
|
|
The "new account" form includes fields for the user's full name and credit card number - these aren't used by this sample system (they are just there to give you an idea of how this might be used in a real application).
The complete CGI program is shown below - this program first connects to the database (using the DSN "eiw") and grabs all the name,password pairs. Next the program determines whether this is a login request or a request to create a new account, and handles both cases. Logins that succeed (the name and password match a record in the database) result in sending back an html file that contains a message indicating the login was a success. After a successful account creation, the original login form is sent back.
The subroutines that do the database operations are included here as well (so you can copy the entire program from here if you want to play with it).
|