Sql server 在Camelcase中添加空格,并在其中添加大写字母

Sql server 在Camelcase中添加空格,并在其中添加大写字母,sql-server,tsql,camelcasing,Sql Server,Tsql,Camelcasing,我有一个外部应用程序在camelcase中传递字符串。用户希望报告字符串,并希望将其格式化为句子。字符串中可能包含我需要在其周围添加空格的所有大写字母 基于此问题构建了一个函数: 然而,它并不适用于所有大写字母。下面是我的修改版本 DECLARE @String NVARCHAR(MAX) = 'ThisIsASentenceWithCAPTIInIt' --, @Len INT -- = LEN(@String) , @Delimite

我有一个外部应用程序在camelcase中传递字符串。用户希望报告字符串,并希望将其格式化为句子。字符串中可能包含我需要在其周围添加空格的所有大写字母

基于此问题构建了一个函数: 然而,它并不适用于所有大写字母。下面是我的修改版本


DECLARE @String    NVARCHAR(MAX) = 'ThisIsASentenceWithCAPTIInIt'
    --, @Len       INT         --  = LEN(@String)
      , @Delimiter CHAR(1)       = ' '
      , @Iterator  INT           = 2; --Don't put space to left of first even if it's a capital

WHILE @Iterator <= LEN(@String)
-- Iterate through string
    BEGIN
        -- Check if current character is Uppercase (lowercase = 0)
        IF PATINDEX('[ABCDEFGHIJKLMNOPQRSTUVWXYZ]', SUBSTRING(@String, @Iterator, 1) COLLATE Latin1_General_CS_AI) <> 0
        -- Do this if capital
            BEGIN
                -- check if the previous character is lowercase, if it is then add a space before the current character.
                IF(
                   (PATINDEX('[ABCDEFGHIJKLMNOPQRSTUVWXYZ]', SUBSTRING(@String, @Iterator - 1, 1) COLLATE Latin1_General_CS_AI) = 0
                    AND SUBSTRING(@String, @Iterator - 1, 1) <> ' '
                   )
                   OR PATINDEX('[ABCDEFGHIJKLMNOPQRSTUVWXYZ]', SUBSTRING(@String, @Iterator + 1, 1) COLLATE Latin1_General_CS_AI) = 0)
                    BEGIN
                        SET @String = STUFF(@String, @Iterator, 0, @Delimiter);
                        SET @Iterator+=1;
                END;
                -- check if the next character is lowercase, if it is then add a space before the current character.
                SET @Iterator+=1;
        END;
        ---- Don't care about current character being lowercase. Just continue iterating
        SET @Iterator+=1;
    END;

SELECT @String;
我从应用程序中获得的示例-此为CaptiInit语句

我想传回的是——这是一个有CAPTI的句子


我从修改后的版本中得到的是—这是一个带有CAPTIIn It的内容

在SQL Server中执行此操作不是最佳选择。此外,重写现有字符串可能会有些困难

我认为有更多的方法来简化这段代码,但我相信这是一个版本,它将实现您所期望的结果

DECLARE @String    NVARCHAR(MAX) = 'ThisIsASentenceWithCAPTIInIt'
    --, @Len       INT         --  = LEN(@String)
      , @Delimiter CHAR(1)       = ' '
      , @Iterator  INT           = 1; --Don't put space to left of first even if it's a capital

DECLARE @retval nvarchar(max) = '';

