📄 jdbc-spec.frame7.html
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<html>
<head>
<meta HTTP-EQUIV="Content-Type" CONTENT="text/html; CHARSET=gb2312">
<title></title>
</head>
<body bgcolor="#ffffff">
<table width="600">
<tr>
<td><font size="-1"><a href="jdbc-spec.frame.html">目录</a> | <a
href="jdbc-spec.frame6.html">上一页</a> | <a href="jdbc-spec.frame8.html">下一页</a>
</font></td>
<td align="right"><i>JDBC<sup><font size="-2">TM</font></sup> 指南:入门</i></td>
</tr>
</table>
<hr>
<p><br>
<a name="20376"></a> </p>
<h2>7 传送参数和接收结果</h2>
<p>有关完整的接口描述,参见单独的 JDBC API 文档。 </p>
<p><a name="5514"></a><strong>另请参阅附录 <a href="jdbc-spec.frame15.html#3883">A</a>
中所述的被拒绝的“Holder”机制。</strong></p>
<p><a name="4149"></a> </p>
<h3>7.1 查询结果</h3>
<p>执行查询语句的结果将生成一些行,这些行可由 java.sql.ResultSet
对象访问。ResultSet 对象提供一套“get”方法,允许访问当前行的不同列。利用
ResultSet.next 方法可实现 ResultSet 行之间移动。 </p>
<pre><code>// 我们将执行返回行集合的 SQL 语句,
</code></pre>
<pre><code>// 其中列 1 为 int、列 2 为 String
</code>// 列 3 为字节数组</pre>
<pre><code>//
</code></pre>
<pre><code>java.sql.Statement stmt = conn.createStatement();
</code></pre>
<pre><code>ResultSet r = stmt.executeQuery("SELECT a, b, c FROM Table1");
</code></pre>
<pre><code>while (r.next()) {
</code></pre>
<pre><code> // 打印当前行的值
</code></pre>
<pre><code> int i = r.getInt("a");
</code></pre>
<pre><code> String s = r.getString("b");
</code></pre>
<pre><code> byte b[] = r.getBytes("c");
</code></pre>
<pre><code> System.out.println("ROW = " + i + " " + s + " " + b[0]);
</code></pre>
<pre><code>}
</code></pre>
<p>指定列的方法有两种:列索引(更有效)或列名(更方便)。对应地,我们提供以列索引为参数的
getString 方法和以列名为参数的 getString 方法。 </p>
<p><a name="26252"></a><strong>评论家使我们确信:我们必须同时支持列索引和列名。某些评论家强调指出,他们需要高效的数据库访问,因此喜欢用列索引,而其它评论家强调他们需要方便地使用列名(注意,某些
SQL
查询可返回不含列名或含多个相同列名的表。这种情况下,程序员应使用列号)。
</strong></p>
<p>为了最大程度的可移植性,应按由左至右的顺序读取某行的各列,且每列只能读一次。这反映了在某些基本数据库协议中存在实现限制。
</p>
<p><a name="26308"></a> </p>
<h4>7.1.1 查询结果的数据转换</h4>
<p>ResultSet.getXXX 方法试图将数据库返回的 SQL 类型转换为 getXXX
方法返回的 Java 类型。 </p>
<p><a name="28700"></a><a href="jdbc-spec.frame7.html#30717">第 21 页的表 1</a>
列出了通过 getXXX 方法实现从 SQL 类型到 Java
类型的转换。例如,可以使用 getInt 尝试将 SQL VARCHAR
值作为整数读取,但不能将 SQL FLOAT 作为 java.sql.Date 读取。 </p>
<p>如果试图进行非法转换或数据转换失败(例如对 SQL VARCHAR 值“foo”执行
getInt),则将抛出 SQLException。 </p>
<p><a name="30761"></a> </p>
<p align="center"><a name="30758"></a> <a name="30717"></a><img src="table1.gif"
width="522" height="567"> </p>
<p><a name="30760"></a> </p>
<h4>7.1.2 空结果值</h4>
<p>要确定给定结果值是否为 SQL“NULL”,则必须首先读取列,然后使用
ResultSet wasNull 方法查看是否返回了 SQL“NULL”(另请参阅附录 <a
href="jdbc-spec.frame15.html#25317">A.9</a>)。 </p>
<p><a name="25307"></a>当使用 getXXX 方法读取 SQL“NULL”时,将得到:
<ul>
<p><a name="26541"></a></p>
<li>返回 Java 对象的 getXXX 方法返回的 Java“null”值<br>
<br>
<a name="26542"></a> </li>
<li>getByte、getShort、getInt、getLong、getFloat 和 getDouble 返回的零值<br>
<br>
<a name="27824"></a> </li>
<li>getBoolean. 返回的 false 值<br>
<br>
</li>
</ul>
<p><a name="27826"></a></p>
<h4>7.1.3 检索特大行值</h4>
<p>JDBC 允许使用 getBytes 和 getString 检索任意大的 LONGVARBINARY 或
LONGVARCHAR 数据,范围只要不超出 Statement.getMaxFieldSize
值限定的界限。但是,应用程序设计人员会经常发现,在相对较小的固定块中检索非常大的数据将更为方便。
</p>
<p>为适应这一点,ResultSet 类可返回 java.io.Input
流,以块为单位读取数据。但是,因为调用 ResultSet 的下一个“get”将会使这些流自动关闭,因此必须立即访问其中的每个流。<strong>这反映了对大块访问的基本实现限制。</strong></p>
<p><a name="25069"></a>Java 流返回无类型的字节,并且对 ASCII 和 Unicode
都适用。我们定义了三种独立的获得流的方法。 GetBinaryStream
返回的流只提供来自数据库的原字节而不进行任何转换。GetAsciiStream
返回的流提供单字节 ASCII 字符。GetUnicodeStream
返回的流则提供两个字节的 Unicode 字符。 </p>
<p><a name="25098"></a>例如: </p>
<pre><code>java.sql.Statement stmt = conn.createStatement();
</code></pre>
<pre><code>ResultSet r = stmt.executeQuery("SELECT x FROM Table2");
</code></pre>
<pre><code>// 在 4 K 的块中检索列 1 的结果:
</code></pre>
<pre><code>byte[] buff = new byte[4096];
</code></pre>
<pre><code>while (r.next()) {
</code></pre>
<pre><code> java.io.InputStream fin = r.getAsciiStream("x");
</code></pre>
<pre><code> for (;;) {
</code></pre>
<pre><code> int size = fin.read(buff);
</code></pre>
<pre><code> if (size == -1) {
</code></pre>
<pre><code> break;
</code></pre>
<pre><code> }
</code></pre>
<pre><code> // 将新填充的缓冲区传给某些 ASCII 输出流:
</code></pre>
<pre><code> output.write(buff, 0, size);
</code></pre>
<pre><code> }
</code></pre>
<pre><code>}
</code></pre>
<h4>7.1.4 可选或多重 ResultSet</h4>
<p>我们通常希望使用 executeQuery(返回单个 ResultSet)或 executeUpdate(可用于任何数据库修改语句,且返回更新行的计数)执行
SQL 语句。 </p>
<p><a name="20214"></a>但在某些环境下,应用程序在语句执行前可能不知道给定语句是否返回
ResultSet。另外,某些存储过程可能返回多个不同的 ResultSet 和/或更新计数。
</p>
<p><a name="20231"></a>为适应这些需要,我们提供一种机制,以使应用程序能执行语句,然后处理
ResultSet 的任意集合并更新计数。该机制基于完全通用的“execute”方法,并得到方法
getResultSet、getUpdateCount 和 getMoreResults
的支持。这些方法允许应用程序每次查询一个语句结果并确定给定结果是
ResultSet 还是更新计数。 </p>
<p><a name="20240"></a> </p>
<h3>7.2 传递 IN 参数</h3>
<p>为将参数传递到 SQL 语句,java.sql.PreparedStatemen 类提供了一系列
setXXX
方法。这些方法可用来在每一次语句执行前填充参数域。一旦为给定语句定义了参数值,该参数值就可用于语句的多重执行,直到调用
PreparedStatement.clearParameters 清除这一参数为止。 </p>
<pre><code>java.sql.PreparedStatement stmt = conn.prepareStatement(
</code></pre>
<pre><code> "UPDATE table3 SET m = ? WHERE x = ?");
</code></pre>
<pre><code>// 传递两个参数。一个在每次 for 循环中都改变,
</code></pre>
<pre><code>// 另一个为常量。
</code></pre>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -