XQuery与XML Sql Server Column的动态XPath

时间:2015-02-03 14:39:56

标签: sql-server xml xpath xquery-sql

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

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

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

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

我创建了以下查询

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

我收到以下错误

XML数据类型方法的参数1"值"必须是字符串文字

我搜索了一种没有结果的方法!

在Sql Server XML列中是否有动态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

3 个答案:

答案 0 :(得分: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;

答案 1 :(得分:0)

SQL Server不允许用变量替换整个XPath表达式,但您可以在表达式中使用sql:variablesql:column扩展名 (我不能说如何完全没有看到你的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;

答案 2 :(得分:0)

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

非常有用的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]','')