SQL Server列名大小写敏感性

7
我使用的数据库具有French_CI_AS排序规则(CI应该代表不区分大小写),但无论如何都区分大小写。我试图理解原因。
我断言的原因是,带有“GIVEN”大小写设置的批量插入会失败,但使用另一种“Given”大小写设置会成功。
例如:
- INSERT INTO SomeTable([GIVEN],[COLNAME]) VALUES ("value1", "value2") 失败,但 - INSERT INTO SomeTable([Given],[ColName]) VALUES ("value1", "value2") 成功。
编辑: 刚看到这个:

http://msdn.microsoft.com/en-us/library/ms190920.aspx

那就意味着可以在不清空所有数据和重新创建相关表的情况下更改列的排序规则吗?

我认为你需要用一个简单的(2列)示例来说明什么是成功的,什么是失败的。我想你可能是在说 INSERT INTO SomeTable([GIVEN],[COLNAME]) VALUES (...) 失败了,但是 INSERT INTO SomeTable([Given],[ColName]) VALUES (...) 成功了。如果是这样,那就涉及到定界符标识符(通常区分大小写)和排序规则(这个是不区分大小写的)之间非常微妙的交互领域。 - Jonathan Leffler
@JonathanLeffler:你的例子恰好与我的问题相关。 - Skippy Fastol
@Jonathan Leffler: "delimited" 在这里是什么意思...? - Skippy Fastol
在标准SQL中,“定界符标识符”是指用双引号括起来的列名、表名或类似物,例如CREATE TABLE "table" (...)。它们用于当名称是关键字或包含通常不允许在标识符中使用的字符(如空格)时。在SQL Server中,定界标识符用方括号括起来:[GIVEN]等。MySQL使用反引号来完成同样的工作。这就是为什么重要的原因是您必须向我们展示您正在使用什么。 SQL有一些晦涩难懂的部分(其中定界标识符处理就是其中之一),但当您遇到问题时,您必须学会如何使用它。 - Jonathan Leffler
@JonathanLeffler:感谢您详细而清晰的解释。实际上,我使用Microsoft .Net的批量插入方法,因此我不知道它发送到DB服务器的确切查询。我将不得不深入挖掘日志。 - Skippy Fastol
显示剩余4条评论
3个回答

8
给出了这个关键信息(在问题的评论中而不是实际问题中):
事实上,我使用Microsoft .Net的批量插入方法,因此我不知道它发送到DB服务器的确切查询。因此,在一个大小写不敏感的数据库中,列名被视为区分大小写是有意义的,因为这就是SqlBulkCopy类的工作方式。请参见SqlBulkCopy中的列映射区分大小写
其他注释:
  1. 在询问错误时,请务必在问题中包含实际的和完整的错误消息。仅仅说有错误会导致很多猜测和无用的搜索,反过来会得到与主题无关的答案。
  2. 在提问时,请不要改变你所处理的情况。例如,问题说明如下(重点已加粗):

    使用给定的情况设置进行批量插入失败,但使用另一种“给定”情况设置却成功。

    然而,示例语句是单个INSERT。此外,问题的评论中指出:

    事实上,我使用Microsoft .Net的批量插入方法,所以我并不知道它发送到DB服务器的确切查询。

    使用.NET和SqlBulkCopy与使用BULK INSERTINSERT大不相同,这使得当前问题具有误导性,难以(甚至不可能)正确回答。这些新信息还引发了更多问题,因为使用SqlBulkCopy时,您不需要编写任何INSERT语句:您只需编写一个SELECT语句,并指定目标表的名称。如果在目标表中根本没有指定列名,则是在可选的列映射中指定。问题出在那里吗?

  3. 关于问题的“编辑”部分:

    不,即使您没有使用SqlBulkCopy,更改列的排序规则也无济于事。列的排序规则决定了存储在列中的数据的行为,而不是列名(即表的元数据)的行为。它是数据库本身的排序规则,决定了数据库级对象元数据的行为。在这种情况下,您声称DB使用不区分大小写的排序规则(正确的是,排序规则名称中的_CI_部分表示“不区分大小写”)。

  4. 关于Jonathan Leffler在问题中提出的以下陈述:

    这涉及到限定标识符(通常区分大小写)和排序规则(此排序规则不区分大小写)之间交互的非常微妙的领域。

    不,限定标识符通常不区分大小写。限定标识符的灵敏度(大小写、重音、假名类型、宽度,在SQL Server 2017中开始采用变化选择器)与相同级别的非限定标识符相同。 “相同级别”意味着实例级别名称(数据库、登录等)受实例级别排序规则控制,而数据库级别名称(模式、对象--表、视图、函数、存储过程等--、用户等)受数据库级别排序规则控制。这两个级别可以具有不同的排序规则。

    您需要研究在数据库中SQL列名是否区分大小写当使用限定符时。它也可能取决于CREATE TABLE语句的编写方式(在其中命名了名称)。通常,SQL对列和表名不区分大小写;您可以编写INSERT INTO SoMeTaBlE(GiVeN, cOlNaMe) VALUES("v1", "v2"),如果名称从未被限定,则没问题。

    无论创建表时列名是否被限定,都不会影响它们的解析方式,至少在如何处理它们的解析

    如果您想了解更多关于排序规则/编码/Unicode/ASCII的信息,特别是与Microsoft SQL Server相关的内容,请访问:

    Collations.Info


你正在处理SQL Server;我的评论中提到的是“标准SQL”(ISO/IEC 9075:201x等)。这是两个不同的东西(非常不同的东西——标准SQL不认可[]作为限定符的引号,还有其他关键差异,而标准SQL在限定符中要求区分大小写)。 - Jonathan Leffler
1
@JonathanLeffler 您可能在“标准SQL”方面是正确的,但这与本问题无关,因为:a) 本问题特定于Microsoft SQL Server,而b) 您错误地将这些“标准SQL”规则应用于SQL Server,而这些规则显然不适用于SQL Server。在您对该问题的每个评论中,您都陈述或暗示SQL Server根据这些“标准SQL”规则运行,并关注列名是否在创建表时被限定等问题。但是在这种情况下,所有这些都不适用,因此会产生误导。这就是我要澄清的内容。 - Solomon Rutzky

1
列名区分大小写的事实意味着MASTER数据库是使用区分大小写的排序规则创建的。
在我刚刚调查的情况下,有人输入了Latin1_CS_AI而不是Latin1_CI_AS,在设置SQL服务器时。

2
嗨,罗杰。不,master数据库的排序规则与系统DB(mastermodelmsdbtempdb)之外处理列名(即数据库级元数据)无关。现在,model数据库用作创建新数据库的模板,但非系统数据库的排序规则可以轻松更改。可以通过执行CREATE DATABASE {db_name} COLLATE {collation_name};来设置不同的排序规则,或者稍后通过ALTER DATABASE {db_name} COLLATE {new_collation_name};进行更改。请参阅我的答案获取更多详细信息。 - Solomon Rutzky

0

请检查您的表定义中列的排序规则以及tempdb数据库(即服务器排序规则)的排序规则。它们可能与您的数据库排序规则不同。


你是否有提供一种简洁方式来做这件事的查询?(尽可能地偷懒,正如任何优秀的开发者:)) - Skippy Fastol
1
@SkippyFastol 和 Anthony:虽然这三个排序规则可能存在差异,但这与 O.P. 遇到的问题无关。问题不在于列中的数据本身,而在于列名称本身,这是数据库级元数据。这受数据库默认排序规则的控制,但即使在使用 SqlBulkCopy 时,这也是无关紧要的。请参阅我的答案获取详细信息。 - Solomon Rutzky

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接