PHP & MySQL のアプリケーションを開発していて、特定のデータが存在しているのかどうかを調べる、いわゆる「存在チェック」をしたくて調べたのでまとめます。
ちなみにPostgresSQLでも同様の方法で存在チェックできます。
この記事では、「簡単な方法」と「高速な方法」を紹介します。
特段の事情がなければ後者の「高速な方法」をオススメします。
とはいえ、そのテーブルは数千件しかレコードが入っていなかったので私のケースでは大した高速化ではありませんでした。
もちろん大規模なデータセットであれば高速な方法を非常に強くオススメしますし、速ければ速いほど良いので基本的には高速な方法をオススメします。
なお、テーブル名は「users」、指定したいカラム名は「age」とします。
そして35歳のユーザーの存在チェックをしたいケースとして、usersにおいてageが35であるレコードの存在チェックをおこないます。
【目次】
簡単な方法
ただCOUNTを利用するだけです。
SELECT COUNT(*) FROM users WHERE age = 35
返ってくる結果は 0 か 1 になりますので、それをチェックすれば良いだけです。
ただし、これはシンプルで読みやすくて良いのですが、大規模なデータセットでは、テーブル全体をスキャンする必要があるため、かなり遅くなる可能性があります。
高速な方法
処理をさらに高速にするために、
- COUNTを使わずに 1 とする
- LIMIT 1 を使う
さらに、高速で処理するには LIMIT を追加します。1件だけあれば存在することになるので、ここでは LIMIT 1 としています。
SELECT 1 FROM users WHERE age = 35 LIMIT 1
返ってくるのは true か false になります。
こちらの方法なら巨大なデータセットにおいても高速に結果を返すことが可能です。
ただし、たとえばレコード数千件程度では速度の違いを全く感じられないので、COUNTを利用する簡単な方法のほうが一般的かつ読みやすいかもしれません。
PHPで実行するには
PHP & PDOで、上記の高速の方法でSQLを実行し、その後コード側で処理します。
($pdoはPDOコネクション)
$age= 35; // チェックしたい年齢
$sql = "SELECT 1 FROM users WHERE age = :age LIMIT 1"; // SQLクエリの作成
$stmt = $pdo->prepare($sql); // クエリの準備
$stmt->bindValue(':age', $age, PDO::PARAM_INT); // プレースホルダに値をバインド
$stmt->execute(); // クエリの実行
$recordExists= $stmt->fetchColumn(); // 結果の取得
// 存在チェック後の処理
// fetchColumn() はデータが存在しない場合に false を返すため、 false かどうかをチェックする
if ($recordExists !== false) {
echo "レコードあり";
} else {
echo "レコードなし";
}
細かな注意点として、この場合のPHPの fetchColumn()
メソッドは以下のように値を返すことに気を付けて実装してください。
- レコードが存在する場合、
fetchColumn()
は1
(文字列または整数として)を返します。 - レコードが存在しない場合、
fetchColumn()
はfalse
を返します。
つまり、レコードが存在しても true
を返すことはないことに注意しなくてはならないということです。
おまけ
このような関数を用意しておくと便利です。
// 指定するパラメータのレコードが存在するかチェックする関数
// デフォルトの型はstringです。$typeによって指定できます。
// 存在する場合にはtrue、存在しない場合にはfalseを返します。
function recordExists($pdo, $table, $column, $value, $type = PDO::PARAM_STR) {
$stmt = $pdo->prepare("SELECT 1 FROM $table WHERE $column = :value LIMIT 1");
$stmt->bindParam(':value', $value, $type);
$stmt->execute();
$result = $stmt->fetchColumn();
return $result !== false;
}
呼び出す際には以下のように。
// 整数 "age" をチェック
recordExists($pdo, 'users', 'age', 123, PDO::PARAM_INT);
// ブール "is_verified" をチェック
recordExists($pdo, 'users', 'is_verified', true, PDO::PARAM_BOOL);
以上です。
実行する際にはテーブル名やカラム名を任意の値に変更してください。