从字符串中获取大写字母

Posted

技术标签:

【中文标题】从字符串中获取大写字母【英文标题】:Get the Capital letters from a string 【发布时间】:2021-09-12 11:01:20 【问题描述】:

我需要从 SQL Server 中的列中提取大写字母。

EX:ABC_DEF_ghi

我只想提取 ABC_DEF。

有时字符串可能类似于 ABC_DEF_GHI_jkl,所以在这种情况下它将是 ABC_DEF_GHI

任何建议都会有所帮助。

提前致谢。

【问题讨论】:

这将是使用正则表达式的小菜一碟。但是 SQL Server 并没有真正的正则表达式支持。我会导出表,在脚本中进行清理,然后重新导入。 您使用的是什么版本的 SQL Server? 这些不仅仅是大写字母,您似乎还需要下划线。 【参考方案1】:

正如Tim Biegeleisen 提到的,这在 SQL Server 中并不容易,因为它不支持正则表达式。因此,您必须具备一些创造性。

由于我们不知道您使用的是哪个版本的 SQL Server(尽管 I did ask)我假设您使用的是最新版本的 SQL Server,并且可以访问 @987654325 @ 和 TRIM。如果没有,您将需要使用旧的 FOR XML PATHSTUFF 方法进行字符串聚合,并使用 LTRIMRTRIM 嵌套 REPLACEs 用于 TRIM

无论如何,我在这里所做的是将值整理到一个二进制排序规则中,该排序规则既区分大小写,又按大写和小写顺序排列字母(尽管先小写然后大写的排序规则也可以,这很重要它不是按字母顺序,然后是大小写)。所以按照ABC...Zabc...z 之类的顺序,而不是AaBb...Zz 之类的顺序。然后我使用 Tally 将整理后的字符串拆分为单独的字符。

然后我使用STRING_AGGCASE 表达式来只保留下划线字符(您似乎也想要)和大写字母。最后,我使用TRIM 删除任何前导和尾随下划线;如果没有这个,返回的值将是'ABC_DEF_GHI_'

我还假设您是针对表而不是标量值执行此操作的,这给出了:

DECLARE @SomeString varchar(100) = 'ABC_DEF_GHI_jkl';

WITH N AS(
    SELECT N
    FROM (VALUES(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL))N(N)),
Tally AS(
    SELECT TOP (SELECT MAX(LEN(V.SomeString)) FROM (VALUES(@SomeString))V(SomeString)) --This would be your table
           ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS I
    FROM N N1, N N2) --100 rows, add more cross joins for more rows
SELECT TRIM('_' FROM STRING_AGG(CASE WHEN SS.C LIKE '[A-Z_]' THEN SS.C END,'') WITHIN GROUP (ORDER BY T.I)) AS NewString
FROM (VALUES(@SomeString))V(SomeString) --This would be your table
     CROSS APPLY (VALUES(V.SomeString COLLATE Latin1_General_BIN))C(SomeString) --Collate to a collation that is both case sensitive and orders Uppercase first
     JOIN Tally T ON LEN(C.SomeString) >= T.I
     CROSS APPLY (VALUES(SUBSTRING(C.SomeString,T.I,1)))SS(C) --Get each character
GROUP BY V.SomeString;

db<>fiddle

当然,“更简单”的解决方案可能是找到并实现 Regex CLR 函数并直接使用它。 ?


原来 OP 使用的是 2014... 这意味着上面需要一些重大的重构。恐怕我不会在这里解释FOR XML PATHREPLACE 是如何工作的(因为我将精力投入到原始解决方案中),但是,搜索会为您提供详细信息。:

WITH N AS(
    SELECT N
    FROM (VALUES(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL))N(N)),
Tally AS(
    SELECT TOP (SELECT MAX(LEN(V.SomeString)) FROM (VALUES(@SomeString))V(SomeString)) --This would be your table
           ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS I
    FROM N N1, N N2) --100 rows, add more cross joins for more rows
SELECT REPLACE(LTRIM(RTRIM(REPLACE((SELECT CASE WHEN SS.C LIKE '[A-Z_]' THEN SS.C END
                                    FROM (VALUES(V.SomeString COLLATE Latin1_General_BIN))C(SomeString) --Collate to a collation that is both case sensitive and orders Uppercase first
                                         JOIN Tally T ON LEN(C.SomeString) >= T.I
                                         CROSS APPLY (VALUES(SUBSTRING(C.SomeString,T.I,1)))SS(C) --Get each character
                                    ORDER BY T.I
                                    FOR XML PATH(''),TYPE).value('(./text())[1]','varchar(100)'),'_',' '))),' ','_') AS NewString
FROM (VALUES(@SomeString))V(SomeString) --This would be your table
GROUP BY V.SomeString;

【讨论】:

抱歉耽搁了,我使用的是 SQL Server 2014。 那么你需要使用FOR XML PATH(和STUFF)并替换我现在指导的TRIM函数,@udaykiran。 string_agg for sql server pre 2017 虽然上述内容也需要大量重构。 我已经为你添加了一个 2014 兼容版本,@udaykiran,但请记住标记你正在使用的版本;特别是如果它是不再完全支持的版本。如果没有版本,大多数用户会认为您至少在使用产品的完全受支持的版本,并且很可能会认为您使用的是最新版本。【参考方案2】:

对于 SQL 2017 及更高版本:

DECLARE @SomeString varchar(100) = 'ABC_DEF_GHI_jkl';
WITH T0 AS
(
SELECT 1 AS INDICE, 
       SUBSTRING(@SomeString, 1, 1) AS RAW_LETTER, 
       SUBSTRING(UPPER(@SomeString), 1, 1) AS UP_LETTER
UNION ALL
SELECT INDICE + 1, 
       SUBSTRING(@SomeString, INDICE + 1, 1) AS RAW_LETTER, 
       SUBSTRING(UPPER(@SomeString), INDICE + 1, 1)
FROM   T0
WHERE  INDICE < LEN(@SomeString)
)
SELECT STRING_AGG(RAW_LETTER, '') WITHIN GROUP (ORDER BY INDICE)
FROM   T0
WHERE  RAW_LETTER COLLATE Latin1_General_BIN = UP_LETTER;

对于 2017 年之前的 SQL Server:

WITH T0 AS
(
SELECT 1 AS INDICE, 
       SUBSTRING(@SomeString, 1, 1) AS RAW_LETTER, 
       SUBSTRING(UPPER(@SomeString), 1, 1) AS UP_LETTER
UNION ALL
SELECT INDICE + 1, 
       SUBSTRING(@SomeString, INDICE + 1, 1) AS RAW_LETTER, 
       SUBSTRING(UPPER(@SomeString), INDICE + 1, 1)
FROM   T0
WHERE  INDICE < LEN(@SomeString)
)
SELECT STUFF((SELECT '' + RAW_LETTER
              FROM   T0
              WHERE  RAW_LETTER COLLATE Latin1_General_BIN = UP_LETTER
              ORDER BY INDICE
              FOR XML PATH('')), 1, 0, '');

【讨论】:

以上是关于从字符串中获取大写字母的主要内容,如果未能解决你的问题,请参考以下文章

从键盘获取字符,字符大小写转换

从核心数据中获取名称并将其转换为大写

如何在Javascript中获取字母表的下一个字母?

如何从 Pyspark Dataframe 中的字符串列中过滤字母值?

如何随机从数组中获取随机字符串项,并将字符串单词的每个字符随机放入li标签中

从字符串向量中获取字符