2017-02-13 70 views
0

我有一个表0123',它包含几十万行XML,我希望将其作为单独的XML文件提取。将SQL表中的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

您可以使用ROW_NUMBER()直接在开始CURSOR创建运行数量。这似乎比在任何迭代中调用完整的SELECT容易。

编辑:我当时快。你想用你的号码ReferenceID。在没有ROW_NUMBER()的情况下采用相同的方式,并在每次迭代中将参考ID读入@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 
+0

通过一些修改(特别是对@sqlStr行),我能够成功完成这项工作。我没有发现有必要将XML作为NVARCHAR。 bcp能够在没有任何问题的情况下处理XML。谢谢! – PicoDeGallo

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; 
+0

这'... WHERE REFERENCE_ID = '+ @ id'不会不打石膏,工作' 事业'@ id'被声明为' INT' – Shnugo

相关问题