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

Jam*_*mes 14 sql-server collation like

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

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

    Where Name like '%hospitalist%'
Run Code Online (Sandbox Code Playgroud)

Sha*_*tor 24

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

-- 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%'
Run Code Online (Sandbox Code Playgroud)

请注意这可能带来的性能问题。执行排序规则时,您将需要扫描聚集索引以调整/查找值。你写这篇文章的方式LIKE也使查询不可 sargable。

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

MSDN 上的校对。


Joh*_*ner 16

虽然您可以使用标量函数,例如UPPERLOWER,并且您可以重新整理该列,使其不再区分大小写,但这些方法都需要对基础数据进行数据转换,而这些数据永远不允许进行索引查找。你也用通配符引导你的 LIKE,所以在这种情况下这对你来说并不重要,但是如果你想以有效的方式搜索字符串的左侧部分允许优化器要搜索索引,您可以使用括号 ([]) 指定字符串,如下所示:

SELECT *
FROM TABLE 
WHERE Name LIKE '[hH][oO][sS][pP][iI][tT][aA][lL][iI][sS][tT]%'
Run Code Online (Sandbox Code Playgroud)

这个例子(这里的 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
Run Code Online (Sandbox Code Playgroud)


Bra*_*adC 15

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

WHERE LOWER(Name) LIKE '%hospitalist%' 
Run Code Online (Sandbox Code Playgroud)

或者

WHERE UPPER(Name) LIKE '%HOSPITALIST%' 
Run Code Online (Sandbox Code Playgroud)