WHILE @Iterator <= LEN(@String)
-- Iterate through string
    BEGIN
        -- Check if current character is Uppercase (lowercase = 0)
        IF PATINDEX('[ABCDEFGHIJKLMNOPQRSTUVWXYZ]', SUBSTRING(@String, @Iterator, 1) COLLATE Latin1_General_CS_AI) <> 0
        -- Do this if capital
            BEGIN
                -- check if the previous character is lowercase, if it is then add a space before the current character.
                IF(
                   (PATINDEX('[ABCDEFGHIJKLMNOPQRSTUVWXYZ]', SUBSTRING(@String, @Iterator - 1, 1) COLLATE Latin1_General_CS_AI) = 0
                    AND SUBSTRING(@String, @Iterator - 1, 1) <> ' '
                   )
                   OR PATINDEX('[ABCDEFGHIJKLMNOPQRSTUVWXYZ]', SUBSTRING(@String, @Iterator + 1, 1) COLLATE Latin1_General_CS_AI) = 0)
                    BEGIN
                        set @retval += ' ' ;
                        --SET @String = STUFF(@String, @Iterator, 0, @Delimiter);
                        --SET @Iterator+=1;
                END;
                -- check if the next character is lowercase, if it is then add a space before the current character.
                --Set @retval += SUBSTRING(@String, @Iterator, 1);
                --SET @Iterator+=1;
            END;
        ---- Don't care about current character being lowercase. Just continue iterating
        Set @retval += SUBSTRING(@String, @Iterator, 1);
        SET @Iterator+=1;
    END;
SET @retval = Ltrim(@retval);
SELECT @retval;

在SQL Server中执行此操作不是最佳选择。此外,重写现有字符串可能会有些困难

我认为有更多的方法来简化这段代码,但我相信这是一个版本,它将实现您所期望的结果

DECLARE @String    NVARCHAR(MAX) = 'ThisIsASentenceWithCAPTIInIt'
    --, @Len       INT         --  = LEN(@String)
      , @Delimiter CHAR(1)       = ' '
      , @Iterator  INT           = 1; --Don't put space to left of first even if it's a capital

DECLARE @retval nvarchar(max) = '';

WHILE @Iterator <= LEN(@String)
-- Iterate through string
    BEGIN
        -- Check if current character is Uppercase (lowercase = 0)
        IF PATINDEX('[ABCDEFGHIJKLMNOPQRSTUVWXYZ]', SUBSTRING(@String, @Iterator, 1) COLLATE Latin1_General_CS_AI) <> 0
        -- Do this if capital
            BEGIN
                -- check if the previous character is lowercase, if it is then add a space before the current character.
                IF(
                   (PATINDEX('[ABCDEFGHIJKLMNOPQRSTUVWXYZ]', SUBSTRING(@String, @Iterator - 1, 1) COLLATE Latin1_General_CS_AI) = 0
                    AND SUBSTRING(@String, @Iterator - 1, 1) <> ' '
                   )
                   OR PATINDEX('[ABCDEFGHIJKLMNOPQRSTUVWXYZ]', SUBSTRING(@String, @Iterator + 1, 1) COLLATE Latin1_General_CS_AI) = 0)
                    BEGIN
                        set @retval += ' ' ;
                        --SET @String = STUFF(@String, @Iterator, 0, @Delimiter);
                        --SET @Iterator+=1;
                END;
                -- check if the next character is lowercase, if it is then add a space before the current character.
                --Set @retval += SUBSTRING(@String, @Iterator, 1);
                --SET @Iterator+=1;
            END;
        ---- Don't care about current character being lowercase. Just continue iterating
        Set @retval += SUBSTRING(@String, @Iterator, 1);
        SET @Iterator+=1;
    END;
SET @retval = Ltrim(@retval);
SELECT @retval;
我的建议是:

DECLARE @s VARCHAR(100)='ThisIsASentenceWithCAPTIInIt';

