'COLLATE SQL_Latin1_General_CP1_CI_AS'是做什么的?


134

我有一个SQL查询可以在SQLServer中创建数据库,如下所示:

create database yourdb
on
( name = 'yourdb_dat',
  filename = 'c:\program files\microsoft sql server\mssql.1\mssql\data\yourdbdat.mdf',
  size = 25mb,
  maxsize = 1500mb,
  filegrowth = 10mb )
log on
( name = 'yourdb_log',
  filename = 'c:\program files\microsoft sql server\mssql.1\mssql\data\yourdblog.ldf',
  size = 7mb,
  maxsize = 375mb,
  filegrowth = 10mb )
COLLATE SQL_Latin1_General_CP1_CI_AS;
go

运行正常。

虽然其余的SQL显然很明显,但我对的功能还是很困惑COLLATE SQL_Latin1_General_CP1_CI_AS

有人可以向我解释吗?另外,我想知道以这种方式创建数据库是否是最佳做法?

Answers:


246

它设置数据库服务器如何排序(比较文本)。在这种情况下:

SQL_Latin1_General_CP1_CI_AS

分解为有趣的部分:

  1. latin1 使服务器使用字符集拉丁文1处理字符串,基本上是ascii
  2. CP1 代表代码页1252
  3. CI 不区分大小写的比较,因此“ ABC”将等于“ abc”
  4. AS 重音敏感,因此“ü”不等于“ u”

PS有关更多详细信息,请务必阅读@ solomon-rutzky的答案


11
和之间有什么区别SQL_Latin1_General_CI_AS?具体来说,CP1让我感到奇怪。
卡德

7
@Kad:似乎没有SQL_Latin1_General_CI_AS。而是有一个Latin1_General_CI_AS。请参阅SELECT * FROM fn_helpcollations() where name IN ('SQL_Latin1_General_CP1_CI_AS','Latin1_General_CI_AS','SQL_Latin1_General_CI_AS');。两种归类在排序和比较方面存在细微的差异。参见olcot.co.uk/sql-blogs/…
Riley Major

4
@ ad:CP1代表代码页1252。代码页是一个查找表,用于将十六进制值映射到字符集中的特定字符。CP1是Microsoft亚文化中CP1252的简写。Windows是唯一在本地使用CP1252的平台,因为它是DOS时代的保留。尽管它与ISO 8859-1非常相似,但它们并不相同。映射字符(例如欧元)和ISO 8859-1中未包含的其他一些字符之间存在差异。
slartibartfast

完美的答案@Kris!
gaurav

@Kris在SQL2019中有SQL_Latin1_General_CP1_CI_AS的UTF-8替代品吗?
Chanky

72

请注意,接受的答案有点不完整。是的,在最基本的级别上,归类处理排序。但是,由选定的归类定义的比较规则在针对用户数据的用户查询之外的许多地方都使用。

如果是“做COLLATE SQL_Latin1_General_CP1_CI_AS什么?” 意思是“什么的COLLATE条款CREATE DATABASE做什么的?”,然后:

语句的COLLATE {collation_name}子句CREATE DATABASE指定数据库的默认排序规则,而不是服务器);数据库级别和服务器级别的默认归类控制不同的事情。

服务器(即实例)级别的控件:

  • 数据库级排序规则系统数据库:mastermodelmsdb,和tempdb
  • 由于控制了数据库级别的排序规则 tempdb,因此它是临时表(全局和本地)中字符串列的默认排序规则,而不是表变量。
  • 由于控制的数据库级别排序规则master,因此它是用于服务器级别数据的排序规则,例如数据库名称(即中的namesys.databases),登录名等。
  • 参数/变量名称的处理
  • 游标名称的处理
  • GOTO标签处理
  • COLLATE缺少该子句时,用于新创建的数据库的默认排序规则

数据库级控件:

  • 默认排序用于新创建的字符串列(CHARVARCHARNCHARNVARCHARTEXT,和NTEXT-但不要使用TEXTNTEXT)当COLLATE从句从列定义丢失。这同样适用于这两个CREATE TABLEALTER TABLE ... ADD语句。
  • 用于字符串文字(即'some text')和字符串变量(即@StringVariable)的默认归类。仅在将字符串和变量与其他字符串和变量进行比较时才使用此归类。将字符串/变量与列进行比较时,将使用列的排序规则。
  • 用于数据库级元数据的归类,例如对象名称(即sys.objects),列名称(即sys.columns),索引名称(即sys.indexes)等。
  • 用于数据库级对象的归类:表,列,索引等。

