将SQL列中的XML列行导出到单个文件中

时间:2017-02-13 20:12:32

标签: sql sql-server xml tsql

我有一个名为REFERENCES的表,其中包含几十万行XML,我想将其作为单独的XML文件提取。

大致格式如下:

+--------------+------------------+
| REFERENCE_ID | REFERENCE_XML    |
+--------------+------------------+
| 1            | <xml>...</xml>   |
| 2            | <xml>...</xml>   |
| 3            | <xml>...</xml>   |
| 4            | <xml>...</xml>   |
| ...          | <xml>...</xml>   |
| 70000        | <xml>...</xml>   |
+--------------+------------------+

我想遍历每一行并批量导出每个REFERENCE_XML列,并将其命名为REFERENCE_ID

我的输出文件夹设置如下:

C:\References\1.xml
C:\References\2.xml
C:\References\3.xml
C:\References\4.xml
C:\References\...
C:\References\70000.xml

我能够找到一个执行单个静态行操作的粗略查询,但是我很难找到创建WHILE循环或CURSOR的最佳方法。如何使文件名和WHERE子句动态循环遍历REFERENCES表中的每一行并将所有XML导出为单个文件?

DECLARE @fileName VARCHAR(MAX)
DECLARE @sqlStr VARCHAR(MAX)
DECLARE @sqlCmd VARCHAR(MAX)

SET @fileName = 'C:\References\1.xml' -- I need the integer value to be dynamic per row.
SET @sqlStr = SELECT REFERENCE_XML FROM REFERENCE_DB.dbo.REFERENCES WHERE REFERENCE_ID = 1'  -- I need the REFERENCE_ID to be dynamic per row.
SET @sqlCmd = 'bcp "' + @sqlStr + '" queryout ' + @fileName + ' -w -T'

EXEC xp_cmdshell @sqlCmd

2 个答案:

答案 0 :(得分:2)

您可以使用ROW_NUMBER()直接在启动CURSOR时创建一个正在运行的号码。这似乎比在任何迭代上调用完整的SELECT更容易。

编辑:我很快。您想使用ReferenceID作为号码。只需在没有ROW_NUMBER()的情况下使用相同的方法,并在每次迭代时将ReferenceID读入@Nr

Declare @YourTable table (ID int,SomeXml xml);
Insert Into @YourTable values
 (100,'<root><test a="1"/></root>')
,(200,'<root><test a="2"/></root>')
,(300,'<root><test a="3"/></root>');

DECLARE @Nr BIGINT,@ID INT,@SomeXml XML;
DECLARE @fileName VARCHAR(MAX)
DECLARE @sqlStr VARCHAR(MAX)
DECLARE @sqlCmd VARCHAR(MAX)

DECLARE cur CURSOR FOR SELECT ROW_NUMBER() OVER(ORDER BY ID) AS Nr,ID,SomeXml FROM @YourTable ;
OPEN cur;

FETCH NEXT FROM cur INTO @Nr,@ID,@SomeXml;   

WHILE @@FETCH_STATUS = 0   
BEGIN   

    SET @fileName = 'C:\YourPath\' + CAST(@Nr AS VARCHAR(100)) + '.xml' ;
    SET @sqlStr = 'SELECT ''' + CAST(@SomeXml AS NVARCHAR(MAX)) + '''';
    SET @sqlCmd = 'bcp "' + @sqlStr + '" queryout ' + @fileName + ' -w -T';

    PRINT @sqlCmd;
    --EXEC xp_cmdshell @sqlCmd

    FETCH NEXT FROM cur INTO @Nr,@ID,@SomeXml;    
END   

CLOSE cur;   
DEALLOCATE cur;

这是打印输出:

bcp "SELECT '<root><test a="1"/></root>'" queryout C:\DVP\1.xml -w -T
bcp "SELECT '<root><test a="2"/></root>'" queryout C:\DVP\2.xml -w -T
bcp "SELECT '<root><test a="3"/></root>'" queryout C:\DVP\3.xml -w -T

答案 1 :(得分:0)

我做这样的事情:

DECLARE @fileName VARCHAR(MAX)
DECLARE @sqlStr VARCHAR(MAX)
DECLARE @sqlCmd VARCHAR(MAX)
DECLARE @id int
DECLARE myCursor CURSOR FOR
    SELECT REFERENCE_ID FROM REFERENCE_DB.dbo.REFERENCES
OPEN myCursor
FETCH NEXT FROM myCursor
INTO @id

WHILE @@FETCH_STATUS = 0
BEGIN
    SET @fileName = 'C:\References\' + @id + '.xml'
    SET @sqlStr = SELECT REFERENCE_XML FROM REFERENCE_DB.dbo.REFERENCES WHERE REFERENCE_ID = ' + @id
    SET @sqlCmd = 'bcp "' + @sqlStr + '" queryout ' + @fileName + ' -w -T'

    EXEC xp_cmdshell @sqlCmd
END
CLOSE myCursor;
DEALLOCATE myCursor;