RAISERROR-Java客户端中SQLException行为的差异

我看到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,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。

iCMS 回答:RAISERROR-Java客户端中SQLException行为的差异

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

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

当我这样做并比较以下两个跟踪输出时:

  1. 唯一违反密钥
  2. 除以零错误

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

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

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

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

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

这解决了我的问题。

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

本文链接:https://www.f2er.com/2167761.html

大家都在问