2014-12-22 32 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) 
; 
相關問題