質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
PDO

PDO(PHP Data Objects)はPHPのデータベース抽象化レイヤーです。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Q&A

解決済

1回答

3589閲覧

PDOでのマイクロ秒

退会済みユーザー

退会済みユーザー

総合スコア0

PDO

PDO(PHP Data Objects)はPHPのデータベース抽象化レイヤーです。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

0グッド

0クリップ

投稿2016/03/22 11:11

編集2016/03/22 11:35

すみません、初めてマトモな質問をします。よろしくお願いします。

MySQL、PostgreSQLでマイクロ秒のカラムを作り、INSERTするのは出来るのですが、SELECTしてfetchすると秒単位に切り詰められてしまうことに気づきました。

php.netのPDOのマニュアルをざっと見てみたのですが、該当の記述が見当たりませんでした。

PDOでマイクロ秒を取得することは出来ないんでしょうか?

PHP

1<?php 2 $dsn = "mysql:dbname=test_db;port=3306;host=localhost"; 3 $hdl = new PDO($dsn, "test_user", "testtest"); 4 5 if(!$hdl){ echo "could not connect"; exit; } 6 7 $hdl->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 8 $hdl->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); 9 10 $qry = "DROP TABLE `hoges`"; 11 $stmt = $hdl->prepare($qry . ";"); 12 $result = $stmt->execute(); 13 if(!$result){ echo "drop table failed"; exit; } 14 15 $qry = <<< EOL 16CREATE TABLE `hoges` ( 17`idx` INT COLLATE utf8mb4_general_ci NOT NULL DEFAULT 0 COMMENT 'ID', 18`add_at` TIMESTAMP(6) COLLATE utf8mb4_general_ci NOT NULL COMMENT 'add_time', 19PRIMARY KEY `p_hoges`(`idx`) 20) ENGINE=InnoDB DEFAULT CHARSET utf8mb4 COLLATE utf8mb4_general_ci COMMENT='hogeテーブル'; 21EOL; 22 23 $stmt = $hdl->prepare($qry . ";"); 24 $result = $stmt->execute(); 25 if(!$result){ echo "create table failed"; exit; } 26 27 $qry = "INSERT INTO `hoges`(idx, add_at) VALUES (1, '2016-03-22 19:38.01.123456')"; 28 $stmt = $hdl->prepare($qry . ";"); 29 $result = $stmt->execute(); 30 if(!$result){ echo "insert failed"; exit; } 31 32 $qry = "SELECT * FROM `hoges` WHERE idx = 1"; 33 $stmt = $hdl->prepare($qry . ";"); 34 $result = $stmt->execute(); 35 if(!$result){ echo "select failed"; exit; } 36 37 $result = $stmt->fetchAll(PDO::FETCH_OBJ); 38 print_r($result);

出力結果

Array ( [0] => stdClass Object ( [idx] => 1 [add_at] => 2016-03-22 19:38:01 ) )

追記:

ふと検索したstackoverflowを見ると、

http://stackoverflow.com/questions/22026570/php-how-to-return-datetime6-from-mysql

かなり古い話ですが、PDOのバグだというような内容が…
まだ治っていないということでしょうか…

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

MySQLに関しては、以下が関係しているかも知れません。
https://bugs.php.net/bug.php?id=67122

PDO::ATTR_EMULATE_PREPARES = falseのとき、マイクロ秒以下が切り捨てられてしまうそうです。

PostgreSQLについては、それらしい情報を見つけることはできませんでした。

投稿2016/03/22 11:34

KiyoshiMotoki

総合スコア4791

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2016/03/22 11:37

有難うございます、確かに $hdl->setAttribute(PDO::ATTR_EMULATE_PREPARES, true); だと、マイクロ秒まで取れました。 しかし、これはセキュリティ的にまずですね… やはり当面はマイクロ秒は無しでいくしかないということですか。
退会済みユーザー

退会済みユーザー

2016/03/22 11:39

PostgreSQLについては他の問題かもしれないので、もう一回テストしてみます。
退会済みユーザー

退会済みユーザー

2016/03/22 11:55

