代码之家  ›  专栏  ›  技术社区  ›  Michael Waterfall

T-SQL:如何从存储过程中返回0行,以及如何使用XACT\u ABORT和TRY/CATCH

  •  7
  • Michael Waterfall  · 技术社区  · 16 年前

    我正在编写一个存储过程,当某些操作失败时,我希望返回0条记录。我似乎不知道如何只返回0行?我用过 SELECT NULL NULL 在第1行第1列。我也尝试过不指定任何 SELECT 语句,但在测试 @@ROWCOUNT 从未从 SP中前面的语句(在 EXISTS() ). 如有任何建议,将不胜感激。

    另外,我还有 XACT_ABORT 设置为ON,但我也使用了 TRY/CATCH 块以确保从存储过程返回正确的错误“return value”。这样行吗?如果出现错误 XACT\u中止 覆盖 尝试/抓住 或者我的错误代码路径仍然会导致返回正确的返回值吗?

    -- 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;
    
    2 回复  |  直到 16 年前
        1
  •  13
  •   AdaTheDev    16 年前

    SELECT TOP 0 NULL AS MyValue
    

    就我个人而言,我会为这个存储过程使用一个输出参数来返回ID,而不是返回一个resultset——这只是我的首选。然后只需将输出参数设置为默认值,例如-1,以指示未执行任何操作。

        2
  •  1
  •   KM.    16 年前

    我会这样做:

    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