如何向Azure SQL Database添加图像?含Blob存储相关技术疑问
问题描述
近期正在重构数据库,希望支持图像存储。在Azure SQL Database环境下,直接从本地PC添加图像无法实现,执行以下SQL代码时出现错误:
INSERT INTO [Lesson_Content] (Lesson_Language, Lesson_Text, Id_Lesson, Lesson_Image) SELECT 'Polish','sample text', 4, BulkColumn FROM OPENROWSET ( Bulk 'C:\Users\ogryz\Desktop\swedish.png', SINGLE_BLOB )AS Lesson_Image
Cannot bulk load because the file "C:\Users\ogryz\Desktop\swedish.png" could not be opened. Operating system error code 997(Overlapped I/O operation is in progress.).
因此考虑使用Blob存储,但不清楚如何通过SQL而非网页界面向其中添加图像。现提出两个技术问题:
- 如何通过SQL向Blob存储添加图像?
- 除使用上述Blob存储外,是否有更优的向Azure SQL Database添加图像的方法?
解决方案
1. 通过SQL向Azure Blob存储添加图像
可以利用Azure SQL的内置功能结合Blob存储的访问凭据实现,核心步骤如下:
- 先为Blob存储容器生成具备写入权限的共享访问签名(SAS令牌),或创建存储凭据关联到SQL数据库。
- 读取本地图像文件后,通过存储过程或外部表写入Blob:
方法一:使用sp_put_object存储过程
-- 读取本地图像文件为二进制数据 DECLARE @image_data VARBINARY(MAX) SELECT @image_data = BulkColumn FROM OPENROWSET(BULK 'C:\Users\ogryz\Desktop\swedish.png', SINGLE_BLOB) AS file_source -- 调用存储过程上传到Blob存储 EXEC sp_put_object @storage_account = '你的存储账户名', @container = '目标容器名', @blob = 'swedish.png', @content = @image_data, @sas_token = '你的SAS令牌'
方法二:通过外部数据源写入
-- 先创建存储凭据(使用SAS令牌或账户密钥) CREATE DATABASE SCOPED CREDENTIAL BlobStorageCredential WITH IDENTITY = 'SHARED ACCESS SIGNATURE', SECRET = '你的SAS令牌'; -- 创建指向Blob容器的外部数据源 CREATE EXTERNAL DATA SOURCE BlobImageSource WITH ( LOCATION = 'https://你的存储账户名.blob.core.windows.net/目标容器名', CREDENTIAL = BlobStorageCredential ); -- 创建外部表映射Blob结构 CREATE EXTERNAL TABLE dbo.BlobImages ( blob_name VARCHAR(255), blob_data VARBINARY(MAX) ) WITH ( LOCATION = '/', DATA_SOURCE = BlobImageSource, FILE_FORMAT = (TYPE = BINARY) ); -- 上传本地图像到Blob INSERT INTO dbo.BlobImages (blob_name, blob_data) SELECT 'swedish.png', BulkColumn FROM OPENROWSET(BULK 'C:\Users\ogryz\Desktop\swedish.png', SINGLE_BLOB) AS file_source;
2. 向Azure SQL Database添加图像的其他优化方案
方案一:直接存储二进制数据到SQL表(小型图像)
如果图像单文件不超过1GB,可直接用VARBINARY(MAX)类型存储在SQL表中,但需通过客户端程序上传(不能直接用本地文件路径的OPENROWSET,因为Azure SQL无法访问本地文件系统):
以C#客户端为例:
byte[] imageBytes = File.ReadAllBytes(@"C:\Users\ogryz\Desktop\swedish.png"); using (SqlConnection conn = new SqlConnection("你的Azure SQL连接字符串")) { string sql = "INSERT INTO Lesson_Content (Lesson_Language, Lesson_Text, Id_Lesson, Lesson_Image) VALUES (@lang, @text, @id, @image)"; SqlCommand cmd = new SqlCommand(sql, conn); cmd.Parameters.AddWithValue("@lang", "Polish"); cmd.Parameters.AddWithValue("@text", "sample text"); cmd.Parameters.AddWithValue("@id", 4); cmd.Parameters.AddWithValue("@image", imageBytes); conn.Open(); cmd.ExecuteNonQuery(); }
方案二:使用Azure SQL托管实例的FILESTREAM功能
若使用的是Azure SQL托管实例,可启用FILESTREAM,将图像存储在关联的Azure文件共享中,SQL表仅保留文件指针,兼顾存储性能与管理便捷性。
方案三:混合存储模式
将图像的元数据(名称、格式、关联课程ID等)存在SQL表中,图像文件本身存在Blob存储,通过SQL存储过程或自定义函数实现两者的关联查询,适合大数量、大尺寸的图像存储,能有效降低SQL数据库的存储压力。
内容的提问来源于stack exchange,提问作者kc99
相关产品推荐
相关产品推荐

