在这种情况下创建CTE有帮助吗?

时间:2011-05-17 10:42:31

标签: sql-server-2008

我在SQL Server 2008中编写的查询非常糟糕

UPDATE  PatientChartImages
SET     PatientChartImages.IsLockDown = @IsLockdown
WHERE   PatientChartImages.IsLockDown = @IsNotLockdown
    AND PatientChartId IN (
    SELECT  PatientCharts.PatientChartId
    FROM    PatientCharts
    WHERE   ( PatientCharts.ChartStatusID = @ChartCompletedStatusID
              OR PatientCharts.ChartStatusID = @ChartOnBaseStatusID
            )
            AND PatientCharts.IsLockDown = @IsNotLockdown
            AND PatientCharts.CompletedOn IS NOT NULL
            AND DATEDIFF(MINUTE, PatientCharts.CompletedOn, GETUTCDATE()) >= ( SELECT
                                                          tf.LockUpInterval
                                                          FROM
                                                          @tblFacCOnf tf
                                                          WHERE
                                                          tf.facilityId = PatientCharts.FacilityId
                                                          ) )

此查询锁定主表并导致TimeOut。如果我首先在所有可更新记录中创建CTE,然后通过加入CTE来更新主表。它有帮助??

4 个答案:

答案 0 :(得分:0)

我建议您做的第一件事是用IN替换EXISTS条件。其次是将所有这些条件逻辑移入CTE。第三是用@tblFacCOnf替换带有连接的子选择。

最后的建议取决于您的业务逻辑,在我看来并不那么重要

所以最后你会得到一些东西

WITH search_cte as (
  SELECT  PatientCharts.PatientChartId
  FROM    PatientCharts 
  JOIN @tblFacCOnf tf on tf.facilityId = PatientCharts.FacilityId
  WHERE   ( PatientCharts.ChartStatusID = @ChartCompletedStatusID
          OR PatientCharts.ChartStatusID = @ChartOnBaseStatusID
        )
        AND PatientCharts.IsLockDown = @IsNotLockdown
        AND PatientCharts.CompletedOn IS NOT NULL
        AND DATEDIFF(MINUTE, PatientCharts.CompletedOn, GETUTCDATE()) >= tf.LockUpInterval
) --cte end                                               
UPDATE  PatientChartImages
SET     PatientChartImages.IsLockDown = @IsLockdown
WHERE   PatientChartImages.IsLockDown = @IsNotLockdown
AND EXISTS (select 1 from PatientChartImages where PatientChartImages.PatientChartId = search_cte.PatientChartId)

答案 1 :(得分:0)

如果其他建议没有给你足够的速度,我可能会建议另外一件事就是不要使用表变量。临时表对于大型数据集通常更快,并且如果需要可以编制索引。

答案 2 :(得分:0)

更新锁定的时间是计算CTE和更新时间。 CTE时间可能导致超时。

将锁定时间减少到更新目标表所需的最小值。我建议你创建一个包含两列的临时表。 Col1是目标表的主键或簇键,Col2是目标表中所需的值。包装创建临时表,并根据事务中的业务逻辑为表填充值。使用临时表的连接更新目标表,并在单独的事务中使用临时表中的值更新目标表。更新后删除临时表。

答案 3 :(得分:-1)

我认为您应该创建一个SQL脚本(或存储过程,如果您将从更高级别使用它),您将选择的结果存储到游标中(您只需找到行的PatientCartId)要更新)然后你应该在更新中使用它,所以答案是肯定的。

这很容易测试,您应该将这些命令放入事务中,回滚事务,在回滚之前,您应该执行选择以测试结果。祝你好运。