我们通过如程序代码列表11-20的 T-SQL 语法对该数据表进行添加、修改与查询数据的操作:
程序代码列表 11-20:通过 T-SQL 访问用户自定义数据类型
--各属性的大小写有别
--若当前的数据填错,不必等到 Insert 就会有错误出来
DECLARE @s Seat,@s2 Desk
SET @s=CONVERT(Seat,N'25,香蕉椅')
SET @s2=CONVERT(Desk,N'100,餐桌')
INSERT BikeSeats VALUES(@s,@s2)
SET @s=CONVERT(Seat,N'20,飞行椅')
SET @s2=CONVERT(Desk,N'30,小圆桌')
INSERT BikeSeats VALUES(@s,@s2)
GO
--若没有定义 Mutator 函数,
--直接 Update 一个用户自定义类型两个以上的属性时,
--无法以一句话来设
UPDATE BikeSeats SET deskInfo.Size=30 WHERE SeatID=2
UPDATE BikeSeats SET deskInfo.Type=N'小方桌' WHERE SeatID=2
GO
--可以通过 "字段.属性" 的方式取得自定义类型个别的属性
SELECT SeatID, SeatInfo.Size '尺寸',SeatInfo.Type '样式',
DeskInfo.Size '尺寸2',DeskInfo.Type '样式2' FROM BikeSeats
程序代码列表11- 20 中的 SELECT 查询结果如图11-25 所示:
图11-25 查询数据表中的自定义数据类型的内容
通过CONVERT 函数调用两个类各自实现的 ToString 函数:
SELECT CONVERT (nvarchar, SeatInfo), CONVERT (nvarchar, DeskInfo) FROM BikeSeats
WHERE SeatID=1
我们可以得到如图11-26 的结果:
图11-26 查询数据表中的自定义数据类型的内容
程序式码列表 11-20 中我通过一般的 Update 语法来更新自定义数据类型的内容,但若该类型有两个以上的属性时,就会需要两句独立的 Update 语法来分别设置不同的属性,这会让人觉得很笨 L。为此,你需要在类中定义 Mutator 函数,并通过 IsMutator 参数定义该函数可用来更新数据,程序代码范例如程序代码列表11-21:
程序代码列表 11-21 通过自定义的 Mutator 函数来更新自定义数据类型的内容
'Mutator 让 T-SQL 可以执行如下的语法
' Update tbl Set <UDT 字段>.<Mutator 函数()> WHERE...
<SqlMethod(ismutator:=True, onnullcall:=False)> _
Public Sub SetDesk(ByVal sSize As SqlTypes.SqlInt16, _
ByVal strType As SqlTypes.SqlString)
'避免用户在 Update 时输入 NULL,所以通过 SqlTypes
'来定义数据类型,并检查 NULL
If sSize.IsNull Or strType.IsNull Then
m_size = -1
m_type = "类型不明"
is_Null = True
Else
Me.Size = sSize.Value
Me.Type = strType.Value
End If
End Sub
当有 Mutator 函数后,就可以通过调用该函数,以一句 T-SQL 语法更新自定义类型的多个属性:
UPDATE BikeSeats SET DeskInfo.SetDesk(40,N'小方桌') WHERE SeatID=2
我们接着通过如程序代码11-22的T-SQL语法插入 NULL 数据,通过T-SQL 的 Convert 函数来检验类 (VB.NET 的 Sub New) ToString 与 Parse 等函数的功能是否正常。
程序代码列表11-22 针对用户自定义数据类型进一步测试其他的运算
--测试 NULL
--故意加入 NULL 数据
INSERT BikeSeats DEFAULT VALUES
GO
DECLARE @s Seat,@s2 Desk
INSERT BikeSeats VALUES(@s,@s2)
--查看覆写 ToString 函数时,是否有考虑到 NULL
SELECT CONVERT(nvarchar,SeatInfo),CONVERT(nvarchar,DeskInfo) FROM BikeSeats
测试结果如图11-27所示。
图11-27 查询数据表中的自定义数据类型的内容
另外,我们再编写一个用户自定义函数如程序代码列表11-23,以此调用程序代码列表11-17 所提供的 IComparable 接口所实现的 CompareTo函数,该函数放在上一节所介绍的用户自定义函数的类内,注册与使用皆是以用户自定义函数的方式:
程序代码列表11-23 以 .NET 编写用户自定义函数,以此比较自定义数据类型的大小
'传进用户自定义数据类型,通过数据类型类所实现的 CompareTo 函数比较大小
<System.Data.Sql.SqlFunction(Name:="CompareDesk", IsDeterministic:=True)> _
Public Shared Function CompareDesk (ByVal obj1 As Desk, ByVal obj2 As Desk, _
ByVal intCompare As Integer) As Integer
Select Case intCompare
Case 0 '依照预定 Desk 自己的 CompareTo 比较
Return obj1.CompareTo(obj2)
Case 1 '依照 Size 比
Return obj1.Size.CompareTo(obj2.Size)
Case 2 '依照 Type 比
Return obj1.ToString.CompareTo(obj2.Type)
End Select
End Function
在上述范例中我们提供用户输入两个 Desk 类型的变量,并通过第三个参数决定比较的方式。而第一种比较方式就是调用程序代码列表11-17 的 CompareTo 方法。第二与第三种选择则是分别以各变量数据类自身提供的 CompareTo 方法做比较,也就是数值或字符串数据的比较。
接着,我们通过 T-SQL 来比较一下存入数据表内的用户自定义数据类实例的大小,程序代码范例如程序代码列表11-24:
程序代码列表11-24 比较自定义数据类实例的大小
CREATE FUNCTION CompareDesk(@obj1 Desk,@obj2 Desk,@intCompare INT)
RETURNS INT
EXTERNAL NAME YukonCLR.[YukonCLR.UserDefineFunc].CompareDesk
--数据类型比较
--通过 SqlUserDefinedType 属性设置参数 IsByteOrdered:=True
--以序列化过后的二进制字节内容来比较大小
DECLARE @s desk,@s2 desk,@res INT
SELECT @s=deskInfo FROM BikeSeats WHERE SeatID=1
SELECT @s2=deskInfo FROM BikeSeats WHERE SeatID=2
PRINT N'依照 Serialize 后的 Bynary 比:'
IF @s>@s2
PRINT CONVERT(nvarchar,@s) + ' > ' + CONVERT(nvarchar,@s2)
ELSE
BEGIN
IF @s=@s2
PRINT CONVERT(nvarchar,@s) + ' = ' + CONVERT(nvarchar,@s2)
ELSE
PRINT CONVERT(nvarchar,@s) + ' < ' + CONVERT(nvarchar,@s2)
END
--调用自定义的 Comparedesk 函数比较大小
PRINT ''
PRINT N'调用我们在类内编写的 CompareTo 函数,也就是依照 ToString 的字符串大小比:'
SELECT @res=dbo.Comparedesk(@s,@s2,0)
IF @res>0
PRINT CONVERT(nvarchar,@s) + ' > ' + CONVERT(nvarchar,@s2)
ELSE
BEGIN
IF @res=0
PRINT CONVERT(nvarchar,@s) + ' = ' + CONVERT(nvarchar,@s2)
ELSE
PRINT CONVERT(nvarchar,@s) + ' < ' + CONVERT(nvarchar,@s2)
END
PRINT ''
PRINT N'依照 type 的字符串大小比:'
SELECT @res=dbo.Comparedesk(@s,@s2,2)
IF @res>0
PRINT CONVERT(nvarchar,@s) + ' > ' + CONVERT(nvarchar,@s2)
ELSE
BEGIN
IF @res=0
PRINT CONVERT(nvarchar,@s) + ' = ' + CONVERT(nvarchar,@s2)
ELSE
PRINT CONVERT(nvarchar,@s) + ' < ' + CONVERT(nvarchar,@s2)
END
程序代码列表 11-24 的执行结果如下:
依照 Serialize 后的 Bynary 比:
100,餐桌 > 30,小方桌
调用我们在类内编写的 CompareTo 函数,也就是依照 ToString 的字符串大小比:
100,餐桌 < 30,小方桌
依照 type 的字符串大小比:
100,餐桌 > 30,小方桌
另外,若 SqlUserDefinedType 属性设置成 IsByteOrderd,则以用户自定义类型所定义的数据字段内的实例可以直接比较大小(比较大小时依照 binary 的内容比大小)。因此也能够在该字段上设置索引,我们以下列的 T-SQL 语法在用户自定义数据类型所定义的字段上创建索引并测试。
CREATE INDEX idxSeat ON BikeSeats(DeskInfo)
SELECT SeatID, DeskInfo.Size '尺寸',DeskInfo.Type '样式2' FROM BikeSeats
ORDER BY DeskInfo
最后,我们通过以下的 T-SQL 语法直接调用自定义数据类型类内所定义的方法:
SELECT DeskInfo.GetPrice() 餐桌价格 FROM BikeSeats
执行结果如下:
餐桌价格
-----------
200
300
若要部署该用户自定义数据类型到 SQL Server 2005,除了可以通过 Visual Studio 2005 提供的部署功能外,你还可以使用如程序代码列表11-25所示的T-SQL语法:
程序代码列表11-25 通过 T-SQL 定义通过 .NET 编写的用户自定义数据类型
CREATE ASSEMBLY YukonCLR FROM
'C:\BookSamples\SQL 2005 Dev\Ch11_Clr\YukonCLR\bin\YukonCLR.dll'
WITH PERMISSION_SET = UNSAFE
GO
CREATE TYPE Seat
EXTERNAL NAME YukonCLR.[YukonCLR.Seat]
GO
CREATE TYPE Desk
EXTERNAL NAME YukonCLR.[YukonCLR.Desk]
最后,若要移除数据库内先前建立的用户自定义数据类型,记得要先移除数据表,因为该数据表参照了用户自定义数据类型。然后才可以移自定义数据类型,之后才是组件。下列为移除的顺序。
DROP TABLE BikeSeats
DROP TYPE Seat
DROP TYPE Desk
DROP ASSEMBLY YukonClr
由于用户自定义数据类型提供了强大的数据定义功能,或许可以让你用它来实际操作局部的面向对象数据库。但相对来说,若用得不好,一定会造成数据处理上的不稳定,甚至性能不佳,因此在设计时不可不慎。
上一页 [1] [2] [3] [4] [5] [6] 下一页
责任编辑:cyth