SunshinePHP Developer Conference 2015

MySQL 関数 (PDO_MYSQL)

導入

PDO_MYSQL は、PHP から MySQL 3.x、4.x および 5.x データベースへのアクセスを可能にするための PHP Data Objects (PDO) インターフェイス を実装したドライバです。

PDO_MYSQL は、MySQL 4.1 以降に存在するプリペアドステートメントを ネイティブにサポートしているという利点があります。 古いバージョンの mysql クライアントライブラリを使用している場合は、 PDO がこの機能をエミュレートします。

警告

注意: MySQL のテーブル型 (ストレージエンジン) の中には、 トランザクションをサポートしていないものがあります。 トランザクションをサポートしていないテーブル型を使用して トランザクションを使用するコードを書くと、 MySQL はトランザクションが正常に使用できたかのように振舞います。 さらに、DDL クエリを実行する際には、 実行中のトランザクションが暗黙的にコミットされます。

インストール手順

--with-pdo-mysql[=DIR] で PDO MySQL 拡張モジュールをインストールします。オプションの [=DIR] には、MySQL の基底インストールディレクトリを指定することができます。 [=DIR]mysqlnd を指定すると、MySQL ネイティブドライバを使用します。

オプションの --with-mysql-sock[=DIR] で MySQL unix ソケットの場所を指定することができます。これは PDO_MYSQL を含むすべての MySQL 拡張モジュールで利用します。省略した場合はデフォルトの場所を検索します。

オプションの --with-zlib-dir[=DIR] で、 libz のインストールプレフィックスを指定することができます。

$ ./configure --with-pdo-mysql --with-mysql-sock=/var/mysql/mysql.sock

SSL サポートを有効にするには、適切な PDO_MySQL 定数 を指定します。これは » MySQL C API 関数 mysql_ssl_set() をコールするのと同じ意味になります。また、SSL を PDO::setAttribute で有効にすることはできません。というのも、この時点ではすでに接続が確立されてしまっているからです。 MySQL のドキュメントで » SSL を使った MySQL への接続 について確認しましょう。

変更履歴
バージョン 説明
5.4.0 MySQL クライアントライブラリ 4.1 を含む、それ以前のバージョンはサポートされなくなりました。
5.3.9 mysqlnd と OpenSSL による SSL サポートが追加されました。
5.3.7 libmysqlclient と OpenSSL による SSL サポートが追加されました。

定義済み定数

このドライバでは以下の定数が定義されて います。これは拡張モジュールが PHP に組み込まれているか、実行時に動的にロード されている場合のみ使用可能です。さらに、これらのドライバ固有の定数は そのドライバを使用している場合にのみ使用されます。 あるドライバ固有の属性を別のドライバで使うと、予期せぬ結果を引き起こします。 もし複数のドライバを使用しているコードを実行している場合、 PDO::getAttribute()PDO_ATTR_DRIVER_NAME 属性を使用することで、使用中のドライバ名を調べることが可能です。

PDO::MYSQL_ATTR_USE_BUFFERED_QUERY (integer)
PDOStatement でこの属性を TRUE に設定すると、 MySQL ドライバはバッファ版の MySQL API を使用します。 移植性の高いコードを書くには、代わりに PDOStatement::fetchAll() を使用すべきです。

例1 mysql でクエリのバッファリングを強制する

<?php
if ($db->getAttribute(PDO::ATTR_DRIVER_NAME) == 'mysql') {
    
$stmt $db->prepare('select * from foo',
        array(
PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => true));
} else {
    die(
"このアプリケーションは mysql でしか動作しません。代わりに \$stmt->fetchAll() を使用すべきです");
}
?>

PDO::MYSQL_ATTR_LOCAL_INFILE (integer)

LOAD LOCAL INFILE を有効にします。

この定数を使うのは、新しいデータベースハンドルを作るときの driver_options 配列内だけであることに注意しましょう。

PDO::MYSQL_ATTR_INIT_COMMAND (integer)

MySQL サーバーへの接続時に実行するコマンドを指定します。 再接続の際には自動的に再実行されます。

