UTF-8 支持、SQL Server 2012 和 UTF8String UDT

2023-11-29

针对我的特定应用程序,研究了 SQL Server VARCHAR 与 NVARCHAR 的优缺点,我意识到如果 SQL Server 本身支持 UTF8 将是理想的选择。一些 SO 帖子表明事实并非如此,例如:

VARCHAR 完全像 20 世纪 90 年代吗?

varchar 和 nvarchar SQL Server 数据类型之间的主要性能差异是什么?

然而,后来我在 SQL Server 2012 的 MSDN 文档中发现了这篇文章,其中展示了如何创建 UTF8String 用户定义的数据类型:

http://msdn.microsoft.com/en-us/library/ff877964(v=sql.110).aspx

看起来 UDT 将允许每个字符 8 位的空间(内存、磁盘)优势,同时足够灵活,可以存储可以用 UTF-8 表示的任何字符串。那是对的吗?此策略是否有缺点(例如,为每行执行托管代码的性能成本……)?


通过 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

考虑到添加的持久计算列和索引的数量,真的节省了空间吗? ;-)


如果需要考虑空间(磁盘、内存等),您有以下三种选择:

  1. 如果您使用的是 SQL Server 2008 或更高版本,并且使用的是企业版,那么您可以启用数据压缩。数据压缩可以(但不会“总是”)压缩 Unicode 数据NCHAR and NVARCHAR字段。决定因素是:

    1. NCHAR(1 - 4000) and NVARCHAR(1 - 4000)使用Unicode 标准压缩方案,但仅从 SQL Server 2008 R2 开始,并且仅适用于 IN ROW 数据,不适用于 OVERFLOW!这似乎比常规的 ROW/PAGE 压缩算法更好。
    2. NVARCHAR(MAX) and XML(而且我想也VARBINARY(MAX), TEXT, and NTEXT) IN ROW(不在 LOB 或 OVERFLOW 页中的行外)的数据至少可以进行 PAGE 压缩,并且maybe还进行了 ROW 压缩(不确定最后一个)。
    3. 任何 OFF ROW 数据、LOB 或 OVERLOW = 不进行压缩!
  2. 如果使用 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)
           );
    
  3. 如果您的字段应该只包含适合扩展 ASCII 字符集的特定代码页的字符,那么只需使用VARCHAR.


附:只是为了清楚起见而说明:新_SCSQL Server 2012 中引入的排序规则仅允许:

  • 正确处理补充字符/代理对的内置函数,以及
  • 用于排序和比较的补充字符的语言规则

但是,即使没有新的_SC排序规则,您仍然可以将任何 Unicode 字符存储到 XML 或N-前缀类型,并在不丢失数据的情况下检索它。但是,当使用较旧的排序规则(即名称中没有版本号)时,所有补充字符彼此相等。您需要使用_90 and _100至少可以进行二进制/代码点比较和排序的排序规则;它们无法考虑语言规则,因为它们没有补充字符的特定映射(因此没有权重或规范化规则)。

请尝试以下操作:

