2014-12-22 70 views
2

我的字段值大小写混合。 我想只返回大写字母的值作为一个结果,同样在另一个返回小写字母的值。我不想将一个转换为另一个,只是按照原样返回当前数据。SQL返回列中的所有大写字母值

我似乎无法找到一份声明中做到这一点,“串”将只返回我指定,即第一个和最后一个字符

价值因此,举例来说,如果我有AABBCCDD并希望返回大写值,我需要的结果是AACC。

+1

在SQL中没有简单的方法来做到这一点 - 在前端语言中有很简单的方法。你确定你需要在服务器端做到这一点吗? – Hogan

+0

我不明白你的问题。你想从单个列中提取大写字母吗?或者你想要返回列中所有字母都是大写的值? –

+0

@GordonLinoff他想提取 – Hogan

回答

2

与函数:

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' 

(不能使用[AZ])

1

下面是使用功能的另一种方式:

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。您需要编写一个类似的函数,只需将UPPER()更改为LOWER()

0

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

但是,这并不能阻止它有点儿乐趣!

关键是使用区分大小写的排序规则。在这个例子中,我走了SQL_Latin1_General_CP1_ CS _As(以下简称“CS” =区分大小写。“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) 
; 
相关问题