【问题标题】:SQL Server: NULL or empty string?SQL Server:NULL 还是空字符串?
【发布时间】:2020-11-26 07:13:20
【问题描述】:

我有一个数据库列,其值以编程方式确定,不受用户输入的影响。该值绝不是空字符串;它是 NULL 或非 0 长度字符串。该列当前可以为空。

通常,我想在两个不同的行之间比较该列。因为该列可以为空,所以我必须执行以下操作:

SELECT *
FROM
    myTable A
    INNER JOIN myTable B ON ISNULL(B.someColumn, '') = ISNULL(A.someColumn, '')
WHERE   B.Id > A.Id

如果空字符串没有意义,我是否会更明智地将列设为NOT NULL 并使用空字符串表示该列没有值?

然后我可以使用以下方法比较列:

SELECT *
FROM
    foo A
    INNER JOIN foo B ON B.someColumn = A.someColumn
WHERE   B.Id > A.Id

我似乎这种方法可以更好地利用列 someColumn 上的索引?

是的,我知道我可以做到:

(B.someColumn = A.someColumn) or (B.someColumn is NULL and A.someColumn is NULL)

但这似乎有点罗嗦。

【问题讨论】:

  • 我正在将表连接到自身,如 SQL 示例和说明中所述。有问题的列不是主键,但出于报告目的,找到与该列具有相同值的行很重要。
  • @WalterVehoeven 但这在数据库范围内正确吗?我无法进行范围如此广泛的更改。不过谢谢你的建议。但它引出了一个问题,为什么默认情况下不关闭 ANSI NULL?另请注意,我们确实有索引视图。
  • 我会倾向于让它成为NOT NULL DEFAULT '',但这可能会影响整个应用程序。琐事:Oracle 数据库不做零长度字符串(好吧:没有,我有一段时间没用过 Oracle) - '' 被翻译成 NULL。酷吧?所以你会被你正在做的事情困住。
  • @GregHNZ 我创建了该列并编写了处理该列的所有代码,因此我确信将其默认为空字符串(而不是 NULL)是安全且面向未来的。

标签: sql sql-server-2016


【解决方案1】:

你自己说的和你给出的代码是正确的。

值得注意的是,您的第一个示例中的代码

`INNER JOIN myTable B ON ISNULL(B.someColumn, '') = ISNULL(A.someColumn, '')`

强制 SQL 服务器扫描整个表并计算 ISNULL(...),然后才能进行连接。这意味着它不能使用任何索引来加速连接,这将大大降低性能。下次执行该查询时将重复相同的过程,因此您不能期望随后再次运行该查询会更快。

[ 作为记录,您当然可以将ISNULL(...) 设为计算列,对其进行索引并在连接中使用它,但考虑到其他可能的解决方案,这似乎有点夸张。 ]

您是否应该使用'' 而不是NULL 或者使用其他方法取决于前者所需的努力:

如果您的应用程序仅在它想在那里写入一个有意义的(读取:非空)值时接触该列,那么您可以通过三个简单的方法解决问题步骤(更新列并将所有NULL 值转换为'';使列不可为空;将列的默认值从NULL 更改为'')。

但是,如果您的应用程序在每种情况下都触及该列并在适当的情况下主动向其写入NULL,您将不得不更改应用程序本身以采用该路线。是否可以更改应用程序只有您自己知道...

如果您无法更改应用程序,则您的第三种方法很好并且工作可靠:

(B.someColumn = A.someColumn) or (B.someColumn is NULL and A.someColumn is NULL)

它“罗嗦”不会打扰我。一般来说,代码的长度对性能没有任何影响,在这种情况下,冗长的代码使您可以在应用程序中保持原样(除了此查询),同时使 SQL Server 能够使用索引来加速加入。

总结:

使用'' 而不是NULL 如果您的应用程序很容易允许,或者可以很容易地更改以允许它。否则,请使用第三种方法。

关于ANSI_NULLS的最后说明:

Walter Vehoeven 在您的问题下方的评论是正确的,但在您的情况下,ANSI_NULLS 不会改变任何东西。来自the documentation(表格下方第一段,格式化我的):

仅当比较的操作数之一是 NULL 变量或文字 NULL 时,SET ANSI_NULLS ON 才会影响比较。 如果比较的两边都是列或复合表达式,则设置不影响比较。

第二句意味着它对您的情况没有任何影响,因为您正在比较/连接两列(即使它实际上是比较两侧的同一列)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-15
    • 1970-01-01
    • 2018-11-17
    • 1970-01-01
    • 2021-03-28
    • 2011-08-02
    相关资源
    最近更新 更多