简体   繁体   中英

How to read(assign) tableID for multiple values for one other column from XML into SQL Server table?

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);

db<>fiddle

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM