SQL Server:String Manipulation,Unpivoting

时间:2010-03-24 19:22:49

标签: sql sql-server sql-server-2005 tsql

我有一个名为body的列,其中包含CMS的正文内容。数据如下:

  

... {斗篷:ID = 1.1.1} ... {斗篷} ... {斗篷:ID = 1.1.2} ... {斗篷} ... {斗篷:ID = 1.1.3 } ... {斗篷} ...

对于可读性示例进行了适度调整:

## h5. A formal process for approving and testing all external network connections and changes to the firewall and router configurations? 
{toggle-cloak:id=1.1.1}{tree-plus-icon} *Compliance:* {color:red}{*}Partial{*}{color} (?) 
{cloak:id=1.1.1} || Date: | 2010-03-15 || || Owner: | Brian || || Researched by: | || || Narrative: | Jira tickets are normally used to approve and track network changes\\ || || Artifacts: | Jira.bccampus.ca\\ || || Recommendation: | Need to update policy that no Jira = no change\\ || || Proposed Remedy(ies): | || || Approved Remedy(ies): | || || Date: | || || Reviewed by: | || || Remarks/comments: | || 
{cloak}## h5. Current network diagrams with all connections to cardholder data, including any wireless networks? 
{toggle-cloak:id=1.1.2}{tree-plus-icon} *Compliance:* {color:red}{*}TBD{*}{color} (?) 
{cloak:id=1.1.2}

我想以下列格式获取披风值:

 requirement_num
 -----------------
 1.1.1
 1.1.2
 1.1.3

我正在考虑使用UNIONs - 有没有人有更好的推荐?

忘记提及:

  • 我无法使用正则表达式,因为数据库上未启用CLR。
  • 这些数字不是连续的。目前的记录从1.1.6跃升至1.2.1
  • 我可以保证每个要求号都有一对 - {toggle-cloak:id=x.y.z}{cloak:id=x.y.z}。我对{cloak:id=x.y.z}{cloak}标记之间的内容感兴趣。

2 个答案:

答案 0 :(得分:2)

我可能会使用一个函数。类似的东西:

create function [dbo].[getCloaks]
(
@String     varchar(8000)
)
returns @tbl table (s varchar(1000))
as
begin
declare @i int, @j int, @k int
    select  @i = 1
    while charindex('{cloak:id=', @String, @i) > 0
    begin
        select @j = charindex('{cloak:id=', @String, @i)
        select @k = charindex('}', @String, @j)
        insert  @tbl select substring(@String, @j + 10, @k - @j - 10)
        select  @i = @k + 1
    end
    return
end

答案 1 :(得分:1)

这是一个递归的CTE版本,希望比迭代的UDF快一点:

DECLARE @Data nvarchar(1000)

SET @Data = N'...{cloak:id=1.1.1}...{cloak}...{cloak:id=1.1.2}...{cloak}...' +
            N'{cloak:id=1.1.3}...{cloak}...'

;WITH Cloak_CTE AS
(
    SELECT
        CAST(NULL AS nvarchar(50)) AS requirement_num,
        CHARINDEX('{cloak:id=', @Data) AS start_index,
        CHARINDEX('}', @Data, CHARINDEX('{cloak:id=', @Data)) AS end_index

    UNION ALL

    SELECT
        CAST(SUBSTRING(@Data, start_index + 10,
            end_index - start_index - 10) AS nvarchar(50)),
        CHARINDEX('{cloak:id=', @Data, end_index + 1),
        CHARINDEX('}', @Data, CHARINDEX('{cloak:id=', @Data, end_index + 1))
    FROM Cloak_CTE
    WHERE start_index > 0
)
SELECT requirement_num
FROM Cloak_CTE
WHERE requirement_num IS NOT NULL

调整多行或不同模式应该相对简单,或者将其放入内联UDF中。