📄 ch18.htm
字号:
<HTML>
<HEAD>
<TITLE>Chapter 18 -- Databases for Perl</TITLE>
<META NAME="GENERATOR" CONTENT="Mozilla/3.0b5aGold (WinNT; I) [Netscape]">
</HEAD>
<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#0000EE" VLINK="#551A8B" ALINK="#CE2910">
<H1><FONT COLOR=#FF0000>Chapter 18</FONT></H1>
<H1><B><FONT SIZE=5 COLOR=#FF0000>Databases for Perl</FONT></B>
</H1>
<P>
<HR WIDTH="100%"></P>
<P>
<H3 ALIGN=CENTER><FONT COLOR="#000000"><FONT SIZE=+2>CONTENTS<A NAME="CONTENTS"></A>
</FONT></FONT></H3>
<UL>
<LI><A HREF="#TheDBMPackages" >The DBM Packages</A>
<LI><A HREF="#ViewingYourData" >Viewing Your Data</A>
<LI><A HREF="#AddingandRemovingItems" >Adding and Removing Items</A>
<LI><A HREF="#OperationsonaDBMFile" >Operations on a DBM File</A>
<LI><A HREF="#UsingDBMinModules" >Using DBM in Modules</A>
<LI><A HREF="#MultipleDBMFiles" >Multiple DBM Files</A>
<LI><A HREF="#TheCatchwithDBMUtilities" >The Catch with DBM Utilities</A>
<LI><A HREF="#WhatIstheDBIPackage" >What Is the DBI Package?</A>
<UL>
<LI><A HREF="#AvailablePackages" >Available Packages</A>
</UL>
<LI><A HREF="#RDB" >RDB</A>
<LI><A HREF="#Summary" >Summary</A>
</UL>
<HR>
<P>
There are two ways to look at working with databases in Perl.
You can either implement the database entirely in Perl or use
Perl as an interface to existing database engines on your machine.
You can use stand-alone database packages, such as the DBM package
that comes with Perl, or you can get other packages, such as the
RDBM package, off the Internet. To use Perl as an interface to
a commercial package, you can use driver front-ends to the database
engine for the package.
<H2><A NAME="TheDBMPackages"><FONT SIZE=5 COLOR=#FF0000>The DBM
Packages</FONT></A></H2>
<P>
Perl comes with a set of database management (DBM) library files.
Here's the list of packages that come with the latest version
of Perl (5.002):
<UL>
<LI><TT><FONT FACE="Courier">GDBM_File.pm</FONT></TT>-GNU's database
interface files
<LI><TT><FONT FACE="Courier">NDBM_File.pm</FONT></TT>-Berkeley
UNIX compatibility
<LI><TT><FONT FACE="Courier">ODBM_File.pm</FONT></TT>-Standard
Perl package
<LI><TT><FONT FACE="Courier">SDBM_File.pm</FONT></TT>-Standard
Perl package
<LI><TT><FONT FACE="Courier">AnyDBM_File.pm</FONT></TT>-Virtual
classes for any of the above database interfaces
</UL>
<P>
The <TT><FONT FACE="Courier">AnyDBM_File</FONT></TT> package encapsulates
the rest of the packages. If you use the <TT><FONT FACE="Courier">AnyDBM</FONT></TT>
file, you'll automatically load one of the standard packages from
the previous list. To use the <TT><FONT FACE="Courier">AnyDBM_File</FONT></TT>
package, insert the following statement at the start of your Perl
script:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">use AnyDBM_File;</FONT></TT>
</BLOCKQUOTE>
<P>
There is nothing preventing you from explicitly naming a particular
DBM package to override the defaults used by the <TT><FONT FACE="Courier">AnyDBM_file</FONT></TT>
package. To use the <TT><FONT FACE="Courier">GDBM_File</FONT></TT>
explicitly, insert this statement instead:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">use GDBM_File;</FONT></TT>
</BLOCKQUOTE>
<P>
A DBM, when used with these packages, is a mapping of an associative
array to a file on disk. To map the associative array to disk,
you use <TT><FONT FACE="Courier">dbmopen()</FONT></TT> to create
or open an existing file, make all the modifications to the associative
array, and then close the file with a call to <TT><FONT FACE="Courier">dmbclose()</FONT></TT>.
<P>
I covered how to bind variables to associative arrays and how
to use the <TT><FONT FACE="Courier">tie()</FONT></TT> function
in <A HREF="ch6.htm" tppabs="http://www.mcp.com/815097600/0-672/0-672-30891-6/ch6.htm" >Chapter 6</A>, "Binding Variables to
Objects." In the future, most <TT><FONT FACE="Courier">dbmopen()</FONT></TT>
function calls will be replaced by, or at least internally work
as, <TT><FONT FACE="Courier">tie()</FONT></TT> function calls.
Basically, a DBM file will be tied to an associative array. Subsequent
updates to the associative array will be reflected in the file
on disk. However, you will come across legacy code that does use
the <TT><FONT FACE="Courier">dbmopen()</FONT></TT> and <TT><FONT FACE="Courier">dbmclose()</FONT></TT>
functions, so it's important to see how these work together. Also,
you may find it easier to use these DBM functions to program for
quick prototyping than to have to code the callback functions
required for the <TT><FONT FACE="Courier">tie()</FONT></TT> function.
After you've read this chapter, you should be able to decide whether
to use DBM functions or write the functions for database access
using the <TT><FONT FACE="Courier">tie()</FONT></TT> function.
<P>
Here's an example to illustrate how the DBM files work. First,
I'll create a small database of some stock symbols and the names
of the companies. The file containing this data sample is called
<TT><FONT FACE="Courier">sym.txt</FONT></TT> and is partially
shown here:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">$ <B>head sym.txt<BR>
</B>ASZ AMSCO INTL Inc<BR>
AMSR AMSERV HEALTHCARE<BR>
ASO AMSOUTH BAncORP<BR>
AMTC AMTEch<BR>
AMTL AMTROL<BR>
AVFC AMVESTORS FIN CORP<BR>
AMW AMWEST INSURAncE GROUP<BR>
AMLN AMYLIN PHARMACEUTICALS<BR>
AAC ANACOMP Inc<BR>
Apc ANADARKO PETROLEUM CORP<BR>
$</FONT></TT>
</BLOCKQUOTE>
<P>
This file contains several lines of records where each record
has two items of data: the first column is the stock ticker symbol
followed by the company name. Note that a company name can contain
one or more space characters.
<P>
Now I'll construct a mini-database of all company names indexed
by their stock symbol. To use the DBM utilities for this endeavor,
I would use the script shown in Listing 18.1.
<HR>
<BLOCKQUOTE>
<B>Listing 18.1. Creating a DBM file.<BR>
</B>
</BLOCKQUOTE>
<BLOCKQUOTE>
<TT><FONT FACE="Courier"> 1 #!/usr/bin/perl<BR>
2 # --------------------------------------------------------
<BR>
3 # Sample script to create a DBM repository.<BR>
4 # Input file "sym.txt" to the script has the
format:<BR>
5 # SYMBOL Company Name
<BR>
6 # --------------------------------------------------------
<BR>
7 #<BR>
8 # Use the default DBM utilites<BR>
9 #<BR>
10 use AnyDBM_File;<BR>
11 open(SFILE, "sym.txt") || die "\n Cannot open
sym.txt $!\n";<BR>
12 #<BR>
13 # Open the database "ticker". If it does not exist,
create it.<BR>
14 # Map the hash stocks to this database.<BR>
15 #<BR>
16 dbmopen(%stocks,"ticker",0666);<BR>
17 while (<SFILE>) {<BR>
18 chop;<BR>
19 ($symbol,@name) = split('
',$_);<BR>
20<BR>
21 $stocks{$symbol} = join(' ',@name);
<BR>
22 # print " $symbol [ @name ] \n";
<BR>
23 }<BR>
24 #<BR>
25 # Close the input file<BR>
26 #<BR>
27 close(SFILE);<BR>
28 #<BR>
29 # Commit changes in hash to disk for the next flush.<BR>
30 #<BR>
31 dbmclose(%stocks);</FONT></TT>
</BLOCKQUOTE>
<HR>
<P>
In Listing 18.1, the <TT><FONT FACE="Courier">AnyDBM_File</FONT></TT>
package is used at line 10 to get the best available package for
the system. You can override the type by replacing the <TT><FONT FACE="Courier">AnyDBM_File</FONT></TT>
package with a DBM package of your choice. In line 11, the input
file is opened.
<P>
Line 16 creates a DBM called <TT><FONT FACE="Courier">ticker</FONT></TT>
and maps it onto an associative array called <TT><FONT FACE="Courier">%stocks{}</FONT></TT>.
Note that you are actually creating two files called <TT><FONT FACE="Courier">ticker.pag</FONT></TT>.
The file permissions given for this <TT><FONT FACE="Courier">open</FONT></TT>
are 0666 so that it's possible for all other users to use this
DBM.
<P>
In lines 17 through 23, the symbol names are read in, and the
values are assigned to the newly created hash, called <TT><FONT FACE="Courier">stocks</FONT></TT>.
Lines 18 and 19 simply take the text input from the <TT><FONT FACE="Courier">sym.txt</FONT></TT>
file and separate it into a symbol and a company name. At line
21 a value is assigned to the associative array using the symbol
as the index into the array. Now that this array has been mapped
to the disk, the data can be kept in the array even after the
script that created this file is long gone.
<P>
Note also that the <TT><FONT FACE="Courier">join() </FONT></TT>function
is used in line 21 to piece together the items of names of the
companies into one string. Had the <TT><FONT FACE="Courier">join()</FONT></TT>
function not been used, <TT><FONT FACE="Courier">$stocks{$symbol}</FONT></TT>
would contain the number of items of the <TT><FONT FACE="Courier">@names</FONT></TT>
array and not the contents.
<P>
In line 31 the <TT><FONT FACE="Courier">dbmclose()</FONT></TT>
function is used to commit the changes to disk. If you do not
use <TT><FONT FACE="Courier">dbmclose()</FONT></TT>, your DBM
file modifications are not be saved to disk. The <TT><FONT FACE="Courier">dbmclose()</FONT></TT>
function disconnects (or un-<I>tie</I>s) the hash from the file
on disk so that any changes made to the hash after the <TT><FONT FACE="Courier">dbmclose()</FONT></TT>
function are made as if to an uninitialized associative array.
When the contents of the hash will be flushed to disk depends
on the underlying system. As far as the program is concerned,
the hash connected to the underlying database is not initialized
anymore.
<P>
Two files are created with the use of the <TT><FONT FACE="Courier">AnyDBM_File</FONT></TT>
package. These are the two files that were created by the script
in Listing 18.1 when I ran it:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">-rw-r--r-- 2 khusain users 6608
Mar 26 08:08 scripts/ticker.dir<BR>
-rw-r--r-- 2 khusain users 6608
Mar 26 08:08 scripts/ticker.pag</FONT></TT>
</BLOCKQUOTE>
<P>
Of course, because you do not have access to the original files
that I used in this example, the sizes shown here will be different
for the data file that you use. Just note that the size of both
the files is the same.
<P>
If the <TT><FONT FACE="Courier">AnyDBM_File</FONT></TT> package
had been substituted with the <TT><FONT FACE="Courier">GDBM_File</FONT></TT>
page, we would only get one file:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">-rw-r--r-- 1 khusain users 6608
Mar 26 08:06 scripts/ticker</FONT></TT>
</BLOCKQUOTE>
<P>
Again, the size of the <TT><FONT FACE="Courier">ticker</FONT></TT>
file will be different depending on the input data file that you
use. However, you should note that the size of the ticker file
is the same as that of the two files created by the <TT><FONT FACE="Courier">AnyDBM-File</FONT></TT>
package.
<H2><A NAME="ViewingYourData"><FONT SIZE=5 COLOR=#FF0000>Viewing
Your Data</FONT></A></H2>
<P>
The database has now been created on disk. Whether it consists
of one file or two is not important in the application that will
access the database because all the internals are hidden with
the DBM function calls.
<P>
In order for us to look at the data in the newly created DBM file,
another script needs to be created. The viewing script is shown
in Listing 18.2.
<HR>
<BLOCKQUOTE>
<B>Listing 18.2. Viewing the contents of a DBM file.<BR>
</B>
</BLOCKQUOTE>
<BLOCKQUOTE>
<TT><FONT FACE="Courier"> 1 #!/usr/bin/perl<BR>
2 # --------------------------------------------------------
<BR>
3 # Sample script to list contents of a DBM repository.
<BR>
4 # --------------------------------------------------------
<BR>
5 #<BR>
6 # Use the default DBM utilites<BR>
7 #<BR>
8 use AnyDBM_File;<BR>
9 #<BR>
10 # Open the database "ticker". (If it does not exist,
create it.)<BR>
11 # Map the hash stocks to this database.<BR>
12 #<BR>
13 dbmopen(%stocks,"ticker",0666);<BR>
14 while (($symbol,$name) = each(%stocks)) {<BR>
15 print "Symbol [$symbol] for [$name]\n";
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -