That produces this page: And here’s the code that builds the page: } elsif param'Show instruments' { # the user wants to see the instruments the musician # plays, start the HTML p
Trang 1After calling Geddy Lee, our music fan might want to see the instruments Thom Yorke plays, so our
curious person goes back to the initial page, select Thom from the drop-down menu, and clicks Show
instruments That produces this page:
And here’s the code that builds the page:
} elsif (param('Show instruments')) {
# the user wants to see the instruments the musician
# plays, start the HTML
header(),
start_html("Instruments played by $musician"),
h1("Instruments played by $musician"),
"$musician plays:",
'<ul>';
Trang 2385
We see that the user wants to show the musician’s instruments, so we start the HTML, print some text, and then start an unordered list (a bullet list) Then we go to the code that queries the database:
# query the database with a table join and retrieve the
# instruments played by musician
my $dbh = DBI->connect("DBI:mysql:musicians_db", "musicfan",
"CrimsonKing");
my $sth = $dbh->prepare("SELECT instrument
FROM instruments
JOIN what_they_play ON instruments.inst_id = what_they_play.inst_id
JOIN musicians ON what_they_play.player_id = musicians.player_id
WHERE musicians.name = ?")
or die "prepare failed: " $dbh->errstr();
$sth->execute($musician) or die "execute failed: " $sth->errstr();
Using the table join we’ve seen a few times in this chapter, we find all the instruments that the musician plays, bringing us to the code that prints the instruments:
my($instrument);
# print all the instruments in a bullet list
while (($instrument) = $sth->fetchrow()) {
print "<li>$instrument</li>";
}
Notice that each instrument is printed within an <li> tag, which makes it into a bullet item in the list
Finally we get to the end of the unordered list and the end of the HTML:
What We Didn’t Talk About
This chapter isn’t meant to be an exhaustive discussion of SQL and DBI There are many topics we didn’t
talk about that you should learn if you want to harness the maximum power of SQL First, there are
several essential commands, including the following:
• UPDATE: Allows data in a table to be modified An example might be
UPDATE musicians SET phone = "555-9999" WHERE player_id = 3;
Trang 3386
• DELETE: Deletes a row from a table An example might be
DELETE FROM instruments WHERE inst_id = 13;
Be careful! If you don’t use the WHERE clause, you’ll delete all rows in the table
• REPLACE: If the key provided does not exist, the data is inserted; otherwise the row
with that key is first deleted, then the new row is inserted An example might be
REPLACE INTO musicians (player_id, name, phone) VALUES (1, "Neil Peart", "555-8888");
Just as knowing these SQL commands is important, so is understanding table indexing Indexing can
significantly increase the speed of SELECT statements with large tables See the docs for more
information Also, be sure to check out Michael Kofler’s excellent book, and remember to look at the
online documentation for MySQL at http://dev.mysql.com/doc/refman/5.1/en/
Summary
In this chapter we described how to access a database using Perl and the DBI module We started with a
description of a relational database and followed with a brief introduction to SQL We then installed
MySQL, created a database with three tables, and talked about several SQL commands INSERT and
SELECT were the most important ones We also discussed using table joins as a way to implement the
relations in relational databases After that, we introduced DBI and DBD::mysql and wrote several Perl
scripts to access and query the database We ended with an example that showed how easily you can
create dynamic web content by connecting Perl, DBI, and CGI.pm And in the middle of that discussion,
we took time out of our busy day to call one of our favorite musicians
Exercises
1 Write a Perl script that prompts the user for an instrument and then prints all the
musicians that play that instrument
2 Write a CGI program similar to musicians.pl that serves as a web interface to the script you
created for exercise 1
Trang 4■ ■ ■
387
Exercise Solutions
This appendix contains the answers to the chapter exercises An important note: each solution is an
answer, not the answer Remember that in Perl, there is more than one way to do it, and that applies to
these solutions as well
print "Currency converter\n\n";
print "Please enter the exchange rate: ";
chomp(my $yen = <STDIN>);
Trang 5388
print "Enter first price to convert: ";
chomp(my $price1 = <STDIN>);
print "Enter second price to convert: ";
chomp(my $price2 = <STDIN>);
print "Enter third price to convert: ";
chomp(my $price3 = <STDIN>);
print "$price1 Yen is ", ($price1/$yen), " dollars\n";
print "$price2 Yen is ", ($price2/$yen), " dollars\n";
print "$price3 Yen is ", ($price3/$yen), " dollars\n";
print "enter a hex number: ";
chomp(my $hexnum = <STDIN>);
print "converted to an int: ", hex($hexnum), "\n";
print "enter an octal number: ";
chomp(my $octal = <STDIN>);
print "converted to an int: ", oct($octal), "\n";
print "enter a value less than 256: ";
chomp(my $bin = <STDIN>);
print((128 & $bin) / 128);
print((64 & $bin) / 64);
print((32 & $bin) / 32);
print((16 & $bin) / 16);
print((8 & $bin) / 8);
print((4 & $bin) / 4);
print((2 & $bin) / 2);
www.wowebook.com
Trang 6print "Guess my number!\n";
print "Enter your guess: ";
} elsif ($guess > $target) {
print "Your number is more than my number\n";
} elsif ($guess < $target) {
print "Your number is less than my number\n";
Trang 7390
use warnings;
use strict;
for (my $i = 1; $i <= 10; $i++) {
print "$i square is: ", $i*$i, "\n"; }
Trang 8scalar => 'dollar sign',
array => 'at sign',
hash => 'percent sign'
Trang 9Java => "None Change it once, and it's the same everywhere.",
Python => "One He just stands below the socket and the world "
"revolves around him.",
Perl => "A million One to change it, the rest to try and do it in " "fewer lines.",
Trang 10print "enter a number: ";
chomp(my $input_num = <STDIN>);
Trang 11# here is the solution using recursion -
# a recursive function is a function that calls
Trang 12Match “hello” followed by zero or more and any character but \n followed by “world”; or, in other words,
any string that contains “hello” followed later by “world”
Match one or more digits at the beginning of the string followed by one whitespace character
followed by zero or more word characters followed by the end of the string
Match an uppercase letter at the beginning of a word followed by zero or more lowercase letters to the end of a word; or, in other words, match a word that begins with an uppercase letter followed by any number of lowercase letters
Match a character, remember it in \1, followed by any number of any characters but \n, followed by
the character remembered In other words, match any string with two occurrences of the same
Trang 13open(INFH, '<', 'gettysburg.txt') or die $!;
open(OUTFH, '>', 'ex1out.txt') or die $!;
Trang 14print "File already exists What should I do?\n";
print "(Enter 'r' to write to a different name, ";
print "'o' to overwrite or\n";
print "'b' to back up to $target.old)\n";
my $choice = <STDIN>;
chomp $choice;
if ($choice eq "r") {
next;
} elsif ($choice eq "o") {
unless (-o $target) {
print "Can't overwrite $target, it's not yours.\n";
Trang 15last if open(OUTPUT, '>', $target);
print "I couldn't write to $target: $!\n";
# and round we go again
}
print OUTPUT "Congratulations.\n";
print "Wrote to file $target\n";
Trang 16die "usage: chap10ex1.pl <dir> <size>\n" unless $dir and $size;
chdir $dir or die "can't chdir: $!";
# first, a file glob
# this gets hidden files too
print "using glob:\n";
# now using a directory handle
print "\n\nusing directory handle:\n";
opendir DH, '.' or die "opendir failed: $!";
while ($_ = readdir(DH)) {
if (-f $_ and -s _ >= $size) {
print ' ', $_, ' ' x (30 - length($_)), -s _, "\n";
Trang 18print "\n$chessboard[$endy][$endx] at (", $endx + 1, ",",
$endy+1, ") is being taken!\n\n";
$chessboard[0]->[$_] = "W" $back[$_]; # White Back Row
$chessboard[1]->[$_] = "WP"; # White Pawns
$chessboard[6]->[$_] = "BP"; # Black Pawns
$chessboard[7]->[$_] = "B" $back[$_]; # Black Back Row
Trang 19unless (defined $chessboard[$starty][$startx]) {
print "There's nothing on that square!\n";
Trang 20print "Enter name: ";
chomp(my $name = <STDIN>);
print "Enter name to view: ";
chomp(my $name = <STDIN>);
if (exists $addressbook{$name}) {
print "Address: $addressbook{$name}{address}\n";
print "Phone: $addressbook{$name}{phone}\n\n";
foreach my $name (sort keys %addressbook) {
print "Name: $name\n";
print "Address: $addressbook{$name}{address}\n";
print "Phone: $addressbook{$name}{phone}\n\n";
}
}
sub delete_entry {
print "Enter name to delete: ";
chomp(my $name = <STDIN>);
if (exists $addressbook{$name}) {
delete $addressbook{$name};
Trang 22print "There are ", Person8->headcount(), " Person8 objects\n";
foreach my $person (Person8->everyone()) {
h1('Thanks for your information!'),
'Thanks for entering the following information:',
Trang 23my $dbh = DBI->connect("DBI:mysql:musicians_db", "musicfan", "CrimsonKing");
die "connect failed: " DBI->errstr() unless $dbh;
# use a table join to query the instrument names
Trang 24407
my $sth = $dbh->prepare("SELECT musicians.name
FROM musicians,what_they_play,instruments
WHERE instruments.instrument = ? AND
musicians.player_id = what_they_play.player_id AND
what_they_play.inst_id = instruments.inst_id")
or die "prepare failed: " $dbh->errstr();
$sth->execute($instrument) or die "execute failed: " $sth->errstr();
# loop through them, printing them
while (($musician) = $sth->fetchrow()) {
start_html("Musicians who play $instrument");
h1("Musicians who play $instrument");
my $dbh = DBI->connect("DBI:mysql:musicians_db", "musicfan",
"CrimsonKing");
my $sth = $dbh->prepare("SELECT name
FROM musicians, what_they_play, instruments
WHERE instruments.instrument = ? AND
instruments.inst_id = what_they_play.inst_id AND
what_they_play.player_id = musicians.player_id")
or die "prepare failed: " $dbh->errstr();
$sth->execute($instrument) or die "execute failed: " $sth->errstr();
my($name);
while (($name) = $sth->fetchrow()) {
Trang 25my $sth = $dbh->prepare("SELECT instrument FROM instruments")
or die "prepare failed: " $dbh->errstr();
$sth->execute() or die "execute failed: " $sth->errstr();
my($instrument);
while (($instrument) = $sth->fetchrow()) {
print qq{<option value="$instrument">$instrument</option>}; }
Trang 26% percent sign, prefixing hashes, 115
< left angle bracket, indicating read mode, 180,
182
< less-than operator comparing numbers and, 29 comparing strings and, 35
<< operator, 20, 37
<> angle brackets, enclosing filehandles, 183
<> diamond See diamond
<= less-than-or-equal-to operator, 30, 71
<STDIN> (standard input), 49, 55, 67
> greater-than operator comparing numbers and, 29 comparing strings and, 35
> right angle bracket, indicating write mode,
& AND operator, 26
&& (and) operator, 31, 61
() parentheses See parentheses
* asterisk metacharacter, 165, 166, 167
Trang 27subroutine declaration and, 136
? question mark metacharacter, 165, 166, 167
: colon, data sources and, 369
“ ” double quotes, for strings, 17
@ at sign, prefixing arrays, 91
@_, passing arguments to subroutines and,
137–142, 147–152
@ARGV array variable
command-line arguments and, 187
<=> spaceship operator, 30, 113
= assignment operator array assignments and, 91 multiple assignments and, 43 operator precedence and, 40 scalar assignments and, 38
=> operator, 36, 116
=~ operator, 37, 155, 158, 170
== comparison operator, 28, 56, 237 -> arrow notation, 241, 245, 289
0 prefix, 22 0x prefix, 22
■ A
\a escape sequence (alarm), 8 a() method, 331, 333
abstraction (encapsulation), 290, 293 accessing
arrays, 95–109 list values, 87–91 accessor methods, 302, 312 action at a distance, variables and, 146 action attribute, CGI programs and, 334, 338 ActivePerl
module installation and, 280 Win32 modules and, 276 addition operator (+), 23
Trang 28and (&&) operator, 31, 61
AND operator (&), 26
angle brackets <>, enclosing filehandles, 183
default values for, 150
how they are passed, 147–152
named parameters and, 151
arithmetic operators, 23–25
array elements, references and, 238
array indexes (array subscripts), 97
exists() function and, 124
for loop and, 100
foreach loop and, 101, 103
tree-like data structures and, 250 variable interpolation and, 93 while loop and, 100
arrow notation (->), 241 matrices and, 245 methods and, 289 ASCII character set, 8 ASCII values, 34 assignable lists, 90 assignment operator (=) array assignments and, 91 multiple assignments and, 43 operator precedence and, 40 scalar assignments and, 38
associative arrays See hashes
asterisk (*) metacharacter, 165, 166, 167
at sign (@), prefixing arrays, 91 attributes, 288
classes and, 304–307, 312 providing, 300
storing, 298 audio, Win32::Sound and, 276 autoclosing files, 180
auto-decrement operator ( ), 41 auto-increment operator (++), 41 automatic conversion of scalars, 21, 34 autovivification, 245–249
Trang 29base 10 (decimal system), 10
base 16 (hexadecimal system), 10
base 2 (binary system), 10
base 8 (octal system), 10
breaking out of loops/blocks, 74
browsers, CGI and, 317–348
DBI module and, 378–385 static vs dynamic, 336 troubleshooting, 320 writing, 318–325 character classes, 161–163 character sets (character encoding), 8 chdir() function, 221