鉴于这条关键信息(即在对问题的评论中,而不是在实际问题中):
事实上,我使用 Microsoft .Net 的批量插入方法,所以我真的不知道它发送到数据库服务器的确切查询。
即使在不区分大小写的数据库中,列名被视为区分大小写也是有道理的,因为这就是SqlBulkCopy
类的工作方式。请参阅SqlBulkCopy 中的列映射区分大小写。
补充说明
- 在询问错误时,请始终在问题中包含实际且完整的错误消息。简单地说有一个错误会导致大量的猜测和疯狂的追逐,进而导致离题的答案。
提出问题时,请不要改变您正在处理的情况。例如,问题状态(强调):
具有“给定”案例设置的批量插入失败,但它们通过另一个“给定”案例设置成功。
然而,示例语句是单INSERT
s。此外,对该问题的评论指出:
事实上,我使用 Microsoft .Net 的批量插入方法,所以我真的不知道它发送到数据库服务器的确切查询。
使用 .NET 与SqlBulkCopy
使用BULK INSERT
or完全不同INSERT
,这会使当前问题具有误导性,从而难以(甚至不可能)正确回答。这条新信息也引发了更多问题,因为在使用 时SqlBulkCopy
,您无需编写任何INSERT
语句:您只需编写一条SELECT
语句并指定目标表的名称。如果您完全为目标表指定列名,则它位于可选列映射中。这就是问题所在吗?
关于问题的“编辑”部分:
不,即使您没有使用SqlBulkCopy
. 列的排序规则决定了存储在列中的数据的行为方式,而不是列名(即表的元数据)的行为方式。数据库本身的排序规则决定了数据库级对象元数据的行为方式。在这种情况下,您声称数据库正在使用不区分大小写的排序规则(正确,_CI_
排序规则名称的一部分确实意味着“不区分大小写”)。
关于 Jonathan Leffler 就该问题所作的以下陈述:
这进入了分隔标识符(通常区分大小写)和排序规则(这个不区分大小写)之间交互的一个非常微妙的领域。
不,分隔标识符通常不区分大小写。分隔标识符的敏感性(大小写、重音、假名类型、宽度和在 SQL Server 2017 变体选择器中的开头)与同一级别的非分隔标识符相同。“同一级别”是指实例级别的名称(数据库、登录名等)由实例级别的排序规则控制,而数据库级别的名称(架构、对象--表、视图、函数、存储过程等--、用户等)由数据库级排序规则控制。并且这两个级别可以有不同的排序规则。
您需要研究数据库中的 SQL 列名在分隔时是否区分大小写。它还可能取决于 CREATE TABLE 语句的编写方式(名称是否在其中分隔?)。通常,SQL 对列名和表名不区分大小写;你可以写INSERT INTO SoMeTaBlE(GiVeN, cOlNaMe) VALUES("v1", "v2")
,如果名字从来没有分隔,那就没问题了。
在创建表时列名是否被分隔并不重要,至少在如何处理它们的分辨率方面无关紧要。列名是数据库级元数据,由数据库的默认排序规则控制。每个数据库中的所有数据库级元数据都是相同的。您不能让某些列名区分大小写而其他列名不区分大小写。
此外,表名和列名也没有什么特别之处。它们是数据库级别的元数据,就像用户名、模式名称、索引名称等一样。所有这些元数据都由数据库的默认排序规则控制。
元数据(实例级别和数据库级别)仅“通常”不区分大小写,因为安装期间建议的默认排序规则是不区分大小写的排序规则。
'delimited identifier' 是列名、表名或用双引号括起来的类似内容,例如 CREATE TABLE "table"(...)
更准确地说,定界标识符是包含在所讨论的 DBMS 定义为其定界符的任何字符中的标识符。哪些特定字符用于分隔符在不同的 DBMS 之间有所不同。
在 SQL Server 中,分隔标识符用方括号括起来:[GIVEN]
虽然方括号始终用作标识符的分隔符,但如果您将会话级属性QUOTED_IDENTIFIER
设置为ON
(最好始终这样做),则可以使用双引号作为分隔符。
SQL 有一些晦涩难懂的部分(分隔标识符处理就是其中之一)
好吧,分隔标识符实际上非常简单。定界标识符的全部意义在于有效地忽略常规(即非定界)标识符的规则。但是,就常规标识符而言,是的,这些规则相当神秘(主要是由于官方文档不完整且不正确)。因此,为了揭开 SQL Server 中标识符实际工作原理的神秘面纱,我进行了大量研究并在此处发布了结果(其中包括研究本身的链接):
完整的 T-SQL 标识符规则列表
有关排序规则 / 编码 / Unicode / ASCII 的更多信息,尤其是与 Microsoft SQL Server 相关的信息,请访问:
校对信息