SQL Server DELETE和SELECT与不同的WHERE子句表现不同

时间:2011-11-14 21:59:24

标签: sql sql-server

我有一个表格,该表格由每日预定作业填充,删除最近7天的数据,然后从另一个来源(大型机)重新填充最近7天的数据。

最近,用户报告了一些重复项,可追溯到2011年10月初......数十万行。

我注意到每个作业运行的删除都有奇怪的行为:

DELETE FROM fm104d 
 WHERE location = '18'
   AND (CONVERT(datetime,CASE WHEN ISDATE(pull_date)=0 THEN '19000101' 
                 ELSE pull_date END)) >  DATEADD(day, -7, getdate())

以上返回“(0行(s)受影响)”。

当我用SELECT *替换DELETE后运行上面的内容时,我获得了32,000多行作为回报。

为什么SELECT和DELETE的行为会有所不同?

更新

这是实际执行计划:

http://pastie.org/2869202

6 个答案:

答案 0 :(得分:1)

你不会相信这一点。事实上我并没有因为它几乎没有逻辑意义,但最终,有效的解决方案是添加索引。

归功于我的本地DBA“我考虑过添加一个索引吗?我只是测试并确定它有效”。

这是添加的索引:

CREATE  INDEX ixDBO_fir104d__SOURCE_LOCATION__Include
ON [dbo].[fir104d] ([SOURCE_LOCATION])
INCLUDE ([Transaction_Date],[PULL_DATE])
GO

我让工作按计划运行,果然,一切都按原样运行。

我的猜测是,解释计划中有一些内容表明它没有使用索引/错误索引,但是我的开发人员的想法无法理解这一详细程度。

感谢大家所花费的时间和精力。

<强>更新

收到来自不同开发人员的消息,该表中的数据另外损坏到需要“几个小时的DBA参与解决”,以及开发人员必须执行其他一些数据修复(读取:数据文件重新加载) 。

在一天结束时,考虑到预定作业的运行方式,添加索引可能是一件好事,显然,故事还有更多内容!

答案 1 :(得分:0)

试试这个:

DELETE FROM fm104d  where fm104d.id in 
(
select  id from fm104d 
 WHERE location = '18'
   AND (CONVERT(datetime,CASE WHEN ISDATE(pull_date)=0 THEN '19000101' 
                 ELSE pull_date END)) >  DATEADD(day, -7, getdate())
)aaa

如果删除则给予回复

P.S。 :这不是解决方案,但会导致决定。

答案 2 :(得分:0)

我认为,当pull_date不是约会时,您永远不想删除 尝试消除明确的字符串替换...也许SELECTDELETE

之间存在不同的解析方式
DELETE 
FROM 
    fm104d 
WHERE 
    [location] = '18' --NOTE if this is an int, then just try with 18, no dits
    AND (
         CASE ISDATE([pull_date])
         WHEN 1 THEN
             CAST([pull_date] AS DATETIME)
         ELSE
             NULL
         END  >  DATEADD(DAY, -7, GETDATE())
        ) 

编辑请注意, 无论如何都删除你的行......我认为这实际上并不是你的意图。

答案 3 :(得分:0)

一种可能的解释可能是有两个表,每个表都在不同的模式中。也许如果您对两个架构都拥有select权限,但只有一个delete权限,则SQL Server可能会为delete选择不同的表。

要验证这一点,请在表格前添加架构名称(默认架构为dbo

FROM schema1.fm104d

(未经测试,只是想一想,无法访问SQL Server安装atm。)

答案 4 :(得分:0)

对于您的选择,将ISDATE(pull_date)添加到选择列表以确定这些影响的案例陈述的哪个部分。同时查看pull_date,看看是否存在一些模式,这些模式与这些拒绝删除的违规者共同使用。

这可能与Convert和IsDate的确定性有关:

“只有在使用CONVERT函数时,如果指定了CONVERT样式参数且样式不等于0,100,9或109,ISDATE才是确定性的。”

请参阅此处的几个示例,其中convert嵌套在isdate中:

http://www.sqlmonster.com/Uwe/Forum.aspx/sql-server-programming/181/CAST-CONVERT-nondeterministic

因此,请尝试调整where子句,看看是否有帮助。另请注意“ISDATE的返回值可能受LANGUAGE和DATEFORMAT设置的影响。”因此,您的服务器上的某些内容可能会在这些问为什么它会影响删除但不影响选择仍然很奇怪。

答案 5 :(得分:0)

如何尝试此操作,看看您是否可以先评估pull_date列,然后删除记录。

DELETE FROM fm104d
WHERE Location = 18 
   AND Pull_date IN
   (
      SELECT CONVERT (DATETIME,
         CASE 
            WHEN ISDATE(pull_Date) = 0
               THEN '19000101'
            ELSE pull_date
         END) AS pull_date
      FROM fm104d 
      WHERE pull_date > DATEADD(DAY, -7, GETDATE())
   )