我有一个数据库列,其值是通过编程确定的,不受用户输入的影响。该值绝不能为空字符串;它可以为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)
但这似乎有些罗word。
您已经说过的话以及所提供的代码是正确的。
值得注意的是,第一个示例中的代码
`INNER JOIN myTable B ON ISNULL(B.someColumn, '') = ISNULL(A.someColumn, '')`
强制SQL ServerISNULL(...)
在能够进行联接之前扫描整个表并进行计算。这意味着它不能使用任何索引来加速连接,这将大大降低性能。下次执行该查询时,将重复相同的过程,因此您不能期望随后再次运行该查询会更快。
[当然,作为记录,您可以创建ISNULL(...)
一个计算列,对其进行索引并在连接中使用它,但是鉴于其他可能的解决方案,这似乎有点夸张。]
是否应使用''
替代方法NULL
还是采用另一种方法取决于前者需要付出的努力:
如果您的应用程序仅在要在其中写入有意义的值(读取:非空)时才触摸该列,则可以通过三个简单的步骤解决该问题(更新该列并将所有NULL
值都变为''
;使该列不可为空) ;将列的默认值从更改NULL
为''
)。
但是,如果您的应用程序在每种情况下都碰到该列并NULL
在适当时主动写入该列,则您必须更改应用程序本身以采用该路由。仅您知道是否可以更改应用程序...
如果您无法更改应用程序,那么您的第三种方法很好并且可以可靠地工作:
(B.someColumn = A.someColumn) or (B.someColumn is NULL and A.someColumn is NULL)
它是“罗y的”,这不会打扰我。通常,代码的长度对性能没有任何影响,在这种情况下,冗长的代码使您可以将事情原样保留在应用程序中(此查询除外),同时使SQL Server能够使用索引来加速加入。
综上所述:
如果您的应用程序允许这样做''
,NULL
则使用代替,或者可以轻松对其进行更改以允许它。否则,请使用第三种方法。
关于ANSI_NULLS
以下内容的最后说明:
Walter Vehoeven在您的问题下方的评论是正确的,但就您而言,ANSI_NULLS
不会有任何改变。从文档(表格下方的第一段,格式化我的格式):
SET ANSI_NULLS ON仅在比较操作数之一是NULL变量或文字NULL的情况下才影响比较。如果比较的两面都是列或复合表达式,则该设置不会影响比较。
第二句话意味着它不会对您造成任何影响,因为您正在比较/加入两列(即使它实际上是比较两边的同一列)。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句