- JDBC 教程
- JDBC - 首页
- JDBC - 简介
- JDBC - SQL 语法
- JDBC - 环境配置
- JDBC - 示例代码
- JDBC - 驱动程序类型
- JDBC - 连接
- JDBC - 语句
- JDBC - 结果集
- JDBC - 数据类型
- JDBC - 事务
- JDBC - 异常
- JDBC - 批量处理
- JDBC - 存储过程
- JDBC - 数据流
- JDBC - RowSet
- JDBC - 复制数据库
- JDBC - ACID 属性
- JDBC - 连接池
- JDBC 示例
- JDBC - 创建数据库
- JDBC - 选择数据库
- JDBC - 删除数据库
- JDBC - 创建表
- JDBC - 删除表
- JDBC - 插入记录
- JDBC - 查询记录
- JDBC - 更新记录
- JDBC - 删除记录
- JDBC - WHERE 子句
- JDBC - LIKE 子句
- JDBC - 数据排序
- JDBC 有用资源
- JDBC - 常见问题解答
- JDBC - 快速指南
- JDBC - 有用资源
- JDBC - 讨论
- 有用 - Java 教程
JDBC - 存储过程
在讨论JDBC - 语句章节时,我们学习了如何在JDBC中使用存储过程。本章节与该部分内容类似,但会提供关于JDBC SQL转义语法的更多信息。
正如Connection对象创建Statement和PreparedStatement对象一样,它也创建CallableStatement对象,该对象用于执行对数据库存储过程的调用。
创建CallableStatement对象
假设,您需要执行以下Oracle存储过程:
CREATE OR REPLACE PROCEDURE getEmpName (EMP_ID IN NUMBER, EMP_FIRST OUT VARCHAR) AS BEGIN SELECT first INTO EMP_FIRST FROM Employees WHERE ID = EMP_ID; END;
注意 - 以上存储过程是为Oracle编写的,但我们使用的是MySQL数据库,因此让我们编写以下MySQL存储过程,以便在EMP数据库中创建它。
DELIMITER $$ DROP PROCEDURE IF EXISTS `EMP`.`getEmpName` $$ CREATE PROCEDURE `EMP`.`getEmpName` (IN EMP_ID INT, OUT EMP_FIRST VARCHAR(255)) BEGIN SELECT first INTO EMP_FIRST FROM Employees WHERE ID = EMP_ID; END $$ DELIMITER ;
存在三种类型的参数:IN、OUT和INOUT。PreparedStatement对象仅使用IN参数。CallableStatement对象可以使用所有三种参数。
以下是每种参数的定义:
参数 | 描述 | 示例 |
---|---|---|
IN | 在创建SQL语句时值未知的参数。您可以使用setXXX()方法将值绑定到IN参数。 | 仅包含IN参数的存储过程 |
OUT | 由SQL语句返回其值的参数。您可以使用getXXX()方法从OUT参数检索值。 | 仅包含OUT参数的存储过程 |
INOUT | 同时提供输入和输出值的参数。您可以使用setXXX()方法绑定变量,并使用getXXX()方法检索值。 | 同时包含IN和OUT参数的存储过程 |
以下代码片段显示了如何使用Connection.prepareCall()方法基于前面的存储过程实例化CallableStatement对象:
CallableStatement cstmt = null; try { String SQL = "{call getEmpName (?, ?)}"; cstmt = conn.prepareCall (SQL); . . . } catch (SQLException e) { . . . } finally { . . . }
字符串变量SQL表示存储过程,其中包含参数占位符。
使用CallableStatement对象与使用PreparedStatement对象非常相似。您必须在执行语句之前将值绑定到所有参数,否则将收到SQLException。
如果您有IN参数,只需遵循适用于PreparedStatement对象的相同规则和技术;使用与您正在绑定的Java数据类型对应的setXXX()方法。
当您使用OUT和INOUT参数时,必须使用附加的CallableStatement方法registerOutParameter()。registerOutParameter()方法将JDBC数据类型绑定到存储过程预期返回的数据类型。
调用存储过程后,您可以使用适当的getXXX()方法从OUT参数检索值。此方法将检索到的SQL类型的值转换为Java数据类型。
关闭CallableStatement对象
正如您关闭其他Statement对象一样,出于同样的原因,您也应该关闭CallableStatement对象。
只需调用close()方法即可。如果您首先关闭Connection对象,它也会关闭CallableStatement对象。但是,您应该始终显式关闭CallableStatement对象以确保正确的清理。
CallableStatement cstmt = null; try { String SQL = "{call getEmpName (?, ?)}"; cstmt = conn.prepareCall (SQL); . . . } catch (SQLException e) { . . . } finally { cstmt.close(); }
我们在Callable - 示例代码中学习了更多细节。
JDBC SQL转义语法
转义语法使您可以灵活地使用通过使用标准JDBC方法和属性无法使用的数据库特定功能。
一般的SQL转义语法格式如下:
{keyword 'parameters'}
以下是一些转义序列,您在执行JDBC编程时会发现它们非常有用:
d、t、ts关键字
它们有助于标识日期、时间和时间戳文字。众所周知,没有两个DBMS以相同的方式表示时间和日期。此转义语法告诉驱动程序以目标数据库的格式呈现日期或时间。例如:
> {d 'yyyy-mm-dd'}
其中yyyy=年,mm=月;dd=日。使用此语法{d '2009-09-03'}是2009年3月9日。
这是一个简单的示例,显示如何将日期插入表中:
//Create a Statement object stmt = conn.createStatement(); //Insert data ==> ID, First Name, Last Name, DOB String sql="INSERT INTO STUDENTS VALUES" + "(100,'Zara','Ali', {d '2001-12-16'})"; stmt.executeUpdate(sql);
类似地,您可以使用以下两种语法之一,即t或ts:
{t 'hh:mm:ss'}
其中hh=小时;mm=分钟;ss=秒。使用此语法{t '13:30:29'}是下午1:30:29。
{ts 'yyyy-mm-dd hh:mm:ss'}
这是上面两种语法'd'和't'的组合语法,用于表示时间戳。
escape关键字
此关键字标识在LIKE子句中使用的转义字符。在使用SQL通配符%(匹配零个或多个字符)时很有用。例如:
String sql = "SELECT symbol FROM MathSymbols WHERE symbol LIKE '\%' {escape '\'}"; stmt.execute(sql);
如果您使用反斜杠字符(\)作为转义字符,则还必须在Java字符串文字中使用两个反斜杠字符,因为反斜杠也是Java转义字符。
fn关键字
此关键字表示在DBMS中使用的标量函数。例如,您可以使用SQL函数length来获取字符串的长度:
{fn length('Hello World')}
这将返回11,即字符字符串'Hello World'的长度。
call关键字
此关键字用于调用存储过程。例如,对于需要IN参数的存储过程,请使用以下语法:
{call my_procedure(?)};
对于需要IN参数并返回OUT参数的存储过程,请使用以下语法:
{? = call my_procedure(?)};
oj关键字
此关键字用于表示外部连接。语法如下:
{oj outer-join}
其中outer-join = 表{LEFT|RIGHT|FULL} OUTERJOIN{表|outer-join}on search-condition。例如:
String sql = "SELECT Employees FROM {oj ThisTable RIGHT OUTER JOIN ThatTable on id = '100'}"; stmt.execute(sql);
在SQL命令示例中使用like语句
在这个例子中,我们有四个静态字符串,包含数据库连接URL、用户名、密码和带有LIKE运算符和特殊字符的SELECT查询,用于选择多个条目。现在,使用DriverManager.getConnection()方法,我们准备了一个数据库连接。连接准备就绪后,我们使用connection.createStatement()方法创建了一个Statement对象。然后使用statement.executeQuery()执行SELECT查询,并将结果存储在结果集中。然后在迭代结果集时打印所有记录。
将以下示例复制并粘贴到ResultSetExample.java中,编译并运行如下:
import java.sql.*; // This class demonstrates the use of mySQL 'like' public class MySQLFunctionExample { static final String DB_URL = "jdbc:mysql://127.0.0.1/TUTORIALSPOINT"; static final String USER = "guest"; static final String PASS = "guest123"; //Select addresses which contain ',' static final String QUERY = "select * from students where address like '%,%'"; public static void main(String args[]) { Connection conn = null; Statement stmt = null; try{ conn = DriverManager.getConnection(DB_URL,USER,PASS); System.out.println("Connection to db established."); stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(QUERY); System.out.println("Successfully executed query."); System.out.println("----------------------------"); while(rs.next()){ System.out.print("StudentID: " + rs.getInt(1)); System.out.print(", FirstName: " + rs.getString(2)); System.out.print(", LastName: " + rs.getString(3) ); System.out.print(", Address: " + rs.getString(4)); } rs.close(); stmt.close(); conn.close(); }catch( SQLException e){ e.printStackTrace(); } } }
输出
现在让我们按如下方式编译以上示例:
C:\>javac MySQLFunctionExample.java C:\>
运行MySQLFunctionExample时,它会产生以下结果:
C:\>java MySQLFunctionExample Connection to db established. Successfully executed query. ---------------------------- StudentID: 1005, FirstName: Kumar, LastName: Kishore, Address: 49 Gorakhpur Rd., Agra StudentID: 1006, FirstName: Khan, LastName: Ganesh, Address: 34 Digha Rd., Digha C:\>
在SQL命令示例中使用函数Length()
在这个例子中,我们有四个静态字符串,包含数据库连接URL、用户名、密码和一个SELECT查询,其中Length()函数计算姓氏的长度。现在,使用DriverManager.getConnection()方法,我们准备了一个数据库连接。连接准备就绪后,我们使用connection.createStatement()方法创建了一个Statement对象。然后使用statement.executeQuery()执行SELECT查询,并将结果存储在结果集中。然后在迭代结果集时打印所有记录。
将以下示例复制并粘贴到ResultSetExample.java中,编译并运行如下:
import java.sql.*; // This class demonstrates the use of mySQL 'like' public class MySQLFunctionExample { static final String DB_URL = "jdbc:mysql://127.0.0.1/TUTORIALSPOINT"; static final String USER = "guest"; static final String PASS = "guest123"; //Select addresses which contain ',' static final String QUERY = "select StudentID, LastName, length(LastName) AS LengthOfLastName from students"; public static void main(String args[]) { Connection conn = null; Statement stmt = null; try{ conn = DriverManager.getConnection(DB_URL,USER,PASS); System.out.println("Connection to db established."); stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(QUERY); System.out.println("Successfully executed query."); System.out.println("----------------------------"); while(rs.next()){ System.out.print("StudentID: " + rs.getInt(1)); System.out.print(", LastName: " + rs.getString(2)); System.out.println(", LengthOfLastName: " + rs.getInt(3) ); } rs.close(); stmt.close(); conn.close(); }catch( SQLException e){ e.printStackTrace(); } } }
输出
现在让我们按如下方式编译以上示例:
C:\>javac MySQLFunctionExample.java C:\>
运行MySQLFunctionExample时,它会产生以下结果:
C:\>java MySQLFunctionExample Connection to db established. Successfully executed query. ---------------------------- StudentID: 1000, LastName: Agarwal, LengthOfLastName: 7 StudentID: 1001, LastName: Pandey, LengthOfLastName: 6 StudentID: 1002, LastName: Kumar, LengthOfLastName: 5 StudentID: 1004, LastName: Ali, LengthOfLastName: 3 StudentID: 1005, LastName: Kumar, LengthOfLastName: 5 StudentID: 1006, LastName: Khan, LengthOfLastName: 4 C:\>