I'm basically trying to reverse what this question is asking...
SQL Server query xml attribute for an element value
I need to produce a result set of "row" elements that contain a group of "field" elements with an attribute that defines the key.
<resultset statement="" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<row>
<field name="id">1</field>
<field name="version”>0</field>
<field name="property">My Movie</field>
<field name="release_date">2012-01-01</field>
<field name="territory_code”>FR</field>
<field name="territory_description">FRANCE</field>
<field name="currency_code”>EUR</field>
</row>
<row>
<field name="id">2</field>
<field name="version”>0</field>
<field name="property">My Sequel</field>
<field name="release_date">2014-03-01</field>
<field name="territory_code”>UK</field>
<field name="territory_description">United Kingdom</field>
<field name="currency_code”>GBP</field>
</row>
</resultset>
I've got a query that returns this...
<resultset statement="" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<row>
<id>1</id>
<version>0</version>
<property>My Movie</property>
<release_date>2012-01-01</release_date>
<territory_code>FR</territory_code>
<territory_description>FRANCE</territory_description>
<currency_code>EUR</currency_code>
</row>
<row>
<id>2</id>
<version>0</version>
<property>My Sequel</property>
<release_date>2014-03-01</release_date>
<territory_code>UK</territory_code>
<territory_description>UNITED KINGDOM</territory_description>
<currency_code>GBP</currency_code>
</row>
</resultset>
Using FOR XML PATH ('row'), ROOT ('resultset') in my SQL statement.
What am I missing? Thanks.
It's a bit involved in SQL Server - the normal behavior is what you're seeing - the column names will be used as XML element names.
If you really want all XML elements to be named the same, you'll have to use code something like this:
SELECT
'id' AS 'field/#name',
id AS 'field',
'',
'version' AS 'field/#name',
version AS 'field',
'',
'property' AS 'field/#name',
property AS 'field',
'',
... and so on ....
FROM Person.Person
FOR XML PATH('row'),ROOT('resultset')
This is necessary to make sure the column name is used as the name attribute on the <field> element, and the empty string are necessary so that the SQL XML parser doesn't get confused about which name attribute belongs to what element......
You can do this without having to specify the columns as constants and that will allow you to also use select *. It is a bit more complicated than the answer provided by marc_s and it will be quite a lot slower to execute.
select (
select T.X.value('local-name(.)', 'nvarchar(128)') as '#name',
T.X.value('text()[1]', 'nvarchar(max)') as '*'
from C.X.nodes('/X/*') as T(X)
for xml path('field'), type
)
from (
select (
select T.*
for xml path('X'), type
) as X
from dbo.YourTable as T
) as C
for xml path('row'), root('resultset')
SQL Fiddle
The query creates a derived table where each row has a XML that looks something like this:
<X>
<ID>1</ID>
<Col1>1</Col1>
<Col2>2014-08-21</Col2>
</X>
That XML is then shredded using nodes() and local-name(.) to create the shape you want.
Your SELECT statement needs to look something like this
SELECT
'id' AS [field/#name],
id AS field,
'version' AS [field/#name],
version AS field,
'property' AS [field/#name],
property AS field,
'release_date' AS [field/#name],
release_date AS field,
'territory_code' AS [field/#name],
territory_code AS field,
'territory_description' AS [field/#name],
territory_description AS field,
'currency_code' AS [field/#name],
currency_code AS field
Related
I have XML column in Oracle table where i have this string:
<field name="Text1" type="String"><value/>
I need to extract the value of this field if exists, in the above example it doesn't exists.
In the below example the value exists:
<field name="Text1" type="String"><value>12345</value>
What will be the best way to do this?
Thank you.
As you said: extract value.
SQL> with test (col) as
2 (select '<field name="Text1" type="String"><value>12345</value></field>'
3 from dual
4 )
5 SELECT extractvalue(xmltype(col), '/field/value') result
6 from test;
RESULT
----------------------------------------------------------------------------------------------------
12345
SQL>
XMLTABLE would be a good choice to use in such a way that
SELECT x.*
FROM xml_tab t,
XMLTABLE('//Root'
PASSING xml_data
COLUMNS
field1 INT PATH 'field[#name="Text1"]/value',
field2 INT PATH 'field[#name="Text2"]/value'
) x
returning
FIELD1
FIELD2
12345
where xml_data is
<Root>
<field name="Text1" type="String">
<value>12345</value>
</field>
<field name="Text2" type="String">
<value/>
</field>
</Root>
Demo
PS. The EXTRACTVALUE function is deprecated. It is still supported for backward compatibility. However, Oracle recommends that you use the XMLTABLE function, or the XMLCAST and XMLQUERY functions instead
I have table DOCUMENTS with:
DOCUMENTS
____________________
DOCUMENTID int
USERID int
CONTENT text
I have following XML stored in TEXT column with name CONTENT in a SQL Server database
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<IDMSDocument>
<DocumentContent>
<Attribute Name="Number" GUID="{FFFFFFFF-0000-0000-0000-000000000001}">
<IDMSType>3060</IDMSType>
<Value Type="Integer">
<Value>122</Value>
</Value>
</Attribute>
<Attribute Name="Date" GUID="{FFFFFFFF-0000-0000-0000-000000000002}">
<IDMSType>3061</IDMSType>
<Value Type="DateTime">
<Date>10-09-2014</Date>
</Value>
</Attribute>
<Attribute Name="Публикуване" GUID="{CA646F55-5229-4FC5-AA27-494B25023F4E}">
<IDMSType>3062</IDMSType>
<Value Type="String">
<Value>Да</Value>
</Value>
</Attribute>
<Attribute Name="Дата" GUID="{AC0465B0-4FB4-49E2-B4FA-70901068FD9B}">
<IDMSType>3063</IDMSType>
<Value Type="DateTime">
<Date>01-10-2014</Date>
</Value>
</Attribute>
<Attribute Name="Предмет на поръчка" GUID="{04A4EC72-6F33-461F-98DD-D8D271997788}">
<IDMSType>3065</IDMSType>
<Value Type="String">
<Value>Избор на консултанти</Value>
</Value>
</Attribute>
</DocumentContent>
</IDMSDocument>
I find a way how to query dingle XML attribute in a single row from table, with heavy conversion :
DECLARE #strContent NVARCHAR(MAX);
DECLARE #xmlContent XML;
SET #strContent = (select content from DOCUMENTS where DocumentID=24);
SET #xmlContent = CAST(REPLACE(CAST(#strContent AS NVARCHAR(MAX)),'utf-8','utf-16') AS XML)
SELECT #xmlContent.query('/IDMSDocument/DocumentContent/Attribute[5]/Value/Value')
where #xmlContent.value('(/IDMSDocument/DocumentContent/Attribute[5]/Value/Value)[1]', 'nvarchar(max)') like '%search%'
I need to make query like "select all rows in table that in fifth attribute in XML have value 'search' "
For me the general problem is that column type is not XML, but I have text column with stored xml inside. when I try cast, query, value directly server return that I can use it Only with XML column.
I would be very grateful if someone suggest how to do this!
Thanks!
Kamen
SQL Server doesn't allow inline XML conversion to have functions applied, i.e.: no CAST(...).query(), use a CTE to handle the conversion:
;WITH cte AS (
SELECT DocumentID, UserID, CAST(Content AS XML) AS XMLContent
FROM Documents
)
SELECT XMLContent.query('/IDMSDocument/DocumentContent/Attribute[5]/Value/Value')
FROM cte
WHERE XMLContent.value('(/IDMSDocument/DocumentContent/Attribute[5]/Value/Value)[1]', 'nvarchar(max)') like '%search%'
One thing though: I saw Unicode (Russian?) characters in the Content column. It may be better to use utf-16 in your XML and ntext for column type.
text and ntext are also on the way out. If this is new code, use nvarchar(max)
say my xml doc is this
<root xmlns="http://www.w3.org/2001/XMLSchema-instance">
<parent prop="1">
<child>
<field name="1">
<value1>abc</value1>
<value2>cdf</value2>
</field>
<field name="2">
<value1>efg</value1>
<value2>hjk</value2>
</field>
</child>
</parent>
<parent2>
<prop atrb="2">abc</prop>
</parent2>
</root>
i have it a table newTable2 and xml datatyped column as xmlcol1
here is the query i worte
SELECT xmlcol1.query('/root/parent/child/field/value1/text()') AS a
FROM newTable2
this works when i remove the xmlns attribute if i put it back it does can anyone explain why is it so and how can i query for same keeping the xmlns attribute.
Try this:
;with xmlnamespaces (
default 'http://www.w3.org/2001/XMLSchema-instance'
)
SELECT xmlcol1.query('/root/parent/child/field/value1/text()') AS a_query
, xmlcol1.value('(/root/parent/child/field/value1/text())[1]', 'varchar(255)') AS a_value_1
, xmlcol1.value('(/root/parent/child/field/value1/text())[2]', 'varchar(255)') AS a_value_2
FROM newTable2
never mind i found the answer
i just need to use the
;WITH XMLNAMESPACES(DEFAULT 'http://www.w3.org/2001/XMLSchema-instance')
before the query
I want to extract the value of Decision using sql from table TRAPTABCLOB having column testclob with XML stored as clob. IN DB2
Sample XML as below
<?xml version="1.0" encoding="UTF-8"?>
<DCResponse>
<Status>Success</Status>
<Authentication>
<Status>Success</Status>
</Authentication>
<ResponseInfo>
<ApplicationId>5701200</ApplicationId>
<SolutionSetInstanceId>
63a5c214-b5b5-4c45-9f1e-b839a0409c24
</SolutionSetInstanceId>
<CurrentQueue />
</ResponseInfo>
<ContextData>
<!--Decision Details Start-->
<Field key="SoftDecision">A</Field>
<Field key="**Decision**">1</Field>
<Field key="NodeNo">402</Field>
<Field key="NodeDescription" />
<!--Decision Details End-->
<!--Error Details Start-->
<Field key="ErrorResponse">
<Response>
<Status>[STATUS]</Status>
<ErrorCode>[ERRORCODE]</ErrorCode>
<ErrorDescription>[ERRORDESCRIPTION]</ErrorDescription>
<Segment>[SEGMENT]</Segment>
</Response>
</Field>
<Field key="ErrorCode">0</Field>
<Field key="ErrorDescription" />
</ContextData>
</DCResponse>
One of the nice things about using XMLTABLE() is that it produces an expression that can be used as a subquery or joined to a table or another SQL expression.
SELECT x.decision
FROM traptabclob, XMLTABLE(
'$d/DCResponse/ContextData[1]' PASSING XMLPARSE(DOCUMENT testclob) AS "d"
COLUMNS
DECISION CHAR(1) PATH 'Field[#key="**Decision**"][1]'
) AS x
;
I need some more help with another XML query. Below is an example of a record of my XML column:
<Fields>
<MappedFields>
<Field name="FormNumber" value="21" />
<Field name="ProcedureCode" value="T2023" />
<Field name="CurrentDate" value="4/23/2012" />
</MappedFields>
</Fields>
The field elements may appear in any order, so it can appear like this as well:
<Fields>
<MappedFields>
<Field name="ProcedureCode" value="G5532" />
<Field name="FormNumber" value="12" />
<Field name="CurrentDate" value="3/29/2011" />
</MappedFields>
</Fields>
What I am looking for, is a query that will get the value of the Field with the name "FormNumber" for all the records in the table. The query I have below works if the Field with the name of "FormNumber" is the first Field element in the XML. What I need is a query that will find the Field element even if it is not the first element. Can someone help me out with this?
SELECT
X.Node.value(N'(Field/#value)[1]', 'nvarchar(max)') AS FormNumber
FROM
dbo.MHTCM_LetterSent A
CROSS APPLY A.LetterXML.nodes(N'/Fields/MappedFields') AS X(Node)
WHERE
X.Node.value(N'(Field/#name)[1]', 'nvarchar(max)') = 'FormNumber'
You can have a test in the xml path like [#name="FormNumber"].
SELECT
X.Node.value(N'(Field[#name="FormNumber"]/#value)[1]', 'nvarchar(max)') AS FormNumber
FROM
dbo.MHTCM_LetterSent A
CROSS APPLY A.LetterXML.nodes(N'//Fields/MappedFields') AS X(Node)
Note the WHERE isn't needed now.
It might make more sense to move the test to the CROSS APPLY:
SELECT
X.Node.value(N'(./#value)[1]', 'nvarchar(max)') AS FormNumber
FROM
dbo.MHTCM_LetterSent A
CROSS APPLY A.LetterXML.nodes(N'//Fields/MappedFields/Field[#name="FormNumber"]') AS X(Node)
Edit- I made the paths absolute (//) and both examples are working for me.