JavaのSQLインジェクションとは?文字列連結でSQLを書く危険性

本記事は、Schooの「Java入門 中級【2026年版】」第2回「データベース処理とオブジェクト設計の基礎」を学ぶ前後に、SQLインジェクションの基本を整理したい方向けの記事です。
SQLインジェクションは、利用者が入力した文字が、検索キーワードではなくSQLの一部として解釈されてしまう問題です。JDBCを使うときは、文字列連結でSQLを組み立てる危険性を理解しておく必要があります。
Schoo コースページ:Java入門 中級【2026年版】
SQLインジェクションは入力によってSQLの意味が変わる問題
たとえば、曲名で検索するプログラムを考えます。利用者が入力した文字を keyword に入れ、その値をSQLに直接つなげると、次のようなコードになります。
String sql = "SELECT id, title, artist FROM songs WHERE title = '" + keyword + "'";
普通に曲名を入力するだけなら、問題が見えにくいかもしれません。しかし、入力欄にSQLとして意味を持つ文字が入ると、プログラムが作るSQLの意味が変わってしまいます。
なぜ全件表示のようなことが起きるのか
攻撃用の文字列を覚える必要はありません。大切なのは、文字列連結でSQLを作ると、入力された引用符や条件式までSQLの一部として読まれてしまう、という点です。
OR は「または」を表します。条件の中に「常に成り立つ条件」が混ざると、本来は1件だけを探すつもりでも、意図しない行まで検索対象になる可能性があります。
つまり、SQLインジェクションは「変な文字を入れるとエラーになる」というだけの話ではありません。入力値によって、検索・更新・削除の対象が変わってしまう可能性がある問題です。
PreparedStatementでは入力値をSQLの命令として扱わない
SQLインジェクションを避ける基本は、SQL文と入力値を分けることです。JDBCでは PreparedStatement を使います。
String sql = "SELECT id, title, artist FROM songs WHERE title = ?";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1, keyword);
ResultSet rs = pstmt.executeQuery();
? は、あとから値を入れる場所です。pstmt.setString(1, keyword) と書くことで、1番目の ? に keyword の値を渡します。
この書き方では、入力値をSQL文そのものとしてつなぎません。そのため、入力欄に引用符や OR のような文字が含まれていても、それはSQLの命令ではなく、検索に使う文字列として扱われます。
初学者がまず避けたい書き方
JDBCで利用者の入力を扱うとき、次のようにSQLと入力値を + でつなぐ書き方は避けます。
String sql = "SELECT id, title, artist FROM songs WHERE title = '" + keyword + "'";
代わりに、SQLの中で値が入る場所を ? にして、setString などで値を渡します。
String sql = "SELECT id, title, artist FROM songs WHERE title = ?";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1, keyword);
確認問題
次のコードには、利用者の入力をSQLに直接つなげている箇所があります。
String keyword = scanner.nextLine();
String sql = "SELECT id, title, artist FROM songs WHERE title = '" + keyword + "'";
- この書き方が危険な理由を説明してください。
PreparedStatementを使う形に書き換えてください。
まとめ
- SQLインジェクションは、入力値がSQLの意味を変えてしまう問題
- 文字列連結でSQLを作ると、入力された記号や条件式までSQLとして読まれる可能性がある
- JDBCでは
PreparedStatementを使い、SQLの形と値を分けて扱う - 利用者の入力をSQLに直接つなげないことが基本