将字符串解析为各种值

时间:2015-04-20 22:43:35

标签: sql sql-server sql-server-2008

假设您有下面的字符串,您会如何建议将其解析为各种值?每个“记录”以break标记结束。第一个值是事件名称,括号中的第二个值是帐号,下一个是票证数量,最后是支付的总价格。

Education Luncheon (501-2620) - 2 - $110<br>Womens Breakfast (512-2620) - 2 - $80<br>Friday Luncheon (502-26200) - 2 - 110<br>

2 个答案:

答案 0 :(得分:2)

我想说使用XML解析以及PARSENAMEREPLACE函数直接查询,而不使用任何UDF

假设这个字符串:

DECLARE @str VARCHAR(MAX)='Education Luncheon (501-2620) - 2 - $110<br>Womens Breakfast (512-2620) - 2 - $80<br>Friday Luncheon (502-26200) - 2 - 110<br>'

现在只需将该字符串转换为XML并在cte内解析它,最后使用提到的字符串函数:

   ;WITH cte AS(   
      SELECT Value = tbl.fld.value('(./text())[1]', 'nvarchar(4000)')            
      FROM 
      ( 
        SELECT 
            v = CONVERT(XML, '<i>' 
                + REPLACE(@str, '<br>' , '</i><i>') 
                + '</i>')
      ) AS a 
      CROSS APPLY v.nodes('i') AS tbl(fld)
      WHERE tbl.fld.value('(./text())[1]', 'nvarchar(4000)') IS NOT NULL
    )
    SELECT PARSENAME(REPLACE(Value ,'(','.'),2) AS [Event],
           PARSENAME(REPLACE(REPLACE(Value ,'(','.') ,')','.'),2)AS AccNumber,
           PARSENAME(REPLACE(Value ,'-','.'),2) AS Qty ,
           PARSENAME(REPLACE(Value ,'-','.'),1) AS Price         
    FROM cte

我们将得到此结果:

|               Event | AccNumber | Qty | Price |
|---------------------|-----------|-----|-------|
| Education Luncheon  |  501-2620 |  2  |  $110 |
|   Womens Breakfast  |  512-2620 |  2  |   $80 |
|    Friday Luncheon  | 502-26200 |  2  |   110 |

答案 1 :(得分:1)

首先创建一个分割功能。然后使用以下查询。

分割功能

CREATE FUNCTION dbo.Split
(
  @delimited nvarchar(max),
  @delimiter nvarchar(100)
) RETURNS @t TABLE
(
-- Id column can be commented out, not required for sql splitting string
  id int identity(1,1), -- I use this column for numbering splitted parts
  val nvarchar(max)
)
AS
BEGIN
  declare @xml xml
  set @xml = N'<root><r>' + replace(@delimited,@delimiter,'</r><r>') + '</r></root>'

  insert into @t(val)
  select
    r.value('.','varchar(max)') as item
  from @xml.nodes('//root/r') as records(r)

  RETURN
END
GO

测试数据&amp;查询

DECLARE @String VARCHAR(1000) = 'Education Luncheon (501-2620) - 2 - $110<br>Womens Breakfast (512-2620) - 2 - $80<br>Friday Luncheon (502-26200) - 2 - 110<br>'


SELECT LEFT(val , CHARINDEX('(', Val) -1 ) AS EventName  
      ,REPLACE( REPLACE(
           SUBSTRING(Val , CHARINDEX('(', Val) , LEN(Val) -  CHARINDEX(')', Val))
             ,'(',''),')','') AS AccountNumber
      ,REPLACE(SUBSTRING(Val, 
                CHARINDEX(') -', Val) +2,  LEN(Val) - CHARINDEX(') -', Val) 
              - CHARINDEX('-', REVERSE(Val)))
              ,'-','') AS Quantity 
     ,PARSENAME(REPLACE(Val ,'-','.'),1) AS PricePaid         
FROM dbo.Split(@String, '<br>')
WHERE NULLIF(val ,'') IS NOT NULL

结果集

╔═════════════════════╦═══════════════╦══════════╦═══════════╗
║      EventName      ║ AccountNumber ║ Quantity ║ PricePaid ║
╠═════════════════════╬═══════════════╬══════════╬═══════════╣
║ Education Luncheon  ║ 501-2620      ║       2  ║  $110     ║
║ Womens Breakfast    ║ 512-2620      ║       2  ║  $80      ║
║ Friday Luncheon     ║ 502-26200     ║       2  ║  110      ║
╚═════════════════════╩═══════════════╩══════════╩═══════════╝