gallu’s blog

エンジニアでゲーマーで講師で占い師なおいちゃんのブログです。

PDO関連備忘録

ちと確認したいことがあったので。
もっそメモ書きなので、適宜脳内保管しつつ読んでくださりませ。


とりあえず

set global long_query_time = 0;
set global slow_query_log = 'on';

して、MySQL側に渡っているものを覗いてみようかなぁとか画策。

create table test(
  a int,
  b varbinary(16),
  c blob,
  d DOUBLE,
  e datetime
);

という、大変にやる気のあふれたテーブルを作成w


以下

<?php
$o = new PDO('mysql:dbname=test;host=localhost', ユーザアカウント, ぱすわぁど);
$o->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

を前提に。

$sql = 'INSERT INTO test(a,b,c,d,e) VALUES(:a, :b, :c, :d, :e);';
$pp = $o->prepare($sql);

// intをintで
$pp->bindValue(':a', 1, PDO::PARAM_INT);
$pp->execute();

// intをSTRで
$pp->bindValue(':a', 2, PDO::PARAM_STR);
$pp->execute();

// intをLOBで
$pp->bindValue(':a', 3, PDO::PDO::PARAM_LOB);
$pp->execute();

ってテストしたら

Invalid parameter number: number of bound variables does not match number of tokens

って怒らりた。パラメタ数、結構まじめにチェックしてやがんの。てっきり「無指定はNULL」とかぬるめな事考えてたのに。


気を取り直して。

$sql = 'INSERT INTO test(a) VALUES(:a);';
$pp = $o->prepare($sql);

// intをintで
$pp->bindValue(':a', 1, PDO::PARAM_INT);
$pp->execute();

// intをSTRで
$pp->bindValue(':a', 2, PDO::PARAM_STR);
$pp->execute();

// intをLOBで
$pp->bindValue(':a', 3, PDO::PDO::PARAM_LOB);
$pp->execute();

あんまり取り直してない気もするけど気にしない。


結果。

INSERT INTO test(a) VALUES(1);
INSERT INTO test(a) VALUES('2');
INSERT INTO test(a) VALUES(3);

まぁ予想通り。

select * from test;

                                                                      • +
a b c d e
                                                                      • +
1 NULL NULL NULL NULL
2 NULL NULL NULL NULL
3 NULL NULL NULL NULL
                                                                      • +

こっちもまぁ。


お次。

$sql = 'INSERT INTO test(b) VALUES(:b);';
$pp = $o->prepare($sql);

// intをintで
$pp->bindValue(':b', 1, PDO::PARAM_INT);
$pp->execute();

// intをSTRで
$pp->bindValue(':b', 2, PDO::PARAM_STR);
$pp->execute();

// intをLOBで
$pp->bindValue(':b', 3, PDO::PARAM_LOB);
$pp->execute();

コメント直しミス。気にスンナ。

INSERT INTO test(b) VALUES(1);
INSERT INTO test(b) VALUES('2');
INSERT INTO test(b) VALUES(3);

こっちもおおむね。…PARAM_LOBがシングルクォートで囲ってくれてないのが、不思議っちゃぁ不思議。LOBって文字列の系譜ぢゃないのかしらん?

select * from test;

                                                                      • +
a b c d e
                                                                      • +
1 NULL NULL NULL NULL
2 NULL NULL NULL NULL
3 NULL NULL NULL NULL
NULL 1 NULL NULL NULL
NULL 2 NULL NULL NULL
NULL 3 NULL NULL NULL
                                                                      • +


お次は小数点。

$sql = 'INSERT INTO test(a, d) VALUES(:a, :d);';
$pp = $o->prepare($sql);

// intをintで
$pp->bindValue(':a', 1.1, PDO::PARAM_INT);
$pp->bindValue(':d', 1.1, PDO::PARAM_INT);
$pp->execute();

// intをSTRで
$pp->bindValue(':a', 2.2, PDO::PARAM_STR);
$pp->bindValue(':d', 2.2, PDO::PARAM_STR);
$pp->execute();

// intをLOBで
$pp->bindValue(':a', 3.3, PDO::PARAM_LOB);
$pp->bindValue(':d', 3.3, PDO::PARAM_LOB);
$pp->execute();

