托管 UDT 使您能够扩展 SQL Server 的类型系统
2007-11-11 04:48:09 来源:WEB开发网在 sql server(WINDOWS平台上强大的数据库平台) 中使用 UDT 创建程序集
一旦将该类编译为程序集,下一步便是在 sql server(WINDOWS平台上强大的数据库平台) Yukon 中注册它。为此,首先需要使用 CREATE ASSEMBLY 语句装载程序集,这样便在当前数据库中注册了程序集。请记住,如果想要在多个数据库中使用一个程序集,必须分别在每个数据库中注册程序集。其语法如下:
CREATE ASSEMBLY ASSEMBLY_NAME FROM 'PATH\ASSEMBLY_NAME.dll'
注意 SQL 程序集名必须与 CLR 程序集名匹配,否则将不能注册。下面是一个示例:
CREATE Assembly YukonCLR FROM'C:\Projects\"Yukon"\UDTs\Point\"Yukon"CLR.dll'
被注册的程序集仅在当前数据库的上下文中存在,并且存储在几个系统对象中。这里暗示,文件系统中的 DLL 仅在创建 DLL 的内部表示形式时被引用一次。完成程序集的注册后,其 DLL 能够从文件系统中删除,而 Yukon 中的 UDT 将继续正常工作。既然程序集被装载到当前的数据库,它将不能被其他数据库所使用。每一个需要程序集引用的数据库必须自己调用 CREATE ASSEMBLY 语句。尽管这听起来显而易见,还是应该注意只有编译了的 DLL 被装载到数据库中,而源代码并没有被装载。正如 sql server(WINDOWS平台上强大的数据库平台) 中的所有对象一样,程序集名必须遵照 sysname 约定(最大长度为 128 字符)。
创建类型
看一下 CREATE TYPE 语句的语法:
CREATE TYPE [TYPE_SCHEMA_NAME.]TYPE_NAME EXTERNAL NAMEASSEMBLY_NAME:CLASS_NAME
只要装载了程序集,便可以使用 CREATE TYPE 语句向数据库的可用类型列表中添加类型。与程序集一样,类型仅在当前数据库中创建,而且与程序集一样也被 sysname 约定所限制。下面的示例将从我刚才展示过的 Visual Basic .NET CLR 代码中创建 Point UDT:
CREATE TYPE Point EXTERNAL NAME YukonCLR:Point
UDT 的名字(这里为 Point)对于数据库上下文中给定的架构名必须唯一。这意味着如果有两个不同的程序集在数据库中注册,且它们含有共同的类名,那么这些类中仅有一个能够被创建为同一个架构中数据库里的类型。在下面的代码示例中,Point 类既存在于 YukonCLR 程序集中,同时也存在于 YukonCLR2 程序集中。一旦 YukonCLR 的 Point 类被创建为当前数据库中的 UDT,YukonCLR2 中的 Point 类除非在一个不同的架构中创建,否则将不能被创建。现在,假设下面的示例在 MySchema 架构中创建:
CREATE Assembly YukonCLR FROM 'C:\Projects\Yukon\UDTs\Point\YukonCLR.dll'CREATE Assembly YukonCLR2 FROM 'C:\Projects\Yukon\UDTs\Point\YukonCLR2.dll'CREATE TYPE Point EXTERNAL NAME YukonCLR:Point --OKCREATE TYPE Point EXTERNAL NAME YukonCLR2:Point--BAD - created in MySchemaCREATE TYPE DifferentSchema.Point EXTERNAL NAME YukonCLR2:Point--OK - created in DifferentSchemaCREATE TYPE Point EXTERNAL NAME YukonCLR2:Triangle --OK
使用 UDT
当类型注册为数据库的可用类型之一后,就可以开始在创建对象(如表)时使用它,如下所示:
CREATE TABLE Points(PointID int NOT NULL,Pnt Point NOT NULL)
在表定义中使用 UDT 不需要特殊编码。使用与内部类型(如 int 或 nchar)一样的方式来定义表。
在我深入阐述之前,让我们看一下使用 Yukon 中用户定义类型的属性和方法的语法。它非常类似于 C# 和 Visual Basic .NET 的语法,只不过在这里属性或方法前面是两个冒号 (::) 而不是一个句点。到 Beta2 版时,:: 符号将要消失,而代之以句点符号。以下为属性和方法的语法:
Property Use Syntax: <implemented_type>::<property_name> =<scalar_expression>Method Use Syntax: <implemented_type>::<method_name>([arguments])
要使用 T-SQL 为表填充数据,可以运行如下脚本:
DECLARE @startPoint PointDECLARE @endPoint PointSET @startPoint = CAST('10:10' AS Point)SET @endPoint::X = 5SET @endPoint::Y = 3INSERT PointsVALUES(1, @startPoint)INSERT PointsVALUES(2, @endPoint)
对于任何使用过以前版本 sql server(WINDOWS平台上强大的数据库平台) 的 T-SQL 变量、DML 语句以及 SELECT 语句的人来说,这些代码中许多都是很熟悉的。但是,还是有一些 T-SQL 代码的元素不太一样。第一个是使用 CAST 函数将 X 和 Y 的值赋给 @startPoint。当您以这种方式使用 CAST 函数时,将对 UDT 调用 Parse 方法以便为 UDT 实例填充数据。接下来,@endPoint 变量的 X 和 Y 属性被单独设置,从而使您能够显示地把值传递给 UDT 的属性。
代码的下一部分使用标准的 INSERT 语句把 UDT 类型的实例插入到 Points 表中。从存储在表中的 UDT 选择适当的值是通过语法 ColumnName::Property 或 ColumnName::Method 指定想调用的属性或方法的过程。即使方法不带参数,同样需要圆括号。在随后的示例中,您将从整个点集中选取 X 和 Y 的值:
SELECT Pnt::X AS XValue, Pnt::Y AS YValue FROM Points
在这里我将选取一点并将它存储到变量 @pt 中,然后使用 DistanceTo 方法检查该点到表中另外一点的距离:
DECLARE @pt PointSELECT @pt = Pnt FROM Points WHERE PointID = 2SELECT Pnt::DistanceTo(@pt) AS DistanceFROM PointsWHERE PointID = 1
下一个例子,如图 6 所示,说明了如何在 Yukon 中使用 Address 类(假设其为 YukonCLR 程序集的一部分并且您已经创建了它的类型)。首先,创建类型 Address 的三个变量。其次,赋予地址信息并使用 cityStateZip 方法获取格式化的城市、州以及邮政编码。代码的第二部分利用 CAST 函数将第一个地址 (@addr) 复制到第二个地址 (@addr2) 中。这创建了一个副本,而不是对第一个变量的引用。随后对于 @addr 的任何改变将不会反映在 @addr2 中。最后,检查变量 @addr3 以确定它是否为空。由于该变量只是被声明而从未被赋值,它实际上为空,正如您看到的那样。
更多精彩
赞助商链接