Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/86.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何从SQL server下载一批XML文件?_Sql_Sql Server_Xml_Tsql - Fatal编程技术网

如何从SQL server下载一批XML文件?

如何从SQL server下载一批XML文件?,sql,sql-server,xml,tsql,Sql,Sql Server,Xml,Tsql,我正在尝试获取一组信息,这些信息目前仅在使用MS SQL server Studio 2008的SQL server中作为XML数据列提供。我的兴趣表有一列,其中包含一个长XML字符串~150000个字符,大约有20000行高。我的目标是将每个XML条目的副本拉到一个单独的文件中,以便在后处理中扁平化数据 不过,我不知道如何按顺序查询XML。似乎应该编写某种脚本来遍历表,一次查询一行XML数据,然后将文本保存为磁盘上的.XML文件,然后转到下一行 您以前是否见过这种想法的任何实现,一次查询一个.

我正在尝试获取一组信息,这些信息目前仅在使用MS SQL server Studio 2008的SQL server中作为XML数据列提供。我的兴趣表有一列,其中包含一个长XML字符串~150000个字符,大约有20000行高。我的目标是将每个XML条目的副本拉到一个单独的文件中,以便在后处理中扁平化数据

不过,我不知道如何按顺序查询XML。似乎应该编写某种脚本来遍历表,一次查询一行XML数据,然后将文本保存为磁盘上的.XML文件,然后转到下一行

您以前是否见过这种想法的任何实现,一次查询一个.xml文件来指向它?对于如何实现这一点,您是否有任何建议,或者其他方法


谢谢

实现这一点有一个明确且非常简单的方法,还有两个潜在的方法,我没有时间确认

我能想到的最快最简单的方法是使用SQLCLR。可以在简单的SELECT语句中使用基于CLR的标量用户定义函数UDF,该函数接受XML并将其写入文件。关于如何编写这样一个函数,互联网上有各种各样的例子,在CodePlex/GitHub/etc上也有一些预先编写好的库,尽管我无法说明这些代码的有效性。这里的一个选项(虽然不是免费的)是SQLCLR函数库,我是该库的作者。虽然不贵,但如果这只是一次性使用,如果不需要其他功能,那么可能我刚才提到的其他来源之一就是最好的选择。但是,下面关于如何使用这样一个函数的示例使用了SQL,因为a这是我所拥有的,b这个特定的用例恰好是我的演示之一,因为这不是第一个需要导出XML文件的请求,所以我想我会很清楚,不会误导

如您所见,一个简单的选择用于为每行创建一个包含XML字段内容的文件。作为一个简单的SELECT语句,可以根据需要方便地进行连接和WHERE条件

选择SQL.File\u WriteFile N'C:\export\path\'+tab.fieldtoseasfilename+N.xml',filename CONVERTNVARCHARMAX,tab.XmlField,-文件内容 0,-如果文件已存在,是否追加数据? 空文件编码;NULL=默认编码 作为[结果] 从dbo.TableName选项卡; 一种可能的方法是通过PowerShell。我不明白为什么不可能遍历表中的行,调用文件系统方法写出内容

另一种可能的方法是通过SQL Server集成服务SSI。我使用SSIS已经有几年了,但是有一个ForEach容器或类似的东西,我认为有一种方法可以导出文件

从技术上讲,还有另一种可能的方法,即使用OLE自动化存储过程,即sp_OA*。我不太愿意提及这些过程,因为它们的使用通常是不受欢迎的,但我这样做只是为了完整性,因为如果这真的是一次性输出,那么项目真正一次性的频率是多少;-?那也许这没关系。如果您可以从T-SQLUDF调用它们,那么您可以执行类似于我上面展示的CLR示例的操作。但是,如果T-SQLUDF中不允许它们,至少在写入文件系统时不允许,那么您必须使用游标来迭代行。仅供参考,为了使用sp_OA*存储过程,需要启用OLE自动化服务器配置选项

测试数据:

CREATE TABLE XMLDocs (
    ID INT IDENTITY NOT NULL PRIMARY KEY
    ,XMLDoc XML NOT NULL
)
GO

