In SQL Server 2008 R2, I have a table with rows of valid XML nodes (one column, xml type) that looks like this:
create table #t (x xml not null);
insert into #t
values ('<service><value1>stuff</value1><value2>more stuff</value2></service>')
, ('<service><value1>I am a different row</value1><value2>more stuff</value2></service>');
I would like to select these into one XML blob:
<services>
<service>. . .</service>
<service>. . .</service>
</services>
I am using FOR XML PATH to try this, but it embeds the column header "x" as a node around the "service" nodes.
select x
from #t
for XML PATH(''), ROOT('services')
This produces:
<services>
<x><service>. . .</service></x>
<x><service>. . .</service></x>
</services>
How can I get rid of the "x" node?
I tried select x as "" and select x as "." but these are reserved words, and the query errors out.
How about this?
select x.query('*')
from #t
for xml path(''), root('services')
Related
I have a table in SQL that contains a list of settings for an application per serverID
I want write a SQL statement that produce a specific XML layout.
The basic SQL statement to retrieve this data:
SELECT SettingName, SettingValue
FROM dbo.ServerSettings
WHERE ServerID = #ServerID
I just need to know the correct FOR XML options.
I want to get back a result like the following. Basically using the value of the SettingName field to be the name of the node.
<ROOT>
<COSTRECOVERYSYSTEM_CONNECTION_STRING></COSTRECOVERYSYSTEM_CONNECTION_STRING>
<COSTRECOVERYSYSTEM_EXTRACT_INTERVAL>60</COSTRECOVERYSYSTEM_EXTRACT_INTERVAL>
<COSTRECOVERYSYSTEM_FILE_DATESTAMP>yyyyMMdd</COSTRECOVERYSYSTEM_FILE_DATESTAMP>
<COSTRECOVERYSYSTEM_FILE_EXTENSION>txt</COSTRECOVERYSYSTEM_FILE_EXTENSION>
<COSTRECOVERYSYSTEM_FILE_NAME>txt</COSTRECOVERYSYSTEM_FILE_NAME>
<COSTRECOVERYSYSTEM_FILE_PATH>txt</COSTRECOVERYSYSTEM_FILE_PATH>
</ROOT>
As in any other query you cannot use a column's value as the output column name. This would need some dynamically created statement and EXEC() for its execution.
But you might do something along this:
DECLARE #tbl TABLE(SettingName VARCHAR(100),SettingValue VARCHAR(100));
INSERT INTO #tbl VALUES ('Setting1','1'),('Setting2','2'),('ForbiddenValue','Huh! What about & and <?');
SELECT CAST((
SELECT '<' + UPPER(t.SettingName) + '>' +
--this embedded FOR XML will implicitly do the escaping for you
(SELECT t.SettingValue AS [*] FOR XML PATH('')) +
'</' + UPPER(t.SettingName) + '>'
FROM #tbl t
FOR XML PATH(''),TYPE
).value('.','nvarchar(max)') AS XML)
FOR XML PATH('ROOT');
In general I would never create XML with string methods. There are so many possible draw backs and traps. But in this case it might be the best choice.
Hint: Be sure, that the setting names are valid XML element names. There are some XML element naming rules
You can see these links for more information:
1. https://learn.microsoft.com/en-us/sql/relational-databases/xml/for-xml-sql-server?view=sql-server-2017
2. https://www.red-gate.com/simple-talk/sql/learn-sql-server/using-the-for-xml-clause-to-return-query-results-as-xml/
I have SQL query for XML like the following (SQL Server 2012):
Use MedStreaming
SELECT distinct 1 as Tag,
NULL as Parent,
NULL AS [ExamTypes!1],
NULL as [ExamType!2!ExamTypeID],
NULL as [Template!3!ShortString],
NULL as [Template!3!Order]
UNION ALL
SELECT distinct 2 as Tag,
1 as Parent,
NULL,
Temp_Type.ExamTypeId as [ExamType!2!ExamTypeID],
NULL as [Template!3!ShortString],
NULL as [Template!3!Order]
FROM LayoutSectionTemplate_ExamType AS Temp_Type
INNER JOIN LayoutSection_Template as temp
ON Temp_Type.TemplateId = temp.TemplateId
UNION ALL
SELECT 3 as Tag,
2 as Parent,
NULL,
Temp_Type.ExamTypeId,
temp.ShortString,
Temp_Type.[Order]
FROM LayoutSectionTemplate_ExamType AS Temp_Type
INNER JOIN LayoutSection_Template as temp
ON Temp_Type.TemplateId = temp.TemplateId
ORDER BY [ExamType!2!ExamTypeID],[Template!3!Order]
FOR XML EXPLICIT
I try to call it and write the XML result in an XML file using the following command:
sqlcmd -i "%~dp0\MedStreaming.Util\Scripts\GetExamTypes-TemplatesRelations.sql" -o "C:\temp\examTypes-reportsTemplates.xml"
But the file result XML format is not correct, and some texts are removed.
I tried to put "XML ON" on the first of the query, but it doesn't work (it gives me syntax error).
Any help ?
This is an annoying limitation of SQLCMD interface (same for Invoke-SqlCmd the Powershell module) - you have to put the XML or JSON output into NVARCHAR(MAX) or XML datatype so that SQLCMD can handle the output properly. There is a 2MB rowsize threshold for SQLCMD output whereafter it starts chunking the output data into additional DataRows.
Note: You should also set MaxCharLength if the data exceeds 4K characters in size.
SQLCMD XML Output
DECLARE #XML as XML
SET #XML= (select Name from TestXML For XML path ('')
SQLCMD JSON Output
DECLARE #json NVARCHAR(MAX)
SELECT #json = (select * from mytable for json auto)
select * from openjson(#json)
Another option is to use bcp utility which outputs directly to disk for larger data dumps.
I am trying to extract XML node from SQL query. I have XML report specification in one of the column of SQL table.
I want to extract sqlText node from the XML using SQL query.
I have uploaded the xml to dropbox:
https://www.dropbox.com/sh/28xu7ifu78h6gm0/AACQS24NEjPFO0GXEI9vLuefa?dl=0
Any help would be greatly appreciated.
If you are using xml document
declare #xml xml ='<report ....</report>'
select #xml.value('(/report/queries/query/source/sqlQuery/sqlText)[1]', 'varchar(100)') as [SqlText]
Assuming that the XML data is stored in XML typed column named myXmlColumn in SQL table named myTable, you can specify the default namespace for the XPath using ;WITH XMLNAMESPACES(), for example :
;WITH XMLNAMESPACES(default 'http://developer.cognos.com/schemas/report/8.0/')
select myTable.myXmlColumn.value('(/report/queries/query/source/sqlQuery/sqlText)[1]'
, 'varchar(max)') as sqlText
If there are more than one sqlQuery node, following SQL XML query can be used
SELECT
[Query].value('.','varchar(100)') AS QueryText
FROM #xml.nodes('/report/queries/query/source/sqlQuery/sqlText') Queries([Query])
I would like to write a stored procedure as below in SQL Server.
CREATE PROC [dbo].[Employee_delete]
AS
BEGIN
SELECT *
FROM #employee
FOR XML PATH(''), root ('EmployeeDelete'),xmlschema
END
But I'm getting the error--> 'inline schema is not supported with for xml path xmlschema'. May I know, how can I achieve XMLSchema with code "FOR XML PATH(''), root ('EmployeeDelete'),xmlschema"
To auto generate schemas in biztalk , I have to use word "xmlSchema"
Thanks in advance
If you are using BizTalk-2010 you should be using the WCF-SQL adapter for which you don't need to select as FOR XML to be able to generate schemas.
Try...
FOR XML AUTO,ROOT('EmployeeDelete'), TYPE, ELEMENTS XSINIL, XMLSCHEMA
i got a snippet which show how to query xml data in sql server but few area still not clear to me.
DECLARE #xml XML
SET #xml = '<root>
<row>one</row>
<row>two</row>
<row>three</row>
</root>'
CREATE TABLE #Fields(Field varchar(MAX))
INSERT INTO #Fields
SELECT
x.y.value('text()[1]', 'varchar(5)')
FROM #xml.nodes('root/row') x(y)
SELECT * FROM #Fields
DROP TABLE #Fields
what is x.y i just do not understand and also what kind of syntax is it 'text()[1]', 'varchar(5)'
if text() is in-built function then does it work for any data type ?
please help me to visualize what x.y ?? thanks
The .nodes() call converts your XML into a list of XML fragments - and a "list" in SQL Server always is a table - so this is really a table alias (x) and a column alias (y) for an internally constructed tables of XML fragments (one "row" per match for .nodes())
If you would be using .nodes('/root)` then you'd get an "pseudo table" with these rows:
Table x
y
----------------
<row>one</row>
<row>two</row>
<row>three</row>
Since you're using .nodes('/root/row') instead, you're really getting just the values of those <row> elements:
Table x
y
----------------
one
two
three
The .value() now takes one of those XML fragments and returns something from it. It could be the name of a sub-element - but text() (yes, a built-in XQuery function) just converts the whole XML fragment into a textual representation. The second parameter of the .value() call just defines what that value should be treated as - what datatype.