尝试使用 PS 脚本从 SQL 中提取数据

Posted

技术标签:

【中文标题】尝试使用 PS 脚本从 SQL 中提取数据【英文标题】:Trying to extract data form SQL using PS script 【发布时间】: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等的二进制数据保存在数据库里吗? 感谢您抽出宝贵时间查看此内容,我设法弄清楚问题是我调用的列不包含我试图提取的数据,一旦审查并纠正所有工作正常。非常感谢 【参考方案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");

【讨论】:

以上是关于尝试使用 PS 脚本从 SQL 中提取数据的主要内容,如果未能解决你的问题,请参考以下文章

SQL Alchemy - 从 Oracle 迁移到 MySQL 的 Python 脚本

如何在一个脚本中使用 R 将 SQL 查询中的数据插入到单独的 SQL 查询中?

在日期范围SQL之间选择PHP脚本中的数据[重复]

如何使用正则表达式从某些文本中提取脚本标签?

从 RPM 规范文件中提取 shell 脚本以进行静态分析

SQL:有没有办法从 Redshift 中的信息模式中计算 Null 记录