也:

  • ASCII是8位的编码(通常使用;从技术上讲,“ ASCII”是7位,字符值为0-127,“ ASCII扩展”是8位,字符值为0-255)。跨文化的人群是相同的。
  • 代码页是扩展ASCII的“扩展”部分,它控制将哪些字符用于值128-255。此组在每种区域性之间有所不同。
  • Latin1并不表示“ ASCII”,因为标准ASCII仅覆盖0到127的值,并且所有代码页(可以在SQL Server中甚至可以表示NVARCHAR)都将相同的128个值映射到相同的字符。

如果是“做COLLATE SQL_Latin1_General_CP1_CI_AS什么?” 表示“此特定归类有什么作用?”,然后:

  • 因为名称以开头SQL_,所以这是SQL Server排序规则,而不是Windows排序规则。即使没有正式弃用,它们也绝对是过时的,并且主要是为了与SQL Server 2000以前的版本兼容。尽管很不幸,SQL_Latin1_General_CP1_CI_AS由于它是在使用美式英语作为其语言的操作系统上安装时的默认设置,所以非常普遍。如果可能,应避免这些归类。

    Windows排序规则(名称不以开头的排序规则SQL_)是较新的,功能更强的,具有相同值之间VARCHARNVARCHAR针对相同值的一致排序,并且正在使用其他/更正的排序权重和大写/小写映射进行更新。这些归类也没有SQL Server归类所具有的潜在性能问题:混合VARCHAR和NVARCHAR类型时对索引的影响

  • Latin1_General 是文化/地区。
    • 对于NCHARNVARCHAR和,NTEXT这确定了用于排序和比较的语言规则。
    • 对于CHARVARCHARTEXT数据(列,文字和变量),这确定:
      • 用于排序和比较的语言规则。
      • 用于编码字符的代码页。例如,Latin1_General排序规则使用代码页1252,Hebrew排序规则使用代码页1255,依此类推。
  • CP{code_page} 要么 {version}

    • 对于SQL Server归类:CP{code_page},是8位代码页,它确定哪些字符映射到值128-255。双字节字符集(DBCS)有四个代码页,可以使用2字节组合来创建多个字符集。 256个字符,这些字符不适用于SQL Server归类。
    • 对于Windows归类:{version}虽然不是所有归类名称中都存在,但指的是引入了归类的SQL Server版本(大部分情况下)。名称中没有版本号的Windows归类为版本80(即SQL Server 2000,即8.0版)。并非所有版本的SQL Server都附带新的排序规则,因此版本号之间存在差距。有一些90(对于SQL Server 2005,它是9.0版),大多数是100(对于SQL Server 2008,是10.0版),还有一小部分具有140(对于SQL Server 2017,版本14.0)。

      我之所以说“大部分”是因为,归类排序规则_SC是在SQL Server 2012(版本11.0)中引入的,但是基础数据并不是新的,它们只是添加了对内置函数补充字符的支持。因此,这些结尾存在于版本90100归类中,但仅从SQL Server 2012开始。

  • 接下来,您可以进行以下任意组合的灵敏度设置,但始终按此顺序指定:
    • CS=区分大小写或CI=不区分大小写
    • AS= AI区分重音或=不区分重音
    • KS =不区分假名类型=不区分假名类型
    • WS =宽度敏感或缺少=宽度不敏感
    • VSS =变体选择器不敏感(仅在140版校对中可用)或丢失=变体选择器不敏感
  • 可选的最后一块:

    • _SC最后是“补充字符支持”。“支持”仅影响内置函数解释代理对的方式(这是在UTF-16中编码辅助字符的方式)。没有_SC结尾(或_140_中间),内置函数看不到单个补充字符,而是看到组成替代对的两个无意义的代码点。可以将此结尾添加到任何非二进制版本90或100归类中。
    • _BIN_BIN2最后表示“二进制”排序和比较。数据仍以相同的方式存储,但是没有语言规则。此结局永远不会与5种敏感度或结合使用_SC_BIN是较旧的样式,_BIN2是较新的,更准确的样式。如果使用SQL Server 2005或更高版本,请使用_BIN2。有关_BIN和之间的区别的详细信息_BIN2,请参见:各种二进制排序规则(文化,版本以及BIN与BIN2)之间的区别
    • _UTF8是SQL Server 2019中的新选项。它是一种8位编码,允许将Unicode数据存储在VARCHARCHAR数据类型中(但不建议使用不赞成使用的TEXT数据类型)。此选项只能用于支持补充字符的归类(例如_SC,名称为90或100的归类,以及140归类的归类)。还有一个单一的二进制_UTF8排序规则(_BIN2,not _BIN)。

      请注意: UTF-8的设计/创建是为了与为8位编码设置但仍要支持Unicode的环境/代码兼容。即使在某些情况下,与整理相比,UTF-8最多可以节省50%的空间。对于任何使用它来实现兼容性的人来说,这都是自然状态,但是对于那些希望将其用于节省空间的人来说,这并不是自然状态。将使用排序规则的VARCHAR数据与使用非排序规则的数据或数据混合使用时要小心,因为您可能会遇到奇怪的行为/数据丢失。有关新的UTF-8归类的更多详细信息,请参阅:SQL Server 2019中的本机UTF-8支持:救星还是假先知?NVARCHAR,,但这是副作用,并且在许多/大多数操作中对性能造成轻微影响。如果为了兼容性需要此功能,则费用是可以接受的。如果您要节省空间,最好进行测试,然后再进行测试。测试包括所有功能,而不仅仅是几行数据。请注意,当ALL列和数据库本身使用VARCHAR带有以下内容的数据(列,变量,字符串文字)时,UTF-8排序规则最有效:_UTF8_UTF8VARCHAR_UTF8NVARCHAR