; With
    -- number generator by power of 2
    n2(n) as ( SELECT 1 as n UNION ALL SELECT 1),
    n4(n) as ( SELECT 1 FROM n2 t1 CROSS JOIN n2 t2 ),
    n16(n) as ( SELECT 1 FROM n4 t1 CROSS JOIN n4 t2 ),
    n256(n) as ( SELECT 1 FROM n16 t1 CROSS JOIN n16 t2 ),
    n65k(n) as ( SELECT 1 FROM n256 t1 CROSS JOIN n256 t2 ),
   Numbers (n) as (SELECT ROW_NUMBER() OVER( ORDER BY n) FROM n65k )
INSERT INTO XMLDocs (XMLDoc)
SELECT CAST('<Root><ProductDescription ProductModelID="' 
            + CAST(n as VARCHAR(10)) 
            + '"><Summary>Some Text</Summary></ProductDescription></Root>'
        as XML)
FROM Numbers;
GO

这听起来像是在描述如何使用光标遍历行,并可能将XML列强制转换为nvarcharmax,以及使用TSQL函数将数据一次一行/一个文件写入文件。从未做过,也没见过有人做过,但听起来确实可行。谢谢。我在开始使用PowerShell时遇到了问题。这很有帮助。
# Configuration data 
[string] $server   = "(local)\";       # SQL Server Instance 
[string] $database = "TestDB";     # Database containing the BLOB data. 
[string] $folder   = "D:\Work\XML\";         # Path to export to 
[string] $filename;
[int]    $bufferSize = 32768;               # Stream buffer size in bytes. 


# Select-Statement for file name & blob data with filter. 
$sql = "SELECT 'XMLFile'
        + CAST([ID] as varchar(10))
        + '.XML' as [FileName]
            ,CAST([XMLDoc] as varbinary(MAX)) as [XMLDoc]
        FROM [XMLDocs]
    WHERE [ID] BETWEEN 10 AND 20;"; 

# Open ADO.NET Connection with Windows authentification. 
$con = New-Object Data.SqlClient.SqlConnection; 
$con.ConnectionString = "Data Source=$server;Initial Catalog=$database;Integrated Security=True;" 
$con.Open(); 

Write-Output ((Get-Date -format yyyy-MM-dd-HH:mm:ss) + ": Started ..."); 

# New command and reader 
$cmd = New-Object Data.SqlClient.SqlCommand $Sql, $con; 
$rd = $cmd.ExecuteReader([System.Data.CommandBehavior]::SequentialAccess); 

# Create a byte array for the stream. 
$out = [array]::CreateInstance('Byte', $bufferSize) 

# Looping through all selected records. 
While ($rd.Read()) 
{ 
    try 
    { 
    $filename = $folder + $rd.GetString(0)
        Write-Output ((Get-Date -format yyyy-MM-dd-HH:mm:ss) + ": Exporting {0}" -f $filename); 

        # New BinaryWriter; existing file will be overwritten. 
        $fs = New-Object System.IO.FileStream ($filename), Create, Write; 
        $bw = New-Object System.IO.BinaryWriter $fs; 

        $start = 0; 
        # Read first byte stream chunk. 
        $received = $rd.GetBytes(1, $start, $out, 0, $bufferSize - 1); 
        While ($received -gt 0) 
        { 
           $bw.Write($out, 0, $received); 
           $bw.Flush(); 
           $start += $received; 
           # Read next byte stream chunk. 
           $received = $rd.GetBytes(1, $start, $out, 0, $bufferSize - 1); 
        } 

        $bw.Close(); 
        $fs.Close(); 
    } 
    catch 
    { 
        Write-Output ($_.Exception.Message) 
    } 
    finally 
    { 
        $fs.Dispose();         
    }         
} 

# Closing & Disposing all objects. 
$rd.Close(); 
$cmd.Dispose(); 
$con.Close(); 

Write-Output ((Get-Date -format yyyy-MM-dd-HH:mm:ss) + ": Finished.");