Java调用SQL语法 Server的存储过程详解 

1应用不带参数的存储过程

  应用 JDBC 驱动程式调用不带参数的存储过程时,必需应用 call SQL语法 转义序列。不带参数的 call 转义序列的句子语法如下所示:

  
以下是引用片段:
{call procedure-name}

  作为举例,在 SQL语法 Server 二零零五 AdventureWorks 示例数据库中创建以下存储过程:

 
以下是引用片段:

CREATE PROCEDURE ContactFormalNames
   AS
   BEGIN
    SELECT TOP 10 Title + ' ' + FirstName + ' ' + LastName AS FormalName
    FROM Person.Contact
   END


此存储过程返回单个结果集,其中包含一列数据(由 Person.Contact 表中前十个请致电的称呼、名字和姓氏组成)。

  在下面的举例中,将向此参数传递 AdventureWorks 示例数据库的打开连接,然后应用 executeQuery 技巧调用 ContactFormalNames 存储过程。

以下是引用片段:

public static void executeSprocNoParams(Connection con) ...{
    try ...{
    Statement stmt = con.createStatement();
   ResultSet rs = stmt.executeQuery("{call dbo.ContactFormalNames}");
   
    while (rs.next()) ...{
  System.out.println(rs.getString("FormalName"));
   }
   rs.close();
   stmt.close();
   }
   catch (Exception e) ...{
   e.printStackTrace();
   }
   }

  2应用带有输入参数的存储过程

  应用 JDBC 驱动程式调用带参数的存储过程时,必需结合 SQL语法ServerConnection 类的 prepareCall 技巧应用 call SQL语法 转义序列。带有 IN 参数的 call 转义序列的句子语法如下所示:

  
以下是引用片段:
{call procedure-name[([参数][,[参数]]...)]}

  构造 call 转义序列时,请应用 ?(如何)char来指定 IN 参数。此char充当要传递给该存储过程的参数值的占位符。应用 SQL语法ServerPreparedStatement 类的 setter 技巧之一为参数指定值。可应用的 setter 技巧由 IN 参数的数据类别决定。

  向 setter 技巧传递值时,不仅需求指定要在参数中应用的实际值,还必需指定参数在存储过程中的序数位置。例如,假如存储过程包含单个 IN 参数,则其序数值为 1。假如存储过程包含两个参数,则第一个的序数值为 1,第二个序数值为 2。

  作为如何调用包含 IN 参数的存储过程的举例,应用 SQL语法 Server 二零零五 AdventureWorks 示例数据库中的 uspEmployeeManagers 存储过程。此存储过程接受名为 EmployeeID 的单个输入参数(它是一个的整数值),然后基于指定的 EmployeeID 返回受雇及其经理的递归列表。下面是调用此存储过程的 Java 代码:

  

以下是引用片段:
 

public static void executeSprocInParams(Connection con) ...{
    try ...{
    PreparedStatement pstmt = con.prepareStatement("{call dbo.uspEmployeeManagers(?)}");
    pstmt.setInt(1, 50);
    ResultSet rs = pstmt.executeQuery();
    while (rs.next()) ...{
    System.out.println("EMPLOYEE:");
    System.out.println(rs.getString("LastName") + ", " + rs.getString("FirstName"));
    System.out.println("MANAGER:");
    System.out.println(rs.getString("ManagerLastName") + ", " + rs.getString("ManagerFirstName"));
    System.out.println();
    }
    rs.close();
    pstmt.close();
    }
    catch (Exception e) ...{
    e.printStackTrace();
    }
   }

  3应用带有输出参数的存储过程

  应用 JDBC 驱动程式调用此类存储过程时,必需结合 SQL语法ServerConnection 类的 prepareCall 技巧应用 call SQL语法 转义序列。带有 OUT 参数的 call 转义序列的句子语法如下所示:

  
以下是引用片段:
{call procedure-name[([参数][,[参数]]...)]}

  构造 call 转义序列时,请应用 ?(如何)char来指定 OUT 参数。此char充当要从该存储过程返回的参数值的占位符。要为 OUT 参数指定值,必需在运行存储过程前应用 SQL语法ServerCallableStatement 类的 registerOutParameter 技巧指定各参数的数据类别。

  应用 registerOutParameter 技巧为 OUT 参数指定的值必需是 Java编程.sql.Types 所包含的 JDBC 数据类别之一,而它又被映射成本地 SQL语法 Server 数据类别之一。有关 JDBC 和 SQL语法 Server 数据类别的详细消息,请参阅了解 JDBC 驱动程式数据类别。

  当您对于 OUT 参数向 registerOutParameter 技巧传递一个的值时,不仅必需指定要用于此参数的数据类别,而且必需在存储过程中指定此参数的序号位置或此参数的名字。例如,假如存储过程包含单个 OUT 参数,则其序数值为 1;假如存储过程包含两个参数,则第一个的序数值为 1,第二个序数值为 2。

  作为举例,在 SQL语法 Server 二零零五 AdventureWorks 示例数据库中创建以下存储过程: 根据指定的整数 IN 参数 (employeeID),该存储过程也返回单个整数 OUT 参数 (managerID)。根据 HumanResources.Employee 表中包含的 EmployeeID,OUT 参数中返回的值为 ManagerID。

  在下面的举例中,将向此参数传递 AdventureWorks 示例数据库的打开连接,然后应用 execute 技巧调用 ImmediateManager 存储过程:

以下是引用片段:

public static void executeStoredProcedure(Connection con) ...{
    try ...{
    CallableStatement cstmt = con.prepareCall("{call dbo.ImmediateManager(?, ?)}");
    cstmt.setInt(1, 5);
    cstmt.registerOutParameter(2, Java编程.sql.Types.INTEGER);
    cstmt.execute();
    System.out.println("MANAGER ID: " + cstmt.getInt(2));
    }
    catch (Exception e) ...{
    e.printStackTrace();
    }
   }


本示例应用序号位置来标识参数。或者,也应用参数的名字(而非其序号位置)来标识此参数。下面的代码示例改正了上一个的示例,以说明如何在 Java 实际运用程式中应用命名参数。请留意,这一些参数名字对应于存储过程的定义中的参数名字: CREATE PROCEDURE ImmediateManager

  
以下是引用片段:

@employeeID INT,
    @managerID INT OUTPUT
   AS
   BEGIN
    SELECT @managerID = ManagerID
    FROM HumanResources.Employee
    WHERE EmployeeID = @employeeID
   END


  存储过程估计返回更新计数和多个结果集。Microsoft(微软) SQL语法 Server 二零零五 JDBC Driver 遵循 JDBC 3.0 规范,此规范规定在INDEX OUT 参数之前应INDEX多个结果集和更新计数。也那是说,实际运用程式应先INDEX所有 ResultSet object和更新计数,然后应用 CallableStatement.getter 技巧INDEX OUT 参数。否则,当INDEX OUT 参数时,尚未INDEX的 ResultSet object和更新计数将丢失。

  4 应用带有返回状态的存储过程

  应用 JDBC 驱动程式调用这种存储过程时,必需结合 SQL语法ServerConnection 类的 prepareCall 技巧应用 call SQL语法 转义序列。返回状态参数的 call 转义序列的句子语法如下所示:

 
以下是引用片段:
 {[?=]call procedure-name[([参数][,[参数]]...)]}
  构造 call 转义序列时,请应用 ?(如何)char来指定返回状态参数。此char充当要从该存储过程返回的参数值的占位符。要为返回状态参数指定值,必需在运行存储过程前应用 SQL语法ServerCallableStatement 类的 registerOutParameter 技巧指定参数的数据类别。

  此外,向 registerOutParameter 技巧传递返回状态参数值时,不仅需求指定要应用的参数的数据类别,还必需指定参数在存储过程中的序数位置。对于返回状态参数,其序数位置始终为 1,这是由于它始终是调用存储过程时的第一个的参数。尽管 SQL语法ServerCallableStatement 类支持应用参数的名字来指示特定参数,但您只能对返回状态参数应用参数的序号位置编号。

  作为举例,在 SQL语法 Server 二零零五 AdventureWorks 示例数据库中创建以下存储过程:

  
以下是引用片段:

CREATE PROCEDURE CheckContactCity
    (@cityName CHAR(50))
   AS
   BEGIN
    IF ((SELECT COUNT(*)
    FROM Person.Address
    WHERE City = @cityName) > 1)
    RETURN 1
   ELSE
    RETURN 0
   END


  该存储过程返回状态值 1 或 0,这取决于也许能在表 Person.Address 中找到 cityName 参数指定的都市。

  在下面的举例中,将向此参数传递 AdventureWorks 示例数据库的打开连接,然后应用 execute 技巧调用 CheckContactCity 存储过程:

 
以下是引用片段:
 

public static void executeStoredProcedure(Connection con) ...{
    try ...{
    CallableStatement cstmt = con.prepareCall("{? = call dbo.CheckContactCity(?)}");
    cstmt.registerOutParameter(1, Java编程.sql.Types.INTEGER);
    cstmt.setString(2, "Atlanta");
    cstmt.execute();
    System.out.println("RETURN STATUS: " + cstmt.getInt(1));
    }
    cstmt.close();
    catch (Exception e) ...{
    e.printStackTrace();
    }
   }


  5 应用带有更新计数的存储过程

  应用 SQL语法ServerCallableStatement 类构建对存储过程的调用之后,应用 execute 或 execute更新 技巧中的任意一个的来调用此存储过程。execute更新 技巧将返回一个的 int 值,该值包含受此存储过程效果的行数,但 execute 技巧不返回此值。假如应用 execute 技巧,并且期望获得受效果的行数计数,则在运行存储过程后调用 get更新Count 技巧。

  作为举例,在 SQL语法 Server 二零零五 AdventureWorks 示例数据库中创建以下表和存储过程:

  
以下是引用片段:

CREATE TABLE TestTable
    (Col1 int IDENTitY,
    Col2 varchar(50),
    Col3 int);
   
   CREATE PROCEDURE 更新TestTable
    @Col2 varchar(50),
    @Col3 int  AS
   BEGIN
    UPDATE TestTable
    SET Col2 = @Col2, Col3 = @Col3
   END;


在下面的举例中,将向此参数传递 AdventureWorks 示例数据库的打开连接,并应用 execute 技巧调用 更新TestTable 存储过程,然后应用 get更新Count 技巧返回受存储过程效果的行计数。
以下是引用片段:

public static void execute更新StoredProcedure(Connection con) ...{
    try ...{
    CallableStatement cstmt = con.prepareCall("{call dbo.更新TestTable(?, ?)}");
    cstmt.setString(1, "A");
    cstmt.setInt(2, 100);
    cstmt.execute();
    int count = cstmt.get更新Count();
    cstmt.close();
   
    System.out.println("ROWS AFFECTED: " + count);
    }
    catch (Exception e) ...{
    e.printStackTrace();
    }
   }