5
尽管我对包含如此多的信息和工作量表示赞赏,但我的回答绝对没有错(数据库存储数据,数据库服务器对此数据起作用,排序在起作用)。我选择简洁而不是完整的数学精度,因为OP可能正在寻找足够的信息,而不是所有可能的信息。
克里斯(Kris)2009年

4
嗨@Kris。谢谢。公平地说,我并不是说您的答案是完全错误的,只是可悲的是不完整。我已更新,希望可以澄清这一点。我明白您的意思,但是OP询问了该COLLATE条款的内容CREATE DATABASE。您说了它所做的几件事之一。您为什么认为OP仅想知道答案的10%?如果提供了所有信息,则每个人都可以决定获取多少信息。但是,如果只给出一些信息,则为他们做出选择。我选择提供尽可能多的信息,因为其中大多数都不为人所知。(续)
所罗门·鲁兹基

5
我想我明白您的意思,但我的目标是提供足够的信息,而不是提供过多的信息。太多的信息很快对许多人来说变得太复杂了。当我无法在任何情况下提供足够的信息时,我都会期待后续的问题。(我也没想到这个话题会引起如此多的关注)
Kris

8
@Kris我已经有一段时间想说“谢谢!”。表现出这种成熟性和专业性。我有些习惯人们冒犯别人,说他们错了,然后变得“困难”(甚至更加困难)与他人互动。但是,您对我的“可接受的答案是错误的 ”的正确回答激发了我淡化我的介绍,并应作为此处其他人如何正确有效地交流的榜样😺。
所罗门·鲁兹基

4
谢谢您,我很高兴听到我以某种方式产生了积极的影响,但是我喜欢“错”,它为学习新事物提供了机会,这很棒!
克里斯(Kris)


16

COLLATE关键字指定要使用什么样的字符集和规则(秩序,对抗规则)的字符串值。

例如,在您的情况下,您正在使用不区分大小写(CI)和重音符号(AS)的

您可以参考此文档


9

这指定数据库的默认排序规则。您在数据库表中创建的每个文本字段都将使用该排序规则,除非您指定不同的排序规则。

数据库始终具有默认排序规则。如果您未指定任何内容,则使用SQL Server实例的默认排序规则。

您使用的排序规则名称表明它使用Latin1代码页1,不区分大小写(CI)和重音符号(AS)。该排序规则在美国使用,因此它将包含在美国使用的排序规则。

排序规则决定如何比较文本值的相等性和相似性,以及如何在排序时比较它们。代码页用于存储非Unicode数据,例如varchar字段。


错误(not虽然您可以接受默认值,但不能指定排序规则)错误(它也用于unicode数据)
RichardTheKiwi 2011年

@Richard aka cyberkiwi:检查文档:msdn.microsoft.com/zh-cn/library/ms176061.aspx指定排序规则可选的。代码页用于存储Unicode数据,因为它存储为16位Unicode代码点,而不是8位代码页索引。
Guffa

我读错了您的答案,但这仍然是错误的。数据库始终具有默认排序规则= SERVER排序规则,而不是专门Latin1_General_CI_AS。现在,我读错了,因为我一半希望该语句与SERVER排序规则有关,这确实需要接受UI中的默认值。对于第二点,您似乎暗示排序规则用于对unicode数据进行排序(即使您在最后2个句子中从切换sortingstoring)。Unicode文本数据也服从排序规则。
RichardTheKiwi 2011年

@Richard aka cyberkiwi:我更改了有关默认排序规则的段落,以使其与链接到的特定文档相对应。(根据服务器的版本而有所不同。)关于第二点,我看不出如何使它更清晰。文本说存储非unicode数据时使用代码页。代码页既不用于unicode数据,也用于非unicode数据,不用于确定排序。
Guffa
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.