【问题标题】:XQuery with dynamic XPath from XML Sql Server ColumnXQuery 与来自 XML Sql Server 列的动态 XPath
【发布时间】:2015-02-03 14:39:55
【问题描述】:

我有一个 log 表有一个包含日志内容的 xml 列

还有一个名为logType的表,它是日志的类型

我需要创建将 xml 内容描述为可读字符串的查询

我在 logtype 表中添加了一个名为 logXPath 的列

我创建了以下查询

SELECT   contents.value(LogXPath, 'nvarchar(max)')
FROM    dbo.Log 
        JOIN dbo.LogType ON dbo.Log.logTypeID = dbo.LogType.logTypeID

我收到以下错误

XML数据类型方法“value”的参数1必须是字符串字面量

我搜索了一种方法来做到这一点,但没有结果!!

Sql Server XML Column中是否有做动态xpath?

编辑

例如假设以下架构和数据

CREATE TABLE [dbo].[logType]
    (
      [logTypeID] [int] NOT NULL ,
      [logTypeName] [nvarchar](50) NOT NULL ,
      [xPath] [nvarchar](MAX) NOT NULL ,
      CONSTRAINT [PK_logType] PRIMARY KEY CLUSTERED ( [logTypeID] ASC )
    )

GO
INSERT  [dbo].[logType]
        ( [logTypeID] ,
          [logTypeName] ,
          [xPath]
        )
VALUES  ( 1 ,
          N'Patient Data' ,
          N'(/Patient/PatientName)[1]'
        )
INSERT  [dbo].[logType]
        ( [logTypeID] ,
          [logTypeName] ,
          [xPath]
        )
VALUES  ( 2 ,
          N'Clinic Data' ,
          N'(/Clinic/ClinicName)[1]'
        )
/****** Object:  Table [dbo].[log]    Script Date: 02/04/2015 13:58:47 ******/
GO
CREATE TABLE [dbo].[log]
    (
      [logID] [int] NOT NULL ,
      [logTypeID] [int] NOT NULL ,
      [Contents] [xml] NULL ,
      CONSTRAINT [PK_log] PRIMARY KEY CLUSTERED ( [logID] ASC )
    )
GO
INSERT  [dbo].[log]
        ( [logID] ,
          [logTypeID] ,
          [Contents]
        )
VALUES  ( 1 ,
          1 ,
          N'<Patient><PatientID>1</PatientID><PatientName>john</PatientName></Patient>'
        )
INSERT  [dbo].[log]
        ( [logID] ,
          [logTypeID] ,
          [Contents]
        )
VALUES  ( 2 ,
          2 ,
          N'<Clinic><ClinicID>1</ClinicID><ClinicName>Clinic 1</ClinicName></Clinic>'
        )

当我进行如下查询时,它给了我错误

SELECT  logTypeName ,
        [Contents].value(dbo.logType.xPath, 'nvarchar(max)') AS data
FROM    dbo.[log]
        JOIN dbo.logType ON dbo.[log].logTypeID = dbo.logType.logTypeID

【问题讨论】:

  • 将整个SELECT语句作为动态SQL执行怎么样?
  • 问题是我的 xpath 不能是它存储在 sql 列中的变量,并且每个 logtype 具有不同的值,并且每个 logtype 的 xml 结构都不同所以如果我想使用动态 sql 我有为每个日志类型创建一个查询,但我需要在一个查询中获取
  • 请提供样本数据。所以我们检查一下。
  • 完成,我写了一个完整的例子

标签: sql-server xml xpath xquery-sql


【解决方案1】:

您可以使用表 LogType 动态构建查询。

declare @SQL nvarchar(max);

set @SQL = 'select case L.logTypeID'+
            (
            select ' when '+cast(LT.logTypeID as varchar(11))+
                     ' then L.Contents.value('''+LT.xPath+''', ''nvarchar(max)'')'
            from LogType as LT
            for xml path('')
            )+' end as Name from dbo.[Log] as L;';

exec (@SQL);

它会给你一个如下所示的查询:

select case L.logTypeID 
         when 1 then L.Contents.value('(/Patient/PatientName)[1]', 'nvarchar(max)')
         when 2 then L.Contents.value('(/Clinic/ClinicName)[1]', 'nvarchar(max)') 
       end as Name 
from dbo.[Log] as L;

【讨论】:

  • 适用于少量类型的良好解决方案,但 logtype 它本身包含大约 1000 多条记录
  • @user897645 是的,这可能是个问题。我的电脑达到了 675 种不同类型的限制。之后 SQL Server 无法创建查询计划。
  • @user897645 xPath 的形状是否始终相同?一个root,获取一个子节点的第一个值给root?
  • 对于示例中的形状,您可以使用select L.Contents.value('(/*/*)[2]', 'nvarchar(max)') from dbo.[log] as L;
【解决方案2】:

好的,这已经有一段时间了(一年),但这可能会有所帮助......

一个非常有用的 TABLE 函数:http://beyondrelational.com/modules/2/blogs/28/posts/10495/xquery-lab-58-select-from-xml.aspx

使用该函数,您可以获得您想要的值,如下所示:

Select l.Contents, t.XPath, x.Value
  From [log] l With (NoLock)
 Inner Join [LogType] t With (NoLock)
         on t.LogTypeID=l.LogTypeID
 CROSS APPLY XMLTable(l.Contents) AS x
 Where REPLACE(REPLACE(REPLACE(t.XPath,'[1]',''),'(',''),')','')=REPLACE('/'+x.XPath,'[1]','')

【讨论】:

    【解决方案3】:

    SQL Server 不允许用变量替换整个 XPath 表达式,但您可以使用 sql:variablesql:column 扩展 inside 表达式(如果没有看到您的 xml,我无法准确说明结构以及要从 XML 列中查询的信息)。

    或者,如上所述,您可以使用动态 SQL:

    DECLARE @xpath NVARCHAR(MAX);
    SET @xpath = ... //Calculate xpath expression here
    
    DECLARE @sql NVARCHAR(MAX);
    SET @sql = N'SELECT contents.value(''' + @xpath + ''', ''NVARCHAR(MAX)''
                 FROM dbo.Log 
                 JOIN dbo.LogType ON dbo.Log.logTypeID = dbo.LogType.logTypeID';
    
    EXEC sp_executesql @sql;
    

    【讨论】:

    • 问题是我的 xpath 不能是它存储在 sql 列中的变量,并且每个 logtype 具有不同的值,并且每个 logtype 的 xml 结构都不同
    猜你喜欢
    • 1970-01-01
    • 2017-07-25
    • 1970-01-01
    • 2010-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-31
    相关资源
    最近更新 更多