この定数を使うのは、新しいデータベースハンドルを作るときの driver_options 配列内だけであることに注意しましょう。

PDO::MYSQL_ATTR_READ_DEFAULT_FILE (integer)

my.cnf ではなく、 指定した名前のファイルからオプションを読み込みます。 このオプションは、mysqlnd を使っている場合は利用できません。 mysqlnd は mysql の設定ファイルを読んでいないからです。

PDO::MYSQL_ATTR_READ_DEFAULT_GROUP (integer)

my.cnf あるいは 別のファイル (MYSQL_READ_DEFAULT_FILE で指定したもの) の中の、指定した名前のグループからオプションを読み込みます。 このオプションは、mysqlnd を使っている場合は利用できません。 mysqlnd は mysql の設定ファイルを読んでいないからです。

PDO::MYSQL_ATTR_MAX_BUFFER_SIZE (integer)

バッファの最大サイズ。デフォルトは 1 MiB です。 mysqlnd を指定してコンパイルした場合は、この定数はサポートされていません。

PDO::MYSQL_ATTR_DIRECT_QUERY (integer)

プリペアドステートメントではなく、直接クエリを実行します。

PDO::MYSQL_ATTR_FOUND_ROWS (integer)

変更された行数ではなく、見つかった (マッチした) 行数を返します。

PDO::MYSQL_ATTR_IGNORE_SPACE (integer)

関数名の後に続く空白を許可します。 すべての関数名を予約語にします。

PDO::MYSQL_ATTR_COMPRESS (integer)

ネットワーク通信の圧縮を有効にします。これは、 mysqlnd を使ってコンパイルした場合はサポートされていません。

PDO::MYSQL_ATTR_SSL_CA (integer)

これが使えるようになった PHP のバージョンは 5.3.7.

PDO::MYSQL_ATTR_SSL_CAPATH (integer)

これが使えるようになった PHP のバージョンは 5.3.7.

PDO::MYSQL_ATTR_SSL_CERT (integer)

これが使えるようになった PHP のバージョンは 5.3.7.

PDO::MYSQL_ATTR_SSL_CIPHER (integer)

これが使えるようになった PHP のバージョンは 5.3.7.

PDO::MYSQL_ATTR_SSL_KEY (integer)

これが使えるようになった PHP のバージョンは 5.3.7.

実行時設定

php.ini の設定により動作が変化します。

PDO_MYSQL 設定オプション
名前 デフォルト 変更可能
pdo_mysql.default_socket "/tmp/mysql.sock" PHP_INI_SYSTEM
pdo_mysql.debug NULL PHP_INI_SYSTEM
PHP_INI_* モードの詳細および定義については どこで設定を行うのか を参照してください。

以下に設定ディレクティブに関する 簡単な説明を示します。

pdo_mysql.default_socket string

Unix ドメインソケットを設定します。 configure の際にドメインソケットが見つかれば、 この値はコンパイル時にも設定されます。この ini 設定は Unix でのみ使えます。

pdo_mysql.debug boolean

PDO_MYSQL のデバッグ機能を有効にします。 この設定が有効になるのは、mysqlnd を使って PDO_MYSQL をでコンパイルし、 かつ PDO がデバッグモードであるときだけです。

目次

add a note add a note

User Contributed Notes 12 notes

up
9
dibakar at talash dot net
8 years ago
PDO is much better option for calling procedures, views or triggers of mysql 5.x versions from PHP instead of using mysqli extension. Following is a simple demo script which can  help anybody on how to call and use mysql procedures through php

try {
        $dbh = new PDO('mysql:host=xxx;port=xxx;dbname=xxx', 'xxx', 'xxx', array( PDO::ATTR_PERSISTENT => false));

        $stmt = $dbh->prepare("CALL getname()");

        // call the stored procedure
        $stmt->execute();

        echo "<B>outputting...</B><BR>";
        while ($rs = $stmt->fetch(PDO::FETCH_OBJ)) {
            echo "output: ".$rs->name."<BR>";
        }
        echo "<BR><B>".date("r")."</B>";
   
    } catch (PDOException $e) {
        print "Error!: " . $e->getMessage() . "<br/>";
        die();
    }
