通过 SQLCLR 创建自定义用户定义类型是not,以任何方式,将为您提供任何本机类型的替代品。它对于创建处理专门数据的东西非常方便。但字符串,即使是不同的编码,也远非专业化。对字符串数据采用这种方法会破坏系统的任何可用性,更不用说性能,因为您将无法使用any内置字符串函数。
如果您能够节省磁盘空间上的任何内容,那么您所损失的整体性能就会抹去这些收益。存储 UDT 是通过将其序列化为VARBINARY
。所以为了做到any字符串比较或排序,除了“二进制”/“序数”比较之外,您必须将所有其他值一一转换回 UTF-8,然后进行可以考虑语言差异的字符串比较。该转换需要在 UDT 内完成。这意味着,与 XML 数据类型一样,您将创建 UDT 来保存特定值,然后公开该 UDT 的方法来接受字符串参数来进行比较(即Utf8String.Compare(alias.field1)
或者,如果为该类型定义一个运算符,则Utf8string1 = Utf8string2
并拥有=
运算符获取UTF-8编码的字符串,然后执行CompareInfo.Compare()
).
除了上述注意事项之外,您还需要考虑通过 SQLCLR API 来回传递值会产生成本,尤其是在使用NVARCHAR(MAX)
or VARBINARY(MAX)
相对于NVARCHAR(1 - 4000)
and VARBINARY(1 - 4000)
分别(请不要将这种区别混淆为暗示使用SqlChars
/ SqlBytes
vs SqlString
/ SqlBinary
).
最后(至少在使用 UDT 方面),请不要忽视这样一个事实:正在查询的 UDT 是示例代码。唯一提到的测试纯粹是功能性的,没有涉及可扩展性或“使用一年后学到的经验教训”。功能测试代码显示在下面的 CodePlex 页面上,在继续做出此决定之前应该先查看一下,因为它让您了解如何编写查询以便与其交互(这对于字段或字段来说很好)两个,但是not对于大多数/所有字符串字段):
http://msftengprodsamples.codeplex.com/SourceControl/latest#Kilimanjaro_Trunk/Programmability/CLR/UTF8String/Scripts/Test.sql
考虑到添加的持久计算列和索引的数量,真的节省了空间吗? ;-)
如果需要考虑空间(磁盘、内存等),您有以下三种选择:
-
如果您使用的是 SQL Server 2008 或更高版本,并且使用的是企业版,那么您可以启用数据压缩。数据压缩可以(但不会“总是”)压缩 Unicode 数据NCHAR
and NVARCHAR
字段。决定因素是:
-
NCHAR(1 - 4000)
and NVARCHAR(1 - 4000)
使用Unicode 标准压缩方案,但仅从 SQL Server 2008 R2 开始,并且仅适用于 IN ROW 数据,不适用于 OVERFLOW!这似乎比常规的 ROW/PAGE 压缩算法更好。
-
NVARCHAR(MAX)
and XML
(而且我想也VARBINARY(MAX)
, TEXT
, and NTEXT
) IN ROW(不在 LOB 或 OVERFLOW 页中的行外)的数据至少可以进行 PAGE 压缩,并且maybe还进行了 ROW 压缩(不确定最后一个)。
- 任何 OFF ROW 数据、LOB 或 OVERLOW = 不进行压缩!
-
如果使用 2008 年之前的版本或不是企业版,则可以有两个字段:一VARCHAR
和一个NVARCHAR
。例如,假设您存储的 URL 大部分都是基本 ASCII 字符(值 0 - 127),因此适合VARCHAR
,但有时有 Unicode 字符。您的架构可以包含以下 3 个字段:
...
URLa VARCHAR(2048) NULL,
URLu NVARCHAR(2048) NULL,
URL AS (ISNULL(CONVERT(NVARCHAR([URLa])), [URLu])),
CONSTRAINT [CK_TableName_OneUrlMax] CHECK (
([URLa] IS NOT NULL OR [URLu] IS NOT NULL)
AND ([URLa] IS NULL OR [URLu] IS NULL))
);
在这个模型中你only选择从[URL]
计算列。对于插入和更新,您可以通过查看转换是否改变传入值来确定要使用哪个字段,该值必须是NVARCHAR
type:
INSERT INTO TableName (..., URLa, URLu)
VALUES (...,
IIF (CONVERT(VARCHAR(2048), @URL) = @URL, @URL, NULL),
IIF (CONVERT(VARCHAR(2048), @URL) <> @URL, NULL, @URL)
);
如果您的字段应该只包含适合扩展 ASCII 字符集的特定代码页的字符,那么只需使用VARCHAR
.
附:只是为了清楚起见而说明:新_SC
SQL Server 2012 中引入的排序规则仅允许:
- 正确处理补充字符/代理对的内置函数,以及
- 用于排序和比较的补充字符的语言规则
但是,即使没有新的_SC
排序规则,您仍然可以将任何 Unicode 字符存储到 XML 或N
-前缀类型,并在不丢失数据的情况下检索它。但是,当使用较旧的排序规则(即名称中没有版本号)时,所有补充字符彼此相等。您需要使用_90
and _100
至少可以进行二进制/代码点比较和排序的排序规则;它们无法考虑语言规则,因为它们没有补充字符的特定映射(因此没有权重或规范化规则)。
请尝试以下操作:
IF (N'
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)