【问题标题】:RAISERROR - differences in SQLException behaviour in Java ClientRAISERROR - Java 客户端中 SQLException 行为的差异
【发布时间】: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。

【问题讨论】:

标签: java sql-server sqlexception raiserror


【解决方案1】:

谢谢https://stackoverflow.com/users/7297700/david-browne-microsoft

我开始发布 Github 问题,他们要求的输出之一是 JDBC 跟踪。

当我这样做并比较 2 个跟踪输出时:

  1. 唯一密钥冲突
  2. 除以零错误

除以零测试用例存在以下几行:

  • 2020 年 6 月 10 日下午 5:28:50 com.microsoft.sqlserver.jdbc.SQLServerResultSet
  • FINE:SQLServerResultSet:1 由 (SQLServerCallableStatement:1) 创建

在另一篇文章中读到当 SP 返回结果集时 RAISERROR 的行为不同(在我的情况下是无意的),我在 uspTestRE 存储过程中更改了以下代码:

IF @inDBZ = 'Y'
  BEGIN
    SELECT 1/0;
  END;

IF @inDBZ = 'Y'
  BEGIN
    SET @dbz = 1/0;
  END;

这解决了我的问题。

现在,我只需要弄清楚要进行哪些更改以捕获存储过程中返回结果集的错误

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-10-19
    • 2023-03-24
    • 1970-01-01
    • 2019-01-25
    • 1970-01-01
    • 1970-01-01
    • 2013-01-01
    • 2019-09-18
    相关资源
    最近更新 更多