up
5
davey at php dot net
7 years ago
To use "PDO::MYSQL_ATTR_USE_BUFFERED_QUERY" you should call
PDO::setAttribute("PDO::MYSQL_ATTR_USE_BUFFERED_QUERY", true);

It will not work when passed into PDO::prepare()

- Davey
up
3
rmottey at gmail dot com
6 years ago
I have been getting the error below when performing multiple queries within a single page.

Setting the attribute below did not seem to work for me.

So building on previous example i am initilizing my stmt  variable on every query and a fetch all into an array. Seems to be working for me.

Error:
PDO Error 1.1: Array ( [0] => xxx[1] => yyy[2] => Lost connection to MySQL server during query )

Fix:

(PDO::setAttribute("PDO::MYSQL_ATTR_USE_BUFFERED_QUERY", true);)

<?

try {
        $dbh = new PDO('mysql:host=xxx;port=xxx;dbname=xxx', 'xxx', 'xxx', array( PDO::ATTR_PERSISTENT => false));
$stmt = $dbh->prepare("CALL getname()");

        // call the stored procedure
        $stmt->execute();
      // fetch all rows into an array.
       $rows = $stmt->fetchAll();
       foreach ($rows as $rs)
    {
          $id = $rs['id'];
         }
//initilise the statement
unset($stmt);
$stmt = $dbh->prepare("call secondprocedure(?);");
$stmt->bindValue(1, $id);
if ( ! $stmt->execute() )
{
    echo "PDO Error 1.1:\n";
    print_r($stmt->errorInfo());
    exit;
}
unset($stmt);
} catch (PDOException $e) {
        print "Error!: " . $e->getMessage() . "<br/>";
        die();
    }
?>
up
1
marty at excudo dot net
7 years ago
Davey wrote:
> To use "PDO::MYSQL_ATTR_USE_BUFFERED_QUERY" you should call
> PDO::setAttribute("PDO::MYSQL_ATTR_USE_BUFFERED_QUERY", true);
>
>It will not work when passed into PDO::prepare()
>
> - Davey

Almost correct. It should be:

PDO::setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true);

so, without the quotes.
otherwise it still won't work :)
up
1
brian at diamondsea dot com
6 years ago
SQLSTATE[HY000]: General error: 2014 Cannot execute queries while other unbuffered queries are active. ...

After spending hours trying to track down why we were getting this error on a new server, after the same code ran fine on other servers, we found the problem to be an old MySQL _client_ library running on our web server, and a latest-version MySQL _server_ running on the database server's box.

Upgraded the MySQL client on the web server to the current revision and the problem went away.
up
1
georgy dot garnov at gmail dot com
5 days ago
PDO::MYSQL_ATTR_LOCAL_INFILE - will not work if you have
open_basedir in your php.ini
up
0
Gerald Schneider
11 months ago
This page suggests that the constant PDO::MYSQL_ATTR_FOUND_ROWS  was always available (no note "exists as of X.X"), but I found the constant missing on an installation with PHP 5.2. After switching the PHP version to 5.3.27 on the webspace the constant was available.
up
0
curt at webmasterbond dot com
3 years ago
Today's PHP snapshot now has SSL support for PDO. Follow the directions here ( http://dev.mysql.com/doc/refman/5.0/en/secure-create-certs.html ) to set up MySQL and then use the following connection options:

<?php
$pdo
= new PDO(
   
'mysql:host=hostname;dbname=ssldb',
   
'username',
   
'password',
    array(
       
PDO::MYSQL_ATTR_SSL_KEY    =>'/path/to/client-key.pem',
       
PDO::MYSQL_ATTR_SSL_CERT=>'/path/to/client-cert.pem',
       
PDO::MYSQL_ATTR_SSL_CA    =>'/path/to/ca-cert.pem'
   
)
);
?>
up
-1
miller_kurt_e at yahoo dot com
6 years ago
SQLSTATE[HY000]: General error: 2014 Cannot execute queries while other unbuffered queries are active. ...

This one can be a royal pain to deal with.  Never stack statements to be executed in one go.  Nobody ever mentions this possibility in all the posts I've seen dealing with this error.

