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