在数据库应用项目开发中,经常会使用一些二进制的图像数据,存储和读取显示图像数据主要采用的是路径链接法和内存流法。路径链接法是将图像文件保存在固定的路径下,数据库中只存储图像文件的路径和名称,此方法数据库容量小,存取速度快,但安全性较差;内存流法是将二进制数据直接存储在数据库中,此方法对数据的共享非常方便,安全性相对较高,常用于图像容量不是很大的时候。
本文主要讨论通过SQL Server 2008使用内存流法如何实现二进制图像数据的存储。
 
1 VARBINARY(MAX)数据类型简介
  在SQL Server 2000和更早的版本中,如果每条记录的数据量远远超过了一个单独记录的8K,我们常用IMAGE数据类型以二进制存储该数据,在使用IMAGE数据类型时,数据是不和普通数据存储在一起的。一个被称作指针的很小的二进制值,和普通数据存储在一起,这个二进制值指向数据文件里的数据实际存储的位置。对IMAGE数据进行读取、插入数据时需要使用READTEXT[1]及WRITETEXT命令,这两个命令需使用TEXTPTR函数来获得正确的二进制指针,这个二进制指针用于定位物理文件中的数据,使用起来较麻烦。
  虽然在SQL Server 2008中依然提供IMAGE数据类型,但微软计划在未来的SQL Server版本中删除IMAGE数据类型, 用VARBINARY(MAX)数据类型来代替,在该版本下不应当使用IMAGE这种类型。
  VARBINARY(MAX) 为可变长度二进制数据,不限最大长度,常用于数据超出 8,000 字节时,可以直接使用insert命令添加数据,使用起来较简单。
 
2 使用T-SQL语句将图像文件直接读入VARBINARY(MAX)字段
  首先在SQL Server 2008的查询窗口中创建测试数据库ImageDB,并建立ImageTable表来存储图像数据:
  

   CREATE DATABASE ImageTest
  GO
  USE ImageTest;
  GO
  CREATE TABLE ImageTable
  (
  ImageData varBinary(MAX)
  );
  然后使用Insert命令将其插入到ImageTest表中(此处图像文件为C:\aa.jpg),OPENROWSET函数包含访问OLE DB数据源中的远程数据所需的全部连接信息,内置的 BULK 访问接口支持大容量操作,实现的代码为:
INSERT INTO ImageTable (ImageData)
SELECT *
FROM OPENROWSET(BULK N'C:\aa.jpg', SINGLE_BLOB) AS Photo
GO
  运行Select * from ImageTable语句将会看到该图像的二进制编码,但SQL Server 2008不提供直接查看图片的方法,为了查看图片,我们需要创建应用程序,本文第4部分介绍其实现的方法。
 
3 在SQL Server中将二进制数据复制到图像文件
  在SQL Server 2008中将二进制数据复制到图像文件,要对Windows的文件进行操作,我们需要用到xp_cmdshell扩展存储过程,在使用之前我们需获得执行该命令的权限:
   

     EXEC sp_configure 'show advanced options', 1
   GO
   RECONFIGURE
   GO
   EXEC sp_configure 'xp_cmdshell', 1
   GO
   RECONFIGURE
   GO
  通过执行xp_cmdshell将二进制数据复制到图像文件:
  

EXEC   master..xp_cmdshell   'bcp "SELECT ImageData FROM ImageTest.dbo.ImageTable" queryout "c:\bb.jpg"-T -c'
Go
  可以看到C盘下增加了一个图像文件bb.jpg。
 
4 使用C#.NET存取SQL Server 2008中的图像数据
  为在2中创建的ImageTable表添加一个ImagePath字段,用于记录图像的路径及文件名。
在窗体上添加一个按钮,用于实现将图像文件读入SQL Server,实现的基本过程是先通过openFileDialog控件选择要读入的图像文件,将图像文件转换成二进制流,连接数据库后使用insert命令将二进制流数据存储到SQL Server,实现的代码如下:
  

public static bool StoreImages(string[] fileNames, string[] filePaths)
{
try
{
for (int i = 0; i < fileNames.Length; i++)
{
string fileName = fileNames[i];
string filePath = filePaths[i]; using (SqlConnection connection = new SqlConnection(PubVariant.ConnectionString))
{
connection.Open();
FileStream byteStream = new FileStream(fileName, FileMode.Open, FileAccess.Read);
byte[] byteImage = new byte[byteStream.Length];
byteStream.Read(byteImage, 0, (int)byteStream.Length);
string strSql = "insert into Data(Name,Data,DataPath) values(@Name,@Data,@DataPath)";
using (SqlCommand cmd = new SqlCommand(strSql, connection))
{
cmd.Parameters.Add("@Name", SqlDbType.Text);
cmd.Parameters.Add("@Data", SqlDbType.Binary);
cmd.Parameters.Add("@DataPath", SqlDbType.Text);
cmd.Parameters["@Name"].Value = fileName;
cmd.Parameters["@Data"].Value = byteImage;
cmd.Parameters["@DataPath"].Value = filePath;
cmd.ExecuteNonQuery();
}
}
} return true;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
return false;
}
}
  再添加一个按钮,用于实现将SQL Server中二进制数据显示为图像,连接数据库后将ImageTable表的记录绑定到dataGridView控件,虽然dataGridView控件可以将二进制数据显示为图片,但行列间距太小,不好看,所以同时还将图像显示在pictureBox控件中,实现的代码如下:

