代码之家  ›  专栏  ›  技术社区  ›  SherlockSpreadsheets

SQL查询-ntext查询(用于节点、子字符串)

  •  2
  • SherlockSpreadsheets  · 技术社区  · 6 年前

    我正在查询ReportServer数据库,其中SSRS元数据存储在名为 Subscriptions.ExtensionSettings 数据类型 NTEXT . 数据值看起来像XML样式的文本 [Name] and [Value] tags 例如: <Name>TO</Name> <Name>CC</Name> , <Name>RenderFormat</Name> ,和 <Value>Some text data here</Value>

    是否有一个SELECT语句可以查询NTEXT字段来提取 为每个记录分别输出字段值--[TO]、[CC]、[RenderFormat]?

    在寻找这个答案的过程中,我看了以下帖子: SQL Query: Grouping by an ntext field ntext/text/image datatypes in SQL server 2016 CTP 3

    示例数据。。。

    DECLARE @TableData as table (
        DeliveryExtension nvarchar(260), ExtensionSettings ntext
        )
    
    INSERT INTO @TableData VALUES
        ('Report Server Email', '<ParameterValues><ParameterValue><Name>TO</Name><Value>name.one@companyinc.com; name.two@companyinc.com; name.3@companyinc.com</Value></ParameterValue><ParameterValue><Name>CC</Name><Value>name.four@companyinc.com; name.five@companyinc.com</Value></ParameterValue><ParameterValue><Name>IncludeReport</Name><Value>True</Value></ParameterValue><ParameterValue><Name>RenderFormat</Name><Value>EXCELOPENXML</Value></ParameterValue><ParameterValue><Name>Subject</Name><Value>@ReportName was executed at @ExecutionTime</Value></ParameterValue><ParameterValue><Name>Comment</Name><Value>Any undefined category is currently being addressed.</Value></ParameterValue><ParameterValue><Name>IncludeLink</Name><Value>False</Value></ParameterValue><ParameterValue><Name>Priority</Name><Value>NORMAL</Value></ParameterValue></ParameterValues>')
        ,('Report Server Email', '<ParameterValues><ParameterValue><Name>TO</Name><Value>name.one@companyinc.com; name.two@companyinc.com</Value></ParameterValue><ParameterValue><Name>CC</Name><Value>name.three@companyinc.com</Value></ParameterValue><ParameterValue><Name>IncludeReport</Name><Value>True</Value></ParameterValue><ParameterValue><Name>RenderFormat</Name><Value>EXCELOPENXML</Value></ParameterValue><ParameterValue><Name>Subject</Name><Value>@ReportName was executed at @ExecutionTime</Value></ParameterValue><ParameterValue><Name>Comment</Name><Value>@ReportName
    
    If there any issues with this report please open a ticket for Reporting Services Portal support.</Value></ParameterValue><ParameterValue><Name>IncludeLink</Name><Value>False</Value></ParameterValue><ParameterValue><Name>Priority</Name><Value>NORMAL</Value></ParameterValue></ParameterValues>')
        ,('Report Server FileShare', '<ParameterValues><ParameterValue><Name>PATH</Name><Value>\\network1234\c$\temp</Value></ParameterValue><ParameterValue><Name>FILENAME</Name><Value>AE Points Report</Value></ParameterValue><ParameterValue><Name>FILEEXTN</Name><Value>True</Value></ParameterValue><ParameterValue><Name>USERNAME</Name><Value>OCSgOkfVICihDFLe9g/oVGCa86jtJJLh2vqiuOYEvtYL1kudnJ6RuGqXlMpxqDz9</Value></ParameterValue><ParameterValue><Name>PASSWORD</Name><Value>f0zrUzblRan6Q9h9iW8FwevA9UKSo3guHz79rx3XG9i+OdAj3LxLaf659MJT0ZjE</Value></ParameterValue><ParameterValue><Name>RENDER_FORMAT</Name><Value>EXCELOPENXML</Value></ParameterValue><ParameterValue><Name>WRITEMODE</Name><Value>Overwrite</Value></ParameterValue><ParameterValue><Name>DEFAULTCREDENTIALS</Name><Value>False</Value></ParameterValue></ParameterValues>')
    
    
    select 
        DeliveryExtension 
        , ExtensionSettings
    from @TableData
    

    期望的结果。。。

    +-------------------------+--------------------------------------------------+----------------------------+--------------+
    | DeliveryExtension       | TO                                               | CC                         | RenderFormat |
    +-------------------------+--------------------------------------------------+----------------------------+--------------+
    | Report Server Email     | name.one@companyinc.com;                         | name.four@companyinc.com;  | EXCELOPENXML |
    |                         |   name.two@companyinc.com; name.3@companyinc.com |   name.five@companyinc.com |              |
    +-------------------------+--------------------------------------------------+----------------------------+--------------+
    | Report Server Email     | name.one@companyinc.com;                         | name.three@companyinc.com  | EXCELOPENXML |
    |                         |   name.two@companyinc.com                        |                            |              |
    +-------------------------+--------------------------------------------------+----------------------------+--------------+
    | Report Server FileShare |                                                  |                            | PDF          |
    +-------------------------+--------------------------------------------------+----------------------------+--------------+
    
    2 回复  |  直到 6 年前
        1
  •  1
  •   Hannover Fist    6 年前

    我知道怎么用 XQuery

    我必须将扩展类型列更改为XML。

    DECLARE @TableData as table (
        DeliveryExtension nvarchar(260), ExtensionSettings xml
        )
    
    INSERT INTO @TableData VALUES
        ('Report Server Email', '<ParameterValues><ParameterValue><Name>TO</Name><Value>name.one@companyinc.com; name.two@companyinc.com; name.3@companyinc.com</Value></ParameterValue><ParameterValue><Name>CC</Name><Value>name.four@companyinc.com; name.five@companyinc.com</Value></ParameterValue><ParameterValue><Name>IncludeReport</Name><Value>True</Value></ParameterValue><ParameterValue><Name>RenderFormat</Name><Value>EXCELOPENXML</Value></ParameterValue><ParameterValue><Name>Subject</Name><Value>@ReportName was executed at @ExecutionTime</Value></ParameterValue><ParameterValue><Name>Comment</Name><Value>Any undefined category is currently being addressed.</Value></ParameterValue><ParameterValue><Name>IncludeLink</Name><Value>False</Value></ParameterValue><ParameterValue><Name>Priority</Name><Value>NORMAL</Value></ParameterValue></ParameterValues>')
        ,('Report Server Email', '<ParameterValues><ParameterValue><Name>TO</Name><Value>name.one@companyinc.com; name.two@companyinc.com</Value></ParameterValue><ParameterValue><Name>CC</Name><Value>name.three@companyinc.com</Value></ParameterValue><ParameterValue><Name>IncludeReport</Name><Value>True</Value></ParameterValue><ParameterValue><Name>RenderFormat</Name><Value>EXCELOPENXML</Value></ParameterValue><ParameterValue><Name>Subject</Name><Value>@ReportName was executed at @ExecutionTime</Value></ParameterValue><ParameterValue><Name>Comment</Name><Value>@ReportName
    
    If there any issues with this report please open a ticket for Reporting Services Portal support.</Value></ParameterValue><ParameterValue><Name>IncludeLink</Name><Value>False</Value></ParameterValue><ParameterValue><Name>Priority</Name><Value>NORMAL</Value></ParameterValue></ParameterValues>')
        ,('Report Server FileShare', '<ParameterValues><ParameterValue><Name>PATH</Name><Value>\\network1234\c$\temp</Value></ParameterValue><ParameterValue><Name>FILENAME</Name><Value>AE Points Report</Value></ParameterValue><ParameterValue><Name>FILEEXTN</Name><Value>True</Value></ParameterValue><ParameterValue><Name>USERNAME</Name><Value>OCSgOkfVICihDFLe9g/oVGCa86jtJJLh2vqiuOYEvtYL1kudnJ6RuGqXlMpxqDz9</Value></ParameterValue><ParameterValue><Name>PASSWORD</Name><Value>f0zrUzblRan6Q9h9iW8FwevA9UKSo3guHz79rx3XG9i+OdAj3LxLaf659MJT0ZjE</Value></ParameterValue><ParameterValue><Name>RENDER_FORMAT</Name><Value>EXCELOPENXML</Value></ParameterValue><ParameterValue><Name>WRITEMODE</Name><Value>Overwrite</Value></ParameterValue><ParameterValue><Name>DEFAULTCREDENTIALS</Name><Value>False</Value></ParameterValue></ParameterValues>')
    
    
    select 
        ExtensionSettings ,
        ExtensionSettings.value(N'(/ParameterValues/ParameterValue[Name="TO"]/Value)[1]', 'varchar(250)') TO_,
        ExtensionSettings.value(N'(/ParameterValues/ParameterValue[Name="CC"]/Value)[1]', 'varchar(250)') CC,
        ExtensionSettings.value(N'(/ParameterValues/ParameterValue[Name="RenderFormat"]/Value)[1]', 'varchar(250)') RenderFormat
    from @TableData 
    
        2
  •  0
  •   S3S    6 年前

    Here is the Fiddle

    ;with cte as(
    select 
        DeliveryExtension 
        , ExtensionSettings
        , x.ItemNumber
        , x.Item
    from @TableData
    cross apply dbo.DelimitedSplit8K(replace(replace(replace(replace(replace(cast(ExtensionSettings as varchar(max)),'<ParameterValue>',''),'</ParameterValue>',''),'<ParameterValues>',''),'</Name>',''),'</Value>',''),'<Name>') x
    where x.Item != '')
    
    select 
        c.DeliveryExtension
        ,[TO] = max(replace(t.Item,'Value>',''))
        ,[CC] = max(replace(cc.Item,'Value>',''))
        ,[Format] = max(replace(form.Item,'Value>',''))
    from cte c
    left join cte t on 
        t.ItemNumber = c.ItemNumber + 1
        and cast(c.ExtensionSettings as varchar(max)) = cast(t.ExtensionSettings as varchar(max))
        and c.Item = 'Name>TO'
    left join cte cc on 
        cc.ItemNumber = c.ItemNumber + 1
        and cast(c.ExtensionSettings as varchar(max)) = cast(cc.ExtensionSettings as varchar(max))
        and c.Item = 'Name>CC'
    left join cte form on 
        form.ItemNumber = c.ItemNumber + 1
        and cast(c.ExtensionSettings as varchar(max)) = cast(form.ExtensionSettings as varchar(max))
        and c.Item in ('Name>RenderFormat','Name>RENDER_FORMAT')
    group by
        c.DeliveryExtension, cast(c.ExtensionSettings as varchar(max))
    

    它依赖于拆分器功能。这是我用过的

    CREATE FUNCTION [dbo].[DelimitedSplit8K] (@pString VARCHAR(8000), @pDelimiter CHAR(1))
    --WARNING!!! DO NOT USE MAX DATA-TYPES HERE!  IT WILL KILL PERFORMANCE!
    
    RETURNS TABLE WITH SCHEMABINDING AS
    RETURN
    
    /* "Inline" CTE Driven "Tally Table" produces values from 1 up to 10,000... enough to cover VARCHAR(8000)*/
    
      WITH E1(N) AS (
                     SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL
                     SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL
                     SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1
                    ),                          --10E+1 or 10 rows
           E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows
           E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max
     cteTally(N) AS (--==== This provides the "base" CTE and limits the number of rows right up front
                         -- for both a performance gain and prevention of accidental "overruns"
                     SELECT TOP (ISNULL(DATALENGTH(@pString),0)) ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4
                    ),
    cteStart(N1) AS (--==== This returns N+1 (starting position of each "element" just once for each delimiter)
                     SELECT 1 UNION ALL
                     SELECT t.N+1 FROM cteTally t WHERE SUBSTRING(@pString,t.N,1) = @pDelimiter
                    ),
    cteLen(N1,L1) AS(--==== Return start and length (for use in substring)
                     SELECT s.N1,
                            ISNULL(NULLIF(CHARINDEX(@pDelimiter,@pString,s.N1),0)-s.N1,8000)
                       FROM cteStart s
                    )
    --===== Do the actual split. The ISNULL/NULLIF combo handles the length for the final element when no delimiter is found.
     SELECT ItemNumber = ROW_NUMBER() OVER(ORDER BY l.N1),
            Item       = SUBSTRING(@pString, l.N1, l.L1)
       FROM cteLen l
    
    
    GO