Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/69.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 这个PowerShell脚本有什么问题?_Sql_Powershell_Filestream - Fatal编程技术网

Sql 这个PowerShell脚本有什么问题?

Sql 这个PowerShell脚本有什么问题?,sql,powershell,filestream,Sql,Powershell,Filestream,我正在尝试使用powershell脚本导出sql filestream数据,它最多只能导出8kb,如果文件超过8kb,则无法导出。但它创建了部分文件。我不知道少了什么 $Server = "(local)"; # SQL Server Instance. $Database = "AdventureWorks"; $Dest = "D:\Export\"; # Path to export to.

我正在尝试使用powershell脚本导出sql filestream数据,它最多只能导出8kb,如果文件超过8kb,则无法导出。但它创建了部分文件。我不知道少了什么

$Server = "(local)";              # SQL Server Instance.            
$Database = "AdventureWorks";            
$Dest = "D:\Export\";             # Path to export to.            
$bufferSize = 8192;               # Stream buffer size in bytes.            

$con = New-Object Data.SqlClient.SqlConnection;            
$con.ConnectionString = "Data Source=$Server;" +             
                    "Integrated Security=True;" +            
                    "Initial Catalog=$Database";            
$con.Open();            

[System.Data.SqlClient.SqlTransaction]$tran = $con.BeginTransaction("fs");            
$Sql = "SELECT GET_FILESTREAM_TRANSACTION_CONTEXT()";            
$ctx = [array]::CreateInstance('Byte', 16);            
$cmdct = New-Object Data.SqlClient.SqlCommand($Sql, $con, $tran);            
$ctx = $cmdct.ExecuteScalar();            
$cmdct.Dispose();            

$Sql = "SELECT [FileName] 
          ,[FileStreamData].PathName()
    FROM dbo.FileStreamStorage ";            

$out = [array]::CreateInstance('Byte', $bufferSize);            

$cmd = New-Object Data.SqlClient.SqlCommand($Sql, $con, $tran);            
$rd = $cmd.ExecuteReader();            

While ($rd.Read())            
{            
Write-Output ("Exporting: {0}" -f $rd.GetString(0));                    

$fs = New-Object System.IO.FileStream ($Dest + $rd.GetString(0)), Create, Write;            
$bw = New-Object System.IO.BinaryWriter($fs);            
$sfs = New-Object System.Data.SqlTypes.SqlFileStream $rd.GetString(1), $ctx, Read, None, 0;            

$start = 0;            
While (1 -eq 1)            
{                             
   $received = $sfs.Read($out, $start, $bufferSize - 1);            
   $bw.Write($out, 0, $received);            
   $bw.Flush();            
   $start += $received;            

   If ($received -lt $bufferSize)            
   { break; }            
}            

$bw.Close();            
$fs.Close();            
$sfs.Close();            
}            

$fs.Dispose();            
$sfs.Dispose();            
$rd.Close();            
$rd.Dispose();            
$tran.Commit();            
$cmd.Dispose();            
$tran.Dispose();            
$con.Close();            
$con.Dispose();            

Write-Output ("Finished");

非常感谢您的帮助。

我想您正在读取8191字节,这意味着如果有更多的数据,那么$received将是8191字节

$received = $sfs.Read($out, $start, **$bufferSize - 1**);
然后比较$received(8191)和$bufferSize(8192)


我在filestreams和Powershell方面做了一些工作,我同意其他的意见——似乎在如何获得长度方面存在问题。下面是我博客中的一些代码,演示如何将filestream数据检索到图像文件:

$server = "Z002sql2k8"
$database = "AdventureWorks2008"
$query = "SELECT TOP(10) Document.PathName(), GET_FILESTREAM_TRANSACTION_CONTEXT(), Title + FileExtension AS FileName FROM Production.Document WHERE FileExtension = '.doc'"
$dirPath = "C:Usersu00"

$connection=new-object System.Data.SqlClient.SQLConnection
$connection.ConnectionString="Server={0};Database={1};Integrated Security=True" -f $server,$database
$connection.Open()
$command=new-object system.Data.SqlClient.SqlCommand("",$connection)
$command.CommandTimeout=120
$tran = $connection.BeginTransaction([System.Data.IsolationLevel]'ReadCommitted')
$command.Transaction = $tran
$command.CommandText = $query
$reader = $command.ExecuteReader()
while ($reader.Read())
{
    $path = $reader.GetString(0)
    [byte[]]$transactionContext = $reader.GetSqlBytes(1).Buffer
    $filepath = "$dirPath{0}" -f $reader.GetValue(2)

    $fileStream = new-object System.Data.SqlTypes.SqlFileStream($path,[byte[]]$reader.GetValue(1), [System.IO.FileAccess]'Read', [System.IO.FileOptions]'SequentialScan', 0)
    $buffer = new-object byte[] $fileStream.Length
    $fileStream.Read($buffer,0,$fileStream.Length)
    $fileStream.Close()
    [System.IO.File]::WriteAllBytes($filepath,$buffer)

}

$reader.Close()
$tran.Commit()
$connection.Close()

有错误吗?异常?否。它会一直创建文件,但问题是如果文件大小超过8kb,它会创建到8kb,而不会在文件中写入剩余字节。结果,由于损坏,文件无法打开。我删除了-1,但现在我收到一个错误,错误是“偏移量和长度超出了数组的界限。请帮助…也许可以尝试更改if语句?例如:if($received-lt$bufferSize-1)将文件流导出到数组的想法似乎是错误的。流中只有一个数据元素。它似乎试图将其全部填充到第一个数组元素中,并遇到数组定义约束。但我得到的是“文件正被另一个进程使用”“使用上述脚本时出错。可能是另一个进程锁定文件,如AV或备份软件。您可以使用Sysinternals进程监视器来确定进程锁定文件是什么。
$server = "Z002sql2k8"
$database = "AdventureWorks2008"
$query = "SELECT TOP(10) Document.PathName(), GET_FILESTREAM_TRANSACTION_CONTEXT(), Title + FileExtension AS FileName FROM Production.Document WHERE FileExtension = '.doc'"
$dirPath = "C:Usersu00"

$connection=new-object System.Data.SqlClient.SQLConnection
$connection.ConnectionString="Server={0};Database={1};Integrated Security=True" -f $server,$database
$connection.Open()
$command=new-object system.Data.SqlClient.SqlCommand("",$connection)
$command.CommandTimeout=120
$tran = $connection.BeginTransaction([System.Data.IsolationLevel]'ReadCommitted')
$command.Transaction = $tran
$command.CommandText = $query
$reader = $command.ExecuteReader()
while ($reader.Read())
{
    $path = $reader.GetString(0)
    [byte[]]$transactionContext = $reader.GetSqlBytes(1).Buffer
    $filepath = "$dirPath{0}" -f $reader.GetValue(2)

    $fileStream = new-object System.Data.SqlTypes.SqlFileStream($path,[byte[]]$reader.GetValue(1), [System.IO.FileAccess]'Read', [System.IO.FileOptions]'SequentialScan', 0)
    $buffer = new-object byte[] $fileStream.Length
    $fileStream.Read($buffer,0,$fileStream.Length)
    $fileStream.Close()
    [System.IO.File]::WriteAllBytes($filepath,$buffer)

}

$reader.Close()
$tran.Commit()
$connection.Close()