INSERT INTO test(a,d) VALUES(1.1, 1.1);
INSERT INTO test(a,d) VALUES('2.2', '2.2');
INSERT INTO test(a,d) VALUES(3.3, 3.3);

select * from test;

                                                                      • +
a b c d e
                                                                      • +
1 NULL NULL 1.1 NULL
2 NULL NULL 2.2 NULL
3 NULL NULL 3.3 NULL
                                                                      • +

そ〜だよね〜的な状況。


少しひねる。

$sql = 'INSERT INTO test(a) VALUES(:a);';
$pp = $o->prepare($sql);

// intをintで
$pp->bindValue(':a', 'a', PDO::PARAM_INT);
$pp->execute();

// intをSTRで
$pp->bindValue(':a', 'b', PDO::PARAM_STR);
$pp->execute();

// intをLOBで
$pp->bindValue(':a', 'c', PDO::PARAM_LOB);
$pp->execute();

エラーでるかしらん? むりしゃりintにするかしらん?

INSERT INTO test(a) VALUES('a');
INSERT INTO test(a) VALUES('b');
INSERT INTO test(a) VALUES('c');

…そ〜きたか。ある意味素直だ。

select * from test;

                                                                      • +
a b c d e
                                                                      • +
0 NULL NULL NULL NULL
0 NULL NULL NULL NULL
0 NULL NULL NULL NULL
                                                                      • +

まぁ値が0になるのは当然だらう。


お次は「無指定」のケース。気になるしねぇ。

// あと「無指定」の場合の挙動も確認
$sql = 'INSERT INTO test(a,b,c,d,e) VALUES(:a, :b, :c, :d, :e);';
$pp = $o->prepare($sql);

//
$pp->bindValue(':a', 1);
$pp->bindValue(':b', 2);
$pp->bindValue(':c', 3);
$pp->bindValue(':d', 4);
$pp->bindValue(':e', 5);
$pp->execute();

//
$pp->bindValue(':a', 'a');
$pp->bindValue(':b', 'b');
$pp->bindValue(':c', 'c');
$pp->bindValue(':d', 'd');
$pp->bindValue(':e', 'e');
$pp->execute();

INSERT INTO test(a,b,c,d,e) VALUES('1', '2', '3', '4', '5');
INSERT INTO test(a,b,c,d,e) VALUES('a', 'b', 'c', 'd', 'e');

どうも「文字列でふぉ」らしい。確かどこかにンなこと書いてあったよねぇ、的な。

                                                                                                    • +
a b c d e
                                                                                                    • +
1 2 3 4 0000-00-00 00:00:00
0 b c 0 0000-00-00 00:00:00
                                                                                                    • +


ほんのりとクラックっぽいことを。

$sql = 'INSERT INTO test(b) VALUES(:b);';
$pp = $o->prepare($sql);

//
$pp->bindValue(':b', "'", PDO::PARAM_INT);
$pp->execute();

//
$pp->bindValue(':b', '"', PDO::PARAM_INT);
$pp->execute();

//
$pp->bindValue(':b', '--', PDO::PARAM_INT);
$pp->execute();

INSERT INTO test(b) VALUES('\'');
INSERT INTO test(b) VALUES('\"');
INSERT INTO test(b) VALUES('--');
INSERT INTO test(b) VALUES(';');

まぁめげませんねぇ当然です。

select * from test;

                                                                                                    • +
a b c d e
                                                                                                    • +
NULL ' NULL NULL NULL
NULL " NULL NULL NULL
NULL -- NULL NULL NULL
NULL ; NULL NULL NULL
                                                                                                    • +


最後、今ひとつ不明なのが「PARAM_STMT」。
いくつか情報はチラ見したんだけど、今ひとつ。情報ある人いらっしゃったら教えてくださいませ ノ


さて…本格的にdata_clumpのほうで対応していかないとねぇこの辺。


追記
そういや「使える文字種別」ってどのくらいまでなんだろう?
ハイフン(-)とアンダースコア(_)、できればイコール(=)とアット(@)あたりくらいまでいけるといいんだけどなぁ。
そのうち実験してみませう。