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

问题描述 投票:1回答:1

我看到Java处理SQL Server错误的行为有差异,这些错误是由 RAISERROR,取决于实际错误是什么,在这。

  • Unique Constraint Violation: 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代码捕获?

我可以看到这两个错误之间的唯一区别是,除以零错误的严重性是16。

java sql-server sqlexception raiserror
1个回答
0
投票

谢谢你 https:/stackoverflow.comusers7297700david-browne-microsoft。

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

当我这样做,并比较了2个跟踪输出。

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

除以零的测试用例出现了以下行。

  • 2020年6月10日 5:28:50 PM com.microsoft.sqlserver.jdbc.SQLServerResultSet.
  • FINE: SQLServerResultSet:1 created by (SQLServerCallableStatement:1)

在另一个帖子中读到,当SP返回一个结果集时,RAISERROR会有不同的表现(在我的例子中是无意的),所以我修改了下面的代码。uspTestRE 存储的过程。

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

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

这解决了我的问题。

现在,我只需要做一些改变,以捕获在存储过程中返回结果集的错误。

© www.soinside.com 2019 - 2024. All rights reserved.