0

I have an XML column in SQL server which contains data like:

<Package>
   <Section name='BOX'>
       <InputNumber description="[1] What is the height of the Box."> 
           <value>25</value>
       </InputNumber>
       <InputNumber description="[2] What is the width of the Box."> 
           <value>30</value>
       </InputNumber>
    </Section>
</Package>

I want to get output such that text present in description becomes the column name and value becomes the record for it. Output should be like:

[1] What is the height of the Box. ------ [2] What is the width of the Box.

25                                        30

I don't want to fetch the description as normal values but as column names

1
  • "I don't want to fetch the description as normal values but as column names" - unless the description strings are fixed there is no sensible way of doing that. You would need to first get it as "normal values" then use that to construct dynamic SQL with the values as column names Commented May 8, 2020 at 11:30

1 Answer 1

1

As @Martin Smith pointed out, only dynamic SQL is capable to help here. Here is how to implement it.

SQL

-- DDL and sample data population, start
USE tempdb;
GO

DROP TABLE IF EXISTS dbo.tbl;

CREATE TABLE dbo.tbl (ID INT IDENTITY PRIMARY KEY, [Configuration] xml);
INSERT INTO dbo.tbl ([Configuration])
VALUES
(N'<Package>
   <Section name="BOX">
       <InputNumber description="[1] What is the height of the Box."> 
           <value>25</value>
       </InputNumber>
       <InputNumber description="[2] What is the width of the Box."> 
           <value>30</value>
       </InputNumber>
    </Section>
</Package>')
, (N'<Package>
   <Section name="BOX">
       <InputNumber description="[1] What is the height of the Box."> 
           <value>770</value>
       </InputNumber>
       <InputNumber description="[2] What is the width of the Box."> 
           <value>771</value>
       </InputNumber>
    </Section>
</Package>');
-- DDL and sample data population, end

DECLARE @xml XML
    , @colHeader VARCHAR(100)
    , @CrLf CHAR(2) = CHAR(13) + CHAR(10)
    , @SQL AS NVARCHAR(MAX);

SET @xml = (SELECT TOP(1) [Configuration] FROM dbo.tbl);

-- count total number of columns
DECLARE @cnt INT, @i INT;
SET @cnt = @xml.value('count(/Package/Section/InputNumber)', 'INT');

SET @SQL = 'SELECT ID' + @CrLf;

-- loop through XML
SET @i = 1;
WHILE @i <= @cnt BEGIN
   SET @colHeader = @xml.value('(/Package/Section/InputNumber[position() = sql:variable("@i")]/@description)[1]', 'VARCHAR(100)');
   SET @SQL += ', c.value(''(InputNumber[' + CAST(@i AS VARCHAR(5)) + ']/value/text())[1]'', ''NVARCHAR(MAX)'') AS "' + @colHeader + '"' + @CrLf

   SET @i += 1;
END

SET @SQL += 'FROM dbo.tbl as tbl
    CROSS APPLY tbl.[Configuration].nodes(''/Package/Section'') AS t(c);';

PRINT @SQL;
EXEC sys.sp_executesql @SQL;

Output

+----+------------------------------------+-----------------------------------+
| ID | [1] What is the height of the Box. | [2] What is the width of the Box. |
+----+------------------------------------+-----------------------------------+
|  1 |                                 25 |                                30 |
|  2 |                                770 |                               771 |
+----+------------------------------------+-----------------------------------+
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.