我获得了备份RayStation数据库RS_Patients.bak
,并且我正在尝试提取和查看存储在其中的DICOM图像。麻烦是双重的:我不知道2000多个字段中的哪一个(或字段的组合)引用图像本身,即使我知道图像在哪里,我也不知道如何提取它们从数据库转换为.dcm
个文件。
通过检查架构,我发现了一些大varbinary
字段(BLOB)的字段,我认为它们可能是我正在寻找的字段。为数据库启用了FileStream,并且有一个FS目录。我尝试使用bcp Utility将这些字段下载到文件中,但是没有生成成功的DICOM。
有没有人有这种数据库/图像结构的经验?拉出和查看图像的任何其他建议?你认为图像是由几个字段而不是一个字段组成的吗?我们认为带有DICOM图像标题的图像字段旁边有一些字段:在表格callefd ImageStack
中,在名为PixelData
的字段旁边,有一些字段称为PixelSize
,{ {1}},SlicePosition
等
另外,如果你能想到另一个地方问这个,我也会很感激。
根据@mcNets建议编辑,bcp命令:
NrPixels
答案 0 :(得分:1)
一般来说,您无法使用SQL Server结果直接写入图像数据。 bcp.exe
也不会帮助你。您需要使用能够理解二进制字符串是原始文件数据的内容,或者,因为这是一个FILESTREAM,所以使用能够为您提供SQL Server上文件路径的内容。我对FILESTREAM的经验有限,但这就是我要做的事。
我无法明确回答要使用哪个字段。这取决于应用程序。如果我们假设DICOM图像存储在FILESTREAM中,那么您可以找到可用的FILESTREAM列:
select t.name TableName
,c.name ColumnName
from sys.tables t
join sys.columns c
on c.object_id = t.object_id
where c.is_filestream = 1
如果我们还假设DICOM图像存储为原始图像文件 - 即,如果它们保存在PACS光盘上,它们将是完整的二进制版本 - 那么您可以运行它来确定路径每个文件由ID:
select TableName_Id
,FileData.PathName()
from TableName.ColumnName
FILESTREAM列的PathName()
功能的文档是here。
如果您想通过传统意义上的SQL Server提取数据,那么我可能会使用PowerShell脚本来执行此操作。这样做的好处是可以让您使用服务器中的任意数据来命名文件。此方法还具有可以在任何二进制或varbinary列上工作的优点。作为缺点,此方法将更慢并使用更多磁盘空间,因为服务器必须读取数据,将其发送到客户端,然后客户端将数据写入磁盘:
$SqlQuery = "select Name, FileData from TableName.ColumnName";
$OutputPath = 'C:\OutputPath';
$SqlServer = 'ServerName';
$SqlDatabase = 'DatabaseName';
$SqlConnectionString = 'Data Source={0};Initial Catalog={1};Integrated Security=SSPI' -f $SqlServer, $SqlDatabase;
$SqlCommand = New-Object -TypeName System.Data.SqlClient.SqlCommand;
$SqlCommand.CommandText = $SqlQuery;
$SqlConnection = New-Object -TypeName System.Data.SqlClient.SqlConnection -ArgumentList $SqlConnectionString;
$SqlCommand.Connection = $SqlConnection;
$SqlConnection.Open();
$SqlDataReader = $SqlCommand.ExecuteReader();
while ($SqlDataReader.Read()) {
$OutputFileName = Join-Path -Path $OutputPath -ChildPath "$($SqlDataReader['Name']).dcm"
[System.IO.File]::WriteAllBytes($OutputFileName,$SqlDataReader['FileData']);
}
$SqlConnection.Close();
$SqlConnection.Dispose();
也可以使用FILESTREAM函数返回Win32 API句柄,但我从未这样做过。