SQL Server 列名区分大小写
Posted
技术标签:
【中文标题】SQL Server 列名区分大小写【英文标题】:SQL Server Column names case sensitivity 【发布时间】:2012-05-13 01:44:28 【问题描述】:我使用的数据库有 French_CI_AS 排序规则(CI 应该代表不区分大小写),但无论如何都是区分大小写的。我正在尝试了解原因。
我断言这一点的原因是带有“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 (...)
有效。如果是这样,这就涉及到分隔标识符(通常区分大小写)和排序规则(这个不区分大小写)之间交互的一个非常微妙的领域。
@JonathanLeffler :您的示例与我的问题完全相关。
您需要区分存储在表中的内容(数据)和存储在系统目录中的名称(元数据)。如果如您所指出的,问题出在列名(而不是数据本身)上,那么您需要研究数据库中的 SQL 列名在分隔时是否区分大小写。它还可能取决于 CREATE TABLE 语句的编写方式(名称是否在其中分隔?)。通常,SQL 对列名和表名不区分大小写;你可以写INSERT INTO SoMeTaBlE(GiVeN, cOlNaMe) VALUES("v1", "v2")
,如果名字从不分隔,那就没问题了。
@Jonathan Leffler:这里的“delimited”代表什么...?
在标准 SQL 中,“分隔标识符”是列名、表名或用双引号括起来的类似内容,例如 CREATE TABLE "table"(...)
。它们用于名称是关键字或包含标识符中通常不允许的字符(例如空格)时。在 SQL Server 中,分隔标识符用方括号括起来:[GIVEN]
等。mysql 对同一作业使用反引号。这就是为什么向我们展示您正在使用的内容至关重要的原因。 SQL 有一些晦涩难懂的部分(分隔标识符处理就是其中之一),但当你遇到它时,你必须学习。
【参考方案1】:
鉴于这条关键信息(即在对问题的评论中,而不是在实际问题中):
实际上我使用的是 Microsoft .Net 的批量插入方法,所以我真的不知道它发送到数据库服务器的确切查询。
列名被视为区分大小写是有道理的,即使在不区分大小写的数据库中也是如此,因为 SqlBulkCopy
类就是这样工作的。请参阅Column mappings in SqlBulkCopy are case sensitive。
附加说明
-
询问错误时,请始终在问题中包含实际和完整错误消息。简单地说有一个错误会导致大量猜测和疯狂追逐,进而导致偏离主题的答案。
在提问时,请不要改变您正在处理的情况。例如,问题状态(强调):
批量插入 'GIVEN' 案例设置失败,但它们通过另一个 'Given' 案例设置成功。
然而,示例语句是单个 INSERT
s。此外,对该问题的评论指出:
实际上我使用的是 Microsoft .Net 的批量插入方法,所以我真的不知道它发送到数据库服务器的确切查询。
使用 .NET 和 SqlBulkCopy
与使用 BULK INSERT
或 INSERT
完全不同,这使得当前的问题具有误导性,使得正确回答变得困难(甚至不可能)。这一新信息也引发了更多问题,因为在使用SqlBulkCopy
时,您无需编写任何INSERT
语句:您只需编写SELECT
语句并指定目标表的名称。如果您完全为目标表指定列名,则它位于可选列映射中。这就是问题所在吗?
关于问题的“编辑”部分:
不,即使您没有使用SqlBulkCopy
,更改列的排序规则也无济于事。列的排序规则决定了列中存储的数据的行为方式,而不是列名(即表的元数据)的行为方式。数据库本身的排序规则决定了数据库级对象元数据的行为方式。在这种情况下,您声称数据库正在使用不区分大小写的排序规则(正确,排序规则名称的 _CI_
部分确实意味着“Case Insensitive ")。
关于 Jonathan Leffler 就该问题所作的以下陈述:
这涉及到分隔标识符(通常区分大小写)和排序规则(这个不区分大小写)之间交互的一个非常微妙的领域。
不,分隔标识符通常不区分大小写。分隔标识符的敏感性(大小写、重音、假名类型、宽度和在 SQL Server 2017 变体选择器中的开头)与同一级别的非分隔标识符相同。 “相同级别”意味着实例级别的名称(数据库、登录名等)由实例级别的排序规则控制,而数据库级别的名称(架构、对象--表、视图、函数、存储过程等--,用户等)由数据库级排序规则控制。并且这两个级别可以有不同的排序规则。
您需要研究数据库中的 SQL 列名在分隔时是否区分大小写。它还可能取决于 CREATE TABLE 语句的编写方式(名称是否在其中分隔?)。通常,SQL 对列名和表名不区分大小写;你可以写
INSERT INTO SoMeTaBlE(GiVeN, cOlNaMe) VALUES("v1", "v2")
,如果名字从不分隔,那就没问题了。
在创建表格时列名是否被分隔并不重要,至少在如何处理它们的分辨率方面没有关系。列名是数据库级元数据,由数据库的默认排序规则控制。每个数据库中的所有数据库级元数据都是相同的。您不能让某些列名区分大小写而其他列名不区分大小写。
此外,表名和列名也没有什么特别之处。它们是数据库级别的元数据,就像用户名、架构名称、索引名称等一样。所有这些元数据都由数据库的默认排序规则控制。
元数据(实例级别和数据库级别)仅“通常”不区分大小写,因为安装期间建议的默认排序规则是不区分大小写的排序规则。
“分隔标识符”是列名、表名或用双引号括起来的类似内容,例如 CREATE TABLE "table"(...)
更准确地说,定界标识符是包含在相关 DBMS 定义为其定界符的任何字符中的标识符。用于分隔符的特定字符在不同的 DBMS 之间有所不同。
在 SQL Server 中,分隔标识符用方括号括起来:[GIVEN]
虽然方括号始终用作标识符的分隔符,但如果您将 QUOTED_IDENTIFIER
的会话级属性设置为 ON
(最好始终这样做),则可以使用双引号作为分隔符。
SQL 有一些晦涩难懂的部分(分隔标识符处理就是其中之一)
好吧,分隔标识符实际上非常简单。定界标识符的全部意义在于有效地忽略常规(即非定界)标识符的规则。但是,就常规标识符而言,是的,这些规则相当神秘(主要是由于官方文档不完整且不正确)。因此,为了揭开 SQL Server 中标识符实际工作原理的神秘面纱,我进行了大量研究并在此处发布了结果(包括研究本身的链接):
Completely Complete List of Rules for T-SQL Identifiers
有关排序规则/编码/Unicode/ASCII 的更多信息,尤其是与 Microsoft SQL Server 相关的信息,请访问:
Collations.Info
【讨论】:
您正在处理 SQL Server;我的评论说“标准 SQL”(ISO/IEC 9075:201x 等)。这是两种不同的动物(非常不同的动物——标准 SQL 不将[]
识别为分隔标识符的引号,以及其他关键差异,标准 SQL 确实要求分隔标识符中区分大小写)。
@JonathanLeffler 您可能是正确的:“标准 SQL”,但这与这个问题无关,因为:a) 这个问题特定于 Microsoft SQL Server,并且 b) 您错误地将那些“标准 SQL”规则应用于显然不适用的 SQL Server。在您陈述或暗示 SQL Server 根据这些“标准 SQL”规则运行的每个问题中,并关注在创建表时是否对列名进行了分隔等。但这些都不是在这里适用,因此在这种情况下具有误导性。这就是我要澄清的。【参考方案2】:
列名区分大小写这一事实意味着 MASTER 数据库是使用区分大小写的排序规则创建的。
如果我只是让我对此进行调查,有人进入
Latin1_CS_AI 而不是 Latin1_CI_AS
设置 SQL 服务器时。
【讨论】:
嗨罗杰。不,master
数据库的排序规则与如何在系统 DB(master
、model
、msdb
和 @987654326 之外处理列名(即数据库级元数据)无关@)。现在,model
DB 用作创建新 DB 的模板,但可以轻松更改非系统 DB 的排序规则。可以通过CREATE DATABASE db_name COLLATE collation_name;
进行不同的设置,也可以稍后通过ALTER DATABASE db_name COLLATE new_collation_name;
进行更改。请查看我的answer 了解更多详情。【参考方案3】:
检查表定义中列的排序规则,以及 tempdb 数据库的排序规则(即服务器排序规则)。它们可能与您的数据库排序规则不同。
【讨论】:
您是否有任何疑问提供了一种紧凑的方式来执行此操作? (试图像任何优秀的开发人员一样偷懒:)) @SkippyFastol 和 Anthony:虽然这 3 个排序规则确实可能存在差异,但这与 O.P. 所遇到的问题无关。问题不在于数据 in 列,而在于列名本身,即数据库级元数据。这由数据库的默认排序规则控制,但即使在使用SqlBulkCopy
时也无关紧要。详情请看我的answer。以上是关于SQL Server 列名区分大小写的主要内容,如果未能解决你的问题,请参考以下文章