2017-03-17 48 views
0

我寫大致具有這種結構的查詢:如何通過遍歷字符串在一行中的SQL

SELECT Name, <calculated-valued> as Version FROM <tables> 

這個計算出來的值需要像這樣的工作:我有一個VARCHAR列「名稱」是可能包含'ABC'之類的東西,我想將每個字母轉換爲ASCII,並將它們附加在一起形成'65 .66.67'。 (一個空字符串應該返回'0')有沒有辦法做到這一點?

我的方法是不是很好,但超過5個字符,我可以做到以下幾點:

SELECT 
CASE WHEN LEN(Name) = 0 THEN '0' 
ELSE CAST(ASCII(SUBSTRING(Name, 1, 1)) as varchar(max)) + 
    CASE WHEN LEN(Name) = 1 THEN '' 
    ELSE '.' + CAST(ASCII(SUBSTRING(Name, 2, 1)) as varchar(max)) + 
     CASE WHEN LEN(Name) = 2 THEN '' 
     ELSE '.' + CAST(ASCII(SUBSTRING(Name, 3, 1)) as varchar(max)) + 
      CASE WHEN LEN(Name) = 3 THEN '' 
      ELSE '.' + CAST(ASCII(SUBSTRING(Name, 4, 1)) as varchar(max)) + 
       CASE WHEN LEN(Name) = 4 THEN '' 
       ELSE '.' + CAST(ASCII(SUBSTRING(Name, 5, 1)) as varchar(max)) 
       END 
      END 
     END 
    END 
END AS MyColumn 
FROM <tables> 

有沒有更好的方式來做到這一點?理想情況下,可以採取任何長度的字符串的方法?

要麼我可以將字母轉換爲hierarchyid數據類型?我需要創建諸如1/2/a/bc/4的東西//或其他,但是hierarchyid不支持。因此,我試圖將其轉換爲1/2/97/98.99/4/0,以便我可以轉換並保持正確的順序。此列僅用於排序。

感謝您的幫助!

+0

我會建議爲此,您在用戶定義的函數中使用'WHILE'循環。 –

回答

0

一種方法是遞歸CTE:

with cte as (
     select Name, 1 as lev 
      cast(ascii(substring(name, 1, 1)) as varchar(max)) as ascii_name 
     from t 
     union all 
     select Name, lev + 1, 
      ascii_name + '.' + cast(ascii(substring(name, lev + 1, 1)) as varchar(max)) 
     from cte 
     where len(Name) > lev 
    ) 
select Name, ascii_name 
from cte; 
0

另一種選擇是一個特設的理貨表和CROSS APPLY

Declare @YourTable table (Name varchar(25)) 
Insert Into @YourTable values 
('ABC'), 
('Jack'), 
('Jill'), 
('') 

Select A.Name 
     ,Version = isnull(B.String,'0') 
From @YourTable A 
Cross Apply (
       Select String=Stuff((Select '.' +cast(S as varchar(5)) 
             From (Select Top (len(A.Name)) 
                S=ASCII(substring(A.Name,Row_Number() Over (Order By (Select NULL)),1)) 
              From master..spt_values) S 
             For XML Path ('')),1,1,'') 
      ) B 

返回

Name String 
ABC  65.66.67 
Jack 74.97.99.107 
Jill 74.105.108.108 
     0