SQL Server中从Java调用的表变量存在问题

SQL Server中从Java调用的表变量存在问题,java,tsql,jdbc,Java,Tsql,Jdbc,我有一个SQL语句,在MS Server Management Studio中执行时可以工作,从C#提交时可以工作,但从Java(1.6,使用sqljdbc4.jar)提交时不能工作 基本问题似乎是选择一个表变量。继第一条评论之后,我用更简单的例子完全重新编写了这个问题,以说明什么有效,什么无效 以下查询: DECLARE @IsLoadRaw as INT = ? DECLARE @PrimaryID as varchar(1000) = ? --Declare temporary tabl

我有一个SQL语句,在MS Server Management Studio中执行时可以工作,从C#提交时可以工作,但从Java(1.6,使用sqljdbc4.jar)提交时不能工作

基本问题似乎是选择一个表变量。继第一条评论之后,我用更简单的例子完全重新编写了这个问题,以说明什么有效,什么无效

以下查询:

DECLARE @IsLoadRaw as INT = ? 
DECLARE @PrimaryID as varchar(1000) = ?
--Declare temporary table to hold message IDs and fill according to Primary ID.
DECLARE @MessageIDs TABLE ( MessageID BIGINT )
SELECT MessageID FROM Messages WHERE PrimaryID = @PrimaryID
DECLARE @IsLoadRaw as INT = ? 
DECLARE @PrimaryID as varchar(1000) = ?
--Declare temporary table to hold message IDs and fill according to Primary ID.
DECLARE @MessageIDs TABLE ( MessageID BIGINT );
INSERT @MessageIDs SELECT MessageID FROM Messages WHERE PrimaryID = @PrimaryID;
SELECT * FROM @MessageIDs;
可以在SQL Management Studio中使用,也可以从Java提交。在这两种情况下,它都返回一个带有两个messageid的结果集(对于我用来测试的给定PrimaryID是正确的)

以下查询:

DECLARE @IsLoadRaw as INT = ? 
DECLARE @PrimaryID as varchar(1000) = ?
--Declare temporary table to hold message IDs and fill according to Primary ID.
DECLARE @MessageIDs TABLE ( MessageID BIGINT )
SELECT MessageID FROM Messages WHERE PrimaryID = @PrimaryID
DECLARE @IsLoadRaw as INT = ? 
DECLARE @PrimaryID as varchar(1000) = ?
--Declare temporary table to hold message IDs and fill according to Primary ID.
DECLARE @MessageIDs TABLE ( MessageID BIGINT );
INSERT @MessageIDs SELECT MessageID FROM Messages WHERE PrimaryID = @PrimaryID;
SELECT * FROM @MessageIDs;
在SQLManagementStudio中工作,它返回具有相同两个MessageID的结果集。从Java提交时,它不会返回任何结果集

当通过ADO.NET从C#提交时,我们可以使用@MessageIDs的完整语句。我想这里的第二个示例也可以。这个问题与Java无关,似乎与使用表变量有关。由于代码看起来是正确的,并且在SQLManagementStudio下运行,因此我对如何调试这段代码感到困惑


你知道为什么这在Java上不起作用吗?当从Java提交查询时,我可以使用哪些工具来理解服务器对该查询所做的操作

我又进行了一些挖掘,找到了答案:

INSERT @MessageIDs SELECT MessageID FROM Messages WHERE PrimaryID = @PrimaryID;
从Java提交时返回更新计数。从C#或SQL管理控制台提交时,它不会返回更新计数。我没想到会有这样的结果,所以我花了一些时间才找到

用于单步执行
execute()
结果的java API这很混乱,可能没有示例,我发现至少有一个示例不完全正确。我会解释我是如何理解这一点的

由于大多数语句都很简单,只需一次更改或一次选择,所以在语句上有一些方便的执行方法,例如返回结果集的
executekery()
。大多数情况下都会用到这些,这就是故事的结尾

如果您有一个更复杂的语句,它执行多个任务,您可以调用
execute()
,并返回一个任务列表<代码>插入,
更新
,和
删除
(我相信)返回修改的记录计数<代码>选择返回结果集。执行复杂语句的结果是更新计数和结果集的列表,按执行顺序排列。然后编写代码,逐步遍历此列表,处理每个项目

声明

DECLARE @MessageIDs TABLE ( MessageID BIGINT )
INSERT @MessageIDs SELECT MessageID FROM Messages WHERE PrimaryID = @PrimaryID;
SELECT * FROM Messages WHERE MessageID IN (SELECT MessageID FROM @MessageIDs) ORDER BY MessageID;
SELECT * FROM Attrs WHERE MessageID IN (SELECT MessageID FROM @MessageIDs) ORDER BY MessageID;
返回2个结果集。在java中,而且仅在java中,出于我不知道的原因,
INSERT@MessageIDs…
语句返回更新计数,这是列表中的第一项

这方面的JavaAPI令人困惑。语句.execute()和语句.getMoreResults()返回:

  • true
    如果下一个结果是ResultSet
  • false
    如果下一个结果是更新计数或没有更多结果
false
有两种含义,不能解释为结果的结束。您还必须检查非零更新计数

最终的运行代码最终是这样的:

List<DtaMessage> msgList = new ArrayList<DtaMessage>();
boolean isResult = stmt.execute();

// Skip over update counts.  
while (!isResult) {
    if (stmt.getUpdateCount() == 0)
        // End of results.
        return msgList;
    isResult = stmt.getMoreResults();
}


// Process first result set.
ResultSet rs = stmt.getResultSet();
while (rs.next())
{
    DtaMessage msg = PopulateMessage(rs, isLoadRaw);
    msgList.add(msg);
}
rs.close();

// Skip over update counts.
isResult = stmt.getMoreResults();
while (!isResult) {
    if (stmt.getUpdateCount() == 0)
        // end of results.
        return msgList;
    isResult = stmt.getMoreResults();
}

// Process second result set.
rs = stmt.getResultSet();
while (rs.next())
{
    // process.
}
rs.close();
return msgList;
List msgList=new ArrayList();
布尔值isResult=stmt.execute();
//跳过更新计数。
而(!isResult){
if(stmt.getUpdateCount()==0)
//结果结束。
返回msgList;
isResult=stmt.getMoreResults();
}
//处理第一个结果集。
ResultSet rs=stmt.getResultSet();
while(rs.next())
{
DtaMessage msg=PopulateMessage(rs,isLoadRaw);
msgList.add(msg);
}
rs.close();
//跳过更新计数。
isResult=stmt.getMoreResults();
而(!isResult){
if(stmt.getUpdateCount()==0)
//结果结束。
返回msgList;
isResult=stmt.getMoreResults();
}
//处理第二个结果集。
rs=stmt.getResultSet();
while(rs.next())
{
//过程。
}
rs.close();
返回msgList;

虽然我的示例SQL不会在两个结果集之间生成更新计数,但此方法将处理来自多个不同SQL语句的结果,因此我添加了代码以跳过某些情况下可能显示的更新计数

“不起作用”是什么意思?你是有错误,还是什么都没发生?工作的“更简单”查询是什么样子的?您是否曾经检查发送到服务器的SQL?你看到了吗?你有哪个版本的SQL Server?也许这篇文章会有所帮助
false有两种含义,不能解释为结果的结束。您还必须检查更新计数是否为非零。
Dynamite。这真让我大吃一惊。非常感谢您回来发布您的结果。我希望我能在这上面投票两次。同样在我的实验中,
-1
是一个潜在的结果,它似乎表明
没有预期的结果