IF (N'									
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

UTF-8 支持、SQL Server 2012 和 UTF8String UDT 的相关文章

  • WinForms 应用程序设计 - 将文档从 SQL Server 移动到文件存储

    我有一个连接到 SQL Server 的标准 WinForms 应用程序 该应用程序允许用户上传当前存储在数据库中的文档 在使用图像列的表中 我需要更改这种方法 以便将文档存储为文件 并将文件的链接存储在数据库表中 使用当前的方法 当用户上
  • 需要 SQL Server 查询帮助

    我在视图中存储一堆数据 将 MS Access 查询转换为视图 现在我想做的是编写一个存储过程来根据添加数据的时间提取数据 这是我正在运行的查询 Select Name PlanID ApptDate 1stAppt rn from Sel
  • Docker连接SQL Server容器非零代码:1

    我正在尝试从创建一个 SQL Server 容器docker compose yml但是当我运行它时 它直接停止并出现一些错误 注意 它运行在带有 docker Preview 的 Apple M1 芯片上 docker compose y
  • 查询所有表数据并进行索引压缩

    是否有人碰巧拥有一个通用 SQL 语句 可以列出数据库中每个分区的所有表和索引及其当前的压缩设置 Thanks 编辑 这是我尝试查询表所得到的 但我不确定连接是否正确 我得到了重复项 这似乎是由于索引的存在引起的 SELECT t name
  • Id 或 [TableName]Id 作为主键/实体标识符

    是否首选使用 Id 作为主键的列名或 TableName Id 作为命名约定 表 账户主键 ID 相对 表 账户主键 AccountId 在我见过的实现中 它似乎分为 50 50 左右 每种方法的优点和缺点是什么 跟进 在我的数据库中使用一
  • 使用 Switch 的报告服务表达式

    我无法让这个表达式与报告服务一起使用 我必须使用 IF 和 ELSE IF 语句 感谢您的任何建议 Switch IsNothing Fields field date Value Fields set flag Value 1 Decli
  • 将大量实体插入 SQL Server 2012 [重复]

    这个问题在这里已经有答案了 我正在进行一个使用 Entity Framework 5 和 SQL Server 2012 的项目 我们需要一次插入大量行 100k 个实体的顺序 基本上 我们有一个物理程序 它输出大量二进制数据 然后我们需要
  • 连接两个表的查询的 SQL Server“FOR XML”输出

    我是 SQL Server 中 FOR XML 功能的新手 我正在使用 SQL Server 2012 我有两个表 Word 和 Word Expansion 样本数据 表 字 WordOID Word 1 PIPE 2 WIRE 表 Wo
  • SQL Server 用分隔符分割字符串

    我有一个输入字符串 100 2 3 101 2 1 103 2 3 我想解析它并将其添加到具有 3 列的表中 因此它应该是 f x col1 col2 col3 100 2 3 类似的其他数据以逗号分隔作为记录和 作为列 Thanks ni
  • Perl 和 Unix 如何以相同的顺序对 Unicode 字符串进行排序?

    我正在尝试获取 Perl 和 GNU Linuxsort 1 程序就如何对 Unicode 字符串进行排序达成一致 我在跑sort with LANG en US UTF 8 在Perl程序中我尝试了以下方法 use Unicode Col
  • Kerberos 双跳

    我们遇到了臭名昭著的 Kerberos 双跳问题 这是一个全新的域 是从以前使用模拟和委派的另一个提供商迁移而来的 我们已将操作系统升级到最新的 SQL 服务器 2017 WPF 应用程序 使用域凭据 gt Web 服务 IIS 10 上的
  • sql server 按组排名

    问题看似简单 但我却无法理解 这是针对 sql 服务器的 what I have in a table What I need as a output cksum id cksum id 2162514679 204 2162514679
  • 对多个数据库执行 SQL 查询

    我知道我的帖子与该论坛中的其他帖子的标题非常相似 但我真的找不到我需要的答案 这是我的问题 我的 Windows Server 上运行着 SQL Server 在我的 SQL Server 中 我有大约 30 个数据库 它们都具有相同的表和
  • Spark.read 在 Databricks 中给出 KrbException

    我正在尝试从 databricks 笔记本连接到 SQL 数据库 以下是我的代码 jdbcDF spark read format com microsoft sqlserver jdbc spark option url jdbc sql
  • C# 按钮文本 Unicode 字符

    C 不想在按钮上放置 Unicode 字符 如果我将 u2129 放入按钮的 文本 属性中 按钮将显示 u2129 而不是 Unicode 字符 例如 我选择 2129 因为我可以在计算机上当前活动的字体中看到它 我之前看到过这个问题链接文
  • 如何在 SQL Server 存储过程中对用户定义的表类型执行 ForEach?

    XX PROCEDURE dbo XXX X dbo IntType readonly AS BEGIN SET NOCOUNT ON how can I foreach X here and do process individually
  • C#的数组列表可以用来填充SSIS对象变量吗?

    我已在 C 脚本中填充了一个列表 并将其值分配给 SSIS 对象变量 然后 我使用该对象变量通过循环遍历 For every do 枚举器来执行一些 SQL 查询 我尝试通过 Foreach ado 枚举器执行此操作 但出现错误 X 变量不
  • 临时表是线程安全的吗?

    我正在使用 SQL Server 2000 它的许多存储过程广泛使用临时表 数据库的流量很大 我担心创建和删除临时表的线程安全性 假设我有一个存储过程 它创建了一些临时表 它甚至可以将临时表连接到其他临时表等 并且还可以说两个用户同时执行存
  • Android访问远程SQL数据库

    我可以直接从 Android 程序访问远程 SQL 数据库 在网络服务器上 吗 即简单地打开包含所有必需参数的连接 然后执行 SQL 查询 这是一个私人程序 不对公众开放 仅在指定的手机上可用 因此我不担心第三方获得数据库访问权限 如果是这
  • 如何跨多个表强制执行 CHECK 约束

    我有一个在 Microsoft SQL Server 2012 Express 中记录奶牛繁殖信息的数据库 显然 一头牛只有在出生后才能配种 并且在其一生中可能会配种多次 我需要在我的数据库中强制执行这些约束 我目前已经根据下图安排了一个架

随机推荐

Powered by Hwhale