【问题标题】:SQL Return all upper case values in a columnSQL 返回列中的所有大写值
【发布时间】:2014-12-23 00:14:37
【问题描述】:

我的字段值混合了大写和小写字符。 我试图只返回大写值作为一个结果,同样只返回另一个结果中的小写值。我不是想将一个转换为另一个,只是按原样返回当前数据。

我似乎找不到执行此操作的语句,“SUBSTRING”只会返回我指定的值,即第一个和最后一个字符

例如,如果我有 AAbbCCdd 并且想要返回大写值,我需要的结果是 AACC。

【问题讨论】:

  • 在 SQL 中没有简单的方法可以做到这一点——在前端语言中有简单的方法可以做到这一点。您确定需要在服务器端执行此操作吗?
  • 我不明白你的问题。您想从单列中提取大写字母吗?还是要返回列中所有字母都是大写的值?
  • @GordonLinoff 他想提取
  • 这是一个很奇怪的要求。这种东西在现实世界中的可能用途是什么?这在 sql 中并不容易(至少不快)。
  • 你想query column 值然后在 PHP 中处理大写/小写的事情还是你想要一个为你做过滤的query

标签: sql sql-server case


【解决方案1】:

有一个功能:

CREATE FUNCTION [dbo].[GetCased](@BUFFER VARCHAR(MAX), @GETUPPER BIT) RETURNS VARCHAR(MAX) AS
BEGIN
    DECLARE @LEN INT = LEN(@BUFFER), @POS INT = 1, @CHAR CHAR(1), @RESULT VARCHAR(MAX) = ''
    WHILE @POS <= @LEN BEGIN
        SET @CHAR = SUBSTRING(@BUFFER, @POS, 1)
        SET @RESULT += CASE WHEN @CHAR COLLATE Latin1_General_CS_AS = 
            CASE WHEN @GETUPPER = 1 THEN UPPER(@CHAR) ELSE LOWER(@CHAR) END COLLATE Latin1_General_CS_AS THEN @CHAR ELSE '' END
        SET @POS += 1
    END
    RETURN @RESULT
END

... 

select
  dbo.GetCased('AAbbCCdd', 1) as 'all upper',
  dbo.GetCased('AAbbCCdd', 0) as 'all lower'

或者

CREATE FUNCTION [dbo].[fnRemovePatternFromString](@BUFFER VARCHAR(MAX), @PATTERN VARCHAR(128)) RETURNS VARCHAR(MAX) AS
BEGIN
    DECLARE @POS INT = PATINDEX(@PATTERN, @BUFFER COLLATE Latin1_General_CS_AS)
    WHILE @POS > 0 BEGIN
        SET @BUFFER = STUFF(@BUFFER, @POS, 1, '')
        SET @POS = PATINDEX(@PATTERN, @BUFFER COLLATE Latin1_General_CS_AS)
    END
    RETURN @BUFFER
END

...

select
  dbo.fnRemovePatternFromString('AAbbCCdd ', '%[ABCDEFGHIJKLMNOPQRSTUVWXYZ]%') as 'all lower'
  dbo.fnRemovePatternFromString('AAbbCCdd ', '%[abcdefghijklmnopqrstuvwxyz]%') as 'all upper'

(不能使用 [a-z])

【讨论】:

    【解决方案2】:

    这是使用函数的另一种方式:

    CREATE FUNCTION [dbo].returnUppers
        (
          @str AS varchar(Max)
        )
    RETURNS varchar(MAX)
    AS
        BEGIN
            DECLARE @len INT
            DECLARE @cc INT = 1
            DECLARE @return VARCHAR(MAX) = ''
    
            SELECT @len = LEN(@str)
    
            WHILE @len >= @cc
                BEGIN
                    IF UPPER(SUBSTRING(@str,@cc,1)) = SUBSTRING(@str,@cc,1) COLLATE sql_latin1_general_cp1_cs_as
                        SELECT @return = @return + SUBSTRING(@str,@cc,1)
                    SET @cc += 1
                END
    
            RETURN @return
        END
    GO
    

    使用方法:

    DECLARE @string VARCHAR(20) = 'AAbbCCdd'
    SELECT dbo.returnUppers(@string)
    

    返回 AACC。您需要为 lowers 编写类似的函数,只需将 UPPER() 更改为 LOWER()

    【讨论】:

      【解决方案3】:

      正如 cmets 中提到的 - 这应该在表示层中完成,而不是在 SQL 中。

      不过,这并不妨碍它变得有趣!

      关键是使用区分大小写的排序规则。在此示例中,我选择了 SQL_Latin1_General_CP1_CS_AS(“CS”=CaseSensitive。“CI”=CaseInsensitive)

      虽然解决方案涉及循环(在这种情况下为递归 CTE),但您永远不会在这种事情上获得良好的性能

      DECLARE @t table (
         a char(10)
      );
      
      INSERT INTO @t (a)
        VALUES ('AbC')
             , ('ABCDEFGHIJ')
             , ('aBCdEFghij')
             , ('AbcdefhhiJ')
             , ('ABcdEFGhij')
      ;
      
      --SELECT a
      --     , a COLLATE SQL_Latin1_General_CP1_CS_AS As case_sensitive_collation
      --     , Replace(a COLLATE SQL_Latin1_General_CP1_CS_AS, 'A', '#') As case_sensitive_replace
      --FROM   @t
      --;
      
      ; WITH characters_to_replace AS (
        SELECT number
             , Char(number) As c
             , Row_Number() OVER (ORDER BY number) As sequence
        FROM   dbo.numbers
        WHERE  number BETWEEN 1 AND 255 -- basic characters
        AND    number NOT BETWEEN 65 AND 90 -- Exclude capital A-Z
      )
      , replacements AS (
      SELECT a As original_value
           , Cast(a COLLATE SQL_Latin1_General_CP1_CS_AS As nvarchar(max)) As new_value
           , Cast(0 As bigint) As sequence
      FROM   @t
      
        UNION ALL
      
          SELECT replacements.original_value
               , Cast(Replace(replacements.new_value, characters_to_replace.c, '') As nvarchar(max))
               , characters_to_replace.sequence
          FROM   replacements
           INNER
            JOIN characters_to_replace
              ON characters_to_replace.sequence = replacements.sequence + 1
      )
      SELECT original_value
           , new_value
      FROM   replacements
      WHERE  sequence = (SELECT Max(sequence) FROM characters_to_replace)
      OPTION (MaxRecursion 255)
      ;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-12-07
        • 1970-01-01
        • 1970-01-01
        • 2018-10-28
        相关资源
        最近更新 更多