【问题标题】:What does 'COLLATE SQL_Latin1_General_CP1_CI_AS' do?'COLLATE SQL_Latin1_General_CP1_CI_AS' 有什么作用?
【发布时间】:2011-06-29 16:19:44
【问题描述】:

我有一个 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 的功能感到很困惑。

谁能给我解释一下?另外,我想知道以这种方式创建数据库是否是最佳做法?

【问题讨论】:

    标签: sql-server database tsql collation


    【解决方案1】:

    它设置数据库服务器的排序方式(比较文本片段)。在这种情况下:

    SQL_Latin1_General_CP1_CI_AS
    

    分成有趣的部分:

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

    P.S.如需更多详细信息,请务必read @solomon-rutzky's answer

    【讨论】:

    • 这和SQL_Latin1_General_CI_AS 有什么区别。具体来说,CP1 让我感到好奇。
    • @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/…
    • @Kad:CP1 代表代码页 1252。代码页是一个查找表,用于将十六进制值映射到字符集中的特定字符。 CP1 是 Microsoft 亚文化中 CP1252 的简写。 Windows 是唯一在本地使用 CP1252 的平台,因为它是 DOS 时代的遗留物。尽管它与 ISO 8859-1 非常相似,但它们并不相同。映射字符(例如欧元)和其他一些 ISO 8859-1 中没有的字符存在差异。
    • @Kris SQL2019 中的 SQL_Latin1_General_CP1_CI_AS 是否有任何 UTF-8 替代方案?
    【解决方案2】:

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

    如果“COLLATE SQL_Latin1_General_CP1_CI_AS 做什么?”表示“CREATE DATABASECOLLATE 子句是做什么的?”,那么:

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

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

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

    数据库级控件:

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

    还有:

    • ASCII 是一种 8 位编码(用于常见用途;技术上“ASCII”是 7 位,字符值是 0 - 127,而“ASCII Extended”是 8 位,字符值是 0 - 255)。这个群体在不同文化中都是相同的。
    • 代码页是扩展 ASCII 的“扩展”部分,用于控制值 128 - 255 使用哪些字符。该组因不同文化而异。
    • Latin1 不是 表示“ASCII”,因为标准 ASCII 仅涵盖值 0 - 127 和 所有 代码页(可以在 SQL Server 中表示,甚至 @987654356 @) 将这 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 排序规则所具有的潜在性能问题:Impact on Indexes When Mixing VARCHAR and NVARCHAR Types

    • Latin1_General 是文化/语言环境。
      • 对于NCHARNVARCHARNTEXT 数据,这决定了用于排序和比较的语言规则。
      • 对于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的区别详见:Differences Between the Various Binary Collations (Cultures, Versions, and BIN vs BIN2)
      • _UTF8 是 SQL Server 2019 的一个新选项。它是一种 8 位编码,允许将 Unicode 数据存储在 VARCHARCHAR 数据类型中(但不是已弃用的 TEXT 数据类型)。此选项只能用于支持补充字符的排序规则(即名称中带有 _SC 的版本 90 或 100 排序规则,以及版本 140 排序规则)。还有一个二进制 _UTF8 排序规则(_BIN2,不是 _BIN)。

        请注意: UTF-8 的设计/创建是为了与为 8 位编码设置但希望支持 Unicode 的环境/代码兼容。尽管在少数情况下 UTF-8 与NVARCHAR 相比可以节省高达 50% 的空间,但这是一个副作用,并且在许多/大多数操作中对性能有轻微影响。如果您需要它以实现兼容性,那么成本是可以接受的。如果你想节省空间,你最好测试一下,然后再测试一次。测试包括所有功能,而不仅仅是几行数据。请注意,当所有列和数据库本身都使用带有_UTF8 排序规则的VARCHAR 数据(列、变量、字符串文字)时,UTF-8 排序规则最有效。对于任何使用它来实现兼容性的人来说,这是自然状态,但对于那些希望使用它来节省空间的人来说却不是。将使用_UTF8 排序规则的VARCHAR 数据与使用非_UTF8 排序规则或NVARCHAR 数据的VARCHAR 数据混合时要小心,因为您可能会遇到奇怪的行为/数据丢失。有关新的 UTF-8 排序规则的更多详细信息,请参阅:Native UTF-8 Support in SQL Server 2019: Savior or False Prophet?

    【讨论】:

    • 虽然我确实赞成这个包含如此多的信息和努力,但我的回答绝对没有错(数据库存储数据,数据库服务器对这些数据进行操作,排序正在起作用)。我选择简洁而不是完整的数学精度,因为 OP 可能正在寻找足够的信息,而不是所有可能的信息。
    • 嗨@Kris。谢谢。公平地说,我并没有说您的答案完全错误,只是非常不完整。我已经更新,希望能澄清这一点。我明白你在说什么,但 OP 询问了 CREATE DATABASECOLLATE 子句的作用。你说了它所做的几件事之一。为什么你认为 OP 只想知道 10% 的答案?如果提供了所有信息,每个人都可以决定取多少。但是,如果只给出一些信息,那么就为他们做出了选择。我选择提供尽可能多的信息,因为其中大部分都不为人所知。 (续)
    • 我想我明白你的意思,但我的目标是提供足够的信息而不是太多。对于很多人来说,太多的信息很快就会变得太复杂。当我无法为任何情况提供足够的信息时,我会期待后续问题。 (我也没想到这个话题会引起这么多关注)
    • @Kris 我一直想说“谢谢!”表现出如此成熟和专业。我有点习惯于有人冒犯别人说他们错了,然后变得“难以”(甚至更难)与之互动。但是,您对我的“接受的答案是 WRONG”的慎重回应启发了我淡化我的介绍,并且应该作为这里其他人关于如何沟通的榜样正确而富有成效地?。
    • 不客气,很高兴听到我以某种方式产生了积极的影响,但我喜欢“错误”,它为学习新事物提供了机会,这很棒!
    【解决方案3】:

    CP1 的意思是“代码页 1” - 从技术上讲,这转换为代码页 1252

    【讨论】:

      【解决方案4】:

      COLLATE 关键字指定您对字符串值使用的字符集和规则(顺序、对抗规则)的类型。

      例如,在您的情况下,您使用不区分大小写 (CI) 和区分重音 (AS) 的拉丁规则

      你可以参考这个Documentation

      【讨论】:

        【解决方案5】:

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

        数据库始终具有默认排序规则。如果不指定,则使用 SQL Server 实例的默认排序规则。

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

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

        【讨论】:

        • 错误(您不能not 指定排序规则,尽管您可以接受默认值)错误(它也用于 unicode 数据)
        • @Richard aka cyberkiwi:查看文档:msdn.microsoft.com/en-us/library/ms176061.aspx 指定排序规则可选的。代码页用于存储 Unicode 数据,因为它存储为 16 位 Unicode 代码点,而不是 8 位代码页索引。
        • 我看错了你的答案,但它仍然是错误的。数据库始终具有默认排序规则 = SERVER 排序规则,而不是专门为 Latin1_General_CI_AS。现在我读错了,因为我有一半认为该语句是关于 SERVER collat​​ion 的,它确实需要在 UI 中接受默认值。对于第二点,您似乎暗示排序规则用于对 unicode 数据进行排序(即使您在最后两句中从 sorting 切换到 storing )。 Unicode 文本数据也遵循排序规则。
        • @Richard aka cyberkiwi:我更改了关于默认排序规则的段落,以与我链接到的特定文档相对应。 (根据服务器的版本而有所不同。)关于第二点,我看不出如何才能更清楚。文本说 代码页存储非 unicode 数据时使用。代码页不用于确定排序,无论是 unicode 数据还是非 unicode 数据。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2010-10-22
        • 1970-01-01
        • 1970-01-01
        • 2018-04-15
        • 2019-09-25
        • 2023-04-10
        • 2011-07-17
        相关资源
        最近更新 更多