using perl dbi to interface to mysql

40
Using Perl DBI to interface to MySQL Why Perl? Why not PHP? After all, PHP4 is supposed to be fast now that it's using a new interpreter. Because Perl is still what's most widely used. I like going with the industry standard. Perl has massive support online and the most books written about it. There is CPAN, the Comprehensive Perl Archive Network, where you'll find modules to do almost anything you'd want. DBI gives you an interface that'll work with the "primitive" CSV format (comma separated value text files) all the way up to the highest end Oracle RDBMS. Let's start by connecting to the database: use DBI; my $dsn = 'DBI:mysql:my_database:localhost'; my $db_user_name = 'admin'; my $db_password = 'secret'; my ($id, $password); my $dbh = DBI->connect($dsn, $db_user_name, $db_password); Let's assume we've received as form input a nickname and password from a login screen. So right now, $input_nickname = 'Cowlick' and $input_password = 'udder' We want to verify that the entered password matches what we have in our database. my $sth = $dbh->prepare(qq{ select id, password from users where nickname = $input_nickname }); $sth->execute(); Notice there is no command-terminating semi-colon.

Upload: daniel-hurtado-brenner

Post on 30-Sep-2015

242 views

Category:

Documents


4 download

DESCRIPTION

usando perl dbi en msyql

TRANSCRIPT

Using Perl DBI to interface to MySQLWhy Perl? Why not PHP? After all, PHP4 is supposed to be fast now that it's using a new interpreter.Because Perl is still what's most widely used. I like going with the industry standard. Perl has massive support online and the most books written about it. There is CPAN, the Comprehensive Perl Archive Network, where you'll find modules to do almost anything you'd want. DBI gives you an interface that'll work with the "primitive" CSV format (comma separated value text files) all the way up to the highest end Oracle RDBMS.Let's start by connecting to the database:use DBI;my $dsn = 'DBI:mysql:my_database:localhost';my $db_user_name = 'admin';my $db_password = 'secret';my ($id, $password);my $dbh = DBI->connect($dsn, $db_user_name, $db_password);Let's assume we've received as form input a nickname and password from a login screen. So right now,$input_nickname = 'Cowlick' and $input_password = 'udder'We want to verify that the entered password matches what we have in our database.my $sth = $dbh->prepare(qq{ select id, password from users where nickname = $input_nickname});$sth->execute();Notice there is no command-terminating semi-colon.How do we get the results? Since we only expect one row,($id, $password) = $sth->fetchrow_array();$sth->finish(): # we're done with this queryif ($input_password eq $password) # case-sensitive{ ... # login successful}What if our result is more than one row? Successive calls to$sth->fetchrow_array()will return the rest of the result set.my $sth = $dbh->prepare(qq{ select nickname, favorite_number from users});$sth->execute();while (my ($nickname, $favorite_number) = $sth->fetchrow_array()) # keep fetching until # there's nothing left{ print "$nickname, $favorite_number\n";}$sth->finish();If we want to save the entire result set first for processing later,my (@matrix) = ();while (my @ary = $sth->fetchrow_array()){ push(@matrix, [@ary]); # [@ary] is a reference}$sth->finish();A reference, for C programers, can be thought of as a pointer. The Matrix is now an array of array references, or a two-dimensional array.You can access row $i with:@{matrix[$i]}Or, you can access a specific row and column ($i, $j) in the table with:$matrix[$i][$j]For MySQL operations that don't return a result you can use the do method instead of prepare then execute.$dbh->do("insert into message_votes (message_id, user_id, vote) values (1, 3, 'good')");When you're done with the database:$dbh->disconnect();That should be enough to get you started. You can see that using Perl DBI is a matter of calling a method with the MySQL command as a string.For more in-depth information regarding Perl DBI and MySQL refer to the book MySQL (OTHER NEW RIDERS) by Paul Dubois. Great reviews on Amazon convinced me to buy it and while I can't quite rave about the book, because it's hard to find what you want most of the time, it seems very competently written. Of course, I have no frame of reference since this is the only MySQL book I've looked at.For the best all-around CGI book out there, you must get the excellent CGI Programming with Perl (2nd Edition) published by O'Reilly. You should know some Perl before starting in on this but you'll learn more than a little bit about everything CGI by the time you've finished. Plenty of relevant examples and excellent sections on Security, DBI, and Maintaining State make this book a must have. Disregard the bad reviews on Amazon unless you're the kind of person who likes to type in the examples from the book, in which case, you will have a tough time. Use it instead to learn the concepts and then write your own code!

