【问题标题】:Trying to extract data form SQL using PS script尝试使用 PS 脚本从 SQL 中提取数据
【发布时间】:2022-01-09 22:11:28
【问题描述】:

我一直在尝试使用 PS 脚本从 SQL Server 数据库中提取文件(pdf、word 等)。我遇到了下面的 PowerShell 脚本。脚本运行并填充目标文件夹,但所有文件都是 0 字节并且在脚本执行期间。它抛出错误:

"从 FILESTREAM 容器中导出对象:.docx 使用“5”参数调用“GetBytes”的异常:“对列“扩展”的 GetBytes 尝试无效。GetBytes 函数只能用于 typ 列 e 文本、NText 或图像。""

谁能指出我做错了什么以及如何解决这个问题?非常感谢。

$Server = ".\xxxxxx";             
$Database = "xxxxxx"; 
$Dest = "C:\DATA\";     
$bufferSize = 8192;       


$Sql = "
SELECT 
      [extension]
      
  FROM [XXXXXXXX].[dbo].[XXXXXXdocuments]
"; 
 
 
$con = New-Object Data.SqlClient.SqlConnection; 
$con.ConnectionString = "Data Source=$Server;" + 
 "Integrated Security=True;" + 
 "Initial Catalog=$Database"; 
$con.Open(); 

Write-Output ((Get-Date -format yyyy-MM-dd-HH:mm:ss) + ": Started ..."); 
 
 
$cmd = New-Object Data.SqlClient.SqlCommand $Sql, $con; 
$cmd.CommandTimeout = 120 
$rd = $cmd.ExecuteReader(); 
 
 
$out = [array]::CreateInstance('Byte', $bufferSize) 
 
 
While ($rd.Read()) 
{ 
 try 
  { 
   Write-Output ("Exporting Objects from FILESTREAM container: {0}" -f $rd.GetString(0)); 
 
   $fs = New-Object System.IO.FileStream ($Dest + $rd.GetString(0)), Create, Write; 
   $bw = New-Object System.IO.BinaryWriter $fs; 
 
   $start = 0; 
 

    enter code here

   $received = $rd.Getbytes(0, $start, $out, 0, $bufferSize - 1); 
   While ($received -gt 0) 
   { 
    $bw.Write($out, 0,      $received); 
    $bw.Flush(); 
    $start += $received; 
 
    $received = $rd.Getbytes(0, $start, $out, 0, $bufferSize - 1); 
   } 
   $bw.Close(); 
   $fs.Close(); 
  } 
  catch 
  { 
   Write-Output ($_.Exception.Message) 
  } 
  finally 
  { 
   $fs.Dispose();         
  }
 }  
   
 
$rd.Close(); 
$cmd.Dispose(); 
$con.Close(); 
 
Write-Output ("Finished");
Read-Host -Prompt "Press Enter to exit"

【问题讨论】:

  • 关于无法在GetBytes() 中调用您尝试读取的字段的数据问题,错误似乎很明显。 extension 字段的数据类型是什么?请记住varcharnvarchartextntext 不同。你是把PDF、DOCX等的二进制数据保存在数据库里吗?
  • 感谢您抽出宝贵时间查看此内容,我设法弄清楚问题是我调用的列不包含我试图提取的数据,一旦审查并纠正所有工作正常。非常感谢

标签: sql sql-server powershell


【解决方案1】:

BinaryWriter 是不必要的。它用于将原始类型写入 Stream。

而且没有必要乱用缓冲区;你可以简单地使用SqlDataReader.GetStream(int).CopyTo(Stream),例如

$Server = "localhost";             
$Database = "adventureworks2017"; 
$Dest = "C:\temp\";     

$Sql = "
SELECT concat('photo', ProductPhotoID, '.jpg') name, LargePhoto from Production.ProductPhoto
"; 
 
 
$con = New-Object Data.SqlClient.SqlConnection; 
$con.ConnectionString = "Data Source=$Server;Integrated Security=True;Initial Catalog=$Database;TrustServerCertificate=true"; 
$con.Open(); 

Write-Output ((Get-Date -format yyyy-MM-dd-HH:mm:ss) + ": Started ..."); 
  
$cmd = New-Object Data.SqlClient.SqlCommand $Sql, $con; 
$cmd.CommandTimeout = 120 
$rd = $cmd.ExecuteReader(); 

 

While ($rd.Read()) 
{ 
 try 
  { 
   Write-Output ("Exporting: {0}" -f $rd.GetString(0)); 
 
   $fs = New-Object System.IO.FileStream ($Dest + $rd.GetString(0)), Create, Write; 
   $rd.GetStream(1).CopyTo($fs) 
   $fs.Close()
  } 
  catch 
  { 
   Write-Output ($_.Exception.Message) 
  } 
  finally 
  { 
   $fs.Dispose();         
  }
 }  
   
 
$rd.Close(); 
$cmd.Dispose(); 
$con.Close(); 
 
Write-Output ("Finished");

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-19
    相关资源
    最近更新 更多