Error when loading date/time via xml SQL Server - sql-server

SQL Server 2016
I am loding bulk records via xml. I have the following query:
DECLARE #xmlString VARCHAR(4000);
SET #xmlString = N'
<Customers>
<OrderID>10248</OrderID>
<CustomerID>VINET</CustomerID>
<CreateDate>10/7/2016 7:31:06 AM</CreateDate>
</Customers>
';
DECLARE #xml XML;
SET #xml = CONVERT(XML, #xmlString);
INSERT INTO [test].dbo.[customers]
( [OrderID] ,
[CustomerID] ,
[CreateDate]
)
SELECT T.Customer.value('(OrderID)[1]', 'INT') AS OrderID ,
T.Customer.value('(CustomerID)[1]', 'nvarchar(20)') AS CustomerID ,
T.Customer.value('(CreateDate)[1]', 'DATETIME') AS CreateDate
FROM #xml.nodes('Customers') AS T ( Customer );
If I remove the CreateDate field, this will load just fine. However, if i leave the CreateDate field in, i receive this error:
Msg 241, Level 16, State 1, Line 35
Conversion failed when converting date and/or time from character string.
CreateDate is a DATETIME field.
Here is the table:
CREATE TABLE [dbo].[Customers](
[OrderID] [INT] NULL,
[CreateDate] [DATETIME] NOT NULL,
[CustomerID] [NVARCHAR](10) NULL
) ON [PRIMARY]
What conversion am I missing to load date/time into my table via xml? Thanks

In your comment you say I am creating the xml. How are you doing this?
In properly created XML date/time value ought to be ISO8601.
Your few lines of code show, that you do not think in XML. XML is not simple text with some extra characters...
Nevertheless your format is convertable with code 131 for dd/mm/yyyy or 101 for mm/dd/yyyy, but you should not do this!
DECLARE #xml XML=
N'
<Customers>
<OrderID>10248</OrderID>
<CustomerID>VINET</CustomerID>
<CreateDate>10/7/2016 7:31:06 AM</CreateDate>
</Customers>
';
SELECT c.value('OrderID[1]','int') AS OrderID
,c.value('CustomerID[1]','nvarchar(100)') AS CustomerID
,CONVERT(DATETIME,c.value('CreateDate[1]','nvarchar(100)'),101) AS CreateDate
FROM #xml.nodes('Customers') AS A(c)
Better try it like this
DECLARE #xml2 XML=
N'
<Customers>
<OrderID>10248</OrderID>
<CustomerID>VINET</CustomerID>
<CreateDate>2016-10-07T07:31:06</CreateDate>
</Customers>
';
SELECT c.value('OrderID[1]','int') AS OrderID
,c.value('CustomerID[1]','nvarchar(100)') AS CustomerID
,c.value('CreateDate[1]','datetime') AS CreateDate
FROM #xml2.nodes('Customers') AS A(c)

Use following if the XML date is in mm/dd/yyyy format
CONVERT(datetime, T.Customer.value('(CreateDate)[1]', 'nvarchar(50)'), 101) AS CreateDate
If the Date in XML is in some other format like dd/mm/yyyy - please visit below link to find out what should be placed instead of 101
https://msdn.microsoft.com/en-us/library/ms187928.aspx

Related

XML Cdata format and variable input TSQL

