将存储过程的结果(XML)输出到文件。
我在SQL Server中有一个创建XML文件的存储过程。当前,它会显示生成的XML,我必须手动将其另存为文件。
我尝试从Powershell as in this question调用该过程,该过程适用于小型文件,但不适用于大型文件(> 1gb文件),因为Powershell尝试将整个内容存储为变量,并且很快用完了记忆。
我将其作为一个新问题开放,因为我认为应该在SQL Server中提供一种方法(或者使用Powershell更好的方法)。
答案 0 :(得分:3)
您不应在此处使用存储过程。只需使用更好的PowerShell。您可以stream large types to and from SQL Server with SqlClient。因此,您只需要下拉列表并使用ADO.NET,而不是使用invoke-sqlcmd
便捷方法。
EG:
$conString = "server=localhost;database=tempdb;integrated security=true"
$sql = @"
select top (1000*1000) *
from sys.messages m
cross join sys.objects o
for xml auto
"@
$fn = "c:\temp\out.xml"
$con = new-object System.Data.SqlClient.SqlConnection
$con.connectionstring = $conString
$con.Open()
$cmd = $con.createcommand()
$cmd.CommandText = $sql
$cmd.CommandTimeout = 0
$rdr = $cmd.ExecuteXmlReader()
$w = new-object System.Xml.XmlTextWriter($fn,[System.Text.Encoding]::UTF8)
$w.WriteNode($rdr,$true)
$w.Close()
$rdr.Close()
write-host "Process Memory: $( [System.GC]::GetTotalMemory($false) )"
write-host "File Size: $( (ls $fn)[0].Length )"
输出
Process Memory: 34738200
File Size: 468194885
答案 1 :(得分:0)
其他解决方案,如果需要的话,您必须逐行在临时表中构建XML文件,然后从Powershell或其他代码逐行输出并读取结果:
SQL示例:
/*
**
** Stored procedure
**
*/
/*** Effacement: ********************************************************
IF EXISTS ( SELECT name FROM sysobjects
WHERE type = 'P' AND name = 'procTEST' )
DROP PROCEDURE procTEST
*** Effacement: ********************************************************/
CREATE PROCEDURE procTEST
AS
CREATE TABLE #TEMP (vInfo VARCHAR(MAX), nLine int)
INSERT INTO #TEMP
SELECT 'Line 1',1
UNION ALL
SELECT 'Line 2',2
UNION ALL
SELECT 'Line 3',3
SELECT vInfo FROM #TEMP ORDER BY nLine ASC
SET NOCOUNT OFF
/*** TESTS ****************************************************************************************************************************************
sp_helptext procTEST
-- DROP PROCEDURE procTEST
EXEC procTEST
*** TESTS ****************************************************************************************************************************************/
Powershell脚本:
$readconn = New-Object System.Data.OleDb.OleDbConnection
$writeconn = New-Object System.Data.OleDb.OleDbConnection
[string]$connstr="Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=TEST;Data Source=.\XXXXX;Workstation ID=OMEGA2"
$readconn.connectionstring = $connstr
$readconn.open()
$readcmd = New-Object system.Data.OleDb.OleDbCommand
$readcmd.connection=$readconn
$readcmd.commandtext='EXEC procTEST'
$reader = $readcmd.executereader()
# generate header
$hash=@{}
for ($i=0;$i -lt $reader.FieldCount;$i++){
$hash+=@{$reader.getname($i)=''}
}
$dbrecords=while($reader.read()) {
for ($i=0;$i -lt $reader.FieldCount;$i++){
$hash[$reader.getname($i)] = $reader.GetValue($i)
}
New-Object PSObject -Property $hash
}
$reader.close()
$readconn.close()
$dbrecords