Select XML from varchar(max) column - sql-server

I have some XML data stored in a varchar(max) column on SQL Server 2005. The data is in the form (FQTN = fully qualified type name):
<?xml version="1.0" encoding="utf-16"?>
<History xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<EntityViews>
<EntityProxy Type="FQTN" Key="386876" />
<EntityProxy Type="FQTN" Key="387981" />
<!-- etc. -->
</EntityViews>
</History>
How can I select Type, Key so that I get a tabular result from the XML data in this column for a single row? The table has an identity primary key named HistoryId.

;with cteCastToXML as (
select CAST(YourColumn as xml) as x
from YourTable
)
select h.ep.value('#Type','varchar(10)') as [Type],
h.ep.value('#Key', 'varchar(10)') as [Key]
from cteCastToXML
cross apply x.nodes('/History/EntityViews/EntityProxy') as h(ep)

My recommendation would be two fold.
If this is what you will be doing with the column, change the column to be an XML column.
If you need to do this one time, look at taking the value and converting it to XML, then you can operate on it like you would normally. (Here is a link on how to convert).

Related

T-SQL: Parse XML Data in from classes which inherit from a common base,

I'm trying to parse XML data in SQL Server. I have a XML column in a table, the XML stored in it can vary by type, but they all inherit from the same base type.
Row 1: has XML like so:
<Form>
<TaskType>1</TaskType>
--Other Properties ...
</Form>
Row 2: has XML like so:
<License>
<TaskType>2</TaskType>
--Other Properties ...
</License>
Normally I might parse XML with this T-SQL code snippet:
SELECT
xmlData.A.value('.', 'INT') AS Animal
FROM
#XMLToParse.nodes('License/TaskType') xmlData(A)
This doesn't work since in a view since I'm dependent on the name to find the node.
How can I always find the TaskType XML element in my XML content?
Please try the following solution.
XPath is using asterisk * as a wildcard.
http://www.tizag.com/xmlTutorial/xpathwildcard.php
SQL
-- DDL and sample data population, start
DECLARE #tbl TABLE (ID INT IDENTITY PRIMARY KEY, xmldata XML);
INSERT #tbl (xmldata) VALUES
(N'<Form>
<TaskType>1</TaskType>
<TaskName>Clone</TaskName>
<!--Other XML elements-->
</Form>'),
(N'<License>
<TaskType>2</TaskType>
<TaskName>Copy</TaskName>
<!--Other XML elements-->
</License>');
-- DDL and sample data population, end
SELECT ID
, c.value('(TaskType/text())[1]', 'INT') AS TaskType
, c.value('(TaskName/text())[1]', 'VARCHAR(20)') AS TaskName
FROM #tbl
CROSS APPLY xmldata.nodes('/*') AS t(c);
Output
ID
TaskType
TaskName
1
1
Clone
2
2
Copy
Apparently you can just interate the nodes like so without being aware of their name:
SELECT xmlData.A.value('.', 'INT') AS Animal
FROM #XMLToParse.nodes('node()/TaskType') xmlData(A)

how to perform FOR XML in SQL Query without column name

I'm outputting a XML formatted response in a select statement.
The XML schema goes: Placemark->MultiGeometry->Polygon-><more children>
I'm using existing data.
The table I am running with, let's call it table1, has a name (varchar datatype), style (varchar datatype), and geometry (XML datatype)
The values of the geometry field have pre-formatted xml already. The root tag for each value for all records is MultiGeometry.
Here's the problem.
If I perform:
select name, style, geometry from table1
for xml path('Placemark'), ELEMENTS
I receive this:
<Placemark>
<Name>stuff</Name>
<style>style stuff</style>
<Geometry>
<MultiGeometry>...xml...</MultiGeometry>
</Geometry>
</Placemark>
This fails schema, because the schema (kml schemas) require that MultiGeometry is the child tag inside PLacemark, and the schema does not recognize the <Geometry> tag.
I need this:
<Placemark>
<Name>stuff</Name>
<style>style stuff</style>
<MultiGeometry>...xml...</MultiGeometry>
</Placemark>
but trying:
select name, style, geometry as [ ]
from table1 for xml path('Placemark'), ELEMENTS
fails the query.
How do I get to where I can put MultiGeometry in Placemark without a intermediate tag (Such as <Geometry>)?
Thanks much
Sure:
select name, style, geometry.query('.')
from table1
for xml path('Placemark'), type, ELEMENTS;
Maybe something like.....
SELECT CAST(
REPLACE(
REPLACE(CAST((select name, style, [Geometry] AS [ReplaceMe]
from Table1
for xml path('Placemark'),ELEMENTS) AS VARCHAR(MAX))
, '<ReplaceMe>' , '')
, '</ReplaceMe>' , '') AS XML)

XML to SQL Tables without explicit column names

I'm trying to insert data into SQL using XML. I've managed to figure out the insert operation like so.
create table #testTable (name varchar(50), designation varchar(50));
declare #xmldata as xml
set #xmldata = '<?xml version="1.0"?>
<Employees>
<Employee name="John" designation="SE"></Employee>
<Employee name="Adam" designation="ASE"></Employee>
</Employees>'
insert into #testTable
select 
  r.value('#name', 'varchar(50)'),
  r.value('#designation', 'varchar(50)')
from #xmldata.nodes('/Employees/Employee') t(r)
Using this method, I am required to pre-specify the column names when I use the value method manually.
What I want is a method to run this query without specifying the columns explicitly in the value() method and get a table with the XML attributes as the column names and the values as the data. I am willing to convert this to typed XML if it gets the job done. Assume that the xml columns will always conform to my existing table.
Thanks in advance.

Pulling a value from Xml in a column

I have a table in Sql server that stores Xml data in one of its columns.
The Xml column data looks like this:
<TestDef Weight="0" FailValue="2" ConceptID="-327">
<ToleranceDef ObjectType="SomeName" TargetValue="0"TargetRange="2" />
</TestDef>
I need to write a query that fetches out all the conceptId's from each rows Xml column.
Here it would be -327
I know I can cast the Xml column to a nvarchar(max) then use some reg exp to get the value but not sure how to use the regular expression
Here's an example using a table variable. It will be the same concept with an actual table:
Declare #XmlTable table (
Id Integer Identity,
XmlValue XML
)
Insert Into #XmlTable (XmlValue) values ('<TestDef Weight="0" FailValue="2" ConceptID="-327"><ToleranceDef ObjectType="SomeName" TargetValue="0" TargetRange="2" /></TestDef>')
Insert Into #XmlTable (XmlValue) values ('<TestDef Weight="0" FailValue="2" ConceptID="-325"><ToleranceDef ObjectType="SomeName" TargetValue="0" TargetRange="2" /></TestDef>')
select
Id,
XmlValue,
XmlValue.value('(/TestDef/#ConceptID)[1]', 'integer') as ConceptId
from
#XmlTable

Update XML Node with Conversion in SQL Server 2005

I have a column that contains XML data, but is TEXT type and not XML type. (I have to leave it like this for another reason).
Basically i need to cast it to NText first and then XML. The only problem is my current format that works for selecting the Node value doesnt work to update it.
Error Message: Incorrect syntax near the keyword 'AS'.
UPDATE tbl_Module_RequestForms_Items
SET CAST(CAST(TicorOregon..tbl_Module_RequestForms_Items.XML AS NTEXT) AS XML).value('(//Record/Submitted)[1]', 'NVARCHAR(max)') = 'True'
WHERE CAST(CAST(TicorOregon..tbl_Module_RequestForms_Items.XML AS NTEXT) AS XML).value('(//Record/Submitted)[1]', 'NVARCHAR(max)') <> 'True'
XML Data:
<Record>
<Submitted>False</Submitted>
</Record>
There might be valid reason to store XML in a [n]varchar(max). If you want to only store the XML it is perfectly OK but if you want to modify parts of the XML using TSQL or if you need to query the XML for values or use node/attribute values in a where clause you should switch to XML where you can benefit from indexes on the data and skip the type conversions. Since text is deprecated you should at least consider to switch data type to [n]varchar(max)
If you had your data in a XML column you would use XML DML to modify the XML. In your case you would use replace value of like this.
update tbl_Module_RequestForms_Items
set XMLData.modify('replace value of (/Record/Submitted/text())[1] with "True"')
where XMLData.value('(/Record/Submitted)[1]', 'bit') = 0
Without the XML data type that is not possible so you have to extract the entire XML document, modify it and then update the table with the modified XML document.
You can of course do that using some kind of client development tool but it is also possible in TSQL.
Declare a table variable with the primary key from tbl_Module_RequestForms_Items and the XMLData column but as data type XML.
Copy the rows from tbl_Module_RequestForms_Items to the table variable that should be updated.
Update the XML using replace value of.
Apply the changes back to tbl_Module_RequestForms_Items.
Something like this where I assume that ID is the primary key for tbl_Module_RequestForms_Items and that your XML data is in column XMLData:
declare #T table
(
ID int primary key,
XMLData xml
)
insert into #T
select M.ID,
M.XMLData
from tbl_Module_RequestForms_Items as M
where cast(cast(XMLData as nvarchar(max)) as xml).value('(/Record/Submitted)[1]', 'bit') = 0
update #T
set XMLData.modify('replace value of (/Record/Submitted/text())[1] with "True"')
update M
set XMLData = cast(T.XMLData as nvarchar(max))
from tbl_Module_RequestForms_Items as M
inner join #T as T
on M.ID = T.ID

Resources