首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> SQL Server 資料庫 >> 關於SqlServer

SQL Server 2005 UDT 處理字串型別完整解析:以年齡區間為例

     編輯:關於SqlServer

問題背景

在開發 UDT 時,若包含 string 等參考型別欄位,會遇到序列化錯誤:

「類型標記為原生序列化,但欄位 'ageGroup' 為 string 型別(非實值型別)...」

本文詳細解析錯誤成因與解決方案。

錯誤成因深度解析

為什麼 Int、Double 沒問題?

基本實值型別(int、double 等)在 C# 與 C++ 中記憶體配置相同,SQL Server 可直接以原生方式序列化。

為什麼 String 會失敗?

string 是參考型別,在作業系統層級無對應的原生資料結構。SQL Server 無法自動推斷其序列化方式,開發者必須透過 IBinarySerialize 明確指定讀寫邏輯。

完整解決方案步驟

步驟 1:實作 IBinarySerialize 介面

public void Read(System.IO.BinaryReader r)
{
    this.ageGroup = r.ReadString();
}

public void Write(System.IO.BinaryWriter w)
{
    w.Write(this.ageGroup);
}

步驟 2:修改 SqlUserDefinedType 屬性

// 原本自動產生
[Microsoft.SqlServer.Server.SqlUserDefinedType(Format.Native)]

// 修改為
[Microsoft.SqlServer.Server.SqlUserDefinedType(Format.UserDefined, MaxByteSize = 10)]

步驟 3:正確設定 MaxByteSize

MaxByteSize 不是字串長度,而是序列化後的總位元組數。以 10 個 Unicode 字元為例:

  • 字元資料:10 × 2 bytes (UTF-16) = 20 bytes
  • 序列化開銷:2 bytes (長度前綴)
  • 總計:22 bytes → 設定 MaxByteSize = 22 或略大於此值

本範例設為 10 屬於保守估計,實際部署時請依據最大可能輸出計算。

完整程式碼架構

[Serializable]
[SqlUserDefinedType(Format.UserDefined, MaxByteSize = 10)]
public struct AgeGroup : INullable, IBinarySerialize
{
    // 核心欄位
    public string ageGroup;
    private bool m_Null;

    // INullable 實作
    public bool IsNull { get { return m_Null; } }
    public static AgeGroup Null { get { ... } }

    // Parse / ToString
    public static AgeGroup Parse(SqlString s) { ... }
    public override string ToString() { return ageGroup; }

    // 核心邏輯:年齡區間判斷
    public static string ComputeAgeGroup(string s) { ... }

    // IBinarySerialize 實作
    public void Read(BinaryReader r) { this.ageGroup = r.ReadString(); }
    public void Write(BinaryWriter w) { w.Write(this.ageGroup); }
}

部署與驗證

  1. 建置專案(Build)
  2. 部署到 SQL Server(Deploy)
  3. 在 SSMS 中測試:SELECT CAST('25' AS AgeGroup);

參考資源

結語

處理參考型別 UDT 的關鍵在於:理解序列化機制差異、正確實作 IBinarySerialize、精確計算 MaxByteSize。掌握這三點,即可突破原生序列化的限制,開發功能豐富的自訂型別。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved