2015-02-03 3 views
0

У меня есть журнала таблица имеет столбец XML, который содержит содержимое журналаXQuery с динамической XPath из столбца XML Sql сервера

Существует также таблица называется LOGTYPE, который является типом журнала

мне нужно для создания запроса descripes содержимого XML в читаемой строке

Я добавил колонку с именем logXPath в LOGTYPE таблицы

и IC reated следующий запрос

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

и я получил следующее сообщение об ошибке

Аргумент 1 метода типа данных XML «значение» должно быть строковым

и я искал способ сделать это без каких-либо результатов!

Есть ли какой-нибудь динамический xpath в столбце XML XML-столбца Sql?

Редактировать

, например, предположить следующую схему и данные

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 
+0

Как насчет выполнения всего оператора SELECT как динамического SQL? –

+0

проблема заключается в том, что моя xpath не может быть переменной, которую она хранит в столбце sql и имеет различное значение для каждого типа журналов, а структура xml отличается для каждого типа журнала , поэтому, если я хочу использовать динамический sql, мне нужно создать запрос для каждый logtype, но мне нужно получить то в одном запросе – user897645

+0

, пожалуйста, дайте образцы данных. поэтому мы проверяем. – Ajay2707

ответ

0

SQL Server делает не разрешить замену всего выражения XPath переменной, но вы можете использовать sql:variable и sql:column extensions внутри выражения (я не могу сказать, как точно не видеть вашу структуру 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; 
+0

проблема в том, что моя xpath не может быть переменной , она хранится в столбце sql и имеет различное значение для каждого типа журнала , а структура xml отличается для каждого типа журнала – user897645

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; 
+0

хорошим решением для небольших номеров типы, но logtype он сам содержит около 1000+ записей – user897645

+0

@ user897645 Да, это может быть проблемой. Я достиг предела на своем компьютере по 675 различным типам. После этого SQL Server не смог создать план запроса. –

+0

@ user897645 Является ли форма xPath одинаковой? Один корень и получить первое значение дочернего узла для root? –

0

Ладно, так что это был здесь некоторое время (год), но это может быть полезно ...

ОЧЕНЬ полезная функция ТАБЛИЦЫ: 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]','') 
Смежные вопросы