すみません、PostgreSQLでは $hdl->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); でも、マイクロ秒とれました。 申し訳ありません、別の問題だったようです。 有難うございました。マイクロ病についてはどちらでも動くようにコードを書き換えます。
mpyw

2016/03/22 12:52

PDO::ATTR_EMULATE_PREPARESがtrueでも大して問題ないですよ.charsetがutf8として設定されている限りはなんの問題もないです.PDOが出たての頃は「PHPのエセプリペアドステートメントは信用出来ない」とかいろいろ言われてましたが,最近では問題ないことが分かってきています.
mpyw

2016/03/22 12:52

$dsn = "mysql:dbname=test_db;port=3306;host=localhost"; ↓ $dsn = "mysql:dbname=test_db;port=3306;host=localhost;charset=utf8";
退会済みユーザー

退会済みユーザー

2016/03/22 13:15

複文が実行できてしまうのではないですか?
KiyoshiMotoki

2016/03/22 16:31 編集

lucker様、解決されたようで何よりです。 > 複文が実行できてしまうのではないですか? おっしゃるとおり、PDO::ATTR_EMULATE_PREPARES = true の場合は複文が実行できるようですね。 徳丸氏のブログに詳しい説明がありました。 http://blog.tokumaru.org/2013/12/pdo-and-mysql-allow-multiple-statements.html しかし、上の記事はプレースホルダを使用せずにクエリを構築した場合の検証結果で、 "対策"の項にも 「この件について特別な対策は必要ありません。」 とした上で具体的な方策を提示されているので、  PDO::ATTR_EMULATE_PREPARES = true の場合でも適切にSQLインジェクション対策をおこなえば問題ないのかな?と予想します。 未検証なので恐縮ですが。。
退会済みユーザー

退会済みユーザー

2016/03/23 11:04

KiyoshiMotoki様、ありがとうございました。 かなり前からマイクロ秒が取れないことに気づいていて、時間がとれず検証ができないでいてずっと気にかかっていましたが、おかげですっきりしました。 複文については「適切にSQLインジェクション対策をおこなえば」というところが私のしていることには少々問題で、SQLインジェクションについて全く知らない人でも、手順通りにコードを書けば脆弱性が生まれない事を目指しています。 マイクロ秒が欲しかったのは楽観排他用のタイムスタンプの精度を上げたかったからですが、複文の危険性を容認するくらいなら、秒単位の楽観排他の方が良いと考えています。
KiyoshiMotoki

2016/03/23 13:02

lucker様、ていねいなご返信、ありがとうございます。 お役に立てたなら幸いです。 CertainN様も、情報の捕捉、ありがとうございます。
mpyw

2016/03/24 20:13 編集

複文のことについては知らなかったので助かりました.こちらに追記しておきます. http://qiita.com/mpyw/items/b00b72c5c95aac573b71#%E3%82%A8%E3%83%9F%E3%83%A5%E3%83%AC%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AB%E9%96%A2%E3%81%99%E3%82%8B%E3%81%BE%E3%81%A8%E3%82%81 使い方次第で複文からなるプリペアドステートメントは便利になりますね.パフォーマンスもエミュレーションONのほうがよく,同名のプレースホルダを用いて簡単に複雑なSQLが組めるというメリットもあるので,徳丸さんとは逆で私は特別な事情がない限りはエミュレーションONの方を好んで使っています. >> 複文については「適切にSQLインジェクション対策をおこなえば」というところが私のしていることには少々問題で、SQLインジェクションについて全く知らない人でも、手順通りにコードを書けば脆弱性が生まれない事を目指しています。 「正しくない使い方をする人」の場合はそもそもSQL文をPHPの変数展開で組み立ててしまい,この場合はどうであれ脆弱性は発生してしまいます.「SQLインジェクションが発生してもDROPなど破壊的な命令は実行されない」という気休め程度の保険がつくだけで,例えばブラインドSQLインジェクションでデータの二分探索などは平然と許してしまいます. >> 複文の危険性を容認するくらいなら、秒単位の楽観排他の方が良いと考えています 「データの破壊は止められるが盗難は防げない」程度の気休めのために機能面での制約を増やす必要があるかどうかは疑問です. http://dsas.blog.klab.org/archives/52021703.html
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問