Integrating SQL with CGI, Part 1
Now that we have created our “postcards” table, let's insert some dummy data directly at the MySQL prompt. Then we will write the program show-postcard.pl to display the dummy postcard. Finally, we will write a program to allow users to enter postcards via an HTML form.
We can insert data into a table by using the SQL insert command. Let's say we wish to insert a postcard with the following information:
ID: 12345 Sender name: Reuven Lerner Sender e-mail: reuven@netvision.net.il Recipient name: Bill Clinton Recipient e-mail: president@whitehouse.gov Graphic: smile.gif Text: Hey there, Mr. President!
To insert this information, use the following SQL command:
insert into postcards (id_number, sender_name, sender_email, recipient_name, recipient_email, graphic_name, postcard_text) values (12345, "Reuven Lerner", "reuven@netvision.net.il", "Bill Clinton", "president@whitehouse.gov", "smile.gif", "Hey there, Mr. President!");Typing this command at the MySQL prompt produces this response:
Query OK, 1 rows affected (0.34 sec)In other words, one new row was successfully added to the table. To retrieve it, use the SQL command:
select * from postcards where id_number = 12345;which produces the result shown in Table 2.
While it might look ugly, this output actually makes sense. The problem is that most CRTs are only 80 columns wide, while the table is nearly twice that width. (And this magazine is even narrower, making it even worse.) Luckily, when our program retrieves a row, it does not have to worry about the formatting.
If you are interested only in certain columns, you can specify a subset of the entire row, as follows:
select sender_name,graphic_name,postcard_text from postcards where id_number = 12345;
Submitting this query produces the result shown in Table 3. The output row contains only the row corresponding to our postcard, and the columns we have requested. As an added benefit, it is easier to read than the entire row that we retrieved earlier.
Table 3. Output of select Query
Now that we have seen the sort of SQL query that is necessary to retrieve information from the database, it should be a snap to write our CGI program. You can see an initial stab in Listing 1.
This version of show-postcard.pl expects to be invoked with a single argument (the postcard's ID number) in the query string, as we mentioned earlier. If we go to the URL /cgi-bin/show-postcard.pl?12345, we should see a postcard addressed to Bill Clinton, with the message that we inserted by hand at the MySQL prompt.
The program works in a relatively straightforward way. First, it creates an instance of CGI, a Perl object (available from CPAN at http://www.perl.com/CPAN/) that makes CGI programming easier. After sending a MIME header indicating that the program will send its output in HTML-formatted text, we retrieve the value of the query string by using the param method, as follows:
my $id = $query->param("keywords");
If the query string is empty, we print out an error message and give the user another chance to enter a postcard ID number, by using the little-known <isindex> tag. Note that we check the numeric value of $id, by using the == operator, rather than simply checking to see if $id is equal (with “eq”) to the null string. This prevents problems if someone invokes show-postcard.pl with an argument that includes characters other than numbers.
Assuming that a number does arrive in the query string, we connect to the test database, and then build up our SQL command in the variable $command. We could, of course, simply insert the command string inside of the call to $dbh->query. However, building the command in a separate string makes it easier to understand. It also has the added benefit of allowing us to debug the program. We can print the literal query by uncommenting the following debugging line:
# Uncomment for debugging
# print "<P>SQL command: \"$command\
"</P>\n";
When the above line is uncommented, we can see exactly what is being passed to MySQL and find our program's problems more easily.
Our program then sends the request to MySQL using the “query” method. The value returned is a handle into the database, which can contain one or more rows matching our query. Since we are requesting all rows matching a particular ID, we can be sure that no more than one row is returned. This is true because we set id_number to be a primary key, which makes it unique.
What happens if the user invokes show-postcard.pl with an ID number that does not correspond to any postcard? If we were to ignore this possible error, users entering nonexistent ID numbers would see the outline of a postcard, but no actual content. This isn't particularly friendly for our users, who would like to know when they make a mistake and to be given a chance to correct it. Thus, before we retrieve information from the returned row, we make sure that there was a returned row. If not, then we can safely assume that this is because the ID number submitted by the user did not match the id_number column for any row in the database.
Our code accomplishes this checking by using the “numrows” method on the statement handle ($sth)--the object which allows us to read the results of our query. If numrows equals 0, we have not received any rows from the server, and we complain to the user that he has entered an ID number which does not match any on our server.
Obviously, to be displayed, the graphic with the specified name must exist in /tmp (or whichever directory you name in the final part of the program) on the server. If the graphic's name is misspelled or if it is placed in the wrong directory on the server, the program will not be able to display it, so take care. (We will take a closer look at this problem next month, when we look at the use of multiple tables for the graphic.)
Finally, show-postcard.pl turns the row into a Web page that can be sent to the user. Indeed, since the “postcard” is really a Web page, you could argue that, while I have talked about this project as if it were useful only for sending postcards, you could easily adapt this strategy for creating personalized home pages on your system, with each user getting a different page.
Realizing the promise of Apache® Hadoop® requires the effective deployment of compute, memory, storage and networking to achieve optimal results. With its flexibility and multitude of options, it is easy to over or under provision the server infrastructure, resulting in poor performance and high TCO. Join us for an in depth, technical discussion with industry experts from leading Hadoop and server companies who will provide insights into the key considerations for designing and deploying an optimal Hadoop cluster.
Sponsored by AMD
Built-in forensics, incident response, and security with Red Hat Enterprise Linux 6
Every security policy provides guidance and requirements for ensuring adequate protection of information and data, as well as high-level technical and administrative security requirements for a system in a given environment. Traditionally, providing security for a system focuses on the confidentiality of the information on it. However, protecting the data integrity and system and data availability is just as important. For example, when processing United States intelligence information, there are three attributes that require protection: confidentiality, integrity, and availability.
Learn more about catching the bad guy in this free white paper.
Sponsored by DLT Solutions
| Designing Electronics with Linux | May 22, 2013 |
| Dynamic DNS—an Object Lesson in Problem Solving | May 21, 2013 |
| Using Salt Stack and Vagrant for Drupal Development | May 20, 2013 |
| Making Linux and Android Get Along (It's Not as Hard as It Sounds) | May 16, 2013 |
| Drupal Is a Framework: Why Everyone Needs to Understand This | May 15, 2013 |
| Home, My Backup Data Center | May 13, 2013 |
- Designing Electronics with Linux
- New Products
- Making Linux and Android Get Along (It's Not as Hard as It Sounds)
- Dynamic DNS—an Object Lesson in Problem Solving
- Linux Systems Administrator
- Senior Perl Developer
- Technical Support Rep
- UX Designer
- Web & UI Developer (JavaScript & j Query)
- Using Salt Stack and Vagrant for Drupal Development
- Reply to comment | Linux Journal
2 hours 24 min ago - Dynamic DNS
2 hours 58 min ago - Reply to comment | Linux Journal
3 hours 56 min ago - Reply to comment | Linux Journal
4 hours 47 min ago - Not free anymore
8 hours 48 min ago - Great
12 hours 36 min ago - Reply to comment | Linux Journal
12 hours 44 min ago - Understanding the Linux Kernel
14 hours 58 min ago - General
17 hours 28 min ago - Kernel Problem
1 day 3 hours ago
Enter to Win an Adafruit Pi Cobbler Breakout Kit for Raspberry Pi

It's Raspberry Pi month at Linux Journal. Each week in May, Adafruit will be giving away a Pi-related prize to a lucky, randomly drawn LJ reader. Winners will be announced weekly.
Fill out the fields below to enter to win this week's prize-- a Pi Cobbler Breakout Kit for Raspberry Pi.
Congratulations to our winners so far:
- 5-8-13, Pi Starter Pack: Jack Davis
- 5-15-13, Pi Model B 512MB RAM: Patrick Dunn
- 5-21-13, Prototyping Pi Plate Kit: Philip Kirby
- Next winner announced on 5-27-13!
Featured Jobs
| Linux Systems Administrator | Houston and Austin, Texas | Host Gator |
| Senior Perl Developer | Austin, Texas | Host Gator |
| Technical Support Rep | Houston and Austin, Texas | Host Gator |
| UX Designer | Austin, Texas | Host Gator |
| Web & UI Developer (JavaScript & j Query) | Austin, Texas | Host Gator |
Free Webinar: Hadoop
How to Build an Optimal Hadoop Cluster to Store and Maintain Unlimited Amounts of Data Using Microservers
Realizing the promise of Apache® Hadoop® requires the effective deployment of compute, memory, storage and networking to achieve optimal results. With its flexibility and multitude of options, it is easy to over or under provision the server infrastructure, resulting in poor performance and high TCO. Join us for an in depth, technical discussion with industry experts from leading Hadoop and server companies who will provide insights into the key considerations for designing and deploying an optimal Hadoop cluster.
Some of key questions to be discussed are:
- What is the “typical” Hadoop cluster and what should be installed on the different machine types?
- Why should you consider the typical workload patterns when making your hardware decisions?
- Are all microservers created equal for Hadoop deployments?
- How do I plan for expansion if I require more compute, memory, storage or networking?




Comments
Making your own provillus
Badly need your help. Keep on going and the chances are you will stumble on something, perhaps when you are least expecting it. I have never heard of anyone stumbling on something sitting down.
I am from Moldova and too poorly know English, give please true I wrote the following sentence: "Dht is a trigger chemotherapy certainly like head but with greater negah for the damage metzorah."
Regards :D Sharon.