如何查找超过 1 个大写字符

How to find more than 1 uppercase character

我正在 运行 一系列 SQL 查询以查找需要清理的数据。我想做的其中一项是寻找:

例如我的名字应该是"John Doe"。我希望它找到 "JOhn Doe" 或 "JOHN DOE" 或 "John doe",但我不希望它找到 "John Doe",因为它的格式正确。

我正在使用 SQL Server 2008。

关键是使用区分大小写的排序规则,即 Latin1_General_BIN*。然后,您可以使用带有 LIKE expression like the following (SQL Fiddle demo):

的查询
select *
from foo
where name like '%[A-Z][A-Z]%' collate Latin1_General_BIN --two uppercase in a row
or name like '% [a-z]%' collate Latin1_General_BIN --space then lowercase

*根据 How do I perform a case-sensitive search using LIKE?,显然 Latin1_General_CS_AS 排序规则中有一个 "bug",其中 [A-Z] 之类的范围失败区分大小写。解决方案是使用 Latin1_General_BIN.

如果您的目标是更新您的列以大写每个单词的第一个字符(在您的例子中是 firstName 和 lastName),您可以使用以下查询。

使用数据

创建样本table
Declare @t table (Id int IDENTITY(1,1),Name varchar(50))
insert into @t (name)values ('john doe'),('lohn foe'),('tohnytty noe'),('gohnsdf fgedsfsdf')

更新查询

UPDATE @t
SET name =  UPPER(LEFT(SUBSTRING(Name, 1, CHARINDEX(' ', Name) - 1), 1)) + RIGHT(SUBSTRING(Name, 1, CHARINDEX(' ', Name) - 1), LEN(SUBSTRING(Name, 1, CHARINDEX(' ', Name) - 1)) - 1) +
            ' ' +
            UPPER(LEFT(SUBSTRING(Name, CHARINDEX(' ', Name) + 1, 8000), 1)) + RIGHT(SUBSTRING(Name, CHARINDEX(' ', Name) + 1, 8000), LEN(SUBSTRING(Name, CHARINDEX(' ', Name) + 1, 8000)) - 1)
FROM @t

输出

SELECT * FROM @t

Id  Name
1   John Doe
2   Lohn Foe
3   Tohnytty Noe
4   Gohnsdf Fgedsfsdf

您可以使用正则表达式。我不是 SQL 服务器高手,但您想使用 RegexMatch。像这样:

select columnName
from tableName
where dbo.RegexMatch( columnName, 
        N'[A-Z]\W[A-Z]' ) = 1

首先,我认为您应该创建一个 returns 专有名称的函数(听起来您无论如何都需要一个)。请参阅标题 "Proper Casing a Persons Name" 下的 here。然后找出不匹配的。

SELECT Id, Name, dbo.ProperCase(Name)
FROM MyTable
WHERE Name <> dbo.PoperCase(Name)  collate Latin1_General_BIN

这将帮助您清理数据并根据需要调整函数。

我是这样使用的:

;WITH yourTable AS(
    SELECT 'John Doe' As name
    UNION ALL SELECT 'JOhn Doe'
    UNION ALL SELECT 'JOHN DOE'
    UNION ALL SELECT 'John doe'
    UNION ALL SELECT 'John DoE'
    UNION ALL SELECT 'john Doe'
    UNION ALL SELECT 'jOhn dOe'
    UNION ALL SELECT 'jOHN dOE'
    UNION ALL SELECT 'john doe'
)
SELECT name
FROM (
    SELECT  name,
            LOWER(PARSENAME(REPLACE(name, ' ', '.'), 1)) part2,
            LOWER(PARSENAME(REPLACE(name, ' ', '.'), 2)) part1
    FROM yourTable) t
WHERE name COLLATE Latin1_General_BIN = UPPER(LEFT(part1,1)) + RIGHT(part1, LEN(part1) -1) + 
                                  ' ' + UPPER(LEFT(part2,1)) + RIGHT(part2, LEN(part2) -1)

Note:
This will be good for just two parted names for more, it should improved.