Sorry if this question sounds dumb and I am new to XML.
I have XML metadata that displays the Name of the table and all of its column names. In this example below, I want to read all 4 column names into 4 rows and also add table name to each iteration of the column name. But with what I tried, I could only partially achieve the output. It either displays one column name with it's respective table name or no table name but all the columns. Any suggestion is greatly appreciated. Thanks in advance!
So far I have tried to materialize a table and then read values using two methods. I would like to retrieve 4 rows and 2 columns (Table @Name, Field), here table name should repeat "CD_SAP_T000" for all four distinct column names.
Method #1 :
DECLARE @xml XML = '<ROOT>
<Table Name="CD_SAP_T000">
<Field>CCCATEGORY</Field>
<Field>MANDT</Field>
<Field>MTEXT</Field>
<Field>ORT01</Field>
</Table>
</ROOT>'
SELECT
ROW_NUMBER() OVER (ORDER BY (SELECT 1)) rowId,
x.Y.value('@Name[1]', 'VARCHAR(100)') AS TableName,
x.y.value('.', 'NVARCHAR(200)' ) AS ColumnName
FROM
@xml.nodes('//*[text()]') AS x(y)
Result for method #1:
rowId TableName ColumnName
--------------------------
1 NULL CCCATEGORY
2 NULL MANDT
3 NULL MTEXT
4 NULL ORT01
Method #2 :
IF OBJECT_ID('dbo.myTable') IS NOT NULL
DROP TABLE dbo.myTable
CREATE TABLE [dbo].[myTable]
(
[Name] VARCHAR(100) NULL,
[Field] VARCHAR(100) NULL
);
DECLARE @Z_xml XML
SET @Z_xml = '<ROOT>
<Table Name="CD_SAP_T000">
<Field>CCCATEGORY</Field>
<Field>MANDT</Field>
<Field>MTEXT</Field>
<Field>ORT01</Field>
</Table>
</ROOT>'
INSERT INTO myTable (Name, Field)
SELECT
x.mytable.value('@Name[1]', 'VARCHAR(100)'),
x.mytable.value('Field[1]', 'VARCHAR(100)')
FROM
@Z_xml.nodes('//ROOT/Table') AS x ( mytable )
SELECT * FROM mytable
Result for method #2:
Name Field
--------------------------
CD_SAP_T000 CCCATEGORY
One method is to cross apply the "Field" nodes to the respective "Table" nodes.
SELECT t.node.value('(@Name)[1]', 'varchar(MAX)') table_name,
c.node.value('(text())[1]', 'varchar(MAX)') column_name
FROM @Z_xml.nodes('/ROOT/Table') t(node)
CROSS APPLY t.node.nodes('./Field') c(node);
Or you can just use this XQuery to grab the table and column names in one go - without the need for a CROSS APPLY
:
-- get a list of all <Field> XML elements
SELECT
-- grab the parent node's (<Table>) "Name" attribute as the table name
TableName = XC.value('(../@Name)[1]', 'VARCHAR(100)'),
-- grab the <Field> text value as column name
ColumnName = XC.value('(.)[1]', 'VARCHAR(100)')
FROM
@Z_xml.nodes('/ROOT/Table/Field') AS XT(XC)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.