I've been reading this article: https://www.red-gate.com/simple-talk/sql/database-administration/manipulating-xml-data-in-sql-server/
I found what I need, but the only difference in my situation I need to use FOR XML PATH(...)
and not ROOT(...)
instead of AUTO
mode.
I have a XML file that uses columns of the table as a elements. The question that I'm trying to resolve:
1) how to produce a single XML file per each record in the select statement;
2) save each xml file with a unique name based on rowId on a shared server
Note: hardcoding values for each XML row is not an option as my output contains thousands of rows.
The problem here is that FOR XML and XML data type are not allowed in the Cursor statement.
CREATE TABLE #T1
(
ID INT NOT NULL,
LName NVARCHAR(30) NULL,
FName NVARCHAR(30) NULL,
Comments NVARCHAR(MAX) NULL
);
GO
INSERT INTO #T1 (ID, LName, FName, Comments)
VALUES
(1, 'JONOTHAN', 'SMITH', 'is the best friend ever'),
(2, 'ROGER', 'SHU`LTS', 'is the boss!'),
(3, 'Jeremy', 'Deimer', 'is the a good drama actor'),
(4, 'Alexandra', 'Norusis', 'is the smart feminist');
GO
SELECT
t.ID,
t.LName,
t.FName,
t.Comments
FROM #T1 t
FOR XML PATH(''), ROOT ('body');
Below is the current output of the XML file format:
<body>
<ID>1</ID>
<LName>JONOTHAN</LName>
<FName>SMITH</FName>
<Comments>is the best friend ever</Comments>
<ID>2</ID>
<LName>ROGER</LName>
<FName>SHU`LTS</FName>
<Comments>is the boss!</Comments>
<ID>3</ID>
<LName>Jeremy</LName>
<FName>Deimer</FName>
<Comments>is the a good drama actor</Comments>
<ID>4</ID>
<LName>Alexandra</LName>
<FName>Norusis</FName>
<Comments>is the smart feminist</Comments>
</body>
Below is the desired out (based on a record with ID = 1)
<body>
<ID>1</ID>
<LName>JONOTHAN</LName>
<FName>SMITH</FName>
<Comments>is the best friend ever</Comments>
<body>
I think it's this what you need:
DECLARE @tbl TABLE
(
ID INT NOT NULL,
LName NVARCHAR(30) NULL,
FName NVARCHAR(30) NULL,
Comments NVARCHAR(MAX) NULL
);
INSERT INTO @tbl (ID, LName, FName, Comments)
VALUES
(1, 'JONOTHAN', 'SMITH', 'is the best friend ever'),
(2, 'ROGER', 'SHU`LTS', 'is the boss!'),
(3, 'Jeremy', 'Deimer', 'is the a good drama actor'),
(4, 'Alexandra', 'Norusis', 'is the smart feminist');
--use this for your CURSOR
SELECT ID
,(SELECT t1.* FOR XML PATH('body'),TYPE) AS TheRowAsXml
FROM @tbl AS t1
The result
ID TheRowAsXml
1 <body><ID>1</ID><LName>JONOTHAN</LName><FName>SMITH</FName><Comments>is the best friend ever</Comments></body>
2 <body><ID>2</ID><LName>ROGER</LName><FName>SHU`LTS</FName><Comments>is the boss!</Comments></body>
3 <body><ID>3</ID><LName>Jeremy</LName><FName>Deimer</FName><Comments>is the a good drama actor</Comments></body>
4 <body><ID>4</ID><LName>Alexandra</LName><FName>Norusis</FName><Comments>is the smart feminist</Comments></body>
DECLARE @tbl TABLE
(
ID INT NOT NULL,
LName NVARCHAR(30) NULL,
FName NVARCHAR(30) NULL,
Comments NVARCHAR(MAX) NULL
);
INSERT INTO @tbl (ID, LName, FName, Comments)
VALUES
(1, 'JONOTHAN', 'SMITH', 'is the best friend ever'),
(2, 'ROGER', 'SHU`LTS', 'is the boss!'),
(3, 'Jeremy', 'Deimer', 'is the a good drama actor'),
(4, 'Alexandra', 'Norusis', 'is the smart feminist');
DECLARE @ID INT;
DECLARE @xml XML;
DECLARE @BusinessCursor as CURSOR;
SET @BusinessCursor = CURSOR FOR
SELECT ID
,(
SELECT t1.*
FOR XML PATH(''),ROOT('body'),TYPE
) AS TheXml
FROM @tbl AS t1
OPEN @BusinessCursor;
FETCH NEXT FROM @BusinessCursor INTO @ID, @xml;
WHILE @@FETCH_STATUS = 0
BEGIN
--Do something with the values
PRINT 'ID: ' + CAST(@ID AS VARCHAR(10));
PRINT 'XML: ' + CAST(@xml AS NVARCHAR(MAX));
--Here you can build your BCP command.
--Use the ID or any other information to build the file's name and save the XML out (use -w -T)
FETCH NEXT FROM @BusinessCursor INTO @ID, @xml;
END
CLOSE @BusinessCursor;
DEALLOCATE @BusinessCursor;