DECLARE #TransactionId NVARCHAR(100)
DECLARE #TransactionDateTime DATETIME
--Setting Variable
SET #TransactionId= (SELECT CONVERT(VARCHAR, CURRENT_TRANSACTION_ID()))
SET #TransactionDateTime= GETDATE()
--Start the XML Selction
SELECT
1 AS Tag,
NULL AS Parent,
NULL AS 'Tag!1!',
NULL AS 'TransactionType!2!CollectSampling!cdata',
NULL AS 'TransactionID!2!TransactionId!cdata',
NULL AS 'TransactionDateTime!2!TransactionDateTime!cdata',
NULL AS 'ContainerName!2!Name!cdata',
NULL AS 'Make!2!Make!cdata',
NULL AS 'Model!2!Model!cdata',
NULL AS 'Price!2!Price!cdata',
NULL AS 'Type!2!Type!cdata'
Union ALL
SELECT
2 AS Tag,
1 AS Parent,
NULL,
'CollectSample',
#TransactionId,
#TransactionDateTime,
[Name] ,
[Make] ,
[Model] ,
[Price] ,
[Type]
from dbo.RepCar
FOR XML EXPLICIT, ROOT('Message')
The below is the output I would like to have but keep getting XML formats errors. Also just the Message is the parent
Would like output as below.I'm using variables to populate a couple of tags and CollectSample is static field.
<Message>
<TransactionType><![CDATA[CollectSamplingData]]></TransactionType>
<TransactionID><![CDATA[0CA4E46F-5143-498C-B1AC-F990FF70462E]]></TransactionID>
<TransactionDate><![CDATA[2020-01-10T14:20:30-05:00]]></TransactionDate>
<CName><![CDATA[Name]]></CName>
<MakeCar><![CDATA[Make]]></MakeCar>
<MakeModel><![CDATA[Model]]></MakeModel>
<DataValue><![CDATA[Price]]></DataValue>
<MakeType><![CDATA[Type]]></MakeType>
</Message>
declare #RepCar table
(
[Name] varchar(10),
[Make] varchar(10),
[Model] varchar(10),
[Price] money,
[Type] varchar(10)
);
insert into #RepCar
(
Name, Make, Model, Price, Type
)
values
('Car1', 'Make1', 'Model1', 100, 'Type1'),
('Car2', 'Make2', 'Model2', 200, 'Type2'),
('Car3', 'Make3', 'Model3', 300, 'Type3');
DECLARE #TransactionId NVARCHAR(100)
DECLARE #TransactionDateTime DATETIME
--Setting Variable
SET #TransactionId= (SELECT CONVERT(VARCHAR, CURRENT_TRANSACTION_ID()))
SET #TransactionDateTime= GETDATE()
--Start the XML Selction
/*
ElementName!TagNumber!AttributeName!Directive
AttributeName
Provides the name of the attribute to construct in the specified ElementName. This is the behavior if Directive is not specified.
!!!! If Directive is specified and it is xml, cdata, or element, this value is used to construct an element child of ElementName, and the column value is added to it.!!!!
*/
select 1 AS Tag,
0 AS Parent,
'CollectSamplingData' as 'Message!1!TransactionType!cdata',
#TransactionId as 'Message!1!TransactionID!cdata',
#TransactionDateTime as 'Message!1!TransactionDate!cdata',
[Name] as 'Message!1!CName!cdata',
[Make] as 'Message!1!MakeCar!cdata',
[Model] as 'Message!1!MakeModel!cdata',
[Price] as 'Message!1!DataValue!cdata',
[Type] as 'Message!1!MakeType!cdata'
from #RepCar --dbo.RepCar
FOR XML EXPLICIT, ROOT('Messages');

Stored procedure which writes xml into a DB, T-SQL