This example is a Zend Framework example but the theory is the same.

As in:

<?php
$sql
= <<<____SQL
     CREATE TABLE IF NOT EXISTS `ticket_hist` (
       `tid` int(11) NOT NULL,
       `trqform` varchar(40) NOT NULL,
       `trsform` varchar(40) NOT NULL,
       `tgen` datetime NOT NULL,
       `tterm` datetime,
       `tstatus` tinyint(1) NOT NULL
     ) ENGINE=ARCHIVE COMMENT='ticket archive';
     CREATE TABLE IF NOT EXISTS `request_hist` (
       `rqid` int(11) NOT NULL,
       `rqtid` int(11) NOT NULL,
       `rqsid` int(11) NOT NULL,
       `rqdate` datetime NOT NULL,
       `rqcode` tinyint(1) NOT NULL,
       `rssid` int(11) NOT NULL,
       `rsdate` datetime,
       `rscode` tinyint(1)
     ) ENGINE=ARCHIVE COMMENT='request archive';
     CREATE TABLE IF NOT EXISTS `relay_hist` (
       `rqid` int(5) NOT NULL,
       `sdesc` varchar(40) NOT NULL,
       `rqemail` varchar(40) NOT NULL,
       `sid` int(11) NOT NULL,
       `rlsid` int(11) NOT NULL,
       `dcode` varchar(5) NOT NULL
     ) ENGINE=ARCHIVE COMMENT='relay archive';
____SQL;
$result = $this->db->getConnection()->exec($sql);
?>

This will run fine but PDO will balk with the 'unbuffered' error if you follow this with another query.

Instead do:

<?php
$sql
= <<<____SQL
     CREATE TABLE IF NOT EXISTS `ticket_hist` (
       `tid` int(11) NOT NULL,
       `trqform` varchar(40) NOT NULL,
       `trsform` varchar(40) NOT NULL,
       `tgen` datetime NOT NULL,
       `tterm` datetime,
       `tstatus` tinyint(1) NOT NULL
     ) ENGINE=ARCHIVE COMMENT='ticket archive';
____SQL;
$result = $this->db->getConnection()->exec($sql);

$sql = <<<____SQL
     CREATE TABLE IF NOT EXISTS `request_hist` (
       `rqid` int(11) NOT NULL,
       `rqtid` int(11) NOT NULL,
       `rqsid` int(11) NOT NULL,
       `rqdate` datetime NOT NULL,
       `rqcode` tinyint(1) NOT NULL,
       `rssid` int(11) NOT NULL,
       `rsdate` datetime,
       `rscode` tinyint(1)
     ) ENGINE=ARCHIVE COMMENT='request archive';
____SQL;
$result = $this->db->getConnection()->exec($sql);

$sql = <<<____SQL
     CREATE TABLE IF NOT EXISTS `relay_hist` (
       `rqid` int(5) NOT NULL,
       `sdesc` varchar(40) NOT NULL,
       `rqemail` varchar(40) NOT NULL,
       `sid` int(11) NOT NULL,
       `rlsid` int(11) NOT NULL,
       `dcode` varchar(5) NOT NULL
     ) ENGINE=ARCHIVE COMMENT='relay archive';
____SQL;
$result = $this->db->getConnection()->exec($sql);
?>

Chopping it into individual queries fixes the problem.
up
-4
david at manifestwebdesign dot com
2 years ago
The SSL options are silently ignored in PHP 5.3.8, see https://bugs.php.net/bug.php?id=55870
Looks like it's addressed upstream, I just want to save others the hour and a half I just wasted :)
up
-5
kat dot shupe dot work at gmail dot com
6 months ago
So, I'm trying to get one PHP file to be able to call from two SQL databases at the same time. How can I do that? Or rather, how can I close a connection being made by SqltoAssoc PDO function so I can start a second one with a completely different SQL database?

Thanks in advanced!
up
-14
konrads dot smelkovs at gmail dot com
7 years ago
A note for the eager:
There is no way how to get returned row count from an executed prepared statement without fetching the rows.
To Top