Sql server 使用Try-Catch:为什么每次查询结果集都不一致

Sql server 使用Try-Catch:为什么每次查询结果集都不一致,sql-server,tsql,Sql Server,Tsql,当我运行下面的代码时,我得到了不一致的数字,有时是1条记录,有时是5条记录 我正试图从临时表中获取数据到最终表或新表。temp表中的数据包含每个成员的多条记录。每次成员访问时,都会将一个新的计数编号插入到带有memberID的表中。这是一种INT数据类型。如果一个成员访问了10次,那么他们的数字从1到10,其中10次是最近的访问 我正在尝试获取最近的访问并插入到新表中,但如果出现错误,我需要回滚 注意:我是引发错误,因为此代码将放置在SSIS TSQL任务中,如果代码失败,则引发错误将使任务停止

当我运行下面的代码时,我得到了不一致的数字,有时是1条记录,有时是5条记录

我正试图从临时表中获取数据到最终表或新表。temp表中的数据包含每个成员的多条记录。每次成员访问时,都会将一个新的
计数编号
插入到带有memberID的表中。这是一种INT数据类型。如果一个成员访问了10次,那么他们的数字从1到10,其中10次是最近的访问

我正在尝试获取最近的访问并插入到新表中,但如果出现错误,我需要回滚

注意:我是
引发错误
,因为此代码将放置在
SSIS TSQL任务中
,如果代码失败,则引发错误将使任务停止

USE MyDB;

GO

BEGIN TRY
    BEGIN TRANSACTION;

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

    WITH Member
         AS (SELECT [MemberID],
                    [LocationID],
                    [CancelledDate],
                    [VisitCount],
                    [VisitDate],
                    ROW_NUMBER() OVER (PARTITION BY MemberID 
                                           ORDER BY [VisitDate] DESC) AS RowNumber
             FROM   [MySchema].[TempMemberTable]
             WHERE  MemberID IS NOT NULL
                    AND LocationID = '121')
    INSERT INTO [MySchema].[NewMemberTable]
                ([MemberID],
                 [LocationID],
                 [CancelledDate],
                 [VisitCount],
                 [VisitDate])
    SELECT [MemberID],
           [LocationID],
           [CancelledDate],
           [VisitCount],
           [VisitDate]
    FROM   Member
    WHERE  RowNumber = 1
           AND [CancelledDate] > GETDATE();

    COMMIT TRANSACTION
END TRY

BEGIN CATCH
    IF @@ERROR > 0
      BEGIN
          ROLLBACK TRANSACTION;
      END

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

    RAISERROR (@ErrorMessage,@ErrorSeverity,@ErrorState );
END CATCH; 

为什么即使源数据没有更改,结果也不一致?

查询中有日期。确实没有添加其他行,因为WHERE子句可能会随着时间的推移添加数据

另外,其他隔离级别有脏读、不可重复读和幻象读。这一切都与其他人在您获取数据时更改数据有关。你不是唯一一个在这个系统上的人

请参阅本文中的矩阵

如果启用快照隔离,并且发生了相同的不一致,则是TSQL代码中的日期或其他内容。然而,它看起来很直截了当

SELECT语句的逻辑顺序

使用派生表可以实现相同的逻辑和功能。该表具有成员Id和最大访问日期。完全联接将返回最新的记录

-- Run Select Statemnt 5 Times
SELECT 
 [MemberID]
,[LocationID]
,[CancelledDate]
,[VisitCount]
,[VisitDate]
FROM [MySchema].[TempMemberTable] as T
JOIN
(
    SELECT MemberID as var_MemberID, Max([VisitDate]) as var_VisitDate
    FROM [MySchema].[TempMemberTable] 
    WHERE LocationID = '121'
) as D
WHERE T.[MemberID] = D.var_MemberID and T.[VisitDate] = D.var_VisitDate
GO 5
执行5次此查询是否会得到不同的结果?

我故意省略了这个额外的过滤器


和T[canceledDate]>GETDATE()

不,没有其他人在操作数据,数据不是活动的,但它位于一个大表中。谢谢基本上,您是按访问日期获取最近的成员,该成员位于位置121中,该位置具有cancel date>getdate()。尝试将行号移动到第一个字段。还有,放一个;在CTE前面。当我点击execute时,结果集中的变化正在发生,每次我都会得到不同数量的记录返回。嘿,我的朋友,我认为这看起来很有希望,但我想进一步测试它。到目前为止,我没有看到相同的行为,但结果集确实发生了变化,但保持不变。你的想法是什么?你是否加回了取消日期。这就是我认为你的问题所在。但是派生表可能更有意义,因为您无论如何都要丢弃rownumber()值。解决问题的方法有很多。每次运行它时,
GETDATE()
都会有所不同。还有
MemberID,VisitDate的任何重复值吗?没有实际的重复值,但是有多个具有不同访问计数和日期但具有相同ID的记录实例。每次单击“执行”时,结果都会发生变化,且数据不活动。我还尝试了
>CAST(GETDATE()AS DATE)
同样的问题。尝试捕获实际的执行计划。当您得到两个具有不同行数的运行时,请查看计划运算符上的实际行数,并查看它们的不同之处。VisitDate的数据类型是什么?是否包括一天中的时间?是否填写了时间,即不总是午夜?是否有理由不将取消日期条件包括在CTE内而不是之后?
-- Run Select Statemnt 5 Times
SELECT 
 [MemberID]
,[LocationID]
,[CancelledDate]
,[VisitCount]
,[VisitDate]
FROM [MySchema].[TempMemberTable] as T
JOIN
(
    SELECT MemberID as var_MemberID, Max([VisitDate]) as var_VisitDate
    FROM [MySchema].[TempMemberTable] 
    WHERE LocationID = '121'
) as D
WHERE T.[MemberID] = D.var_MemberID and T.[VisitDate] = D.var_VisitDate
GO 5