如何在区分大小写的数据库中执行不区分大小写的LIKE?


11

我的供应商要求数据仓库数据库区分大小写,但是我需要对此进行区分大小写的查询。

在区分大小写的数据库中,如何将其写为不区分大小写?

    Where Name like '%hospitalist%'

Answers:


17

您可以将新的排序规则附加到选择查询中,以区分大小写或不区分大小写。

-- Case sensitive example
SELECT *
FROM TABLE 
WHERE Name collate SQL_Latin1_General_CP1_CS_AS like '%hospitalist%'

-- Case insensitive example
SELECT *
FROM TABLE 
WHERE Name collate SQL_Latin1_General_CP1_CI_AS like '%hospitalist%'

只是要意识到可能会出现的性能问题。执行排序规则时,您将需要扫描聚簇索引以调整/查找值。您编写文章的方式LIKE也使查询不可修改。

我从Kendra Little的 SELECT Seminar课程中学习了整理技巧。您可以从MS SQL Tips的Ben Snaidero中找到其他排序规则信息

在Collat​​e上的MSDN。


@stom有两种方法。要么a)将性能问题转移到处理时间,而不是select时间。为此,您可以创建一个新列,其中包含转换后的数据的一个子集,然后对其进行索引(通常在运行ETL的时间)。这将有一个维护成本,不是一个好方法。B)您可以使查询搜索可辩论或可辩论。将查询更改为SELECT * FROM TABLE WHERE VALUE LIKE %hospitalistSELECT * FROM TABLE WHERE VALUE LIKE hospitalist%将起作用。除此之外,您正在寻找硬件或功能,以提高不良设计的速度。
Shaulinator

14

尽管您可以使用诸如UPPERLOWER之类的标量函数,并且可以重新排序列,使其不再区分大小写,但是这些方法都要求对基础数据进行数据转换,而这将永远不允许索引查找。您也将通配符放在LIKE的前面,因此在这种情况下,这对您来说并不是什么大问题,但是如果您想以有效的方式搜索字符串的左侧部分允许使用优化器要搜索索引,可以按如下所示用方括号([])指定字符串:

SELECT *
FROM TABLE 
WHERE Name LIKE '[hH][oO][sS][pP][iI][tT][aA][lL][iI][sS][tT]%'

这个例子(这里的dbfiddle链接)在显示我的意思方面做得更好:

CREATE TABLE #tmp_cohellation_fun
(
        ID  INT IDENTITY(1,1) PRIMARY KEY CLUSTERED
    ,   myValue VARCHAR(50) COLLATE SQL_Latin1_General_CP1_CS_AS
)

-- Garbage values to represent data you don't want
INSERT INTO #tmp_cohellation_fun
SELECT  CAST(NEWID() AS VARCHAR(50))
FROM master.sys.configurations t1
    CROSS JOIN master.sys.configurations t2
    CROSS JOIN master.sys.configurations t3;

-- Sprinkle a little bit of good data
INSERT INTO #tmp_cohellation_fun
        (myValue)
VALUES  ('Apple')
    ,   ('apple')

-- Another healthy helping of garbage that we don't care about
INSERT INTO #tmp_cohellation_fun
SELECT  CAST(NEWID() AS VARCHAR(50))
FROM master.sys.configurations t1
    CROSS JOIN master.sys.configurations t2
    CROSS JOIN master.sys.configurations t3;

-- Some more good data
INSERT INTO #tmp_cohellation_fun
        (myValue)
VALUES
        ('aPple')
    ,   ('APPLE')
    ,   ('APple')


-- Final insert of garbage that we don't care about
INSERT INTO #tmp_cohellation_fun
SELECT  CAST(NEWID() AS VARCHAR(50))
FROM master.sys.configurations t1
    CROSS JOIN master.sys.configurations t2
    CROSS JOIN master.sys.configurations t3
;

-- Create a nonclustered rowstore index
CREATE INDEX ix_myValue ON #tmp_cohellation_fun (myValue)
;

SET STATISTICS XML ON
;

-- Seek, but incorrect results
SELECT  *
FROM    #tmp_cohellation_fun
WHERE   myValue LIKE 'apple%'
;

-- Scan, with correct results
SELECT  *
FROM    #tmp_cohellation_fun
WHERE   myValue COLLATE SQL_Latin1_General_CP1_CI_AS LIKE 'apple%'
;

-- Seek, with correct results
SELECT  *
FROM    #tmp_cohellation_fun
WHERE   myValue LIKE '[aA][pP][pP][lL][eE]%'
;

SET STATISTICS XML OFF
;

DROP TABLE IF EXISTS #tmp_cohellation_fun

爱它。当您说从两个大小写区分为不区分大小写的排序规则时(如果您有两个其他相同的排序规则),SQL不仅会像这样优雅地回退,这超出了我的理解。我明白了为什么你不能走另一条路。无论如何,这是好东西。
约翰·莱德格伦

13

这和COLLATE答案都会影响性能,因为它们使查询成为非SARGable,但是最简单的方法(如Edgar在评论中建议的那样)是:

WHERE LOWER(Name) LIKE '%hospitalist%' 

要么

WHERE UPPER(Name) LIKE '%HOSPITALIST%' 
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.