PostgreSQLのDBに対しPDOのbindValue()を使って、boolean型のカラムの値が false のレコードをインサートしようとしたらバグった。
せっかくなのでboolean型のカラムをインサートした時の挙動について、場合別にしてまとめてみた。
準備
PDOインスタンス生成
$pdo = new PDO(
'pgsql:host=localhost dbname=mydb port=5432',
'user',
'pass'
);
query()
クエリに直書きした場合、特に問題なくインサートされた。
query() 直書き
$sql = <<<SQL
INSERT INTO boolean_test (bool) VALUES (true);
SQL;
$stmt = $pdo->query($sql); // OK
$sql = <<<SQL
INSERT INTO boolean_test (bool) VALUES (false);
SQL;
$stmt = $pdo->query($sql); // OK
変数を埋め込んだ場合、文字列として埋め込まないとインサートしてくれない。
query() 変数埋め込み
$bool = true; // NG
$bool = 'true'; // OK
$bool = false; // NG
$bool = 'false'; // OK
$sqlQuery = <<<SQL
INSERT INTO boolean_test (bool) VALUES ({$bool});
SQL;
$stmt = $pdo->query($sqlQuery);
execute()、bindValue、bindParam()
boolean型の false をセットした時だけインサートしてくれなかった。
execute()
$bool = true; // OK
$bool = 'true'; // OK
$bool = false; // NG
$bool = 'false'; // OK
$sqlExecute = <<<SQL
INSERT INTO boolean_test (bool) VALUES (:bool);
SQL;
$stmt = $pdo->prepare($sqlExecute);
$stmt->execute([':bool' => $bool]);
bindValue()
$bool = true; // OK
$bool = 'true'; // OK
$bool = false; // NG
$bool = 'false'; // OK
$sqlExecute = <<<SQL
INSERT INTO boolean_test (bool) VALUES (:bool);
SQL;
$stmt = $pdo->prepare($sqlExecute);
$stmt->bindValue(':bool', $bool);
$stmt->execute();
bindParam()
$bool = true; // OK
$bool = 'true'; // OK
$bool = false; // NG
$bool = 'false'; // OK
$sqlExecute = <<<SQL
INSERT INTO boolean_test (bool) VALUES (:bool);
SQL;
$stmt = $pdo->prepare($sqlExecute);
$stmt->bindParam(':bool', $bool);
$stmt->execute();
結論
boolean型のカラムの値について、変数を埋め込んでインサートする場合、変数の値を文字列型に直してしてからじゃないとうまくクエリが実行されないケースがある。
プリペアドステートメントを利用した時に true は実行されて false が実行されないのが謎。
(追記)PDO::PARAM_BOOLでもいけた
bindValue、bindParam の第三引数にPDO::PARAM_BOOLをセットしたら無事インサートされた
PDO::PARAM_BOOL
$stmt->bindValue(':bool', $bool, PDO::PARAM_BOOL);