为什么在单个数据库中混合列排序规则被认为是不好的?


11

有两个原因促使我问这个问题:

tSQLt当存在具有非默认归类的列时
,T-SQL测试框架tSQLt认为它是“高严重性”问题。测试的作者指出以下内容:

我不建议每个字符串列都应具有与数据库默认排序规则匹配的排序规则。相反,我建议,如果有所不同,应该有充分的理由。

但是,如上所述,失败测试的严重性被认为是很高的。

Octopus Deploy
在配置Octopus Deploy Server时,在OctopusServer-instance初始化期间,安装失败并出现致命错误。与错误消息相关的文章没有解释为什么这样做是必需的,而只是指出,从(包括)Octopus 3.8版开始,它将成为将来部署的要求。

作为附带说明,RedGate的CI工具包DLM自动化套件支持具有多种排序规则的部署,而不会产生任何抱怨。

对我而言,将所有列排序规则保留为数据库默认值的建议似乎更像是准则或最佳实践。为什么有些人将其视为如此严重的错误?


您指的是SQL Cop测试的tSQLt化身。由于tSQLt测试通过或失败,因此必须提供建议的默认值。完全希望用户根据自己的需求调整SQLCop测试,因为它们只不过是tSQLt框架在SQLCop架构中选择的存储过程。
大卫·阿特金森

Answers:


19

对我而言,将所有列排序规则保留为数据库默认值的建议似乎更像是准则或最佳实践。

您在这里是完全正确的。

为什么有些人将其视为如此严重的错误?

出于同样的原因,您经常会听到/读到“ 永远不要使用:”

  • 游标
  • GOTO 陈述
  • SQLCLR
  • WITH (NOLOCK)
  • 等等等等

一些功能/选项/技术比其他功能/选项/技术更复杂,并且通常需要用户更多的知识,因为使用它时遇到麻烦的机会比没有任何问题的机会要大得多。因此,对于一般人群而言,针对此类事物制定通用规则会更容易。实际上,在工作中编写“编码标准”时,我总是有一条永远不要使用CURSOR,但我自己使用它们,因为我知道“何时”使用它们以及“如何”有效使用它们。但是不应该只偶尔写查询的人知道这一点。这也类似于“除非您完全知道自己在做什么,否则不要编辑注册表”,或者类似于我们作为(非常小的)孩子的父母制定的规则,我们需要告诉他们不要仅仅因为他们是无法解决何时可以做某件事或如何去做的复杂性。

在“排序规则”的情况下,这是一个非常复杂且令人困惑的主题,您可能会遇到两种硬错误(这是一个问题,但由于其显而易见且易于修复,因此问题不多)和“奇数”难以解释事物为何按其行为方式运行的行为(为什么某些项目在期望值之外被过滤或未过滤,或者为什么排序在期望值之外发生)。可悲的是,似乎有大量的错误信息在周围徘徊,这进一步加剧了混乱。我实际上正在从事一个项目,以极大地提高整理和编码等方面的常识,并希望消除错误信息和神话,但还没有准备好发布它(完成后,我将通过链接更新它)。

对于整理,您需要使用最适合业务案例的内容。在表或数据库中不混合排序规则的概念是一种默认方法,但是如果您查看用于系统目录视图各列的排序规则,则会注意到正在使用各种排序规则。因此,我同意以下问题的主要引文:如果“归类”将有所不同,这应该是有意为之,但它本身并没有错。


关于这个问题(强调):

在配置Octopus Deploy服务器时,在OctopusServer实例初始化期间,安装失败并显示FATAL错误。与错误消息有关的文章没有解释为什么这是必需的

我检查了链接的文档页面,它确实解释了为什么这样做是必需的。我已经从以下文档中复制了相关信息:

您必须确保还更改了章鱼数据库中所有对象的排序规则,否则在章鱼版本升级期间修改数据库时可能会发生错误。创建的新对象将使用更新的归类,并且在尝试(例如)使用原始归类在这些对象与现有对象之间执行SQL连接时,可能会出现归类不匹配错误。