public static Image GetImageFromName(string fileName)
{
try
{
using (SqlConnection connection = new SqlConnection(PubVariant.ConnectionString))
{
connection.Open();
string strSql = "select Data from Data where Name = '" + fileName + "'";
SqlCommand cmd = new SqlCommand(strSql, connection);
SqlDataReader dr = cmd.ExecuteReader();
dr.Read();
MemoryStream ms = new MemoryStream((byte[])dr[0]);
Image img = Image.FromStream(ms);
return img;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
return null;
}
}

SQL SERVER 2008中使用VARBINARY(MAX)进行图像存取的实现方法的更多相关文章

  1. SQL Server 2008中新增的 1.变更数据捕获(CDC) 和 2.更改跟踪

    概述 1.变更数据捕获(CDC)        每一次的数据操作都会记录下来 2.更改跟踪       只会记录最新一条记录   以上两种的区别:         http://blog.csdn.n ...

  2. SQL Server 2008中新增的变更数据捕获(CDC)和更改跟踪

    来源:http://www.cnblogs.com/downmoon/archive/2012/04/10/2439462.html  本文主要介绍SQL Server中记录数据变更的四个方法:触发器 ...

  3. SQL点滴15—在SQL Server 2008中调用C#程序

    原文:SQL点滴15-在SQL Server 2008中调用C#程序 T-SQL的在执行普通的查询的时候是很高效的,但是在执行循环,判断这样的语句的时候效率就不那么的高了.这时可以借助CLR了,我们可 ...

  4. 在SQL Server 2008中调用.net,dll

    原文:在SQL Server 2008中调用.net,dll T-SQL的在执行普通的查询的时候是很高效的,但是在执行循环,判断这样的语句的时候效率就不那么的高了.这时可以借助CLR了,我们可以在SQ ...

  5. SQL Server 2008中的数据压缩

    SQL Server 2008中引入了数据压缩的功能,允许在表.索引和分区中执行数据压缩.这样不仅可以大大节省磁盘的占用空间,还允许将更多数据页装入内存中,从而降低磁 盘IO,提升查询的性能.当然,凡 ...

  6. SQL Server 2008中增强的"汇总"技巧

    本文转载:http://www.cnblogs.com/downmoon/archive/2012/04/06/2433988.html SQL Server 2008中的Pivot和UnPivot: ...

  7. SQL Server 2008中数据压缩

    SQL Server 2008中引入了数据压缩的功能,允许在表.索引和分区中执行数据压缩.这样不仅可以大大节省磁盘的占用空间,还允许将更多数据页装入内存中,从而降低磁盘IO,提升查询的性能.当然,凡事 ...

  8. 利用Ring Buffer在SQL Server 2008中进行连接故障排除

    原文:利用Ring Buffer在SQL Server 2008中进行连接故障排除 出自:http://blogs.msdn.com/b/apgcdsd/archive/2011/11/21/ring ...

  9. SQL Server 2008中的CDC(Change Data Capture)功能使用及释疑

    SQL Server 2008中的CDC(Change Data Capture)功能使用及释疑 关键词:CDC   原文:http://www.cnblogs.com/chenxizhang/arc ...

随机推荐

  1. mpvue微信小程序分包

    ## 微信小程序分包(mpvue) 使用mpvue分包示例:1.下载vue脚手架(先有node环境,v8.12.0) npm install -g vue-cli 2.先用vue初始化一个mpvue小 ...

  2. table内 获取同一行 其他列的value

    table内  获取同一行 其他列的value function move(obj,ud){ var code = document.getElementById("reportName&q ...

  3. bzoj 2600 ricehub

    2600: [Ioi2011]ricehub Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 783  Solved: 417[Submit][Stat ...

  4. 构建一个简单的Angular工程

    1.创建一个空的工程,之后用webstorm打开,添加一个bower.json文件: { "name": "AngularTpl", "depende ...

  5. float和Float的区别

    float是基本数据类型,Float是包装类(封装类).封装类可将接本数据类型封装后当作对象进行操作,并为各种基本数据类型提供各种转换功能.例如Float f = new Float(3.4f);,即 ...

  6. PHP正则匹配中文汉字注意

    preg_match('/^[a-zA-Z\x{4e00}-\x{9fa5}]+$/u', $str) 如上,是匹配字母或者汉字的,一定要在后面加模式修饰符 u , 不然就出错! u (PCRE_UT ...

  7. .pdm文件怎么打开

    1. 用PowerDesigner打开.pdm文件

  8. linux进程状态D和Z的处理

    长期生活在 Linux 环境里,渐渐地就有一种环保意识油然而生.比如,我们会在登录提示里写上"悟空,我跟你说过叫你不要乱扔东西,乱扔东西是不对的.哎呀我话没说完你怎么把 棍子扔掉了?月光宝盒 ...

  9. java读取文件:文本文件

    一般使用串行方式读出或者写入文件.总的来说,使用输入流把文件内容读入内存,使用输出流把内存中的信息写出到文件.这些类位于java.io包下.输入和输出的类和方法往往是对应的 文本文件 先了解如何读写文 ...

  10. 20个Flutter实例视频教程-第08节: 保持页面状态

    博客地址: https://jspang.com/post/flutterDemo.html#toc-bb9 视频地址: https://www.bilibili.com/video/av397092 ...