1

我需要編寫一個存儲過程,其輸入是一個字符串。解析字符串的存儲過程

輸入字符串包含變量名稱和它們的值由管道分隔符這樣的分離:

Name =Praveen | City=Hyderabad | Mobile=48629387429| Role=User| etc 

在存儲過程中我已聲明的變量,比如@x, @y, @z, @t獲得值

@x=Praveen (Name value) 
@y=Hyderabad (City Value) 
@z=48629387429(Mobile Value) 
@t=User(Role Value) 

而且輸入字符串可以具有任意順序的值,如

City=Hyderabad | Mobile=48629387429 | Role=User | Name =Praveen |etc 

一旦我將這些值解析爲@x, @y, @z, @t等,我必須在存儲過程中使用這些值。

請讓我如何解析輸入字符串,分別獲得Name, City, Mobile, Role的值爲@x, @y, @z@t

+0

用4個參數代替1會容易得多 – Soader03 2012-04-05 18:56:03

+0

我試圖用CHARINDEX,SUBSTRING等函數來解析字符串,但無法弄清楚邏輯。 – user1316031 2012-04-05 19:42:44

回答

4

一個POS sible的解決方案是使用XML

DECLARE @text VARCHAR(1000) 
     ,@xml xml 

SELECT @text = 'City=Hyderabad | Mobile=48629387429 | Role=User | Name =Praveen' 

SELECT @text = REPLACE(@text,'|','"') 
    ,@text = REPLACE(@text,'=','="') 
    ,@text = '<row ' + @text + '"/>' 

SELECT @xml = CAST(@text AS XML) 

select 
    line.col.value('@Name[1]', 'varchar(100)') AS Name 
    ,line.col.value('@City[1]', 'varchar(100)') AS City 
    ,line.col.value('@Mobile[1]', 'varchar(100)') AS Mobile 
    ,line.col.value('@Role[1]', 'varchar(100)') AS Role 
FROM @xml.nodes('/row') AS line(col) 
+1

+1。 XML是將一串鍵/值對傳遞給SQL Server的更簡潔的方法之一。 – 2012-04-05 20:14:45

+0

爲什麼大家都跳轉到在恰好支持XML的關係數據庫中轉換爲XML? – 2012-04-05 20:25:22

+3

對我來說,這是一個非常簡單的解決方案,理想情況下,您的關係數據庫不應該被迫去做。 – 2012-04-05 20:27:27

0

假設您的輸入參數被稱爲@Text。

DECLARE @Text varchar(255), 
    @x varchar(255) 

SET @Text = 'Name=Praveen | City=Hyderabad | Mobile=48629387429| Role=User' 

-- Added to show how to account for non-trailing | 
SET @Text = @Text + ' | '; 

SET @x = LTRIM(RTRIM(substring(
     @Text, 
     charindex('Name=', @Text) + LEN('Name='), 
     charindex(' | ', @Text, charindex('Name=', @Text)) - LEN('Name=') 
     ))) 

SELECT @x 

然後只需對@y,@z,@t重複此操作即可將Name =更改爲任何您的休息時間。

+0

嗨Michael感謝您的解決方案在輸入字符串中,最後一個參數不會以|例如:'Name = Praveen |城市=海得拉巴|手機= 48629387429 | Role = User'在這種情況下,代碼在最後一個參數中失敗。因爲沒有|爲字符串中的最後一個變量定界。我們該如何處理? – user1316031 2012-04-05 19:57:44

+0

更新,看看。 – 2012-04-05 20:24:10

0

我絕對推薦你在程序端進行字符串解析,而不是數據端。話雖這麼說,如果你絕對必須,你可以嘗試做一些與此類似:

DECLARE @String [nvarchar](256) = 'Name=Praveen | City=Hyderabad | Mobile=48629387429 | Role=User |' 

DECLARE @name [nvarchar](256) = (SELECT SUBSTRING(@String, CHARINDEX('Name=', @String)+5, CHARINDEX('|', @String))) 

DECLARE @city [nvarchar](256) = (SELECT SUBSTRING(@String, CHARINDEX('City=', @String)+5, CHARINDEX('|', @String))) 

DECLARE @mobile [nvarchar](256) = (SELECT SUBSTRING(@String, CHARINDEX('Mobile=', @String)+7, CHARINDEX('|', @String))) 

DECLARE @role [nvarchar](256) = (SELECT SUBSTRING(@String, CHARINDEX('Role=', @String)+5, CHARINDEX('|', @String))) 

SELECT RTRIM(LTRIM(LEFT(@name, CHARINDEX('|', @name)-1))) AS Name, 
     RTRIM(LTRIM(LEFT(@city, CHARINDEX('|', @city)-1))) AS City, 
     RTRIM(LTRIM(LEFT(@mobile, CHARINDEX('|', @mobile)-1))) AS Mobile, 
     RTRIM(LTRIM(LEFT(@role, CHARINDEX('|', @role)-1))) AS Role 

這將返回:

Name | City  | Mobile  | Role 
________________________________________________ 
Praveen | Hyderabad | 48629387429 | User 

注意,長度爲addedfrom在初始查詢CHARINDEX等於搜索字符串。

「名稱=」等於5個字符,所以我們添加5移動索引過去等號(=), 「移動=」等於7,所以我們到底SELECT添加7.

同樣查詢我們從每個CHARINDEX減去1以除去|符號。

來源:

SUBSTRING

CHARINDEX

LEFT

LTRIM

RTRIM

+0

嗨jon3laze,非常感謝您的解決方案!在輸入字符串中,最後一個參數不以|結尾例如:'Name = Praveen |城市=海得拉巴|手機= 48629387429 | Role = User'在這種情況下,代碼在最後一個參數中失敗。因爲沒有|爲字符串中的最後一個變量定界。我們該如何處理? – user1316031 2012-04-05 19:54:30

0

這是一個使用循環進行字符串操作的有趣方法。請注意我們如何定義我們的@x,@y等變量來獲取特定值。

-- Simulate proc parameter 
declare @input nvarchar(max) = 'Name =Praveen | City=Hyderabad | Mobile=48629387429| Role=User' 

-- OP's preferred destination vars 
declare @x nvarchar(max) = 'Name' 
declare @y nvarchar(max) = 'City' 
declare @z nvarchar(max) = 'Mobile' 
declare @t nvarchar(max) = 'Role' 

-- The key/value delimiters we are expecting 
declare @recordDelim nchar(1) = '|' 
declare @valueDelim nchar(1) = '=' 

-- Temp storage 
declare @inputTable table (
     name nvarchar(128) not null primary key 
    , value nvarchar(max) null 
) 

-- Get all key/value pairs 
while ltrim(rtrim(@input)) != '' begin 
    insert into @inputTable (name) select ltrim(rtrim(replace(left(@input, isnull(nullif(charindex(@recordDelim, @input), 0), len(@input))), @recordDelim, ''))) 
    select @input = ltrim(rtrim(right(@input, len(@input) - isnull(nullif(charindex(@recordDelim, @input), 0), len(@input))))) 
end 

-- Separate keys and values 
update @inputTable 
set name = ltrim(rtrim(left(name, isnull(nullif(charindex(@valueDelim, name) - 1, 0), len(name))))) 
    , value = ltrim(rtrim(right(name, len(name) - isnull(nullif(charindex(@valueDelim, name), 0), len(name))))) 

-- Populate the variables 
-- If any are null, then this key/value wasn't present 
set @x = (select value from @inputTable where name = @x) 
set @y = (select value from @inputTable where name = @y) 
set @z = (select value from @inputTable where name = @z) 
set @t = (select value from @inputTable where name = @t) 

此外,從您輸入的不規則間隔,我猜你要修剪的一切在未來(這就是爲什麼這個PROC確實是所有的地方)。