| 方法 | 說明 |
| GetChunk(size) | 從目前位置讀取指定位元組,回傳 Byte 陣列 |
| AppendChunk(data) | 寫入 Byte 陣列,首次呼叫覆寫,後續附加 |
關鍵行為
- 循序存取:每次 GetChunk/AppendChunk 從上次位置繼續
- 切換欄位會重置位置指標
- 欄位為 Null 時呼叫會報錯 → 需先
UPDATE SET col = 0x0 初始化
完整 VB6 範例:檔案寫入資料庫
Public Function AppendBlobFromFile(blobColumn As ADODB.Field, ByVal FileName As String) As Boolean
On Error GoTo ErrHandler
Dim FileNum As Long, FileLen As Long, ChunkSize As Long
Dim Chunks As Long, Fragment As Long, i As Long
Dim Buffer() As Byte
ChunkSize = 2048 ' 2KB 區塊,避免大記憶體配置
FileNum = FreeFile
Open FileName For Binary Access Read As #FileNum
FileLen = LOF(FileNum)
If IsNull(blobColumn) Then Exit Function
If FileLen = 0 Then Close #FileNum: AppendBlobFromFile = True: Exit Function
Chunks = FileLen \ ChunkSize
Fragment = FileLen Mod ChunkSize
' 先寫入零碎區塊
If Fragment > 0 Then
ReDim Buffer(Fragment - 1)
Get #FileNum, , Buffer
blobColumn.AppendChunk Buffer
End If
' 迴圈寫入完整區塊
ReDim Buffer(ChunkSize - 1)
For i = 1 To Chunks
Get #FileNum, , Buffer
blobColumn.AppendChunk Buffer
Next i
Close #FileNum
AppendBlobFromFile = True
Exit Function
ErrHandler:
AppendBlobFromFile = False
MsgBox "寫入圖像錯誤: " & Err.Description, vbCritical
End Function
完整 VB6 範例:資料庫讀出檔案
Public Function ReadBlobToFile(blobColumn As ADODB.Field, ByVal FileName As String) As Boolean
On Error GoTo ErrHandler
Dim FileNum As Long, DataLen As Long, ChunkSize As Long
Dim Chunks As Long, Fragment As Long, i As Long
Dim Buffer() As Byte
ChunkSize = 2048
If IsNull(blobColumn) Then Exit Function
DataLen = blobColumn.ActualSize
If DataLen < 8 Then Exit Function ' 非有效圖像
FileNum = FreeFile
Open FileName For Binary Access Write As #FileNum
Chunks = DataLen \ ChunkSize
Fragment = DataLen Mod ChunkSize
If Fragment > 0 Then
ReDim Buffer(Fragment - 1)
Buffer = blobColumn.GetChunk(Fragment)
Put #FileNum, , Buffer
End If
ReDim Buffer(ChunkSize - 1)
For i = 1 To Chunks
Buffer = blobColumn.GetChunk(ChunkSize)
Put #FileNum, , Buffer
Next i
Close #FileNum
ReadBlobToFile = True
Exit Function
ErrHandler:
ReadBlobToFile = False
MsgBox "讀取圖像錯誤: " & Err.Description, vbCritical
End Function
四、現代 .NET 最佳實務(SqlClient 串流)
強烈建議新專案使用 .NET SqlClient 串流 API,效能與易用性遠勝 VB6/ADO。
寫入範例
using (var conn = new SqlConnection(connStr))
using (var cmd = new SqlCommand("UPDATE Docs SET Content = @Content WHERE Id = @Id", conn))
{
cmd.Parameters.Add("@Id", SqlDbType.Int).Value = id;
var param = cmd.Parameters.Add("@Content", SqlDbType.VarBinary, -1); // -1 = max
param.Value = File.OpenRead(filePath); // 串流直接繫結,不載入記憶體
conn.Open();
cmd.ExecuteNonQuery();
}
讀取範例
using (var conn = new SqlConnection(connStr))
using (var cmd = new SqlCommand("SELECT Content FROM Docs WHERE Id = @Id", conn))
{
cmd.Parameters.Add("@Id", SqlDbType.Int).Value = id;
conn.Open();
using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess))
{
if (reader.Read())
using (var fs = File.Create(outPath))
using (var stream = reader.GetStream(0)) // .NET 4.5+ GetStream
stream.CopyTo(fs);
}
}
五、效能與架構建議
| 場景 | 建議方案 | 關鍵點 |
| 小檔案(< 1MB)、高頻存取 | varbinary(max) 行內/行外 | 啟用壓縮、檢查 fill factor |
| 大檔案(> 1MB)、較少存取 | FILESTREAM | 需啟用檔案流層級、獨立檔案群組、備份含檔案 |
| 非交易式檔案存取、完整目錄 | FileTable | Win32 API 直接存取、全文檢索整合 |
| 雲端/混合雲 | Azure Blob + 資料庫存 URL | 資料庫只存中繼資料、Blob 儲存體成本低 |
結語
從 TEXTPTR/WRITETEXT 到 GetChunk/AppendChunk,再到 .NET 串流與 FILESTREAM,SQL Server BLOB 存取經歷了三代演進。現代開發應優先採用 varbinary(max) + .NET 串流 API,大檔案考慮 FILESTREAM,避免將資料庫當成檔案伺服器濫用。記住:資料庫擅長結構化查詢與交易一致性,檔案系統擅長大型二進位串流——各司其職才是王道。
- 上一篇文章: SQL Server 2005 效能調優工具:Database Engine Tuning Advisor 實戰
- 下一篇文章: SQL Server 2005 資料表分區技術深度解析與實戰
Copyright ©
程式碼之家 All Rights Reserved