2017-06-12 101 views
2

我已经彻底查找了有关BCP和从SQL服务器数据库中提取BLOB的答案。我遵循在其他线程中发现的各种步骤,并不断发现相同的文件损坏错误。BCP BLOB导出损坏的文件

我的数据库有一个BLOB格式的数据类型为IMAGE的列。在用户端,他们可以输入照片,pdf,任何东西到这个领域,服务器将它们转换为非常长的BLOB。我的任务是提取这些文件,以便我们可以用文件扩展名替换它们,从而减轻数据库的压力。

我现在的命令是:

bcp "select notes_activex from myDatabase where NCR_NO = '1361'" queryout "C:\BCPtest\testOutput" -S -U -P -f C:\BCPtest\testOutput.fmt 

我的格式文件是一个图像文件按照发布一些其他文件正确。我已经尝试将图像文件首先转换为varbinary(max),但仍然无法解决我的解决方案。无论我尝试什么,我都可以获取要导出的BLOB,但它是一个损坏的文件。

加我的格式文件:

11.0 
1 
1  SQLIMAGE   0  0  "" 1  notes_activex     "" 
+0

请发布您的格式文件。我在这里猜测,但也许你没有在格式文件中设置前缀长度为零。 –

回答

1

至于二进制数据,BCP是为使以后可以插入到另一个SQL Server中提取数据。它没有以与二进制数据文件兼容的格式保存。您需要使用程序或脚本来提取数据,基本上可以将数据转换为字节。

我以前用PowerShell脚本完成了这项工作。我会用下面的脚本。如果您一次只能读取多个记录,我强烈建议您从SQL查询中确定文件。

# Define the connection parameters 
$SqlServer = 'MyServerName'; 
$SqlDatabase = 'MyDatabase'; 
$SqlConnectionString = 'Data Source={0};Initial Catalog={1};Integrated Security=SSPI' -f $SqlServer, $SqlDatabase; 

# Define the query. Note that one field is the file name and the other is the data. 
# Modify the WHERE clause to pull the records you need. I am assuming that NCR_NO is not a unique identifier. 
$SqlQuery = "select SomeUniqueID AS FileName, notes_activex AS FileData from myDatabase where NCR_NO = '1361'"; 

# Or use a GUID for the filename 
# $SqlQuery = "select NEWID() AS FileName, notes_activex AS FileData from myDatabase"; 

# Define the path pattern for the output files. {0} will get filled in with the filename. 
$OutputFileFullNamePattern = 'C:\Path\To\Output\{0}'; 

# Create the Connection object and the Command object 
$SqlConnection = New-Object -TypeName System.Data.SqlClient.SqlConnection -ArgumentList $SqlConnectionString; 
$SqlCommand = $SqlConnection.CreateCommand(); 
$SqlCommand.CommandText = $SqlQuery; 

# Open the connection 
$SqlConnection.Open(); 

# Create the Sql Data Reader 
$SqlDataReader = $SqlCommand.ExecuteReader(); 

while ($SqlDataReader.Read()) { 
    # Set in the file name 
    $OutputFileFullName = $OutputFileFullNamePattern -f $SqlDataReader['FileName']; 

    # Save the data to the file 
    [System.IO.File]::WriteAllBytes($OutputFileFullName,$SqlDataReader['FileData']); 
} 

# Close and dispose of the SQL connection 
$SqlConnection.Close(); 
$SqlConnection.Dispose(); 

它使用一个SqlDataReader的,它加载记录一次一个。这意味着您的系统不需要将整个表加载到内存中,但是这意味着您将在表上拥有一个共享锁,直到完成整个表的倾倒。如果可能,请在停机期间运行此查询。

+0

我正在使用的表只是具有标识符号和数据库中的BLOB字段,因此不幸的是无法事先确定文件类型。 谢谢你对此的回应和帮助。 – CC09

+0

@ CC09但是,应用程序必须知道文件名或文件类型是在什么地方,对吗?也许它不在myDatabase表中,但它必须位于数据库中的某个位置。你没有认真存储任意的二进制数据,绝对没有描述它的元数据。 –

+0

不幸的是,我以这种方式进入了这个数据库。我的老板是要求完成这项任务的人。没有描述其文件类型的元数据,只是一个字段中可笑的大BLOB。 – CC09