他们说他们的代码在Octopus数据库中的字符串列之间具有JOIN,并且在将来的升级中可能会引入新的代码,而在新的字符串列中具有附加的JOIN 。如果通过CREATE TABLEALTER TABLE ... ADD,新列将被分配数据库的默认排序规则,如果COLLATE没有为新的字符串列指定关键字。并且,不具有相同归类的字符串列之间的JOIN将产生归类不匹配错误。他们似乎还允许用户选择自己的归类(可能容纳不同的语言环境),因为他们在顶部说,唯一的要求是归类不区分大小写。而且由于不能保证代码所在的数据库排序规则始终相同,因此他们不能使用COLLATE关键字在所有新的字符串列上强制使用相同的排序规则(从技术上讲,它们可以,但是需要动态SQL,因此在生成更新脚本时不容易处理。如果他们能够使用COLLATE关键字,那么他们可以让数据库的默认排序规则与字符串列有所不同。这样可以避免严重的“排序规则不匹配”错误,但仍可能涉及涉及这些字符串列之一和字符串文字或变量的比较操作,从而导致“奇数”行为,因为它将使用列的排序规则而不是数据库的排序规则整理。当然,这很可能是预期的行为。但是,由于这是第三方应用程序,因此行为应该是他们想要的,而不是a)用户想要(或不反对)与b)用户认为有bug(然后在疯狂的追逐和/或关于他们的软件有问题的博客上浪费了供应商的支持时间)。


嘿,有关该项目的有关该项目的任何新闻吗?
Yaroslav

10

简短地说:COLLATION 定义了排序和比较

因此,排序规则确定了SQL Server用于比较和排序字符数据的规则。这些规则了解语言/地区,并且可能对大小写,重音,假名和宽度敏感。排序规则后缀标识字典规则(不区分大小写):_CS(区分大小写),_ CI(不区分大小写),_ AS(区分重音),_ AI(区分重音)和_KS(区分假名)。由后缀_BIN(二进制)和_BIN2(二进制代码点)标识的二进制排序规则在所有方面都很敏感。

当然,不同的归类将需要变通方法来避免“无法解决归类冲突”错误,并且由于已知的不可保留表达式而可能导致性能下降。处理不同的归类可能是一场噩梦(去过那里),所以这就是为什么建议选择一个并坚持下去的原因。

更多参考:


1

与许多事情一样,在早期版本的SQL中,这可能会导致相当大的问题。请参阅SQL7 / 2000的这篇文章

SqlServerCentral排序规则

现在,它的功能更加强大,在某些情况下,它在更现代的系统中是合理的,但是在更改它时仍然存在一些相当有趣的警告。

这是有关更现代版本的另一个有用的系列。我相信丹·古兹曼(Dan Guzman)经常在这里发帖,因此他可能很快就会加入:)

SQL排序规则地狱

简而言之,兼容性,标准化和潜在的性能影响是不使用混合排序规则的主要原因。


0

如果排序规则是char(8位文本)而不是nchar(16位),则在归类之间传输数据可以更改数据。

我相信从此页面https://the.agilesql.club/blogs/Blogs/Ed-Elliott/What-c​​ollat​​ion-variables-take-on-inT-SQL上 ,当使用表中的文本分配变量时,隐式转换为当前数据库的排序规则。但是,当您移至其他数据库时,变量中的文本会如何处理?这些字节是否再次转换为新的归类(如果需要)?

我整理排序技巧,以删除“拉丁”字母重音符号,只保留ASCII文本,这是我所需要的,因为我们的第三方软件阻塞了重音符号。Collate SQL_Latin1_General_CP1253_CI_AI。罗马字母的重音是“Slán”!;-)

但是,如果我想保留它们,那就是坏消息!

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.