JSTL リファレンス

<sql:query>
xmlns:sql="http://java.sun.com/jsp/jstl/sql"

SYNOPSIS

<sql:query
var*="変数名"
scope="page|request|session|application"
sql="SQL"
dataSource="データソース"
startRow="0|数値"
maxRows="-1|数値"
>
<sql:param> * -  クエリーの SQL にパラメータを埋め込みます.
<sql:dateParam> * -  クエリーの SQL に日付型のパラメータを埋め込みます.
sql 属性を省略した場合の SQL.
</sql:query>

説 明

タグの内部または sql 属性で定義されたクエリーを実行します。 PreparedStatement#executeQuery()Java™ API リファレンス の処理に相当します。

クエリーが実行された時点で条件に一致する全ての行が読み込まれて変数に 格納されます。取得するレコードの件数には十分注意してください。

SQL 条件などに可変値を埋め込みたい場合は <sql:param> を使用してください。SQL 上に文字列として直接埋め込むと SQL インジェクションGoogle I'm Feeling Lucky™ などを引き起こす可能性があるため危険です。

属 性

var="変数名"
required

このクエリーの実行結果を格納する変数名です。 ResultJava™ API リファレンス のインスタンスが格納されます (java.sql.ResultSet ではありません)。

scope="page|request|session|application"
optional
var 属性で指定した変数を格納するスコープです。 page, request, session, application のいずれかを指定できます。
sql="SQL"
optional

実行する SQL を指定します。 文字列内のプレースホルダ ? はタグ内で定義した <sql:param>, <sql:dateParam> とマップされます。

この sql 属性を省略した場合はタグ内の評価結果が SQL として使用されます。

dataSource="データソース"
optional

このクエリーの実行で使用する java.sql.Connection のデータソース を指定します。以下のいずれかを使用できます。

  • jdbc/XXX 形式のデータソース名 (文字列)
  • jdbc:dbname:database 形式の JDBC URL (文字列)
  • <sql:setDataSource> でデータソースを設定した変数

個別にデータソースや JDBC URL を指定した場合のトランザクションスコープはこの クエリーの実行だけに限定されます (自動コミットと似た動きになります)。 また JDBC URL が指定された場合はコネクションプールは使用されません。

startRow="0|数値"
optional

取得する結果セットの開始位置を指定します。 0 を指定した場合は最初の行から取得を行います。

これは一致したレコードから範囲外のものを読み飛ばしているにすぎないため、 大量の一致レコードから一部のみを抜き出すのには向いていません (RDBMS レベルの最適化が行われません)。 この属性を使用する前に SQL で同等の絞込み (LIMIT n OFFSET mFETCH FIRST n ROWS ONLY など) が行えないか検討してください。

maxRows="-1|数値"
optional

取得するレコード数の上限を指定します。 負の値を指定した場合は上限なしで読み込みを行います。

これは一致したレコードから範囲外のものを読み飛ばしているにすぎないため、 大量の一致レコードから一部のみを抜き出すのには向いていません (RDBMS レベルの最適化が行われません)。 この属性を使用する前に SQL で同等の絞込み (LIMIT n OFFSET mFETCH FIRST n ROWS ONLY など) が行えないか検討してください。

内 容

sql 属性を省略した場合の SQL。 通常の JSP と同じ書式で記述できるため、SQL の条件やソート方法を 動的に変更することができます。
クエリーの SQL にパラメータを埋め込みます。
クエリーの SQL に日付型のパラメータを埋め込みます。

使用例

テーブル FOO が保持している BAR 列を列挙します。 結果の列挙には <c:forEach> を使用します。
JSP
<sql:query var="rs"
    sql="SELECT ID,BAR FROM FOO" dataSource="jdbc/MYDS" />
<c:forEach var="r" items="${rs.rows}">
    <c:out value="${r.id}" />. <c:out value="${r.bar}" /><br>
</c:forEach>
上記の実行結果です。
実行結果
1. Alpha
2. Beta
3. Gamma
4. Delta
5. Epsilon
PreparedStatement のような埋め込みパラメータが必要な場合は タグ内で <sql:param>, <sql:dateParam> を使用します。この時、パラメータの順番は対応する ? の出現順序とあわせる 必要があります。
JSP
<sql:query var="rs"
    sql="SELECT ID,BAR FROM FOO WHERE ID=?" dataSource="jdbc/MYDS">
    <sql:param>3</sql:param>
</sql:query>
<c:forEach var="r" items="${rs.rows}">
    <c:out value="${r.id}" />. <c:out value="${r.bar}" /><br>
</c:forEach>
実行結果
3. Gamma
SQL はタグ内に記述することも可能です。 長い SQL を記述する必要がある場合はインデントや改行を付けながらタグ内で記述したほうが 読みやすくなります。
JSP
<sql:query var="rs" dataSource="jdbc/MYDS">
    SELECT ID,BAR FROM FOO WHERE ID=?
    <sql:param>3</sql:param>
</sql:query>
<c:forEach var="r" items="${rs.rows}">
    <c:out value="${r.id}" />. <c:out value="${r.bar}" /><br>
</c:forEach>
実行結果
3. Gamma
条件分岐などを使用して発行する SQL を動的に変更することも可能です。 以下の例はリクエストパラメータ id に該当するレコードを表示しますが、 省略されている場合は全件表示を行います。
JSP
<sql:query var="rs">
    SELECT ID,BAR FROM FOO
    <c:if test="${not empty param['id']}">
        WHERE ID=?
        <sql:param>${param['id']}</sql:param>
    </c:if>
</sql:query>
<c:forEach var="r" items="${rs.rows}">
    <c:out value="${r.id}" />. <c:out value="${r.bar}" /><br>
</c:forEach>
</sql:transaction>
パラメータを省略した場合:
実行結果
2. Beta
3. Gamma
4. Delta
5. Epsilon
1. Alpha
id=2 を指定した場合:
実行結果
2. Beta
SQL インジェクションを意識して id=4+or+id%3D3 ("4 or id=3") を指定した場合:
実行結果
なし
SQL インジェクションは発生しないようです。ちなみに <sql:param> を 使用しないで単純な連結により生成した SQL でも実行してみました。
JSP
<sql:query var="rs">
    SELECT ID,BAR FROM FOO
    <c:if test="${not empty param['id']}">
        WHERE ID=${param['id']}
    </c:if>
</sql:query>
上記にパラメータ id=4+or+id%3D3 を指定した結果は以下の通り。 SQL インジェクションが発生しています。
実行結果
3. Gamma
4. Delta
CVS 2008/03/09