【发布时间】:2020-06-09 18:58:28
【问题描述】:
我发现 Java 处理 RAISERROR 引发的 SQL Server 错误的行为有所不同,具体取决于实际错误是什么,其中:
- 违反唯一约束:SQL 异常被 Java Catch 块捕获和处理
- 除以零:未捕获 SQL 异常
演示:
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 代码捕获?
我可以看到 2 个错误之间的唯一区别是除以零错误的严重性为 16。
【问题讨论】:
-
这看起来应该是这里的问题:github.com/microsoft/mssql-jdbc/issues
标签: java sql-server sqlexception raiserror