创建用户定义类型 - 需求

适用于:SQL Server

在创建要在 Microsoft SQL Server中安装的 UDT) (用户定义的类型时,必须做出几个重要的设计决策。 对于大多数 UDT,建议将 UDT 作为结构创建,尽管也可以选择将其作为类创建。 UDT 定义必须符合创建 UDT 的规范,才能将其注册到 SQL Server。

实现 UDT 的要求

若要在 SQL Server 中运行,UDT 必须在 UDT 定义中实现以下要求:

UDT 必须指定 Microsoft.SqlServer.Server.SqlUserDefinedTypeAttributeSystem.SerializableAttribute 的使用是可选的,但建议使用。

  • UDT 必须通过在 Microsoft Visual Basic) Null 方法中创建公共静态 (共享,在 类或结构中实现 System.Data.SqlTypes.INullable 接口。 默认情况下,SQL Server为 null 感知。 这是为使在 UDT 中执行的代码能够识别 Null 值所必需的。

  • UDT 必须包含一个公共 静态 (或 Shared) Parse 方法(支持从 中进行分析)和一个用于转换为对象的字符串表示形式的公共 ToString 方法。

  • 具有用户定义的序列化格式的 UDT 必须实现 System.Data.IBinarySerialize 接口并提供 ReadWrite 方法。

  • UDT 必须实现 System.Xml。Serialization.IXmlSerializable 或所有公共字段和属性的类型都必须是 XML 可序列化或用 XmlIgnore 属性修饰的类型(如果需要重写标准序列化)。

  • 一个 UDT 对象必须只存在一个序列化。 如果序列化或反序列化例程识别了某一特定对象的多个表示形式,则验证将失败。

  • SqlUserDefinedTypeAttribute.IsByteOrdered 必须 为 true 才能按字节顺序比较数据。 如果未实现 IComparable 接口,并且 SqlUserDefinedTypeAttribute.IsByteOrderedfalse,则字节顺序比较将失败。

  • 在类中定义的 UDT 必须具有不采用任何参数的公共构造函数。 您可以选择创建其他重载类构造函数。

  • 该 UDT 必须将数据元素作为公共字段或属性过程公开。

  • 公共名称不能超过 128 个字符,并且必须符合数据库标识符中定义的标识符SQL Server命名规则。

  • sql_variant 列不能包含 UDT 的实例。

  • 无法从 Transact-SQL 访问继承的成员,因为SQL Server类型系统不知道 UDT 之间的继承层次结构。 但是,您可以在创建类的结构时使用继承,并且可以在该类型的托管代码实现方式中调用此类方法。

  • 成员不能被重载,但类构造函数除外。 如果确实创建了重载方法,则注册程序集或在 SQL Server 中创建类型时不会引发错误。 在运行时将检测到重载的方法,而不是在创建类型时检测到。 只要永不调用重载的方法,重载的方法就可以存在于类中。 一旦您调用重载的方法,就会引发错误。

  • 任何 静态 (或 共享) 成员都必须声明为常量或只读。 静态成员将无法改变。

  • 如果 SqlUserDefinedTypeAttribute.MaxByteSize 字段设置为 -1,则序列化的 UDT 可以与当前 2 GB) (LOB) 大小限制 (大对象一样大。 UDT 的大小不能超过 MaxByteSized 字段中指定的值。

注意

尽管服务器不使用它来执行比较,但可以选择实现 System.IComparable 接口,该接口公开单个方法 CompareTo。 此方法用于客户端上希望精确比较或排序 UDT 值的情况中。

本机序列化

为您的 UDT 选择正确的序列化属性取决于您正尝试创建的 UDT 的类型。 本机序列化格式利用非常简单的结构,使SQL Server能够在磁盘上存储 UDT 的高效本机表示形式。 如果 UDT 简单且仅包含以下类型的字段,则建议使用 本机 格式:

boolbytesbyteshortushortintuintlongulongfloatdoubleSqlByteSqlInt16SqlInt32SqlInt64SqlDateTimeSqlSingleSqlDoubleSqlMoneySqlBoolean

由上述类型的字段组成的值类型非常适合 本机 格式,例如 Visual C# 中的 结构 、 (或 Visual Basic) 中已知的 结构 。 例如,使用 本机 序列化格式指定的 UDT 可能包含另一个 UDT 的字段,该字段也是使用 本机 格式指定的。 如果 UDT 定义更为复杂,并且包含上述列表中的数据类型,则必须改为指定 用户定义的 序列化格式。

本机格式具有以下要求:

  • 类型不得指定 Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute.MaxByteSize 的值。

  • 所有字段必须均可序列化。

  • 如果 UDT 是在类而不是结构中定义的,则必须将 System.Runtime.InteropServices.StructLayoutAttribute 指定为 StructLayout.LayoutKindSequential 。 此属性控制数据字段的物理布局,并用来按照成员的出现顺序对它们进行布局。 SQL Server使用此属性来确定具有多个值的 UDT 的字段顺序。

有关使用 本机 序列化定义的 UDT 的示例,请参阅 编码User-Defined类型中的点 UDT。

UserDefined 序列化

Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute 属性的 UserDefined 格式设置使开发人员可以完全控制二进制格式。 将 Format 属性属性指定为 UserDefined 时,必须在代码中执行以下操作:

  • 指定可选的 IsByteOrdered 属性。 默认值是 false秒。

  • 指定 Microsoft.SqlServer.Server.SqlUserDefinedTypeAttributeMaxByteSize 属性。

  • 编写代码,通过实现 System.Data.Sql.IBinarySerialize 接口来实现 UDT 的 ReadWrite 方法。

有关使用 用户定义的 序列化定义的 UDT 的示例,请参阅 编码User-Defined类型中的货币 UDT。

注意

为了编制索引,UDT 字段必须使用本机序列化或者是持久化的。

序列化特性

属性确定如何使用序列化来构造 UDT 的存储表示形式以及如何按值将 UDT 传输到客户端。 创建 UDT 时,需要指定 Microsoft.SqlServer.Server.SqlUserDefinedTypeAttributeMicrosoft.SqlServer.Server.SqlUserDefinedTypeAttribute 属性指示类是 UDT,并指定 UDT 的存储。 可以选择指定 Serializable 属性,但SQL Server不需要此属性。

Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute 具有以下属性。

格式
指定序列化格式,可以是 本机 格式或 用户定义格式,具体取决于 UDT 的数据类型。

IsByteOrdered
一个布尔值,确定SQL Server如何对 UDT 执行二进制比较。

IsFixedLength
指示此 UDT 的所有实例是否都具有相同的长度。

MaxByteSize
实例的最大大小(以字节为单位)。 必须使用用户定义的序列化格式指定 MaxByteSize。 对于指定了用户定义序列化的 UDT, MaxByteSize 引用其序列化形式的 UDT 的总大小(由用户定义)。 MaxByteSize 的值必须在 1 到 8000 的范围内,或设置为 -1 以指示 UDT 大于 8000 字节 (总大小不能超过最大 LOB 大小) 。 考虑一个 UDT,其属性为 10 个字符的字符串 (System.Char) 。 当使用 BinaryWriter 序列化 UDT 时,序列化字符串的总大小为 22 字节:每个 Unicode UTF-16 字符占 2 个字节,乘以最大字符数,再加上因序列化二进制流而导致的系统开销 2 个控制字节。 因此,在确定 MaxByteSize 的值时,必须考虑序列化 UDT 的总大小:以二进制形式序列化的数据的大小以及序列化产生的开销。

ValidationMethodName
用于验证 UDT 的实例的方法的名称。

设置 IsByteOrdered

Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute.IsByteOrdered 属性设置为 true 时,实际上可以保证序列化的二进制数据可用于信息的语义排序。 因此,以字节排序的 UDT 对象的每个实例只能有一种序列化表示形式。 在序列化字节SQL Server中执行比较操作时,其结果应与托管代码中发生的相同比较操作相同。 当 IsByteOrdered 设置为 true 时,也支持以下功能:

  • 可以对此类型的列创建索引。

  • 可以对此类型的列创建主键和外键以及 CHECK 和 UNIQUE 约束。

  • 能够使用 Transact-SQL ORDER BY、GROUP BY 和 PARTITION BY 子句。 此时,将使用该类型的二进制表示形式确定顺序。

  • 在 Transact-SQL 语句中使用比较运算符的功能。

  • 可以保持此类型的计算列。

请注意,当 IsByteOrdered 设置为 true,NativeUserDefined 序列化格式都支持以下比较运算符:

  • 等于 (=)

  • 不等于 (!=)

  • 大于号 (>)

  • 小于号 (<)

  • 大于或等于 (>=)

  • 小于或等于 (<=)

实现为 Null 性

除了正确指定程序集的属性外,类还必须支持为 Null 性。 加载到SQL Server中的 UDT 是 null 感知的,但为了使 UDT 识别 null 值,类必须实现 INullable 接口。 有关详细信息以及如何在 UDT 中实现可为空性的示例,请参阅 编码User-Defined类型

字符串转换

若要支持与 UDT 的字符串转换,必须在类中提供 Parse 方法和 ToString 方法。 Parse 方法允许将字符串转换为 UDT。 它必须在 Visual Basic) 中声明为 静态 (或 共享 ,并采用 类型为 System.Data.SqlTypes.SqlString 的参数。 有关详细信息以及如何实现 ParseToString 方法的示例,请参阅 编码User-Defined类型

XML 序列化

UDT 必须通过符合 XML 序列化协定来支持与 xml 数据类型的转换。 System.Xml。序列化命名空间包含用于将对象序列化为 XML 格式的文档或流的类。 可以选择使用 IXmlSerializable 接口实现 xml 序列化,该接口为 XML 序列化和反序列化提供自定义格式。

除了执行从 UDT 到 xml 的显式转换外,XML 序列化还使你能够:

  • 在转换为 xml 数据类型后,对 UDT 实例的值使用 Xquery

  • 在参数化查询中使用 UDT,在 Web 方法中使用本机 XML Web 服务SQL Server。

  • 使用 UDT 可以接收 XML 数据的大容量加载。

  • 序列化包含具有 UDT 列的表的数据集。

UDT 在 FOR XML 查询中不序列化。 若要执行显示 UDT XML 序列化的 FOR XML 查询,请在 SELECT 语句中将每个 UDT 列显式转换为 xml 数据类型。 还可以将列显式转换为 varbinaryvarcharnvarchar

另请参阅

创建User-Defined类型