2013-07-05 73 views
0

我有一個字符串,它是一個命令行選項。比方說,這是使用TSQL解析命令行選項

/server:server1.mydomain.com /用戶名:用戶1 /密碼: 「我的密碼」 /其他 「AA/BB \」 CC」

我需要解析它使用TSQL並得到以下結果:

+----------+----------------------+ 
| Key  | Value    | 
+----------+----------------------+ 
| server | server1.mydomain.com | 
| username | user1    | 
| password | my password   | 
| other | aa /bb "cc   | 
+----------+----------------------+ 

我知道TSQL是一種數據庫語言,並在這樣的任務確實不夠好,但我只是想它可能TSQL沒有內置的正則表達式。支持,很難完成這項任務,任何人都可以試一試嗎?漢克斯。

DECLARE @options NVARCHAR(MAX); 
SELECT @options = N'/server:server1.mydomain.com /username:user1 /password:"my password" /other:"aa /bb \"cc"'; 

IF OBJECT_ID('dbo.store', N'U') IS NOT NULL DROP TABLE dbo.store; 
CREATE TABLE dbo.store 
(
    key NVARCHAR(MAX), 
    value NVARCHAR(MAX) 
) 

// This is the result I want 
// +----------+----------------------+ 
// | Key  | Value    | 
// +----------+----------------------+ 
// | server | server1.mydomain.com | 
// | username | user1    | 
// | password | my password   | 
// | other | aa /bb "cc   | 
// +----------+----------------------+ 
+0

如果命令行總是看起來相同,則應該很容易使用子字符串和len函數進行解析。如果我沒有在手機上瀏覽,我會爲你寫信:) – jpw

+0

謝謝jpw。命令行不固定。代碼中的字符串就是一個例子。 – user133580

回答

2

你可以做一些

USE [DEI] 
GO 
/****** Object: UserDefinedFunction [dbo].[fnSplit] Script Date: 07/06/2013 00:00:35 ******/ 
SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 
create FUNCTION [dbo].[fnSplit](
    @sInputList VARCHAR(8000) -- List of delimited items 
    , @sDelimiter VARCHAR(8000) = ',' -- delimiter that separates items 
) RETURNS @List TABLE (item VARCHAR(8000)) 

BEGIN 
DECLARE @sItem VARCHAR(8000) 
WHILE CHARINDEX(@sDelimiter,@sInputList,0) <> 0 
BEGIN 
    SELECT 
    @sItem=RTRIM(LTRIM(SUBSTRING(@sInputList,1,CHARINDEX(@sDelimiter,@sInputList,0)-1))), 
    @sInputList=RTRIM(LTRIM(SUBSTRING(@sInputList,CHARINDEX(@sDelimiter,@sInputList,0)+LEN(@sDelimiter),LEN(@sInputList)))) 

IF LEN(@sItem) > 0 
INSERT INTO @List SELECT @sItem 
END 

IF LEN(@sInputList) > 0 
INSERT INTO @List SELECT @sInputList -- Put the last item in 
RETURN 
END 

然後嘗試以下查詢:

DECLARE @options NVARCHAR(MAX); 
SELECT @options = N'/server:server1.mydomain.com /username:user1 /password:"my password" /other:"aa /bb \"cc"'; 


DECLARE @temp NVARCHAR(MAX); 

set @temp = (SELECT REPLACE(REPLACE(REPLACE(REPLACE(@options,'/SERVER:' , '&&&&') , '/username:' , '&&&&'),'/password:' , '&&&&') , '/other:' , '&&&&')) 

SELECT 
case 
when row_number() over(order by getdate()) = 1 then 'server' 
when row_number() over(order by getdate()) = 2 then 'username' 
when row_number() over(order by getdate()) = 3 then 'password' 
when row_number() over(order by getdate()) = 4 then 'other' 
end, * 
FROM fnsplit(@temp , '&&&&') as a 
+0

對你有幫助嗎? –

+0

感謝您的答案。但是,您的解決方案取決於事先知道選項的事實。事實上,這些信息現在是事先知道的。 – user133580

+0

服務器,用戶名,密碼等僅僅是例子。實際項目不固定。 – user133580

0

試試這個

SQL Fiddle Demo

DECLARE @options NVARCHAR(MAX) = '/server:server1.mydomain.com /username:user1 /password:"my password" /other:"aa /bb \"cc"' 
    ,@str NVARCHAR(MAX) 

WHILE LEN(@options) > 0 
BEGIN 
    IF LEN(@options) - LEN(REPLACE(@options,':','')) >= 2 
     BEGIN 
      SELECT @str = REVERSE(LEFT(@options, CHARINDEX(':', @options,CHARINDEX(':', @options)+ 1))) 
      SELECT @str = REVERSE(SUBSTRING(@str,CHARINDEX(' ',@str) + 1, LEN(@str))) 
     END 
    ELSE 
     SET @str = @options 

    INSERT INTO store ([key],[value]) 
    SELECT [email protected] AS str 
     SUBSTRING(@str, 2, CHARINDEX(':', @str) - 2) as [key] 
     ,RIGHT(@str, LEN(@str) - CHARINDEX(':',@str)) as [value] 
    SET @options = LTRIM(SUBSTRING(@options,LEN(@str) + 1, LEN(@options)) ) 
END 

SELECT * from store 
+0

感謝Eric的回答,但是你的解決方案依賴於字符串中的「:」,如果字符串中有一些「:」,那麼你的解決方案就會中斷。 – user133580