m6uのエンジニアっぽい日記

PHP利用開発やFuelPHP利用開発、PostgreSQL利用開発、Androidアプリ開発、CentOS7サーバー構築など、テクニカルでエンジニアっぽい内容の日記

PostgreSQL: 日数を求める

日数を求めるのに、日付と日付の引き算をします

 日付型どうしなら、引き算すると整数値が出てきます。

select cast('2016-12-01' as date) - cast('2016-11-01' as date) 

f:id:m6u:20170112113757p:plain
 タイムスタンプ型どうしなら、interval型で出てきます。

select cast('2016-12-01' as timestamp) - cast('2016-11-01' as timestamp) 

f:id:m6u:20170112113827p:plain
 interval型には数値と単位が融合していて便利な半面、単純に日数の数値だけほしいときに困ります。
 そんなときは、下記のように「extract(epoch from ~ )」を活用します。

select extract(epoch from (cast('2016-12-01' as timestamp) - cast('2016-11-01' as timestamp))) / (60 * 60 * 24) 

f:id:m6u:20170112114310p:plain
 interval型をepochで抽出すると秒数に変わるので、一日の秒数である「60 * 60 * 24」つまり「86400」で割れば良いとのことです。
 こちらのブログ記事を参考にしました。 ありがとうございます。
d.hatena.ne.jp

余談ですが、timestamp型どうしの日数を求めるときの注意点

select cast('2016-12-01 9:00:00' as timestamp) - cast('2016-11-01 15:00:00' as timestamp) 

f:id:m6u:20170112115214p:plain
 timestamp型の場合、時刻成分の影響で期待する日数が得られない場合があります。 この事例だと厳密には30日に達していないのですが、時刻成分を無視して日付単位で日数を得るには、「date_trunc('day', ~)」を活用します。

select date_trunc('day', cast('2016-12-01 9:00:00' as timestamp)) - date_trunc('day', cast('2016-11-01 15:00:00' as timestamp))

f:id:m6u:20170112115604p:plain

PHP: PDO経由でMySQL接続するときのあれこれ

 数週間後(?)の自分に向けてのメモ(?)

基本形

 公式ドキュメント「PHP: PDO::__construct」にある方法。

<?php
    /* ドライバ呼び出しを使用して MySQL データベースに接続する */
    $dsn = 'mysql:dbname=testdb;host=127.0.0.1';
    $user = 'dbuser';
    $password = 'dbpass';

    try {
        $dbh = new PDO($dsn, $user, $password);
    } catch (PDOException $e) {
        echo 'Connection failed: ' . $e->getMessage();
    }
?>

基本形+UTF8トラブル対策

 アレンジして、DSNに文字エンコーディング指定を加える。

<?php
    /* ドライバ呼び出しを使用して MySQL データベースに接続する */
    $dsn = 'mysql:dbname=testdb;host=127.0.0.1;charset=utf8';
    $user = 'dbuser';
    $password = 'dbpass';

    try {
        $dbh = new PDO($dsn, $user, $password);
    } catch (PDOException $e) {
        echo 'Connection failed: ' . $e->getMessage();
    }
?>

基本形+UTF8トラブル対策+エラートラップ強化

 さらにアレンジして、DB接続時以降の処理でエラー派生した時にも例外処理できるように強化する。
 公式ドキュメントにある方法「PHP: エラーおよびエラー処理」を参考に。

<?php
    /* ドライバ呼び出しを使用して MySQL データベースに接続する */
    $dsn = 'mysql:dbname=testdb;host=127.0.0.1;charset=utf8';
    $user = 'dbuser';
    $password = 'dbpass';

    try {
        $dbh = new PDO($dsn, $user, $password);
        $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);  // エラー発生時に例外スロー
    } catch (PDOException $e) {
        echo 'Connection failed: ' . $e->getMessage();
    }
?>

基本形+UTF8トラブル対策+エラートラップ強化(別な書き方)

 もしくは、接続時にもう設定してしまう方法。 これは知らなかったなぁ。

<?php
    /* ドライバ呼び出しを使用して MySQL データベースに接続する */
    $dsn = 'mysql:dbname=testdb;host=127.0.0.1;charset=utf8';
    $user = 'dbuser';
    $password = 'dbpass';
    $options = array(
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION  // エラー発生時に例外スロー
    );

    try {
        $dbh = new PDO($dsn, $user, $password, $options);
    } catch (PDOException $e) {
        echo 'Connection failed: ' . $e->getMessage();
    }
?>

あわせて読みたい

 PHP: 文字セットでは、PHPからMySQLに接続する際の文字セットにまつわる話がまとまっています。
 PDOを使うか、mysqliを使うかで、やり方も変わってくるそうで。