BCP BLOB exporting corrupted file

时间:2017-06-12 17:09:10

标签: sql-server blob extract bcp

I have looked thoroughly for an answer regarding BCP and extracting a BLOB from my SQL server database. I have followed the various steps found in other threads and I keep coming up with the same file corrupted error.

My database has a column with data type IMAGE in BLOB format. On the users end they can enter photos, pdfs, anything to this field and the server converts them to extremely long BLOBs. My task is to extract these so we can replace them with file name extensions, putting less stress on the database.

My current command is:

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

My format file is correct for an image file as per some of the other files posted. I have tried casting the image file first to a varbinary(max) and that still doesnt solve my solution. No matter what I try I can get the BLOB to export but it is a corrupted file.

Added my format file:

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

1 个答案:

答案 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,它一次加载一个记录。这意味着您的系统不需要将整个表加载到内存中,但它确实意味着您将在表上拥有共享锁,直到它完成后才转储整个表。如果可能,请在停机期间运行此查询。