JavaのPreparedStatementとは?SQLに値を安全に渡す考え方

本記事は、Schooの「Java入門 中級【2026年版】」第2回「データベース処理とオブジェクト設計の基礎」を学ぶ前後に、JDBCの PreparedStatement の考え方を整理したい方向けの記事です。
PreparedStatement は、SQLの中で値が変わる部分を ? にしておき、Java側からあとで値をセットして実行するための仕組みです。
Schoo コースページ:Java入門 中級【2026年版】
PreparedStatementはSQLに値を安全に渡すために使う
検索条件や登録する値は、プログラムを実行するたびに変わることがあります。たとえば「idが1の曲を検索する」「idが11の曲を追加する」のように、SQLの一部だけが変わる場面です。
このとき、SQL文字列を毎回つなぎ合わせて作るのではなく、SQLの形を先に用意し、変わる値だけをあとから入れる書き方ができます。それが PreparedStatement です。
PreparedStatement は、SQLの形と値を分けて扱うための仕組みです。? は値を入れる場所を表す
? は、あとから値を入れる場所を表します。この ? のことをプレースホルダと呼びます。
String sql = "SELECT id, title, artist FROM songs WHERE id = ?";
このSQLは、まだ具体的なidの値を持っていません。PreparedStatement を作ったあとで、Javaの変数を ? にセットします。
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, id);
setInt(1, id) は、「1番目の ? に、int型の id をセットする」という意味です。
複数の?は左から1番、2番、3番と数える
? が複数ある場合は、SQL文の左から順番に番号を付けて考えます。
setInt(1, id) の 1 は、1番目の ? を表します。配列のように0からではなく、1から数えます。ここで大切なのは、setInt や setString の第1引数が「何番目の ? か」を表していることです。Javaの配列とは違い、? の番号は1から数えます。
executeQueryやexecuteUpdateにはSQL文字列を渡さない
Statement では、実行するときにSQL文字列を渡していました。
ResultSet rs = stmt.executeQuery(sql);
一方、PreparedStatement では、SQLは conn.prepareStatement(sql) の時点で渡しています。そのため、実行時にはSQL文字列を渡しません。
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, id);
ResultSet rs = pstmt.executeQuery();
INSERT、UPDATE、DELETEの場合も同じです。
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, id);
pstmt.setString(2, title);
pstmt.setString(3, artist);
int count = pstmt.executeUpdate();
文字列連結よりPreparedStatementを使う理由
SQLにJavaの値を入れたいだけなら、文字列連結でも書けそうに見えます。しかし、SQL文と値を直接つなぐ書き方は、引用符の扱いが複雑になり、読み間違いや書き間違いが起きやすくなります。
また、利用者が入力した文字をSQLに混ぜる場合、意図しないSQLとして解釈される危険があります。これをSQLインジェクションと呼びます。
? にして、あとからJavaの値をセットします。PreparedStatement を使うと、SQLの形と値を分けて扱えます。初学者の段階では、まず「SQL本文に値を直接つなげない」「? にあとから値をセットする」と覚えると理解しやすいです。
確認問題
次のINSERT文を PreparedStatement で実行するとします。
String sql = "INSERT INTO songs (id, title, artist) VALUES (?, ?, ?)";
int id = 11;
String title = "夜明けのビート";
String artist = "スカイライン";
conn.prepareStatement(sql)で作成したPreparedStatementを変数pstmtに代入してください。- 1番目、2番目、3番目の
?に、それぞれid、title、artistをセットしてください。 - INSERTを実行し、登録件数を
countに代入してください。
まとめ
PreparedStatementは、SQLの形と値を分けて扱うために使う?は、あとから値を入れる場所を表すsetInt(1, id)の1は、1番目の?を表すPreparedStatementでは、実行時のexecuteQuery()やexecuteUpdate()にSQL文字列を渡さない