调整存储过程

时间:2017-05-08 20:45:23

标签: sql-server tsql stored-procedures

如何在不使用光标的情况下改善这一点?我在想使用表变量会有所帮助,但我是否正确的方向呢?我省略了光标并尝试使用表变量。请帮忙,这是代码。

IF EXISTS (SELECT * FROM sysobjects WHERE id = object_id(N'[dbo].[BatchProcessBridge_CustomerEvent]') AND [xtype] IN (N'P'))

BEGIN   

    DROP PROCEDURE [dbo].[BatchProcessBridge_CustomerEvent]

END
GO

CREATE PROCEDURE [dbo].[BatchProcessBridge_CustomerEvent]
(
    @BatchJobTable Bridge_CustomerEventBatchJobTable READONLY,
    @Name VARCHAR(50)
)
AS
BEGIN
    SET NOCOUNT ON;

    DECLARE @Lsn BINARY(10), 
    DECLARE @SeqVal BINARY(10), 
    DECLARE @Action VARCHAR(300), 
    DECLARE @CustId VARCHAR(MAX)

    --using tabel variable. Cursor gives bad performance. 
    DECLARE  @TEMP_TABLE TABLE ( [Lsn] BINARY(10), [SeqVal] BINARY(10), [Action] VARCHAR(300), [CustId]  VARCHAR(MAX))

    INSERT INTO @TEMP_TABLE
    SELECT Lsn, SeqVal, [Action], [CustId] FROM @BatchJobTable


    --DECLARE GetBatchJobCursor CURSOR FAST_FORWARD
    --FOR
    --SELECT Lsn, SeqVal, [Action], [CustId] FROM @BatchJobTable

    --OPEN GetBatchJobCursor
    --FETCH NEXT FROM GetBatchJobCursor INTO @Lsn, @SeqVal, @Action, @CustId
    --WHILE @@FETCH_STATUS = 0

    BEGIN

    BEGIN TRY
    BEGIN TRANSACTION

        IF (@Action = 'create')
        BEGIN
            -- Create.
            INSERT INTO [Bridge_Customer]
            (
            [CustId]
            ,[PersonId]
            ,[DisplayName]
            ,[CreatedDate]
            ,[ModifiedDate]
            )

        SELECT 
            [CustId]
            ,[PersonId]
            ,[DisplayName]
            ,[CreatedDate]
            ,[ModifiedDate]
        FROM
            @BatchJobTable
        WHERE
            (Lsn = @Lsn) AND (SeqVal = @SeqVal)
        END
        ELSE IF (@Action = 'update')
        BEGIN
            -- Update.
            UPDATE [Target]
            SET
                [Target].[CustId] = [Ref].[CustId]
                ,[Target].[PersonId] = [Ref].[PersonId]
                ,[Target].[DisplayName] = [Ref].[DisplayName]
                ,[Target].[CreatedDate] = [Ref].[CreatedDate]
                ,[Target].[ModifiedDate] = [Ref].[ModifiedDate]

            FROM
                [dbo].[Bridge_Customer] AS [Target]
            INNER JOIN 
                (SELECT * FROM @BatchJobTable WHERE (Lsn = @Lsn) AND (SeqVal = @SeqVal)) AS [Ref]
            ON 
                ([Target].[CustId] = [Ref].[CustId])
        END
        ELSE IF (@Action = 'delete')
        BEGIN
            DELETE FROM [dbo].[Bridge_Customer] WHERE [CustId] = @CustId 
        END

        -- Update last processed event.
        EXEC [dbo].[UpdateLastProcessedEvent]
        @Name = @Name,
        @Lsn = @Lsn,
        @SeqVal = @SeqVal

    COMMIT TRANSACTION
    END TRY
    BEGIN CATCH

        DECLARE @ErrorMessage NVARCHAR(4000);  
        DECLARE @ErrorSeverity INT;  
        DECLARE @ErrorState INT;  

        SELECT   
            @ErrorMessage = ERROR_MESSAGE(),  
            @ErrorSeverity = ERROR_SEVERITY(),  
            @ErrorState = ERROR_STATE();  

        -- Use RAISERROR inside the CATCH block to return error  
        -- information about the original error that caused  
        -- execution to jump to the CATCH block.  
        RAISERROR (@ErrorMessage, -- Message text.  
                   @ErrorSeverity, -- Severity.  
                   @ErrorState -- State.  
                   );  

        ROLLBACK TRANSACTION

    END CATCH

    --FETCH NEXT FROM GetBatchJobCursor INTO @Lsn, @SeqVal, @Action, @CustId

    END
    --CLOSE GetBatchJobCursor
    --DEALLOCATE GetBatchJobCursor
END
GO

1 个答案:

答案 0 :(得分:0)

此处不需要光标;这只是基本的SQL。原谅我的代码有任何错误,因为你没有提供任何DLL,但我很确定你可以这样做:

IF (@Action = 'create')
  INSERT INTO Bridge_Customer
  (
    CustId
   ,PersonId
   ,DisplayName
   ,CreatedDate
   ,ModifiedDate
  )
  SELECT 
      CustId
     ,PersonId
     ,DisplayName
     ,CreatedDate
     ,ModifiedDate
  FROM @BatchJobTable
ELSE IF (@Action = 'update')
  UPDATE tgt
  SET  tgt.CustId       = Ref.CustId
      ,tgt.PersonId     = Ref.PersonId
      ,tgt.DisplayName  = Ref.DisplayName
      ,tgt.CreatedDate  = Ref.CreatedDate
      ,tgt.ModifiedDate = Ref.ModifiedDate
  FROM dbo.Bridge_Customer AS tgt
  INNER JOIN @BatchJobTable AS ref 
  ON (tgt.CustId = Ref.CustId)
ELSE IF (@Action = 'delete')
  DELETE FROM dbo.Bridge_Customer 
  WHERE CustId IN (SELECT CustId FROM @BatchJobTable);

就个人而言,我会将其拆分为三个存储,并从应用程序层调用任何一个。你正在做的事情被称为" Catch All查询"这很好但是,如果你必须走这条路,请阅读:Catch All Queries (Gail Shaw)