【问题标题】:What does this SQL WHERE clause mean?这个 SQL WHERE 子句是什么意思?
【发布时间】:2010-07-07 17:16:41
【问题描述】:

我在理解 T-SQL (SQL Server 2000/2005) 查询中的以下 WHERE 子句时遇到了一些困难:

update #tempTable
SET
    Total_Avg=isnull(TerminationReason,'terminated'),
    Individual_Subscriptions=null,
    Business_Subscriptions=null,
    Other_subscriptions=null,
    -- snip. 10 more fields set to NULL.
    PMIE_BI=null,
    Digital_Editions_BI=null
where
(
    AbcTerminationDate<=dbo.fnGetPeriodFinalDate(@periodid)
    and (AbcTerminationDate!=19000101 or  AbcTerminationDate is  null)
    and (Total_Avg is not NULL or PrevTotalAvg is not NULL)
)

具体来说,第二个子句对我来说没有意义 - 它是由 OR 运算符分隔的 2 个子句似乎是矛盾的。

AbcTerminationDate 字段在名为 Members 的表中声明为 INT NULL。我相信系统中的日期 19000101 意味着 NULL 或默认值或无值,即成员终止。因此,如果成员被标记为已终止,则查询似乎会清除大量字段/数字,这将是当 AbcTerminationDate 为 NULL 或具有默认值时。

在不知道更多信息的情况下,你怎么看?

【问题讨论】:

    标签: sql-server tsql where-clause


    【解决方案1】:

    看起来确实是矛盾的。也许他们的意思是 and !(AbcTerminationDate==19000101 or AbcTerminationDate is null) ?

    【讨论】:

    • 正是我的想法。希望其他人也能捡起这个..
    • en.wikipedia.org/wiki/De_Morgan%27s_laws 是我的想法。但他们以某种方式设法将其填满,但由于某些奇怪的逻辑,它仍然可以正常工作,并且仅在某些边缘情况下失败。
    【解决方案2】:

    无论 19000101 是什么“应该”的意思,在数据库的眼中它都与 NULL 不同。 NULL 是 NULL。如果您尝试将任何其他值评估为 NULL,那么它可能会出现问题,因为 NULL 表示“未知”。例如,1=NULL 吗?也许会,也许不会。事实上,你甚至不能说 NULL=NULL,因为每个 NULL 都是未知的,所以可能等于也可能不等于另一个。明确检查 NULL 条件是最安全的。

    编辑: 正如我在评论中指出的那样,如果要包含 NULL,则查询的第一部分会排除这种情况。如果应包含 NULL,则应按以下方式编写:

    (
        (
            (
                AbcTerminationDate <= dbo.fnGetPeriodFinalDate(@periodid) AND
                AbcTerminationDate != 19000101
            ) OR
            AbcTerminationDate is NULL
        ) AND
        (Total_Avg is not NULL or PrevTotalAvg is not NULL)
    )
    

    【讨论】:

    • 同意,上面的代码似乎是相当普遍的做法。仅仅因为 AbcTerminationDate 不等于“19000101”并不意味着它等于 NULL...正如您所说,您必须专门对此进行测试。
    • 我对你所说的没有异议,我从技术角度理解 NULL 的含义。但这不是我的问题。在系统中,日期值 19000101 在“语义上”等同于 NULL 值。我对查询的语义价值更感兴趣——他们想要达到什么目的?
    • 如果不是虚拟日期,则包含它。如果它为 NULL,则包含它。同样,无论语义如何,如果您想要正确的结果,查询仍然需要在技术上是正确的。这就是那行代码正在尝试做的事情 - 如果日期为 NULL,请确保返回正确的结果。但它做得不好,因为如果它是 NULL,那么查询的第一部分可能会失败。
    • “虽然它做得不好,因为如果它为 NULL,那么查询的第一部分可能会失败”。这也是我的感受。虽然这种类型的 WHERE 子句在整个系统的很多地方都使用过。如果是不正确的,那么为什么客户没有更早或更频繁地抱怨它。也许它只在某些边缘情况下失败......
    • 只有 AbcTerminationDate 为 NULL 时才会失败。如果您的应用程序默认使用 19000101 填充它,那么这可能不会发生。该列允许 NULL 的事实意味着它在理论上可能发生,所以我总是会为它编写代码,但也许它只是没有。
    【解决方案3】:

    如果“或”参数在 () 分组之外,它将否定:

    AbcTerminationDate<=dbo.fnGetPeriodFinalDate(@periodid) 
    

    [编辑] 基本上它的意思是从第一个子句中获取任何结果,并执行一个额外的过滤器以确保它不是 19000101 或它为空,这很可能是 fnGetPeriodFinalDate 函数正确评估的异常值。

    【讨论】:

    • 谢谢.. 有道理。我最感兴趣的是第 2 个子句及其含义,但它的结果可能会否定第 1 个子句,因此需要考虑第 1 个子句以提取含义...
    猜你喜欢
    • 2021-11-16
    • 1970-01-01
    • 1970-01-01
    • 2022-01-28
    • 2011-08-29
    • 1970-01-01
    • 2012-09-09
    • 2017-03-20
    相关资源
    最近更新 更多