我看到Java处理SQL Server错误的行为有差异,这些错误是由 RAISERROR
,取决于实际错误是什么,在这。
为了演示。
1. 存储过程:uspTestRE
ALTER PROCEDURE demo.uspTestRE (
@inKey VARCHAR(5), --Primary Key value in TestRE table
@inDBZ VARCHAR(1) --Y/N flag to trigger Divide By Zero error
)
AS
BEGIN
SET XACT_ABORT, NOCOUNT ON;
BEGIN TRY
BEGIN TRANSACTION
--Insert record into TestRE table
INSERT INTO TestRE (tREKey) VALUES (@inKey);
--Trigger DBZ error
IF @inDBZ = 'Y'
BEGIN
SELECT 1/0;
END;
--Transaction is in a state to be committed
IF (XACT_STATE())=1
BEGIN
COMMIT TRANSACTION;
END;
END TRY
BEGIN CATCH
DECLARE
@errorMessage NVARCHAR(MAX) = ERROR_MESSAGE(),
@errorState INT = ERROR_STATE(),
@errorSeverity INT = ERROR_SEVERITY();
--Transaction is uncommitable so rollback
IF (XACT_STATE()) = -1
BEGIN
ROLLBACK TRANSACTION;
END;
RAISERROR(@errorMessage,@errorSeverity,@errorState);
RETURN 23;
END CATCH
END;
当从SQLCMD执行SP时,它会产生以下错误信息。
测试1:密钥违规
Msg 50000, Level 14, State 1, Server WW-HV5FQV2, Procedure demo.uspTestRE, Line 44
Violation of PRIMARY KEY constraint 'PK__TestRE__0FEE01A3EEF4E2AE'. Cannot insert duplicate key in object 'dbo.TestRE'. The duplicate key value is (UKV).
测试2:除以零
Msg 50000, Level 16, State 1, Server WW-HV5FQV2, Procedure demo.uspTestRE, Line 42
Divide by zero error encountered.
即两者的预期行为。
但是,我的Java程序却没有给出同样的行为。
2. Java程序:uspTestRE.java
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.CallableStatement;
public class uspTestRE {
// Connect to DEMO_INST database as svcDemoInst Login
public static void main(String[] args) {
String connectionUrl =
"jdbc:sqlserver://localhost:1433;"
+ "database=DEMO;"
+ "user=svcDemoLogin;"
+ "password=Demo;"
+ "trustServerCertificate=true;"
+ "loginTimeout=30;";
ResultSet resultSet = null;
CallableStatement cstmt = null;
try {cstmt = DriverManager.getConnection(connectionUrl).prepareCall("{? = call demo.uspTestRE(?,?)}");
int i = 0;
cstmt.registerOutParameter(++i,java.sql.Types.INTEGER);
cstmt.setString(++i,args[0]);
cstmt.setString(++i,args[1]);
cstmt.execute();
int returnCode = cstmt.getInt(1);
System.out.println("Success: Stored Procedure Return Status: " + returnCode);
}
catch (SQLException e) {
System.out.println("Error Code: " + e.getErrorCode() +", Error Message: "+e.getMessage());
// e.printStackTrace();
}
}
}
当我在这里运行同样的测试用例时,我得到了以下结果。
测试1: 钥匙违规(行为如预期)。
C:\>java uspTestRE UKV N
Error Code: 50000, Error Message: Violation of PRIMARY KEY constraint 'PK__TestRE__0FEE01A3EEF4E2AE'. Cannot insert duplicate key in object 'dbo.TestRE'. The duplicate key value is (UKV).
测试2:除以零(不会被套牢)。
C:\>java uspTestRE DBV Y
Success: Stored Procedure Return Status: 23
谁能向我解释一下,为什么除以零的错误--在SQL Server中被捕获并在SP Catch块中处理--却没有被Java代码捕获?
我可以看到这两个错误之间的唯一区别是,除以零错误的严重性是16。
谢谢你 https:/stackoverflow.comusers7297700david-browne-microsoft。
我开始发布Github问题,他们要求的输出之一是JDBC跟踪。
当我这样做,并比较了2个跟踪输出。
除以零的测试用例出现了以下行。
在另一个帖子中读到,当SP返回一个结果集时,RAISERROR会有不同的表现(在我的例子中是无意的),所以我修改了下面的代码。uspTestRE 存储的过程。
IF @inDBZ = 'Y'
BEGIN
SELECT 1/0;
END;
至
IF @inDBZ = 'Y'
BEGIN
SET @dbz = 1/0;
END;
这解决了我的问题。
现在,我只需要做一些改变,以捕获在存储过程中返回结果集的错误。