【问题标题】:T-SQL: How to return 0 rows in from stored procedure, and how to use XACT_ABORT and TRY/CATCHT-SQL:如何从存储过程中返回 0 行,以及如何使用 XACT_ABORT 和 TRY/CATCH
【发布时间】:2010-08-18 10:13:45
【问题描述】:

我正在编写一个存储过程,我想在失败时返回 0 条记录。我似乎无法弄清楚如何只返回 0 行?我已经使用了SELECT NULL,但这会在第 1 列第 1 行返回 1 行,其中有 NULL。我也尝试在错误代码路径中不指定任何 SELECT 语句,但是在测试 @@ROWCOUNT 的值之后调用 SP,它返回 1。我认为这可能是因为 @@ROWCOUNT 从未从 SP 早期的 SELECT 语句中重置(在 EXISTS() 中)。任何建议将不胜感激。

另外,我将XACT_ABORT 设置为ON,但我还使用了TRY/CATCH 块来确保从存储过程返回正确的错误“返回值”。这个可以吗?如果出现错误,XACT_ABORT 会覆盖TRY/CATCH 还是我的错误代码路径仍会导致返回正确的返回值?

-- Setup
SET NOCOUNT ON; -- SET NOCOUNT ON added to prevent extra result sets from interfering with SELECT statements.
SET XACT_ABORT ON; -- SET XACT_ABORT ON rollback transactions on errors
DECLARE @return int; SET @return = 1; -- Default to general error

-- Start transaction
BEGIN TRANSACTION
    BEGIN TRY

        IF NOT EXISTS(SELECT NULL FROM [MyTable] WHERE [Check] = 1) 
        BEGIN

            -- Insert new record    
            INSERT INTO [MyTable] (Check, Date) VALUES (1, GETDATE());
            SELECT SCOPE_IDENTITY() AS [MyValue]; -- Return 1 row
            SET @return = 0; -- Success

        END
        ELSE
        BEGIN

            -- Fail
            SELECT NULL AS [MyValue]; -- Want to return 0 rows not 1 row with NULL
            SET @return = 2; -- Fail error

        END

    END TRY
    BEGIN CATCH

        -- Error
        ROLLBACK TRANSACTION;
        SELECT NULL AS [MyValue]; -- Want to return 0 rows not 1 row with NULL
        SET @return = 1; -- General error

    END CATCH

-- End transaction and return
COMMIT TRANSACTION
RETURN @return;

【问题讨论】:

    标签: sql sql-server sql-server-2005 tsql stored-procedures


    【解决方案1】:

    要返回 0 行,您可以这样做:

    SELECT TOP 0 NULL AS MyValue
    

    就我个人而言,我会为此存储过程使用 OUTPUT 参数来返回 ID,而不是返回结果集——但这只是我的偏好。然后只需将该输出参数设置为例如-1 默认表示什么都没做。

    【讨论】:

    • 感谢您的快速响应!我从中得到了 0 结果集:) 但是知道为什么在EXEC MySP 为什么@@ROWCOUNT = 1 之后?
    • EXEC @ret = MySP; SET @rows = @@ROWCOUNT; SELECT 'Rows' = @rows 返回 1 作为行数!?
    • 啊,我是否认为 @@ROWCOUNT 仅针对影响行的语句(即 INSERTUPDATE)进行更改?
    • @Michael Waterfall,运行print 'wow wee!!'; select @@ROWCOUNT,您将获得零行数。
    【解决方案2】:

    这就是我的做法:

    CREATE PROCEDURE YourProcedure
    AS
    (   @NewMyValue  int OUTPUT   --<<<<<use output parameter and not a result set
    )
    BEGIN TRY
    
        --<<<<put everything in the BEGIN TRY!!!
    
        -- Setup
        SET NOCOUNT ON; -- SET NOCOUNT ON added to prevent extra result sets from interfering with SELECT statements.
        SET XACT_ABORT ON; -- SET XACT_ABORT ON rollback transactions on errors
        DECLARE @return int
    
        --<<init multiple variables in a select, it is faster than multiple SETs
        --set defaults
        SELECT @return = 1       -- Default to general error
              ,@NewMyValue=NULL
    
        -- Start transaction
        BEGIN TRANSACTION  --<<<put the transaction in the BEGIN TRY
    
        --<<<lock rows for this transaction using UPDLOCK & HOLDLOCK hints
        IF NOT EXISTS(SELECT NULL FROM [MyTable] WITH (UPDLOCK, HOLDLOCK) WHERE [Check] = 1)
        BEGIN
                -- Insert new record    
            INSERT INTO [MyTable] (Check, Date) VALUES (1, GETDATE());
            SELECT @NewMyValue=SCOPE_IDENTITY()  --<<<set output parameter, no result set
                  ,@return = 0; -- Success
        END
        ELSE
        BEGIN
            -- Fail
            --<<no need for a result set!!! output parameter was set to a default of NULL
            SET @return = 2; -- Fail error
        END
    
        COMMIT TRANSACTION  --<<<commit in the BEGIN TRY!!!
    END TRY
    BEGIN CATCH
        -- Error
        IF XACT_STATE()!=0  --<<<only rollback if there is a bad transaction
        BEGIN
            ROLLBACK TRANSACTION
        END
        --<<any insert(s) into log tables, etc
        --<<no need for a result set!!! output parameter was set to a default of NULL
        SET @return = 1; -- General error
    END CATCH
    
    -- End transaction and return
    RETURN @return;
    GO
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-06-23
      • 2022-01-06
      • 1970-01-01
      • 2010-12-01
      • 1970-01-01
      • 2014-10-25
      • 2015-03-22
      • 1970-01-01
      相关资源
      最近更新 更多