Introduction to MySQL (using Perl DBI)My theory is, if the title doesn't sound alien to you, then you're probably in the right place.MySQL is a relational database management system. It sounds fancy, but doesn't have to be. The novice, like me, can treat it as a black box. Put stuff in, ask for certain stuff out. It just works. That simple.MySQL is based on a client/server model, so the black box is the MySQL server and your interface to it is the MySQL client program. All the examples of MySQL commands in this article can be entered straight into the MySQL client command line. MySQL supports multi-line commands and uses a semicolon to designate the end of the command.Why MySQL and not another database system that supports SQL?Because MySQL is free, well-supported and fast.Even for a novice, it's probably more helpful to think of MySQL as a secretary ready to do your filing for you. You give her instructions on how to file the items. If you know that you'll be asking for items by their date, then tell the secretary to file by date and when you ask for things, it doesn't take her all day to find what you're looking for.Data is organized into rows and columns, defining a matrix. In SQL-speak, the matrix is called a table.The best way for a C programmer to think of it is:Each row is a structure reference.Every column is a member of that structure.Here's a typical C data structure:struct users{ int id; char nickname[17]; // 16 char NULL terminated string char password[17]; // ditto int socks; // pairs of socks int favorite_number;};It looks like user information collected by a web-site, perhaps.The MySQL version of this structure is created with this command to the MySQL client program:create table users( id int auto_increment not null, nickname varchar(16) not null, password varchar(16) not null, socks int, favorite_number int, primary key (user_id), unique (nickname));See any similairities?This is what it looks like as a row in MySQL:+----+----------+----------+-------+-----------------+| id | nickname | password | socks | favorite_number |+----+----------+----------+-------+-----------------+What is The Matrix?The matrix of data for three hypothetical users:+----+----------+----------+-------+-----------------+| 1 | GdayMate | dingo | 57 | 42 |+----+----------+----------+-------+-----------------+| 2 | Javier | cigar | 1 | 945 |+----+----------+----------+-------+-----------------+| 3 | Rolo | pudding | 9 | 8 |+----+----------+----------+-------+-----------------+That's it? Yup. In fact, these tables are exactly what you'd see if you gave MySQL this command:select * from users;The asterisk means to select all the columns from the users table.The table is the structural foundation for the multi-billion dollar a year database industry which includes companies like Oracle and Informix.Simple MySQL CommandsLet's run through some simple SQL commands. You already know the create table command.create table users( id int auto_increment not null, nickname varchar(16) not null, password varchar(16) not null, socks int, favorite_number int, primary key (user_id), unique (nickname));What if we just want user nicknames and their favorite number?select nickname, favorite_number from users;This gives us:+----------+-----------------+| nickname | favorite_number |+----------+-----------------+| GdayMate | 42 |+----------+-----------------+| Javier | 945 |+----------+-----------------+| Rolo | 8 |+----------+-----------------+And if we want all nicknames of users with less than 10 pairs of socks and whose favorite number is greater than 100?select nickname from users where socks < 10 and favorite_number > 100;+----------+| nickname |+----------+| Javier |+----------+So how do you insert a row of data into the table? Simple.insert into users (nickname, socks) values ('Cowlick', 0);Uh oh, the row that's created is missing the password column! Remember the line used to create the password column in the users table?create table users( ... password varchar(16) not null, ...);The not null means you must have some value for the column. So MySQL gives an error in this case. We should use instead:insert into users (nickname, password, socks) values ('Cowlick', 'udder', 0);This results in a row like this:+----+----------+----------+-------+-----------------+| id | nickname | password | socks | favorite_number |+----+----------+----------+-------+-----------------+ | 4 | Cowlick | udder | 0 | NULL |+----+----------+----------+-------+-----------------+But wait! Why didn't we have to specify an id? That's not null also. The line from the create table users command:create table users( id int auto_increment not null, ...);In the case of the id column, we have specified auto_increment and MySQL creates the value for us by adding 1 to the greatest value it finds in that column (Rolo has an id of 3).We've forgotten to include Cowlick's favorite number. Which is -1, by the way. For this we use the update command.update users set favorite_number = -1 where id = 4;We could have also used:update users set favorite_number = -1 where nickname = 'Cowlick';But what if there were more than one user with the nickname Cowlick? In our example, there can't be, because in the create table command we've specifiedcreate tables users( ... unique (nickname));If we try and insert another user with the nickname Cowlick, we'd get an error from MySQL.Let's say you've built up a large community of sock aficionados/numerologists and you've been having a lot of problems with Javier. He keeps talking off subject about high jumping and hunting for truffles. The other members of the community are up in arms because they see Javier as a trouble maker and his posts as noise.delete from users where nickname = 'Javier';Of course, this doesn't stop Javier from re-registering and continuing his annoying banter.Let's say you're sick of all the talk about gold toe vs. tube and Western-Lucky-7 vs. Chinese-Good-Fortune-8. You realize there is a demand for a site about high jumping and hunting for truffles. You want to revamp the site.drop table users;The table definition and all the data are now gone. Be very careful with this command.MySQL types and primary keyWe haven't talked about the primary key directive in the create table command.create table users( ... primary key (user_id), ...)This is an instruction to the MySQL "secretary" to file things by user_id. The constraint imposed on a primary key is that each row must have a unique value for the key. Technically, MySQL creates a B-tree to make lookup of a specific row by user_id fast. So thisselect * from users where user_id = 2;is faster thanselect * from users where favorite_number = 945;Is MySQL limited to small data types? Only if you think 4 gigabytes is small. That's what the LongBlob and LongText types can hold.Let's say we want to create a message system. A simple example of a message row is created with:create table messages( id int auto_increment not null, user_id int not null, posting_date datetime not null, comment_body text primary key (id))This introduces two new SQL types: datetime and text.The datetime column data is structured like so, "YYYY-MM-DD hh:mm:ss". This way, datetimes can be ASCII sorted into chronological order. To us, it's a string, that's the format we give to MySQL and the format we get out, but internally, it's an 8 byte bitstream.The text type holds up to 64Kb of data, more than enough for a message.The user_id column, that's the relational part of Relational Database Management System (RDBMS). The user_id in our example references the id column of the users table. This way we're relating the message to the user who is the author. The table is the structural foundation but this concept of referencing is the functional basis for RDBMS.

Here's an example message row (the message_body can be much longer):+----+---------+---------------------+--------------+| id | user_id | posting_date | message_body |+----+---------+---------------------+--------------+| 1 | 3 | 2000-10-10 10:00:00 | Wassup! |+----+---------+---------------------+--------------+Let's say we have a voting system, where users can vote on whether or not the message was worth reading. We'd create a table like this:create table message_votes( message_id int not null, user_id int not null, vote enum('good', 'bad') not null, primary key (message_id, user_id));In this example, the vote column can contain either the value 'good' or the value 'bad'.The primary key directive specifies two columns to "file" by. Since primary keys are by definition unique, (message_id, user_id) as a value pair must be unique. This imposes the constraint that each user can only vote on a specific message once.Also, in this example, MySQL "files" message votes "sorting" by message_id first then by user_id. Which means lookups like:select * from message_votes where message_id = 3;are going to be faster thanselect * from message_votes where user_id = 2;But the fastest way to lookup a message vote is:select * from message_votes where message_id = 3 and user_id = 2;Now we're ready to use Perl DBI to interface with MySQL.

Database Management in PERL - DBIThis session will teach you how to access Oracle Database and other databases using PERL.Starting from Perl 5 it has become very easy to write database applications using DBI. DBI stands for Database independent interface for Perl which means DBI provides an abstraction layer between the Perl code and the underlying database, allowing you to switch database implementations really easily.The DBI is a database access module for the Perl programming language. It defines a set of methods, variables, and conventions that provide a consistent database interface, independent of the actual database being used.Architecture of a DBI ApplicationDBI is independent of any database available in backend. You can use DBI whether you are working with Oracle, MySQL or Informix etc. This is clear from the following architure diagram.Here DBI is responsible of taking all SQL commands through the API, or Application Programming Interface, and to dispatch them to the appropriate driver for actual execution. And finally DBI is responsible of taking results from the driver and giving back it to the calling scritp.Notation and ConventionsThroughout this chapter following notations will be used and it is recommended that you should also follow the same convention. $dsn Database source name $dbh Database handle object $sth Statement handle object $h Any of the handle types above ($dbh, $sth, or $drh) $rc General Return Code (boolean: true=ok, false=error) $rv General Return Value (typically an integer) @ary List of values returned from the database. $rows Number of rows processed (if available, else -1) $fh A filehandle undef NULL values are represented by undefined values in Perl \%attr Reference to a hash of attribute values passed to methodsDatabase ConnectionAssuming we are going to work with MySQL database. Before connecting to a database make sure followings:You have created a database TESTDB.You have created TEST_TABLE in TESTDB.This table is having fields FIRST_NAME, LAST_NAME, AGE, SEX and INCOME.User ID "testuser" and password "test123" are set to access TESTDBPerl Module DBI is installed properly on your machine.You have gone through MySQL tutorial to understand MySQL Basics.

Following is the example of connecting with MySQL database "TESTDB"#!/usr/bin/perluse DBIuse strict;

my $driver = "mysql"; my $database = "TESTDB"; my $dsn = "DBI:$driver:database=$database"; my $userid = "testuser"; my $password = "test123"; my $dbh = DBI->connect($dsn, $userid, $password ) or die $DBI::errstr;If a connection is established with the datasource then a Database Handle is returned and saved into $dbh for further use otherwise $dbh is set to undef value and $DBI::errstr returns an error string.

INSERT OperationINSERT operation is required when you want to create your records into TEST_TABLE. So once our database connection is established, we are ready to create records into TEST_TABLE. Following is the procedure to create single record into TEST_TABLE. You can create many records in similar fashion.Record creation takes following stepsPrearing SQL statement with INSERT statement. This will be done using prepare() API.Executing SQL query to select all the results from the database. This will be done using execute() API.Releasing Stattement handle. This will be done using finish() APIIf everything goes fine then commit this operation otherwise you can rollback complete transaction. Commit and Rollback are explained in next sections. my $sth = $dbh->prepare("INSERT INTO TEST_TABLE (FIRST_NAME, LAST_NAME, SEX, AGE, INCOME ) values ('john', 'poul', 'M', 30, 13000)"); $sth->execute() or die $DBI::errstr; $sth->finish(); $dbh->commit or die $DBI::errstr;Using Bind ValuesThere may be a case when values to be entered is not given in advance. In such case binding values are used. A question mark is used in place of actual value and then actual values are passed through execute() API. Following is the example.

my $first_name = "john"; my $last_name = "poul"; my $sex = "M"; my $income = 13000; my $age = 30; my $sth = $dbh->prepare("INSERT INTO TEST_TABLE (FIRST_NAME, LAST_NAME, SEX, AGE, INCOME ) values (?,?,?,?)"); $sth->execute($first_name,$last_name,$sex, $age, $income) or die $DBI::errstr; $sth->finish(); $dbh->commit or die $DBI::errstr;READ OperationREAD Operation on any databasse means to fetch some useful information from the database. So once our database connection is established, we are ready to make a query into this database. Following is the procedure to query all the records having AGE greater than 20. This will take four stepsPrearing SQL query based on required conditions. This will be done using prepare() API.Executing SQL query to select all the results from the database. This will be done using execute() API.Fetching all the results one by one and printing those results.This will be done using fetchrow_array() API.Releasing Stattement handle. This will be done using finish() API

my $sth = $dbh->prepare("SELECT FIRST_NAME, LAST_NAME FROM TEST_TABLE WHERE AGE > 20"); $sth->execute() or die $DBI::errstr; print "Number of rows found :" + $sth->rows; while (my @row = $sth->fetchrow_array()) { my ($first_name, $last_name ) = @row; print "First Name = $first_name, Last Name = $last_name\n"; } $sth->finish();

Using Bind ValuesThere may be a case when condition is not given in advance. In such case binding values are used. A question mark is used in place of actual value and then actual value is passed through execute() API. Following is the example.

$age = 20; my $sth = $dbh->prepare("SELECT FIRST_NAME, LAST_NAME FROM TEST_TABLE WHERE AGE > ?"); $sth->execute( $age ) or die $DBI::errstr; print "Number of rows found :" + $sth->rows; while (my @row = $sth->fetchrow_array()) { my ($first_name, $last_name ) = @row; print "First Name = $first_name, Last Name = $last_name\n"; } $sth->finish();UPDATE OperationUPDATE Operation on any databasse means to update one or more records already available in the database. Following is the procedure to update all the records having SEX as 'M'. Here we will increase AGE of all the males by one year. This will take three steps

Prearing SQL query based on required conditions. This will be done using prepare() API.Executing SQL query to select all the results from the database. This will be done using execute() API.Releasing Stattement handle. This will be done using finish() APIIf everything goes fine then commit this operation otherwise you can rollback complete transaction. See next section for commit and rollback APIs.

my $sth = $dbh->prepare("UPDATE TEST_TABLE SET AGE = AGE + 1 WHERE SEX = 'M'"); $sth->execute() or die $DBI::errstr; print "Number of rows updated :" + $sth->rows; $sth->finish(); $dbh->commit or die $DBI::errstr;

Using Bind ValuesThere may be a case when condition is not given in advance. In such case binding values are used. A question mark is used in place of actual value and then actual value is passed through execute() API. Following is the example.

$sex = 'M'; my $sth = $dbh->prepare("UPDATE TEST_TABLE SET AGE = AGE + 1 WHERE SEX = ?"); $sth->execute('$sex') or die $DBI::errstr; print "Number of rows updated :" + $sth->rows; $sth->finish(); $dbh->commit or die $DBI::errstr;In some case you would like to set a value which is not given in advance so you can use binding value as follows. In this example income of all males will be set to 10000.

$sex = 'M'; $income = 10000; my $sth = $dbh->prepare("UPDATE TEST_TABLE SET INCOME = ? WHERE SEX = ?"); $sth->execute( $income, '$sex') or die $DBI::errstr; print "Number of rows updated :" + $sth->rows; $sth->finish();DELETE OperationDELETE operation is required when you want to delete some records from your database. Following is the procedure to delete all the records from TEST_TABLE where AGE is equal to 30. This operation will take following steps.Prearing SQL query based on required conditions. This will be done using prepare() API.Executing SQL query to delete required records from the database. This will be done using execute() API.Releasing Stattement handle. This will be done using finish() API

If everything goes fine then commit this operation otherwise you can rollback complete transaction.

$age = 30; my $sth = $dbh->prepare("DELETE FROM TEST_TABLE WHERE AGE = ?"); $sth->execute( $age ) or die $DBI::errstr; print "Number of rows deleted :" + $sth->rows; $sth->finish(); $dbh->commit or die $DBI::errstr;

Using do StatementIf you're doing an UPDATE, INSERT, or DELETE there is no data that comes back from the database, so there is a short cut to perform this operation. You can use do statement to execute any of the command as follows.$dbh->do('DELETE FROM TEST_TABLE WHERE age =30');do returns a true value if it succeeded, and a false value if it failed. Actually, if it succeeds it returns the number of affected rows. In the example it would return the number of rows that were actually deleted.

COMMIT OperationCommit is the operation which gives a green signal to database to finalize the changes and after this operation no change can be reverted back.Here is a simple example to call commit API.$dbh->commit or die $dbh->errstr;

ROLLBACK OperationIf you are not satisfied with all the changes and you want to revert back those changes then use rollback API.Here is a simple example to call rollback API.$dbh->rollback or die $dbh->errstr;

Begin TransactionMany databases support transactions. This means that you can make a whole bunch of queries which would modify the databases, but none of the changes are actually made. Then at the end you issue the special SQL query COMMIT, and all the changes are made simultaneously. Alternatively, you can issue the query ROLLBACK, in which case all the queries are thrown away.begin_work API enables transactions (by turning AutoCommit off) until the next call to commit or rollback. After the next commit or rollback, AutoCommit will automatically be turned on again.$rc = $dbh->begin_work or die $dbh->errstr;

AutoCommit OptionIf your transactions are simple, you can save yourself the trouble of having to issue a lot of commits. When you make the connect call, you can specify an AutoCommit option which will perform an automatic commit operation after every successful query. Here's what it looks like:

my $dbh = DBI->connect($dsn, $userid, $password, {AutoCommit => 1}) or die $DBI::errstr;Here AutoCommit can take value 1 or 0.Automatic Error HandlingWhen you make the connect call, you can specify a RaiseErrors option that handles errors for you automatically. When an error occurs, DBI will abort your program instead of returning a failure code. If all you want is to abort the program on an error, this can be convenient. Here's what it looks like:my $dbh = DBI->connect($dsn, $userid, $password, {RaiseError => 1}) or die $DBI::errstr;Here RaiseError can take value 1 or 0.

Disconnecting DatabaseTo disconnect Database connection, use disconnect API.$rc = $dbh->disconnect or warn $dbh->errstr;The transaction behaviour of the disconnect method is, sadly, undefined. Some database systems (such as Oracle and Ingres) will automatically commit any outstanding changes, but others (such as Informix) will rollback any outstanding changes. Applications not using AutoCommit should explicitly call commit or rollback before calling disconnect.Using NULL valuesUndefined values, or undef, are used to indicate NULL values. You can insert and update columns with a NULL value as you would a non-NULL value. These examples insert and update the column age with a NULL value:

$sth = $dbh->prepare(qq{ INSERT INTO TEST_TABLE (FIRST_NAME, AGE) VALUES (?, ?) }); $sth->execute("Joe", undef);Here qq{} is used to return q quoted string to prepare API.However, care must be taken when trying to use NULL values in a WHERE clause. Consider:

SELECT FIRST_NAME FROM TEST_TABLE WHERE age = ?Binding an undef (NULL) to the placeholder will not select rows which have a NULL age! At least for database engines that conform to the SQL standard. Refer to the SQL manual for your database engine or any SQL book for the reasons for this. To explicitly select NULLs you have to say "WHERE age IS NULL".A common issue is to have a code fragment handle a value that could be either defined or undef (non-NULL or NULL) at runtime. A simple technique is to prepare the appropriate statement as needed, and substitute the placeholder for non-NULL cases:

$sql_clause = defined $age? "age = ?" : "age IS NULL";$sth = $dbh->prepare(qq{ SELECT FIRST_NAME FROM TEST_TABLE WHERE $sql_clause });$sth->execute(defined $age ? $age : ());Some other DBI functionsavailable_drivers@ary = DBI->available_drivers;@ary = DBI->available_drivers($quiet);Returns a list of all available drivers by searching for DBD::* modules through the directories in @INC. By default, a warning is given if some drivers are hidden by others of the same name in earlier directories. Passing a true value for $quiet will inhibit the warning.installed_drivers%drivers = DBI->installed_drivers();Returns a list of driver name and driver handle pairs for all drivers 'installed' (loaded) into the current process. The driver name does not include the 'DBD::' prefix.data_sources@ary = DBI->data_sources($driver);Returns a list of data sources (databases) available via the named driver. If $driver is empty or undef, then the value of the DBI_DRIVER environment variable is used.quote$sql = $dbh->quote($value);$sql = $dbh->quote($value, $data_type);Quote a string literal for use as a literal value in an SQL statement, by escaping any special characters (such as quotation marks) contained within the string and adding the required type of outer quotation marks.$sql = sprintf "SELECT foo FROM bar WHERE baz = %s", $dbh->quote("Don't");For most database types, quote would return 'Don''t' (including the outer quotation marks). It is valid for the quote() method to return an SQL expression that evaluates to the desired string. For example:$quoted = $dbh->quote("one\ntwo\0three")may produce results which will be equivalent toCONCAT('one', CHAR(12), 'two', CHAR(0), 'three')Methods Common to all Handleserr$rv = $h->err;or$rv = $DBI::error$rv = $h->errReturns the native database engine error code from the last driver method called. The code is typically an integer but you should not assume that. This is equivalent to $DBI::err or $h->err.errstr$str = $h->errstr;or$str = $DBI::errstror$str = $h->errstrReturns the native database engine error message from the last DBI method called. This has the same lifespan issues as the "err" method described above. This is equivalent to $DBI::errstr or $h->errstr.

rows$rv = $h->rows;or$rv = $DBI::rowsThis returns the number of rows effected by previous SQL statement and equivalent to $DBI::rows.trace$h->trace($trace_settings);DBI sports an extremely useful ability to generate runtime tracing information of what it's doing, which can be a huge time-saver when trying to track down strange problems in your DBI programs. You can use different values to set trace level. These values varies from 0 to 4. The value 0 means disable trace and 4 means generate complete trace.Interpolated Statements are ProhebitedIt is highly recommended not to use interpolated statements as follows:while ($first_name = ) { my $sth = $dbh->prepare("SELECT * FROM TEST_TABLE WHERE FIRST_NAME = '$first_name'"); $sth->execute(); # and so on ...}There are following reasons to avoid interploated statements:First, prepare calls can take a long time. The database server has to compile the SQL and figure out how it is going to run the query. If you have many similar queries, that is a waste of time.Second, it will not work if $first_name contains a name like O'Brien or D'Fecto or some other name with an '. The ' has a special meaning in SQL, and the database will not understand when you ask it to prepare an SQL statement.

Finally, if you're going to be constructing your query based on a user input then it's unsafe to simply interpolate the input directly into the query, because the user can construct a strange input in an attempt to trick your program into doing something it didn't expect. For example, suppose the user enters the following bizarre value for $input:x' or first_name = first_name or first_name = 'yNow our query has become something very surprising:SELECT * FROM TEST_TABLE WHERE first_name = 'x' or first_name = first_name or first_name = 'y'The part of this query that our sneaky user is interested in is the second or clause. This clause selects all the records for which first_name is equal to first_name; that is, all of them.Thus don't use interpolated statement instead use bind value to prepare dynamic SQL statement.

A simple introduction to database interface using perl dbi.DBI DataBase Interface module (more precisely a collection of modules) is a feature rich, efficient and yet simple tool to access databases using perl. Almost all Linux distributions have them, if not you can download from cpan.org. The interface to any DBMS requires two sets of tools one DBI itself which is generic, two the DBD::the_database. DBD is the driver component and you should install drivers for whatever database you are using. DBI drivers are available for almost all standard databases.Normally database access workflow is like this:a.Connect to the database (logging) using username,password etc.. Once properly authenticated a database-handle will be given.b.Create the sql query, use database-handle to send the query to the server and ask it to prepare the query.c. Server parses the sql, if no errors, returns a statement-handle.d.Use the statement-handle to execute the query.f.Use statement-handle to fetch data single row or multiple rows at a time.g.Close the statement handleh. Repeat steps b to g as long as you want, with new queriesi.Finally disconnect from database(logout) using database-handle.

Let us see them by means of a sample code.Assumptions:Database Server: mysql running on local hostDatabase user name: test Password: test123Database name : testdbTable : namesColumns in the table: id,name,ageObjective 1:1. List all records in the table and find out average age

Let us start the code. (codes are give in italics and bold)

Step 1:Connecting to the databaseuse DBI;my $dbh=DBI->connect(DBI:mysql:database=testdb;host=localhost,'test,'test123);Connect requires three arguments : datasource, username,passwordFirst argument -datasource gives information about the database server like type of dbms, location etc.In our example datasource is specified as DBI:mysql:database=testdb;host=localhostHere DBI:mysql means use mysql driver.database=testdb means use the database testdb.host=localhost means the host in which the database is running.Other two arguments are username and password which need no explanation.

Step 2Run the select query on the server.First store sql in a variable like thismy $query=select * from name ;Then send the sql to the server for parsing and checkingmy $sth=$dbh->prepare($query) or die could not prepare $query\n;In the above statement$dbh is the database connection handle we got while using DBI->connect earlier.$sth is the statement handle returned upon successful preparation.

$query refers to the sql statement. The query can be given directly as string also.Here we do some error checking by using die. The $sth that is returned will be required for any further opertion on this query.Now we will run the query on the server$sth->execute();Note here, we are simply using $sth to run the query. Once we call execute, the server runs the query and keeps the result set ready for retrieval.Step 3Get results from the server one row at a time.fetchrow_array() is a function that will return one row of data and store result in an array.We will use a while loop to fetch all rows from the server.while (($id,$name,$age)=$sth->fetchrow_array()){print id=$id name=$name age=$age\n;}$sth->fetchrow will return a null when there are no more rows. Thus this loop will run until null.($id,$name,$age)=$sth->fetchrow_array() is used to equate the rows returned to a set of variables.Step 4Close the statement handle$sth->finish();Step 5Close the database connection$dbh->disconnect();Here is the output of running the script.id=1 name=RAMAN age=45id=2 name=RAVI age=35

For the sake convenience I am repeating program listing here.use DBI;my $dbh=DBI->connect(DBI:mysql:database=testdb;host=localhost,'test,'test123);my $query=select * from name ;my $sth=$dbh->prepare($query) or die could not prepare $query\n;$sth->execute();while (($id,$name,$age)=$sth->fetchrow_array()){print id=$id name=$name age=$age\n;}$sth->finish();$dbh->disconnect()

Objective 2.Insert a record accepting input from terminalHere is the code to insert a row into name table.Step 1:Establishing connection with database. For explanation see previous exampleuse DBI;my $dbh=DBI->connect(DBI:mysql:database=testdb;host=localhost,'test,'test123);Step 2Accept input from keyboardprint Enter id:;$id=;print Enter Name:;$name=;

print Enter age;$age=;use chomp to remove any newlineschomp $id;chomp $age;chomp $name;Explanation : The print statement is simple just shows message on the screen.$id= means accept value from standard input (by default keyboard) and store the value in the variable $id;Step 3Create the Sql statement$query=sprintf insert into name(id,name,age) values(%d,%s,%d),$id,$dbh->quote($name),$age;Explanation: Here we create a string using sprintf function, by variable substitution.The sprintf in perl is similar to sprintf in c.$dbh->quote() function is used on string values, so that quotes are properly taken care of -e.g names like DSilva. It is a best practice to use this.At the end of this line the $query variable will have an sql which is an insert statement.Step 4.Run the query on the server and insert data.$dbh->do($query) or die could not do $query\n;The sql execution in the previous example was done in three stages namely prepare, execute,fetchrow_array. In the case of insert statement no rows are returned. Hence, we can use do(), which combines all three stages into one. It will return number of rows affected.Step 5.Disconnect from the server$dbh->disconnect();

For the sake of convenience the code is repeated here.use DBI;my $dbh=DBI->connect(DBI:mysql:database=testdb;host=localhost,'test,'test123);print Enter id:;$id=;print Enter Name:;$name=;print Enter age;$age=;chomp $id;chomp $age;chomp $name;$query=sprintf insert into name(id,name,age) values(%d,%s,%d),$id,$dbh->quote($name),$age;$dbh->do($query) or die could not do $query\n;$dbh->disconnect();As you can see from the above examples dbi is pretty simple. Same code can be used for any database. Only change required will be in connection step.The performance of dbi is very good, and it has lot features like fetching column names, types etc.

MySQL Perl DBI TutorialBy Deborah Lee Soltesz, eHow ContributorOne of the most powerful features of Perl is its ability to process, parse, manipulate and format text and data, making it an ideal language for developing database applications. The Perl Database Interface (DBI) Module makes it easy to connect to and use a wide range of database systems, including MySQL. In addition to Perl, the Perl::DBI module and DBD::mysql database driver must be installed on the system where the scripts are developed and executed. Most of the functionality of MySQL can be accessed through the MySQL driver for Perl::DBI.Connecting to the MySQL ServerBefore you can execute queries and other statements on a database, your script needs to establish a connection. Import the DBI module in your script with "use DBI":use DBI;The DBI->connect function connects to a database and returns a database handle. Establish a connection to a local database, providing the name of your database in the source parameter, and the user name and password for the MySQL user your script will use for the connection:my $dbh = DBI->connect('DBI:mysql:dbname', 'user', 'password') or die "Connection failed: $DBI::errstr";Connecting to a remote database is similar to a local connection by providing the remote host address in the source parameter. In the following example, the RaiseError attribute is set to report errors via die() in place of the "or die" manual error checking clause in the previous example. The PrintError attribute is disabled. PrintError automatically reports errors via warn() when enabled.my $dbh = DBI->connect('DBI:mysql:dbname;host=db.server.edu', 'user', 'password', { PrintError => 0, RaiseError => 1 });Before exiting the script, disconnect from the database using the disconnect function.$dbh->disconnect();Basic QueriesThe most common statement executed on a database is the SELECT statement. Create a statement handle by calling the prepare function with the SELECT statement. For example, this SELECT will query a table listing of people for the first name field for all entries where the last name is "Johnson":my $sth = $dbh->prepare("SELECT firstname FROM people WHERE lastname='Johnson'");Execute the statement:

$sth->execute();Retrieve one row of data at a time as a hash and print the results:print "Query for last name Johnson: \n";while (my $resultrow = $sth->fetchrow_hashref()) {my $fn = $resultrow->{firstname};print "$fn\n";}There are several functions for retrieving query results, such as fetchrow_array to fetch the next row as an array and fetchall_hashref to fetch all of the results at once into a hash.Using PlaceholdersPlaceholders can be used in the statement prepare function. This is useful in interactive scripts where query filter values are provided by the user, particularly if a loop allows the user to submit multiple queries before exiting. For example, the placeholder (the question mark) provides the spot where user input will be provided when the statement is executed:my $sth = $dbh->prepare('SELECT * FROM people WHERE lastname = ?') or die "Statement error: " . $dbh->errstr;A while loop repeatedly prompts the user for a last name:print "Search for last name: ";while ($lastname = ) {chomp $lastname;my @results;The statement prepared earlier is executed, with $lastname provided as a parameter. This parameter will be inserted into the query statement in place of the question mark placeholder:$sth->execute($lastname) or die "Statement error: " . $sth->errstr;The results, if any, are printed out:if ($sth->rows == 0) {print "No matches for `$lastname'.\n\n";}

while (@results = $sth->fetchrow_array()) {my $firstname = $results[1];my $age = $results[3];print "$firstname $lastname ($age)\n";}The statement handle is tidied up with the finish method, and the loop continues:$sth->finish;print "Search for last name: ";}Adding, Updating and Deleting RecordsUpdates, inserts and deletes can be executed simply by using the do function. For example:$dbh->do("INSERT INTO people(firstname, lastname, age) VALUES('Bob', 'Johnson', 32)");$dbh->do("UPDATE people set firstname='Robert' where firstname=?", undef, "Bob");$dbh->do("DELETE FROM people WHERE lastname='Johnson'");Building and Managing a DatabaseDatabase administration functions are executed with the func function using the database handle obtained from the connection:$dbh->func("createdb", $dbname, 'admin');$dbh->func("dropdb", $dbname, 'admin');The server can also be reloaded and shut down. This functionality is useful for simplifying and automating database systems administration tasks. Sufficient privileges are required for these actions.Database table create and alter statements can be executed with the do function. For example, this statement creates the people table:$dbh->do("CREATE TABLE people (id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, firstname VARCHAR(50), lastname VARCHAR(50), age INT)");Creating and updating existing databases is useful for automating the installation of distributed applications, such as discussion boards, photo galleries and blogs.