DBD::mysql(3pm) | User Contributed Perl Documentation | DBD::mysql(3pm) |
DBD::mysql - MySQL driver for the Perl5 Database Interface (DBI)
use DBI; my $dsn = "DBI:mysql:database=$database;host=$hostname;port=$port"; my $dbh = DBI->connect($dsn, $user, $password); my $sth = $dbh->prepare( 'SELECT id, first_name, last_name FROM authors WHERE last_name = ?') or die "prepare statement failed: $dbh->errstr()"; $sth->execute('Eggers') or die "execution failed: $dbh->errstr()"; print $sth->rows . " rows found.\n"; while (my $ref = $sth->fetchrow_hashref()) { print "Found a row: id = $ref->{'id'}, fn = $ref->{'first_name'}\n"; } $sth->finish;
#!/usr/bin/perl use strict; use warnings; use DBI; # Connect to the database. my $dbh = DBI->connect("DBI:mysql:database=test;host=localhost", "joe", "joe's password", {'RaiseError' => 1}); # Drop table 'foo'. This may fail, if 'foo' doesn't exist # Thus we put an eval around it. eval { $dbh->do("DROP TABLE foo") }; print "Dropping foo failed: $@\n" if $@; # Create a new table 'foo'. This must not fail, thus we don't # catch errors. $dbh->do("CREATE TABLE foo (id INTEGER, name VARCHAR(20))"); # INSERT some data into 'foo'. We are using $dbh->quote() for # quoting the name. $dbh->do("INSERT INTO foo VALUES (1, " . $dbh->quote("Tim") . ")"); # same thing, but using placeholders (recommended!) $dbh->do("INSERT INTO foo VALUES (?, ?)", undef, 2, "Jochen"); # now retrieve data from the table. my $sth = $dbh->prepare("SELECT * FROM foo"); $sth->execute(); while (my $ref = $sth->fetchrow_hashref()) { print "Found a row: id = $ref->{'id'}, name = $ref->{'name'}\n"; } $sth->finish(); # Disconnect from the database. $dbh->disconnect();
DBD::mysql is the Perl5 Database Interface driver for the MySQL database. In other words: DBD::mysql is an interface between the Perl programming language and the MySQL programming API that comes with the MySQL relational database management system. Most functions provided by this programming API are supported. Some rarely used functions are missing, mainly because no-one ever requested them. :-)
In what follows we first discuss the use of DBD::mysql, because this is what you will need the most. For installation, see the separate document DBD::mysql::INSTALL. See "EXAMPLE" for a simple example above.
From perl you activate the interface with the statement
use DBI;
After that you can connect to multiple MySQL database servers and send multiple queries to any of them via a simple object oriented interface. Two types of objects are available: database handles and statement handles. Perl returns a database handle to the connect method like so:
$dbh = DBI->connect("DBI:mysql:database=$db;host=$host", $user, $password, {RaiseError => 1});
Once you have connected to a database, you can execute SQL statements with:
my $query = sprintf("INSERT INTO foo VALUES (%d, %s)", $number, $dbh->quote("name")); $dbh->do($query);
See DBI for details on the quote and do methods. An alternative approach is
$dbh->do("INSERT INTO foo VALUES (?, ?)", undef, $number, $name);
in which case the quote method is executed automatically. See also the bind_param method in DBI. See "DATABASE HANDLES" below for more details on database handles.
If you want to retrieve results, you need to create a so-called statement handle with:
$sth = $dbh->prepare("SELECT * FROM $table"); $sth->execute();
This statement handle can be used for multiple things. First of all you can retrieve a row of data:
my $row = $sth->fetchrow_hashref();
If your table has columns ID and NAME, then $row will be hash ref with keys ID and NAME. See "STATEMENT HANDLES" below for more details on statement handles.
But now for a more formal approach:
use DBI; $dsn = "DBI:mysql:$database"; $dsn = "DBI:mysql:database=$database;host=$hostname"; $dsn = "DBI:mysql:database=$database;host=$hostname;port=$port"; $dbh = DBI->connect($dsn, $user, $password);
The "database" is not a required attribute, but please note that MySQL has no such thing as a default database. If you don't specify the database at connection time your active database will be null and you'd need to prefix your tables with the database name; i.e. 'SELECT * FROM mydb.mytable'.
This is similar to the behavior of the mysql command line client. Also, 'SELECT DATABASE()' will return the current database active for the handle.
Should the MySQL server be running on a non-standard port number, you may explicitly state the port number to connect to in the "hostname" argument, by concatenating the hostname and port number together separated by a colon ( ":" ) character or by using the "port" argument.
To connect to a MySQL server on localhost using TCP/IP, you must specify the hostname as 127.0.0.1 (with the optional port).
When connecting to a MySQL Server with IPv6, a bracketed IPv6 address should be used. Example DSN:
my $dsn = "DBI:mysql:;host=[1a12:2800:6f2:85::f20:8cf];port=3306";
If you want the number of rows changed in response to an UPDATE statement, specify "mysql_client_found_rows=0" in the DSN.
$dsn = "DBI:mysql:test;mysql_read_default_file=/home/joe/my.cnf"; $dbh = DBI->connect($dsn, $user, $password)
The option mysql_read_default_group can be used to specify the default group in the config file: Usually this is the client group, but see the following example:
[client] host=localhost [perl] host=perlhost
(Note the order of the entries! The example won't work, if you reverse the [client] and [perl] sections!)
If you read this config file, then you'll be typically connected to localhost. However, by using
$dsn = "DBI:mysql:test;mysql_read_default_group=perl;" . "mysql_read_default_file=/home/joe/my.cnf"; $dbh = DBI->connect($dsn, $user, $password);
you'll be connected to perlhost. Note that if you specify a default group and do not specify a file, then the default config files will all be read. See the documentation of the C function mysql_options() for details.
mysql_socket=/dev/mysql
Usually there's no need for this option, unless you are using another location for the socket than that built into the client.
When enabling SSL encryption you should set also other SSL options, at least mysql_ssl_ca_file or mysql_ssl_ca_path.
mysql_ssl=1 mysql_ssl_verify_server_cert=1 mysql_ssl_ca_file=/path/to/ca_cert.pem
This means that your communication with the server will be encrypted.
Please note that this can only work if you enabled SSL when compiling DBD::mysql; this is the default starting version 4.034. See DBD::mysql::INSTALL for more details.
When set MySQL server certificate is checked that it is signed by some CA certificate in the list. Common Name value is not verified unless "mysql_ssl_verify_server_cert" is enabled.
When set MySQL server certificate is checked that it is signed by some CA certificate in the list. Common Name value is not verified unless "mysql_ssl_verify_server_cert" is enabled.
Please note that this option is supported only if your MySQL client was compiled with OpenSSL library, and not with default yaSSL library.
Verification of the host name is disabled by default.
mysql_ssl_cipher=AES128-SHA mysql_ssl_cipher=DHE-RSA-AES256-SHA:AES128-SHA
This option was introduced in 4.043 version of DBD::mysql. Due to The BACKRONYM <http://backronym.fail/> and The Riddle <http://riddle.link/> vulnerabilities in libmysqlclient library, enforcement of SSL encryption was not possbile and therefore "mysql_ssl_optional=1" was effectively set for all DBD::mysql versions prior to 4.043. Starting with 4.043, DBD::mysql with "mysql_ssl=1" could refuse connection to MySQL server if underlaying libmysqlclient library is vulnerable. Option "mysql_ssl_optional" can be used to make SSL connection vulnerable.
To use server side prepared statements, all you need to do is set the variable mysql_server_prepare in the connect:
$dbh = DBI->connect( "DBI:mysql:database=test;host=localhost;mysql_server_prepare=1", "", "", { RaiseError => 1, AutoCommit => 1 } );
or:
$dbh = DBI->connect( "DBI:mysql:database=test;host=localhost", "", "", { RaiseError => 1, AutoCommit => 1, mysql_server_prepare => 1 } );
There are many benefits to using server side prepare statements, mostly if you are performing many inserts because of that fact that a single statement is prepared to accept multiple insert values.
To make sure that the 'make test' step tests whether server prepare works, you just need to export the env variable MYSQL_SERVER_PREPARE:
export MYSQL_SERVER_PREPARE=1
Please note that mysql server cannot prepare or execute some prepared statements. In this case DBD::mysql fallbacks to normal non-prepared statement and tries again.
Useful when you want to be sure that statement is going to be executed as server side prepared. Error message and code in case of failure is propagated back to DBI.
Example:
use DBI; $testdsn="DBI:mysqlEmb:database=test;mysql_embedded_options=--help,--verbose"; $dbh = DBI->connect($testdsn,"a","b");
This would cause the command line help to the embedded MySQL server library to be printed.
Example:
$testdsn="DBI:mysqlEmb:database=test;mysql_embedded_groups=embedded_server,common";
You can then later read these attributes from the performance schema tables which can be quite helpful for profiling your database or creating statistics. You'll have to use a MySQL 5.6 server and libmysqlclient or newer to leverage this feature.
my $dbh= DBI->connect($dsn, $user, $password, { AutoCommit => 0, mysql_conn_attrs => { foo => 'bar', wiz => 'bang' }, });
Now you can select the results from the performance schema tables. You can do this in the same session, but also afterwards. It can be very useful to answer questions like 'which script sent this query?'.
my $results = $dbh->selectall_hashref( 'SELECT * FROM performance_schema.session_connect_attrs', 'ATTR_NAME' );
This returns:
$result = { 'foo' => { 'ATTR_VALUE' => 'bar', 'PROCESSLIST_ID' => '3', 'ATTR_NAME' => 'foo', 'ORDINAL_POSITION' => '6' }, 'wiz' => { 'ATTR_VALUE' => 'bang', 'PROCESSLIST_ID' => '3', 'ATTR_NAME' => 'wiz', 'ORDINAL_POSITION' => '3' }, 'program_name' => { 'ATTR_VALUE' => './foo.pl', 'PROCESSLIST_ID' => '3', 'ATTR_NAME' => 'program_name', 'ORDINAL_POSITION' => '5' }, '_client_name' => { 'ATTR_VALUE' => 'libmysql', 'PROCESSLIST_ID' => '3', 'ATTR_NAME' => '_client_name', 'ORDINAL_POSITION' => '1' }, '_client_version' => { 'ATTR_VALUE' => '5.6.24', 'PROCESSLIST_ID' => '3', 'ATTR_NAME' => '_client_version', 'ORDINAL_POSITION' => '7' }, '_os' => { 'ATTR_VALUE' => 'osx10.8', 'PROCESSLIST_ID' => '3', 'ATTR_NAME' => '_os', 'ORDINAL_POSITION' => '0' }, '_pid' => { 'ATTR_VALUE' => '59860', 'PROCESSLIST_ID' => '3', 'ATTR_NAME' => '_pid', 'ORDINAL_POSITION' => '2' }, '_platform' => { 'ATTR_VALUE' => 'x86_64', 'PROCESSLIST_ID' => '3', 'ATTR_NAME' => '_platform', 'ORDINAL_POSITION' => '4' } };
my $drh = DBI->install_driver("mysql"); @dbs = $drh->func("$hostname:$port", '_ListDBs'); @dbs = $drh->func($hostname, $port, '_ListDBs'); @dbs = $dbh->func('_ListDBs');
Returns a list of all databases managed by the MySQL server running on $hostname, port $port. This is a legacy method. Instead, you should use the portable method
@dbs = DBI->data_sources("mysql");
The DBD::mysql driver supports the following attributes of database handles (read only):
$errno = $dbh->{'mysql_errno'}; $error = $dbh->{'mysql_error'}; $info = $dbh->{'mysql_hostinfo'}; $info = $dbh->{'mysql_info'}; $insertid = $dbh->{'mysql_insertid'}; $info = $dbh->{'mysql_protoinfo'}; $info = $dbh->{'mysql_serverinfo'}; $info = $dbh->{'mysql_stat'}; $threadId = $dbh->{'mysql_thread_id'};
These correspond to mysql_errno(), mysql_error(), mysql_get_host_info(), mysql_info(), mysql_insert_id(), mysql_get_proto_info(), mysql_get_server_info(), mysql_stat() and mysql_thread_id(), respectively.
print "$dbh->{mysql_clientinfo}\n"; 5.2.0-MariaDB
print "$dbh->{mysql_clientversion}\n"; 50200
print "$dbh->{mysql_serverversion}\n"; 50200
$info_hashref = $dbh->{mysql_dbd_stats};
DBD::mysql keeps track of some statistics in the mysql_dbd_stats attribute. The following stats are being maintained:
The DBD::mysql driver also supports the following attributes of database handles (read/write):
It is also possible to set the default value of the "mysql_auto_reconnect" attribute for the $dbh by passing it in the "\%attr" hash for "DBI-"connect>.
$dbh->{mysql_auto_reconnect} = 1;
or
my $dbh = DBI->connect($dsn, $user, $password, { mysql_auto_reconnect => 1, });
Note that if you are using a module or framework that performs reconnections for you (for example DBIx::Connector in fixup mode), this value must be set to 0.
It is possible to set the default value of the "mysql_use_result" attribute for the $dbh via the DSN:
$dbh = DBI->connect("DBI:mysql:test;mysql_use_result=1", "root", "");
You can also set it after creation of the database handle:
$dbh->{mysql_use_result} = 0; # disable $dbh->{mysql_use_result} = 1; # enable
You can also set or unset the "mysql_use_result" setting on your statement handle, when creating the statement handle or after it has been created. See "STATEMENT HANDLES".
When set, a data retrieved from a textual column type (char, varchar, etc) will have the UTF-8 flag turned on if necessary. This enables character semantics on that string. You will also need to ensure that your database / table / column is configured to use UTF8. See for more information the chapter on character set support in the MySQL manual: <http://dev.mysql.com/doc/refman/5.7/en/charset.html>
Additionally, turning on this flag tells MySQL that incoming data should be treated as UTF-8. This will only take effect if used as part of the call to connect(). If you turn the flag on after connecting, you will need to issue the command "SET NAMES utf8" to get the same effect.
CAVEAT: Even though you can insert an integer value into a character column, if this column is indexed, if you query that column with the integer value not being quoted, it will not use the index:
MariaDB [test]> explain select * from test where value0 = '3' \G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: test type: ref possible_keys: value0 key: value0 key_len: 13 ref: const rows: 1 Extra: Using index condition 1 row in set (0.00 sec) MariaDB [test]> explain select * from test where value0 = 3 -> \G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: test type: ALL possible_keys: value0 key: NULL key_len: NULL ref: NULL rows: 6 Extra: Using where 1 row in set (0.00 sec)
See bug: https://rt.cpan.org/Ticket/Display.html?id=43822
"mysql_bind_type_guessing" can be turned on via
- through DSN my $dbh= DBI->connect('DBI:mysql:test', 'username', 'pass', { mysql_bind_type_guessing => 1}) - OR after handle creation $dbh->{mysql_bind_type_guessing} = 1;
See the bug report:
https://rt.cpan.org/Public/Bug/Display.html?id=46308
"mysql_no_autocommit_cmd" can be turned on when creating the database handle:
my $dbh = DBI->connect('DBI:mysql:test', 'username', 'pass', { mysql_no_autocommit_cmd => 1});
or using an existing database handle:
$dbh->{mysql_no_autocommit_cmd} = 1;
$rc = $dbh->ping();
The statement handles of DBD::mysql support a number of attributes. You access these by using, for example,
my $numFields = $sth->{NUM_OF_FIELDS};
Note, that most attributes are valid only after a successful execute. An "undef" value will returned otherwise. The most important exception is the "mysql_use_result" attribute, which forces the driver to use mysql_use_result rather than mysql_store_result. The former is faster and less memory consuming, but tends to block other processes. (That's why mysql_store_result is the default.)
To set the "mysql_use_result" attribute, use either of the following:
my $sth = $dbh->prepare("QUERY", { mysql_use_result => 1});
or
my $sth = $dbh->prepare($sql); $sth->{mysql_use_result} = 1;
Column dependent attributes, for example NAME, the column names, are returned as a reference to an array. The array indices are corresponding to the indices of the arrays returned by fetchrow and similar methods. For example the following code will print a header of table names together with all rows:
my $sth = $dbh->prepare("SELECT * FROM $table") || die "Error:" . $dbh->errstr . "\n"; $sth->execute || die "Error:" . $sth->errstr . "\n"; my $names = $sth->{NAME}; my $numFields = $sth->{'NUM_OF_FIELDS'} - 1; for my $i ( 0..$numFields ) { printf("%s%s", $i ? "," : "", $$names[$i]); } print "\n"; while (my $ref = $sth->fetchrow_arrayref) { for my $i ( 0..$numFields ) { printf("%s%s", $i ? "," : "", $$ref[$i]); } print "\n"; }
For portable applications you should restrict yourself to attributes with capitalized or mixed case names. Lower case attribute names are private to DBD::mysql. The attribute list includes:
Typically, you'd access the value via $sth->{mysql_insertid}. The value can also be accessed via $dbh->{mysql_insertid} but this can easily produce incorrect results in case one database handle is shared.
The transaction support works as follows:
$dbh->{AutoCommit} = 0;
or
$dbh->{AutoCommit} = 1;
then the driver will set the MySQL server variable autocommit to 0 or 1, respectively. Switching from 0 to 1 will also issue a COMMIT, following the DBI specifications.
$dbh->rollback(); $dbh->commit();
will issue the commands ROLLBACK and COMMIT, respectively. A ROLLBACK will also be issued if AutoCommit mode is off and the database handles DESTROY method is called. Again, this is following the DBI specifications.
Given the above, you should note the following:
$dbh->{AutoCommit} = 0; if ($dbh->{AutoCommit}) { # An error occurred! }
DBD::mysql supports multiple result sets, thanks to Guy Harrison!
The basic usage of multiple result sets is
do { while (@row = $sth->fetchrow_array()) { do stuff; } } while ($sth->more_results)
An example would be:
$dbh->do("drop procedure if exists someproc") or print $DBI::errstr; $dbh->do("create procedure someproc() deterministic begin declare a,b,c,d int; set a=1; set b=2; set c=3; set d=4; select a, b, c, d; select d, c, b, a; select b, a, c, d; select c, b, d, a; end") or print $DBI::errstr; $sth=$dbh->prepare('call someproc()') || die $DBI::err.": ".$DBI::errstr; $sth->execute || die DBI::err.": ".$DBI::errstr; $rowset=0; do { print "\nRowset ".++$i."\n---------------------------------------\n\n"; foreach $colno (0..$sth->{NUM_OF_FIELDS}-1) { print $sth->{NAME}->[$colno]."\t"; } print "\n"; while (@row= $sth->fetchrow_array()) { foreach $field (0..$#row) { print $row[$field]."\t"; } print "\n"; } } until (!$sth->more_results)
Please be aware there could be issues if your result sets are "jagged", meaning the number of columns of your results vary. Varying numbers of columns could result in your script crashing.
The multithreading capabilities of DBD::mysql depend completely on the underlying C libraries. The modules are working with handle data only, no global variables are accessed or (to the best of my knowledge) thread unsafe functions are called. Thus DBD::mysql is believed to be completely thread safe, if the C libraries are thread safe and you don't share handles among threads.
The obvious question is: Are the C libraries thread safe? In the case of MySQL the answer is yes, since MySQL 5.5 it is.
You can make a single asynchronous query per MySQL connection; this allows you to submit a long-running query to the server and have an event loop inform you when it's ready. An asynchronous query is started by either setting the 'async' attribute to a true value in the "do" in DBI method, or in the "prepare" in DBI method. Statements created with 'async' set to true in prepare always run their queries asynchronously when "execute" in DBI is called. The driver also offers three additional methods: "mysql_async_result", "mysql_async_ready", and "mysql_fd". "mysql_async_result" returns what do or execute would have; that is, the number of rows affected. "mysql_async_ready" returns true if "mysql_async_result" will not block, and zero otherwise. They both return "undef" if that handle was not created with 'async' set to true or if an asynchronous query was not started yet. "mysql_fd" returns the file descriptor number for the MySQL connection; you can use this in an event loop.
Here's an example of how to use the asynchronous query interface:
use feature 'say'; $dbh->do('SELECT SLEEP(10)', { async => 1 }); until($dbh->mysql_async_ready) { say 'not ready yet!'; sleep 1; } my $rows = $dbh->mysql_async_result;
See DBD::mysql::INSTALL.
Originally, there was a non-DBI driver, Mysql, which was much like PHP drivers such as mysql and mysqli. The Mysql module was originally written by Andreas König <koenig@kulturbox.de> who still, to this day, contributes patches to DBD::mysql. An emulated version of Mysql was provided to DBD::mysql from Jochen Wiedmann, but eventually deprecated as it was another bundle of code to maintain.
The first incarnation of DBD::mysql was developed by Alligator Descartes, who was also aided and abetted by Gary Shea, Andreas König and Tim Bunce.
The current incarnation of DBD::mysql was written by Jochen Wiedmann, then numerous changes and bug-fixes were added by Rudy Lippan. Next, prepared statement support was added by Patrick Galbraith and Alexy Stroganov (who also solely added embedded server support).
For the past nine years DBD::mysql has been maintained by Patrick Galbraith (patg@patg.net), and recently with the great help of Michiel Beijen (michiel.beijen@gmail.com), along with the entire community of Perl developers who keep sending patches to help continue improving DBD::mysql
Anyone who desires to contribute to this project is encouraged to do so. Currently, the source code for this project can be found at Github:
<https://github.com/perl5-dbi/DBD-mysql/>
Either fork this repository and produce a branch with your changeset that the maintainer can merge to his tree, or create a diff with git. The maintainer is more than glad to take contributions from the community as many features and fixes from DBD::mysql have come from the community.
This module is
This module is released under the same license as Perl itself. See <http://www.perl.com/perl/misc/Artistic.html> for details.
This module is maintained and supported on a mailing list, dbi-users.
To subscribe to this list, send an email to
dbi-users-subscribe@perl.org
Mailing list archives are at
<http://groups.google.com/group/perl.dbi.users?hl=en&lr=>
Additional information on the DBI project can be found on the World Wide Web at the following URL:
<http://dbi.perl.org>
where documentation, pointers to the mailing lists and mailing list archives and pointers to the most current versions of the modules can be used.
Information on the DBI interface itself can be gained by typing:
perldoc DBI
Information on DBD::mysql specifically can be gained by typing:
perldoc DBD::mysql
(this will display the document you're currently reading)
Please report bugs, including all the information needed such as DBD::mysql version, MySQL version, OS type/version, etc to this link:
<https://rt.cpan.org/Dist/Display.html?Name=DBD-mysql>
Note: until recently, MySQL/Sun/Oracle responded to bugs and assisted in fixing bugs which many thanks should be given for their help! This driver is outside the realm of the numerous components they support, and the maintainer and community solely support DBD::mysql
2024-10-15 | perl v5.40.0 |