SQL 服务器。使用 FOR XML PATH(...) 将 XML 文件分隔成一个 XML 文件

SQL Server. Separate XML file with FOR XML PATH(...) into a single XML file

我一直在阅读这篇文章: https://www.red-gate.com/simple-talk/sql/database-administration/manipulating-xml-data-in-sql-server/

我找到了我需要的东西,但我的情况唯一不同的是我需要使用 FOR XML PATH(...) 而不是 ROOT(...) 而不是 AUTO模式。

我有一个 XML 文件,它使用 table 的列作为元素。我要解决的问题:

1) 如何为 select 语句中的每条记录生成单个 XML 文件;

2) 在共享服务器

上使用基于 rowId 的唯一名称保存每个 xml 文件

注意:每个 XML 行的硬编码值不是一个选项,因为我的输出包含数千行。

这里的问题是 Cursor 语句中不允许使用 FOR XML 和 XML 数据类型。

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

下面是XML文件格式的当前输出:

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

下面是所需的输出(基于 ID = 1 的记录)

        <body>
          <ID>1</ID>
          <LName>JONOTHAN</LName>
          <FName>SMITH</FName>
          <Comments>is the best friend ever</Comments>
        <body>
SELECT 
    ID, 
    LName, 
    FName, 
    Comments
FROM #T1
    FOR XML PATH('body');

我认为这是您的预期结果:

<body>
  <ID>1</ID>
  <LName>JONOTHAN</LName>
  <FName>SMITH</FName>
  <Comments>is the best friend ever</Comments>
</body>
<body>
  <ID>2</ID>
  <LName>ROGER</LName>
  <FName>SHU`LTS</FName>
  <Comments>is the boss!</Comments>
</body>
<body>
  <ID>3</ID>
  <LName>Jeremy</LName>
  <FName>Deimer</FName>
  <Comments>is the a good drama actor</Comments>
</body>
<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');

--将此用于您的 CURSOR

SELECT ID
     ,(SELECT t1.* FOR XML PATH('body'),TYPE) AS TheRowAsXml
FROM @tbl AS t1 

结果

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>

更新您使用 CURSOR 的示例

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;
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 @xml XML

DECLARE @BusinessCursor as CURSOR;

SET @BusinessCursor = CURSOR FOR

SELECT
-- ID
   --  ,
   (
     SELECT * 
     FROM @tbl AS t2 
--   WHERE t1.ID=t2.ID 
     FOR XML PATH(''),ROOT('body'),TYPE
     ) AS TheRowAsXml
FROM @tbl AS t1

OPEN @BusinessCursor;

FETCH NEXT FROM @BusinessCursor INTO @xml;

WHILE @@FETCH_STATUS = 0 

BEGIN
  SELECT ( 
     SELECT *
     FROM @tbl AS t2 
     WHERE t1.ID=t2.ID 
     FOR XML PATH(''),ROOT('body'), TYPE
     ) AS TheRowAsXml
FROM @tbl AS t1
FETCH NEXT FROM @BusinessCursor INTO @xml;
END

CLOSE @BusinessCursor;
DEALLOCATE @BusinessCursor;