ページの作成
親となるページを選択してください。
親ページに紐づくページを子ページといいます。
例: 親=スポーツ, 子1=サッカー, 子2=野球
子ページを親ページとして更に子ページを作成することも可能です。
例: 親=サッカー, 子=サッカーのルール
親ページはいつでも変更することが可能なのでとりあえず作ってみましょう!
| この記事の要点 |
|
WHERE 句とは
WHERE 句は SQL の SELECT / UPDATE / DELETE 文で対象行を絞り込むための条件指定です。条件は各行に対して評価され、true となった行だけが結果に含まれます。
基本構文
SELECT カラム FROM テーブル WHERE 条件;
UPDATE テーブル SET カラム = 値 WHERE 条件;
DELETE FROM テーブル WHERE 条件;
-- 例
SELECT * FROM users WHERE id = 1;
SELECT id, name FROM users WHERE age >= 20 AND status = 'active';
UPDATE users SET status = 'inactive' WHERE last_login < '2023-01-01';
DELETE FROM logs WHERE created_at < '2024-01-01';
比較演算子
| 演算子 | 意味 | 例 |
|---|---|---|
= | 等しい | id = 1 |
<> / != | 等しくない | status <> 'deleted' |
< | 未満 | age < 18 |
> | より大きい | score > 80 |
<= | 以下 | price <= 1000 |
>= | 以上 | created_at >= '2024-01-01' |
論理演算子 (AND / OR / NOT)
-- AND: 両方真
SELECT * FROM users WHERE age >= 20 AND status = 'active';
-- OR: いずれか真
SELECT * FROM users WHERE role = 'admin' OR role = 'editor';
-- NOT: 否定
SELECT * FROM users WHERE NOT (status = 'deleted');
-- 優先順位: NOT > AND > OR → 括弧で明示推奨
SELECT * FROM products
WHERE (category = 'food' OR category = 'drink')
AND price < 1000;
-- 括弧無しだと意図と異なる
WHERE category = 'food' OR category = 'drink' AND price < 1000
-- ⇔ WHERE category = 'food' OR (category = 'drink' AND price < 1000)
LIKE (パターンマッチ)
| ワイルドカード | 意味 |
|---|---|
% | 0 文字以上の任意の文字列 |
_ | 任意の 1 文字 |
-- 前方一致 (インデックス効く)
WHERE name LIKE 'Yam%' -- Yamada, Yamaguchi, Yamamoto
-- 後方一致 (インデックス効かない)
WHERE name LIKE '%hi'
-- 部分一致 (インデックス効かない)
WHERE name LIKE '%am%'
-- 任意 1 文字
WHERE code LIKE 'A_01' -- AB01, AC01, A001 等
-- エスケープ
WHERE name LIKE '50\%引%' ESCAPE '\' -- "50%引" で始まる
WHERE name LIKE '50!%引%' ESCAPE '!' -- 同上 (ESCAPE 文字を ! に)
-- 大文字小文字
WHERE name LIKE 'yam%' -- MySQL/MariaDB: utf8_general_ci なら大小区別なし
WHERE LOWER(name) LIKE 'yam%' -- 明示的に小文字化 (インデックス効かない)
IN / NOT IN
-- リストに含まれる
WHERE status IN ('active', 'pending')
WHERE id IN (1, 2, 3, 4, 5)
-- リストに含まれない
WHERE status NOT IN ('deleted', 'banned')
-- サブクエリ
WHERE user_id IN (
SELECT id FROM users WHERE status = 'active'
)
-- ★ NULL の罠
WHERE id NOT IN (1, 2, NULL)
-- → 常に何もマッチしない (NULL との比較は UNKNOWN)
-- 対処: NULL を含まないようにする or NOT EXISTS を使う
BETWEEN
-- 範囲指定 (両端含む)
WHERE price BETWEEN 1000 AND 5000
-- ⇔ WHERE price >= 1000 AND price <= 5000
WHERE created_at BETWEEN '2024-01-01' AND '2024-12-31'
-- 否定
WHERE price NOT BETWEEN 1000 AND 5000
-- ★ 日付の罠: BETWEEN は 23:59:59.999 を含まない
WHERE created_at BETWEEN '2024-01-01' AND '2024-12-31'
-- → 2024-12-31 00:00:00 までしか含まれない!
-- 正しくは:
WHERE created_at >= '2024-01-01' AND created_at < '2025-01-01'
IS NULL / IS NOT NULL
NULL は = NULL では判定できません。必ず IS NULL / IS NOT NULL:
-- ❌ 動かない (常に false)
WHERE email = NULL
WHERE email <> NULL
-- ✅ 正しい
WHERE email IS NULL
WHERE email IS NOT NULL
-- NULL を別の値として扱う
WHERE COALESCE(email, '') = '' -- NULL または空文字
WHERE IFNULL(email, '') = '' -- MySQL
WHERE NVL(email, '') IS NULL -- Oracle
EXISTS / NOT EXISTS
-- 注文を 1 件以上持つユーザー
SELECT * FROM users u
WHERE EXISTS (
SELECT 1 FROM orders o WHERE o.user_id = u.id
);
-- 注文を持たないユーザー
SELECT * FROM users u
WHERE NOT EXISTS (
SELECT 1 FROM orders o WHERE o.user_id = u.id
);
-- IN との違い: EXISTS は 1 件見つけた時点で終わる → 大規模データで速い
-- IN は全件展開してから判定 → 小規模リスト向き
CASE WHEN (条件分岐)
-- SELECT で使うのが一般的だが WHERE でも使える
SELECT id,
CASE
WHEN age < 20 THEN '未成年'
WHEN age < 65 THEN '成人'
ELSE '高齢者'
END AS age_group
FROM users;
-- WHERE で動的フィルタ
WHERE
CASE WHEN @flag = 1 THEN status END = 'active'
SARGable: インデックスが効く書き方
SARGable (Search ARGument able) = インデックスが使える形の WHERE 句。カラムをそのまま比較するのが基本:
-- ❌ Non-SARGable: 関数でラップ → インデックス使えない
WHERE YEAR(created_at) = 2024
WHERE UPPER(email) = 'FOO@BAR.COM'
WHERE created_at + INTERVAL 1 DAY > NOW()
WHERE name LIKE '%abc%' -- 先頭ワイルドカード
WHERE price * 1.1 > 1000
-- ✅ SARGable: カラムは素のまま、定数側で計算
WHERE created_at >= '2024-01-01' AND created_at < '2025-01-01'
WHERE email = LOWER('Foo@Bar.com') -- email は CI 照合順序前提
WHERE created_at > NOW() - INTERVAL 1 DAY
WHERE name LIKE 'abc%'
WHERE price > 1000 / 1.1
Prepared Statement / SQL Injection 対策
WHERE 句にユーザー入力を直接埋め込むと SQL Injection 脆弱性になります。必ずバインドパラメータを使ってください:
// ❌ 危険: SQL Injection
$id = $_GET['id'];
$sql = "SELECT * FROM users WHERE id = $id";
// /?id=1 OR 1=1 → 全件取得される
// ✅ 安全: PDO の Prepared Statement
$stmt = $pdo->prepare('SELECT * FROM users WHERE id = ?');
$stmt->execute([$_GET['id']]);
$users = $stmt->fetchAll(PDO::FETCH_ASSOC);
// ✅ Laravel Query Builder
$users = DB::table('users')->where('id', $request->id)->get();
// ✅ 名前付きバインド
$stmt = $pdo->prepare('SELECT * FROM users WHERE email = :email AND status = :status');
$stmt->execute([':email' => $email, ':status' => 'active']);
UPDATE / DELETE の WHERE 抜け事故防止
-- ❌ WHERE 抜け = 全件更新・全件削除
UPDATE users SET status = 'inactive'; -- 全ユーザーが inactive に!
DELETE FROM users; -- 全ユーザーが消えた!
-- ✅ 事前に SELECT で対象確認
SELECT * FROM users WHERE last_login < '2023-01-01';
-- → 対象 OK と確認してから
UPDATE users SET status = 'inactive' WHERE last_login < '2023-01-01';
-- ✅ MySQL の safe mode (本番推奨)
-- my.cnf: sql_safe_updates = 1
-- → WHERE 無しの UPDATE/DELETE をエラーに
FAQ
Q: AND と OR、どっちが先に評価される?
A: AND が先(優先順位が高い)。意図通りにするため括弧で明示するのが安全です。
Q: WHERE 1=1 をよく見るのはなぜ?
A: 動的 SQL 構築時、後続の AND ... を機械的に追加できるテクニックです。例: SELECT * FROM t WHERE 1=1 に条件を増やしていく。
Q: NOT IN と NOT EXISTS どちらを使うべき?
A: NULL を含む可能性があるなら必ず NOT EXISTS。NOT IN (..., NULL) は 1 件も返さない罠があります。
ページの作成
親となるページを選択してください。
親ページに紐づくページを子ページといいます。
例: 親=スポーツ, 子1=サッカー, 子2=野球
子ページを親ページとして更に子ページを作成することも可能です。
例: 親=サッカー, 子=サッカーのルール
親ページはいつでも変更することが可能なのでとりあえず作ってみましょう!
子ページ
子ページはありません
人気ページ
- 1 Eclipseで「サーバーに追加または除去できるリソースがありません。」の原因と対処法
- 2 tomcat の起動 / 停止ログと catalina.log・catalina.out の違い
- 3 JavaScript base URL 取得方法|window.location.origin と SSR/Node.js 対応
- 4 YouTube Data API v3 エラー一覧|403/400/404 の主要原因と切り分け
- 5 Spring Frameworkのアノテーション一覧
- 6 Laravel エラー一覧|500/Blade/DB 接続/ルーティングの代表エラー
- 7 3Dグラフィックスとは|モデリング/レンダリング/主要ソフトウェア (Blender / Maya)
- 8 【Spring】@Valueアノテーションとは
- 9 CATALINA_HOME の確認方法 (Linux / Mac)
- 10 【Spring】@Autowiredアノテーションとは
最近更新/作成されたページ
- IPv6とは|128bitアドレス・コロン16進表記/::省略・リンクローカル・SLAAC・デュアルスタック NEW 2026-06-22 12:34:44
- MAC アドレスフィルタリングの仕組みと限界 | ネットワーク入門 NEW 2026-06-22 12:19:10
- VPNとは|暗号トンネル・サイト間/リモートアクセス・IPsec/SSL-VPN/WireGuardを解説 NEW 2026-06-22 12:19:10
- WebRTC とは ブラウザ間 P2P の音声・映像・データ通信 | ネットワーク入門 NEW 2026-06-22 12:17:25
- HTTP/2 とは 多重化・HPACK・バイナリフレーム | ネットワーク入門 NEW 2026-06-22 12:17:25
- Web通信プロトコル入門 HTTP/2・HTTP/3・WebSocket・gRPC・WebRTC | ネットワーク入門 NEW 2026-06-22 12:17:25
- gRPC とは HTTP/2 + Protocol Buffers の高速 RPC | ネットワーク入門 NEW 2026-06-22 12:17:25
- HTTP/3 (QUIC) とは UDP ベースの低遅延 Web 通信 | ネットワーク入門 NEW 2026-06-22 12:17:25
- WebSocket とは 全二重リアルタイム通信 ws/wss | ネットワーク入門 NEW 2026-06-22 12:17:25
- 証明書と認証局(CA)とは|X.509・信頼チェーン・DV/OV/EV・失効(CRL/OCSP)を解説 NEW 2026-06-22 12:17:24
- ファイアウォールとは|パケットフィルタ・ステートフル・DMZ・次世代FW(L4/L7)を解説 NEW 2026-06-22 12:17:24
- iptables/nftablesとは|テーブル・チェーン・ルール例・永続化をLinux視点で解説 NEW 2026-06-22 12:17:24
- HAProxy とは frontend/backend と設定例 | ネットワーク入門 NEW 2026-06-22 12:17:24
- CDN とは エッジキャッシュ・TTL・Cloudflare/CloudFront | ネットワーク入門 NEW 2026-06-22 12:17:24
- TLS/SSLの仕組み|ハンドシェイク・暗号スイート・前方秘匿性・証明書検証をわかりやすく解説 NEW 2026-06-22 12:17:24
コメントを削除してもよろしいでしょうか?