使用JDBC创建临时表时,结果集为空的问题

6
我正在使用MS SQL Driver版本3.0通过标准的JDBC连接执行存储过程。我发现,当我创建并向临时表插入数据时,存储过程无法正常执行。Java代码不会抛出异常,但javax.sql.ResultSet将为null。存储过程失败的关键点是当我取消注释INSERT INTO #TBL CLM_NAME VALUES('VAL')语句时。当我使用SQL Studio Manager执行该语句时,它可以顺利执行并按预期返回数据。有人遇到过这种情况或知道原因吗?最初,我认为这是由于SQL驱动程序引起的,现在我仍然认为是这样。谢谢。

你能确保在同一个连接中创建、加载临时表并从中读取吗? - CoolBeans
是的,临时表是从我创建的存储过程中创建的。我只从Java代码中调用存储过程,例如connect.executeQuery("{procName(?)}")。 - Koekiebox
1
触发问题的 INSERT 指令是否位于创建临时表的同一存储过程中? - Andriy M
你使用哪种方法来调用存储过程? - MRalwasser
3个回答

14

也许这篇文章能帮到你:

建议如果想使用临时表,不要调用"prepareStatement"函数。你可以直接从statement对象中执行查询。

例如:

String sql = "select uuid, name from Component";

Statement stmt = dbCon.createStatement();
ResultSet rs = stmt.executeQuery(sql);

如果您必须调用"prepareStatement",那么您需要创建一个真正的表格,并且如果需要,在之后删除该表格。


当然,如果您有任何参数,应该使用prepareStatement而不是createStatement,或者您应该非常小心地处理SQL注入问题:https://dev59.com/13I-5IYBdhLWcg3w-9yb - Guy Schalnat

6

executeQuery()方法通常用于返回ResultSet的查询,例如SELECT语句。

executeUpdate()方法用于INSERT、UPDATE、DELETE或DDL语句,这些语句返回更新计数。

JDBC将以上两种(ResultSet和更新计数)均视为“结果”。对于返回多个结果的查询,需要使用execute()调用。

如果存储过程使用临时表,可能会先返回一个更新计数,然后是一个ResultSet。您应该使用execute()运行查询,调用getMoreResults()跳过更新计数,然后调用getResultSet()来获取您想要的ResultSet。问题在于我们必须通过多次调用getMoreResults()来尝试获取我们想要的结果集,这种方式很麻烦。

与其进行试错式的尝试,不如通过指定"SET NOCOUNT ON"来抑制所有额外的“查询结果”。

所需更改:

  1. Put your logic in SP "SPCHILD". This Stored procedure will have logic along with temp table creation.

  2. Create a SP "SPPARENT" as below,

     CREATE PROCEDURE [dbo].[SPPARENT]    @Id int = NULL
     AS
     BEGIN
     SET NOCOUNT ON;
     EXEC(' SPCHILD @Id = ' + @Id)
     END
    

    From parent SP "SPPARENT" you have to call your actual SP i.e. "SPCHILD".

  3. From your JDBC code make a SP call to "SPPARENT".


很棒的答案!在使用declare table temp tables时也是有效的。 - revau.lt
太棒了!我爱你! - Benyamin

2

我也遇到了同样的问题。为了解决这个问题,我将在我的SQL服务器上设置跟踪,查看所有在MS JDBC驱动程序执行实际SP调用之前被执行的语句。这应该可以帮助我搞清楚事情。不幸的是,我们的DBA今天不在,所以我明天要在她的帮助下完成这项工作。我会告诉您发生了什么以及如何修复它。


我放弃了使用临时表或表变量,改用子查询。 - Chirag Nirmal

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接