WITH cte AS
(
    SELECT 1 AS Position
          ,@s AS Original
          ,CAST(SUBSTRING(@s,1,1) AS VARCHAR(MAX)) AS GrowingString
    UNION ALL
    SELECT cte.Position+1
          ,cte.Original
          ,CONCAT(cte.GrowingString 
          ,CurrentLetter
          ,CASE WHEN CurrentCapit=0 AND NextCapit=1 THEN ' ' ELSE 
                CASE WHEN CurrentCapit=1 AND NextCapit=1 AND ThirdCapit=0 THEN ' ' ELSE '' END END ) AS GrowingString
    FROM cte
    CROSS APPLY(SELECT SUBSTRING(@s,cte.Position+1,1) CurrentLetter
                      ,SUBSTRING(@s,cte.Position+2,1) NextLetter
                      ,SUBSTRING(@s,cte.Position+3,1)ThirdLetter) A
    CROSS APPLY(SELECT CASE WHEN ASCII(CurrentLetter) BETWEEN 65 AND 90 THEN 1 ELSE 0 END CurrentCapit
                      ,CASE WHEN ASCII(NextLetter) BETWEEN 65 AND 90 THEN 1 ELSE 0 END NextCapit
                      ,CASE WHEN ASCII(ThirdLetter) BETWEEN 65 AND 90 THEN 1 ELSE 0 END ThirdCapit) B
    WHERE cte.Position < LEN(@s)
)
SELECT TOP 1 GrowingString
FROM cte
ORDER BY Position DESC;
简而言之:

我们使用递归CTE。这个简单的方法只需逐个字符读取字符串,并在末尾以growinString的形式返回整个字符串。这将与原始字符串相同

棘手的部分是:在哪里插入空格

如果当前字母未大写,而下一个字母大写,则需要一个空格。那是肯定的。此外,嵌入的CASE将测试当前和下一个字母是否大写,但第三个字母是否大写。在这种情况下,我们也需要空间。

这是我的建议:

DECLARE @s VARCHAR(100)='ThisIsASentenceWithCAPTIInIt';

WITH cte AS
(
    SELECT 1 AS Position
          ,@s AS Original
          ,CAST(SUBSTRING(@s,1,1) AS VARCHAR(MAX)) AS GrowingString
    UNION ALL
    SELECT cte.Position+1
          ,cte.Original
          ,CONCAT(cte.GrowingString 
          ,CurrentLetter
          ,CASE WHEN CurrentCapit=0 AND NextCapit=1 THEN ' ' ELSE 
                CASE WHEN CurrentCapit=1 AND NextCapit=1 AND ThirdCapit=0 THEN ' ' ELSE '' END END ) AS GrowingString
    FROM cte
    CROSS APPLY(SELECT SUBSTRING(@s,cte.Position+1,1) CurrentLetter
                      ,SUBSTRING(@s,cte.Position+2,1) NextLetter
                      ,SUBSTRING(@s,cte.Position+3,1)ThirdLetter) A
    CROSS APPLY(SELECT CASE WHEN ASCII(CurrentLetter) BETWEEN 65 AND 90 THEN 1 ELSE 0 END CurrentCapit
                      ,CASE WHEN ASCII(NextLetter) BETWEEN 65 AND 90 THEN 1 ELSE 0 END NextCapit
                      ,CASE WHEN ASCII(ThirdLetter) BETWEEN 65 AND 90 THEN 1 ELSE 0 END ThirdCapit) B
    WHERE cte.Position < LEN(@s)
)
SELECT TOP 1 GrowingString
FROM cte
ORDER BY Position DESC;
简而言之:

我们使用递归CTE。这个简单的方法只需逐个字符读取字符串,并在末尾以growinString的形式返回整个字符串。这将与原始字符串相同

棘手的部分是:在哪里插入空格


如果当前字母未大写,而下一个字母大写,则需要一个空格。那是肯定的。此外,嵌入的CASE将测试当前和下一个字母是否大写,但第三个字母是否大写。在这种情况下,我们也需要空间。

在我看来,SQL Server并不是最好的选择。您最好使用CLR或应用程序来执行此操作。此外,发布您的SQL Server版本也是值得的。在我看来,SQL Server并不是最佳选择。您最好使用CLR或应用程序来执行此操作。此外,发布您的SQL Server版本也是值得的。与我所做的相比,这是非常有效的。谢谢与我所做的相比,这是非常有效的。谢谢