I am trying to write a stored procedure which writes xml into a DB, T-SQL.
Here is my sample xml (which will have a significant number of <RECORD>s in prod environment):
<?xml version="1.0" encoding="windows-1251"?>
<DATA FORMAT_VERSION="1.0">
<RECORD>
<NAME>МІЖНАРОДНА ГРОМАДСЬКА ОРГАНІЗАЦІЯ МІЖНАРОДНА АКАДЕМІЯ БІОЕНЕРГОТЕХНОЛОГІЙ</NAME>
<SHORT_NAME>МАБЕТ</SHORT_NAME>
<EDRPOU>00011601</EDRPOU>
<ADDRESS>01001, м.Київ, Шевченківський район, ВУЛИЦЯ ПРОРІЗНА, будинок 8, офіс 426</ADDRESS>
<STAN>зареєстровано</STAN>
</RECORD>
</DATA>
I pass the path to the xml file in the #pathToXml parameter.
Here is my stored procedure:
CREATE PROCEDURE [dbo].[LegalContractorsDataSynchronize]
(
#pathToXml varchar
)
AS
BEGIN
BEGIN TRANSACTION
DELETE FROM [dbo].[LegalContractors];
INSERT INTO [dbo].[LegalContractors]([Code], [ShortName], [Name], [LegalAddress], [Status])
SELECT CONVERT([Code], [ShortName], [Name], [LegalAddress], [Status])
FROM OPENROWSET(BULK, #pathToXml, SINGLE_CLOB) as x
COMMIT TRANSACTION
END
I am using Entity Framework to call the stored procedure. The call just happens (with no errors), but the DB is not updated. I am very sure that I mistyped something in the INSERT statement. I followed this example.
Could someone point out how could I fill the three columns in my DB using the data from the respective elements in xml? The columns are Code, ShortName, Name, LegalAddress and Status.
UPDATE
After the answer being posted I tried the suggested solution. I am getting the error:
Msg 102, Level 15, State 1, Procedure LegalContractorsDataSynchronize, Line 15 [Batch Start Line 0]
Incorrect syntax near '#pathToXml'.
Here is my code:
CREATE PROCEDURE [dbo].[LegalContractorsDataSynchronize]
(
#pathToXml varchar
)
AS
BEGIN
BEGIN TRANSACTION
DELETE FROM [dbo].[LegalContractors];
;WITH XmlFile (xmlData) AS
(
SELECT TRY_CAST(BulkColumn AS XML)
FROM OPENROWSET(BULK #pathToXml, SINGLE_BLOB) AS x
)
INSERT INTO [dbo].[LegalContractors] ([Code], [ShortName], [Name], [LegalAddress], [Status])
SELECT c.value('(EDRPOU/text())[1]','NVARCHAR(100)') AS [Code]
, c.value('(SHORT_NAME/text())[1]','NVARCHAR(512)') AS [ShortName]
, c.value('(NAME/text())[1]','NVARCHAR(2048)') AS [Name]
, c.value('(ADDRESS/text())[1]','NVARCHAR(2048)') AS [LegalAddress]
, c.value('(STAN/text())[1]','NVARCHAR(100)') AS [Status]
FROM XmlFile CROSS APPLY xmlData.nodes('/DATA/RECORD') AS t(c);
COMMIT TRANSACTION
END
Please try the following. To the best of my knowledge, OPENROWSET() doesn't accept file name parameter as a variable.
SQL
-- DDL and sample data population, start
DECLARE #tbl TABLE (
ID INT IDENTITY PRIMARY KEY,
Code NVARCHAR(50) NOT NULL,
ShortName NVARCHAR(100) NOT NULL,
[Name] NVARCHAR(100) NOT NULL,
LegalAddress NVARCHAR(100) NOT NULL,
[Status] NVARCHAR(50) NOT NULL
);
-- DDL and sample data population, end
-- Method #1
-- XML file is hardcoded
;WITH XmlFile (xmlData) AS
(
SELECT TRY_CAST(BulkColumn AS XML)
FROM OPENROWSET(BULK 'c:\...\Ukraine.xml', /*CODEPAGE = '65001',*/ SINGLE_BLOB) AS x
)
INSERT INTO #tbl (Code, ShortName, [Name], LegalAddress, [Status])
SELECT c.value('(EDRPOU/text())[1]','NVARCHAR(50)') AS [Code]
, c.value('(SHORT_NAME/text())[1]','NVARCHAR(100)') AS [ShortName]
, c.value('(NAME/text())[1]','NVARCHAR(100)') AS [Name]
, c.value('(ADDRESS/text())[1]','NVARCHAR(100)') AS [LegalAddress]
, c.value('(STAN/text())[1]','NVARCHAR(50)') AS [Status]
FROM XmlFile CROSS APPLY xmlData.nodes('/DATA/RECORD') AS t(c);
-- test
SELECT * FROM #tbl;
-- Method #2
-- dynamic XML file name as a parameter
DECLARE #xml XML
, #sql NVARCHAR(MAX)
, #fileName VARCHAR(256) = 'c:\...\Ukraine.xml';
SET #sql = N'SELECT #xmlOut = XmlDoc FROM OPENROWSET (BULK ' + QUOTENAME(#fileName,NCHAR(39)) + ', SINGLE_BLOB) AS Tab(XmlDoc)';
EXEC master.sys.sp_executesql #sql, N'#xmlOut XML OUTPUT', #xmlOut = #xml OUTPUT;
INSERT INTO #tbl (Code, ShortName, [Name], LegalAddress, [Status])
SELECT c.value('(EDRPOU/text())[1]','NVARCHAR(50)') AS [Code]
, c.value('(SHORT_NAME/text())[1]','NVARCHAR(100)') AS [ShortName]
, c.value('(NAME/text())[1]','NVARCHAR(100)') AS [Name]
, c.value('(ADDRESS/text())[1]','NVARCHAR(100)') AS [LegalAddress]
, c.value('(STAN/text())[1]','NVARCHAR(50)') AS [Status]
FROM #xml.nodes('/DATA/RECORD') AS t(c);
-- test
SELECT * FROM #tbl;

SQL Server XML query values to columns

I'm trying to shred a table of XML documents into SQL Server columns and am going around in circles with one bit.
Basically I have a table (ID int, XMLData XML) and each row will contain a document in the XML column.
I need to turn it into the following format
(
ID int,
ReferenceCurrency varchar,
TargetCurrency varchar,
ReferenceAmount decimal,
TargetAmount decimal,
DueDate date
)
I've cut down this table.
The code I have inherited was a mix of XML.value and string searches with charindex which haven't been too reliable.
This is a snippet of the message we have.
<ReferenceCurrency>
<Ccy>GBP</Ccy>
</ReferenceCurrency>
<TargetCurrency>
<Ccy>USD</Ccy>
</TargetCurrency>
<BalanceAmtItem Type="technical_account_settlement_balance_due_to_sender">
<Amt Ccy="USD" CcyIndic="reference_currency" Share="receiver_share">65.62</Amt>
<Amt Ccy="USD" CcyIndic="target_currency" Share="receiver_share">96.62</Amt>
<DueDate>2019-09-04</DueDate>
</BalanceAmtItem>
I can get most of the data just using XML.value
SELECT
ID,
XMLDATA.value('(Jv-Ins-Reinsurance/TechAccount/ReferenceCurrency)[1]', 'varchar(4)') AS ReferenceCurrency ,
XMLDATA.value('(Jv-Ins-Reinsurance/TechAccount/TargetCurrency)[1]', 'varchar(4)') AS TargetCurrency,
XMLDATA.value('(Jv-Ins-Reinsurance/TechAccount/BalanceAmtItem/DueDate)[1]', 'date') AS DueDate
FROM
dta
The bit I'm struggling with is how to get the two amount columns where CcyIndic = reference_currency or target_currency.
In this example I would expect to get a single line of 1, GBP, USD, 65.62, 96.62, 2019-09-04
Any help appreciated.
SQL
-- DDL and sample data population, start
DECLARE #tbl TABLE(ID INT IDENTITY(1,1) PRIMARY KEY, XMLData XML);
INSERT INTO #tbl
VALUES
(N'<Jv-Ins-Reinsurance>
<TechAccount>
<ReferenceCurrency>
<Ccy>GBP</Ccy>
</ReferenceCurrency>
<TargetCurrency>
<Ccy>USD</Ccy>
</TargetCurrency>
<BalanceAmtItem Type="technical_account_settlement_balance_due_to_sender">
<Amt Ccy="USD" CcyIndic="reference_currency" Share="receiver_share">65.62</Amt>
<Amt Ccy="USD" CcyIndic="target_currency" Share="receiver_share">96.62</Amt>
<DueDate>2019-09-04</DueDate>
</BalanceAmtItem>
</TechAccount>
</Jv-Ins-Reinsurance>');
-- DDL and sample data population, end
SELECT ID,
c.value('(ReferenceCurrency/Ccy)[1]', 'varchar(4)') AS ReferenceCurrency ,
c.value('(TargetCurrency/Ccy)[1]', 'varchar(4)') AS TargetCurrency,
c.value('(BalanceAmtItem/Amt[#CcyIndic="reference_currency"])[1]', 'MONEY') AS ref_money,
c.value('(BalanceAmtItem/Amt[#CcyIndic="target_currency"])[1]', 'MONEY') AS target_money,
c.value('(BalanceAmtItem/DueDate)[1]', 'date') AS DueDate
FROM #tbl AS tbl
CROSS APPLY tbl.xmldata.nodes('/Jv-Ins-Reinsurance/TechAccount') AS t(c);
Something like this:
declare #doc xml =
'<ReferenceCurrency>
<Ccy>GBP</Ccy>
</ReferenceCurrency>
<TargetCurrency>
<Ccy>USD</Ccy>
</TargetCurrency>
<BalanceAmtItem Type="technical_account_settlement_balance_due_to_sender">
<Amt Ccy="USD" CcyIndic="reference_currency" Share="receiver_share">65.62</Amt>
<Amt Ccy="USD" CcyIndic="target_currency" Share="receiver_share">96.62</Amt>
<DueDate>2019-09-04</DueDate>
</BalanceAmtItem>';
SELECT
-- ID,
XMLDATA.value('(/ReferenceCurrency)[1]', 'varchar(4)') AS ReferenceCurrency,
XMLDATA.value('(/TargetCurrency)[1]', 'varchar(4)') AS TargetCurrency,
XMLDATA.value('(/BalanceAmtItem/Amt[#CcyIndic="reference_currency"])[1]', 'varchar(4)') AS ReferenceAmount ,
XMLDATA.value('(/BalanceAmtItem/Amt[#CcyIndic="target_currency"])[1]', 'varchar(4)') AS TargetAmount ,
XMLDATA.value('(/BalanceAmtItem/DueDate)[1]', 'date') AS DueDate
FROM
(select #doc XMLDATA) d
outputs
ReferenceCurrency TargetCurrency ReferenceAmount TargetAmount DueDate
----------------- -------------- --------------- ------------ ----------
GBP USD 65.6 96.6 2019-09-04

Open XML select values with XML name space

I am trying to select some values using open xml in sql server 2012. This works when I don't have any xml name space. But whenever the below prefix get added with root element, I am not able to select values. Any suggestion how I can select values with xmlns:
xmlns="somenamspace/2006-10-31" order-no="00000001"
USE grails
GO
DECLARE #XML AS XML, #hDoc AS INT, #SQL NVARCHAR (MAX), #rootxmlns varchar(100)
SELECT #XML = N'<order xmlns="somenamspace/2006-10-31" order-no="00000001">
<order-date>2017-07-24T20:48:57.000Z</order-date>
<original-order-no>00000001</original-order-no>
<customer>
<customer-name>abcd abcd</customer-name>
<customer-email>jjj#gmail.com</customer-email>
</customer>
<current-order-no>00000001</current-order-no>
<payments>
<payment>
<credit-card>
<card-type>VISA</card-type>
<card-number>XXXX-XXXX-XXXX-1111</card-number>
<card-holder>abcd</card-holder>
<expiration-month>1</expiration-month>
<expiration-year>2021</expiration-year>
</credit-card>
<amount>325.48</amount>
</payment>
</payments>
</order>';
SET #rootxmlns = '<root xmlns:ns1="somenamspace/2006-10-31"/>'
EXEC sp_xml_preparedocument #hDoc OUTPUT, #XML, #rootxmlns
SELECT orderNo
FROM OPENXML(#hDoc, 'ns1:order',2)
WITH
(
orderNo [varchar](50) 'original-order-no'
)
SELECT *
FROM OPENXML(#hDoc, 'ns1:order/customer',2)
WITH
(
customerName [varchar](50) 'customer-name',
customerEmail [varchar](100) 'customer-email'
)
SELECT cardType, cardNumber, cardHolder
FROM OPENXML(#hDoc, '/order/payments/payment/credit-card',2)
WITH
(
cardType [varchar](50) 'card-type',
cardNumber [varchar](100) 'card-number',
cardHolder [varchar](100) 'card-holder'
)
EXEC sp_xml_removedocument #hDoc
GO
Great, that you've found an answer yourself, but this can be solved better.
FROM OPENXML with the corresponding SPs to open and to remove a document is outdated and should not be used any more. Rather use the methods, the native XML type provides:
The following will give you at least some templates how to access the values within your XML:
DECLARE #XML AS XML=
N'<order xmlns="somenamspace/2006-10-31" order-no="00000001">
<order-date>2017-07-24T20:48:57.000Z</order-date>
<original-order-no>00000001</original-order-no>
<customer>
<customer-name>abcd abcd</customer-name>
<customer-email>jjj#gmail.com</customer-email>
</customer>
<current-order-no>00000001</current-order-no>
<payments>
<payment>
<credit-card>
<card-type>VISA</card-type>
<card-number>XXXX-XXXX-XXXX-1111</card-number>
<card-holder>abcd</card-holder>
<expiration-month>1</expiration-month>
<expiration-year>2021</expiration-year>
</credit-card>
<amount>325.48</amount>
</payment>
</payments>
</order>';
--The query
WITH XMLNAMESPACES(DEFAULT N'somenamspace/2006-10-31')
SELECT #xml.value(N'(/order/#order-no)[1]',N'int') AS OrderNumber
,#xml.value(N'(/order/order-date/text())[1]',N'datetime') AS OrderDate
,#xml.value(N'(/order/customer/customer-name/text())[1]',N'nvarchar(max)') AS CustomerName
,p.value(N'local-name(.)',N'nvarchar(max)') AS PaymentType
,p.value(N'(card-type/text())[1]','nvarchar(max)') AS CardType
,p.value(N'(../amount/text())[1]','decimal(10,4)') AS Amount
FROM #xml.nodes(N'/order/payments/payment/*[local-name()!="amount"]') AS A(p)
The result
Nr OrderDate CustomerName PaymentType CardType Amount
1 2017-07-24 20:48:57.000 abcd abcd credit-card VISA 325.4800
Explanation
Some data is taken directly via XPath out of #xml. The statement FROM #xml.nodes() will create a derived table of <payments><payment> nodes (as the wording suggests a 1:n relationship. The <amount> node is handled explicitly, the other node within <payment> is taken as payment details.
Got it,need to add name space in property level as well:
SET #rootxmlns = '<root xmlns:ns1="http://www.demandware.com/xml/impex/order/2006-10-31"/>'
EXEC sp_xml_preparedocument #hDoc OUTPUT, #XML, #rootxmlns
SELECT orderNo
FROM OPENXML(#hDoc, 'ns1:order',2)
WITH
(
orderNo [varchar](50) 'ns1:original-order-no'
)
SELECT *
FROM OPENXML(#hDoc, 'ns1:order/ns1:customer',2)
WITH
(
customerName [varchar](50) 'ns1:customer-name',
customerEmail [varchar](100) 'ns1:customer-email'
)
SELECT cardType, cardNumber, cardHolder
FROM OPENXML(#hDoc, 'ns1:order/ns1:payments/ns1:payment/ns1:credit-card',2)
WITH
(
cardType [varchar](50) 'ns1:card-type',
cardNumber [varchar](100) 'ns1:card-number',
cardHolder [varchar](100) 'ns1:card-holder'
)
EXEC sp_xml_removedocument #hDoc
GO

XQuery with dynamic XPath from XML Sql Server Column

I have a log table has xml column which contains log contents
There is also table called logType which is the type of log
I need to create query descripes the xml contents as readable string
I added a column with name logXPath to logtype table
and i created the following query
SELECT contents.value(LogXPath, 'nvarchar(max)')
FROM dbo.Log
JOIN dbo.LogType ON dbo.Log.logTypeID = dbo.LogType.logTypeID
and I got the following error
The argument 1 of the XML data type method "value" must be a string literal
and I searched for a way to do this with no results!!
Is there any do dynamic xpath in Sql Server XML Column?
Edit
for example assume the following schema and data
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>'
)
When I make query like the following ,it gives me the error
SELECT logTypeName ,
[Contents].value(dbo.logType.xPath, 'nvarchar(max)') AS data
FROM dbo.[log]
JOIN dbo.logType ON dbo.[log].logTypeID = dbo.logType.logTypeID
You can build a query dynamically using the table 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);
It will give you a query that looks like this:
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;
Okay, so this has been here a while (a year), but this might be helpful...
A VERY helpful TABLE function: http://beyondrelational.com/modules/2/blogs/28/posts/10495/xquery-lab-58-select-from-xml.aspx
Using that function, you can get the values you're after something like this:
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]','')
SQL Server does not allow replacing entire XPath expression with a variable, but you can use sql:variable and sql:column extensions inside the expression (I can't say how exactly without seeing your xml structure and what information you want to query from XML column).
Or, as mentioned above, you can use dynamic 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;

Resources