【ばいんどへんすう】

バインド変数 とは?

💡 SQLの「穴埋め問題方式」、安全にユーザー入力を組み込む仕組み
📌 このページのポイント
バインド変数 ― 安全なSQL vs 危険なSQL ✓ バインド変数(安全) SELECT * FROM users WHERE id = ? ↓ パラメータとして渡す ? → "123" SQLインジェクション防止 ✗ 文字列結合(危険) SELECT * FROM users WHERE id = ' + input + ' ↓ 悪意ある入力 input → "1' OR '1'='1" 全データ漏洩の危険!
バインド変数と文字列結合の比較
ひよこ ひよこ

バインド変数って何のためにあるの?

ペンギン先生 ペンギン先生

2つの目的がある。①セキュリティ:「WHERE name = ?」として?に値を後から渡せばSQLに特殊文字が混入しても安全(SQLインジェクション防止)。②パフォーマンス:DBが実行計画キャッシュして繰り返し使えるから高速化できる。

ひよこ ひよこ

使わないとどんな問題が?

ペンギン先生 ペンギン先生

文字列SQLを組み立てると「WHERE name = '」+ユーザー入力+「'」という書き方になる。ユーザーが「'; DROP TABLE users; --」と入力するとDBが破壊されるSQLインジェクションが起きる。バインド変数を使えばユーザー入力がSQL文として解釈されない。

ひよこ ひよこ

Pythonでの書き方は?

ペンギン先生 ペンギン先生

「cursor.execute('SELECT * FROM users WHERE email = %s', (email,))」のように書く。「%s」がプレースホルダで、タプルで渡した値が安全に埋め込まれる。SQLAlchemyなどのORMも内部でバインド変数を使っている。

ひよこ ひよこ

バインド変数を使わないとSQLインジェクション以外にも問題があるの?

ペンギン先生 ペンギン先生

パフォーマンスにも影響するんだよ。データベースSQL文を実行するとき「実行計画」を作るんだけど、バインド変数を使うと同じ構造のSQL実行計画を再利用できる。文字列連結で毎回違うSQLになると、毎回実行計画を作り直す「ハードパース」が発生してCPUを消費するんだ。Oracleでは特にこの影響が大きくて、バインド変数を使うだけで何倍もスループットが改善することがあるよ。セキュリティとパフォーマンスの両方で必須のテクニックなんだ。

ペンギン
まとめ:ざっくりこれだけ覚えればOK!
バインド変数って出てきたら「SQLに?などのプレースホルダを使い値を後から埋め込む仕組み、SQLインジェクション防止の基本」と思えばOK!
📖 おまけ:英語の意味
「Bind Variable(Prepared Statement)」 = 束縛変数・変数の紐付け
💬 SQLに「変数を束縛(bind)する」ことから。「プリペアドステートメント(Prepared Statement)」とも呼ばれ、事前にSQLを準備して後から値を差し込む方式
← 用語集にもどる