2014-10-27 28 views
3

我在表格中的一列中有下面的數據。在SQL服務器中獲取小寫數據

john;144;ny; 
Nelson;154;NY; 
john;144;NC; 
john;144;kw; 

我想找回這 ,所以我需要得到

john;144;kw; 
john;144;ny; 

可以得到這樣的數據的數據的第三部分已經小寫行?

+2

我必須同意[Marc's comment below](http://stackoverflow.com/questions/26592015/get-lowercase-data-in-sql-server#comment41799236_26592147) - 你爲什麼要以這種方式存儲數據?這些信息顯然是分開的,因此請修復設計並將它們存儲在單獨的列中。 – 2014-10-27 16:33:22

+0

但它是記錄,已經有20k條記錄 – Abhiram 2014-10-27 16:38:56

+0

假設你的列被稱爲'數據',那麼以下內容將提取第二個分號後的所有內容:'SUBSTRING(Data,1 + CHARINDEX(';',Data,CHARINDEX (';',Data)+ 1),LEN(Data))' - 我不得不同意Aaron和Marc,儘管如此,如果您經常需要將數據作爲連接字符串添加計算結果將三列連接在一起的列。從長遠來看,一次分離數據的價值將遠遠超過它。 – GarethD 2014-10-27 16:43:39

回答

2

這並沒有真正回答你的問題,這當然增加了什麼馬克現有的答案條款解決您的實際問題,它僅僅是爲了演示如何簡單地更正您的設計(整個腳本在本地快速SQL Server 2012實例中運行大約一秒鐘)。

CREATE TABLE dbo.T 
(
    ThreePartData VARCHAR(60) 
); 

-- INSERT 20,000 ROWS 
INSERT dbo.T (ThreePartData) 
SELECT t.ThreePartName 
FROM (VALUES ('john;144;ny;'), ('Nelson;154;NY;'), ('john;144;NC;'), ('john;144;kw;')) t (ThreePartName) 
     CROSS JOIN 
     ( SELECT TOP (5000) Number = 1 
      FROM sys.all_objects a 
        CROSS APPLY sys.all_objects b 
     ) n; 
GO 

-- HERE IS WHERE THE CHANGES START 
/**********************************************************************/ 
-- ADD A COLUMN FOR EACH COMPONENT 
ALTER TABLE dbo.T ADD PartOne VARCHAR(20), 
        PartTwo VARCHAR(20), 
        PartThree VARCHAR(20); 
GO 
-- UPDATE THE PARTS WITH THEIR CORRESPONDING COMPONENT 
UPDATE dbo.T 
SET  PartOne = PARSENAME(REPLACE(ThreePartData, ';', '.') + 't', 4), 
     PartTwo = PARSENAME(REPLACE(ThreePartData, ';', '.') + 't', 3), 
     PartThree = PARSENAME(REPLACE(ThreePartData, ';', '.') + 't', 2); 
GO 

-- GET RID OF CURRENT COLUMN 
ALTER TABLE dbo.T DROP COLUMN ThreePartData; 
GO 

-- CREATE A NEW COMPUTED COLUMN THAT REBUILDS THE CONCATENATED STRING 
ALTER TABLE dbo.T ADD ThreePartData AS CONCAT(PartOne, ';', PartTwo, ';', PartThree, ';'); 
GO 

-- OR FOR VERSIONS BEFORE 2012 
--ALTER TABLE dbo.T ADD ThreePartData AS PartOne + ';' + PartTwo + ';' + PartThree + ';'; 

然後將查詢很簡單,只要:

SELECT * 
FROM T 
WHERE LOWER(PartThree) = PartThree COLLATE Latin1_General_CS_AS; 

既然你已經重新創建具有相同名稱的計算列,使用任何select語句也不會受到影響,但更新和插入會需要尋址。

5

強制區分大小寫的匹配,然後強制小寫比較原始的:

SELECT ... 
FROM .. 
WHERE LOWER(name) = name COLLATE Latin1_General_CS_AS 
               ^^---case sensitive 

如果名字是所有下部下手,然後LOWER()將不會改變它,你會得到一場比賽。如果它是類似於John,那麼你會做john = John,並且區分大小寫將會使比賽失敗。

+0

謝謝如何比較小寫字母的第三部分? – Abhiram 2014-10-27 16:27:58

+2

使用字符串操作來提取該部分,然後使用較低/區分大小寫的東西。你真的應該正常化你的設計,因爲你現在顯然已經沒有這樣做了。從不在單個字段中存儲多個獨立的數據位,特別是當您需要分別訪問這些位時。 – 2014-10-27 16:30:16

+0

@Abhiram是否有任何約束確保數據總是以's1; s2; s3;'的形式出現?從來沒有's1; s2; s3; s4;'或's1; s2;'或者完全缺少分號? – 2014-10-27 16:30:30

0

使用BINARY_CHECKSUM我們可以檢索已小寫行或大寫

CREATE TABLE #test 
    (
    NAME VARCHAR(50) 
) 

INSERT INTO #test 
VALUES  ('john;144;ny;'), 
      ('Nelson;154;NY;'), 
      ('john;144;NC;'), 
      ('john;144;kw;') 

SELECT * 
FROM #test 
WHERE Binary_checksum(NAME) = Binary_checksum(Lower(NAME)) 

輸出

name 
----------- 
john;144;ny; 
john;144;kw;