我正在尝试调试 MS SQL Server 错误 242:
将 char 数据类型转换为 datetime 数据类型会导致 datetime 值超出范围。
该错误是由以下语句引起的:
CREATE TABLE db.schema.test (
Column1 datetime NULL
) GO
INSERT INTO db.schema.test (Column1)
VALUES (convert(varchar,convert(datetime,{D '2019-06-30'}),102));
这是我的服务器版本:
Microsoft SQL Server 2017 (RTM-CU15) (KB4498951) - 14.0.3162.1 (X64)
May 15 2019 19:14:30
Copyright (C) 2017 Microsoft Corporation
Standard Edition (64-bit) on Linux (Debian GNU/Linux 9 (stretch))
而且语言@@LANGUAGE
是Italiano
。
相同的语句适用于
Microsoft SQL Server 2017 (RTM-CU10) (KB4342123) - 14.0.3037.1 (X64)
Jul 27 2018 09:40:27
Copyright (C) 2017 Microsoft Corporation
Standard Edition (64-bit) on Windows Server 2012 R2 Standard 6.3 <X64> (Build 9600: ) (Hypervisor)
带语言:us_english
无需明确转换样式即可工作
INSERT INTO db.schema.test (Column1)
VALUES (convert(varchar,convert(datetime,{D '2019-06-30'})));
转换样式 102 是 ANSI yyyy.mm.dd
,不应该被英语和意大利语 SQL Server 识别?
从内部开始,ODBC 转义序列
{D '2019-06-30'}
返回一个datetime
.(忽略多余的转换为
datetime
)然后,您将其转换为具有 102 样式的字符串(而不是意大利语的 105)。
然后,您依靠隐式转换回
datetime
以匹配目标列的类型。正如您在执行计划中看到的那样,隐式转换的默认样式为 0:
(注意:使用时应始终指定最大长度
varchar
)当您使用样式 102 时
yyyy.mm.dd
,您还必须设置DATEFORMAT
为,YMD
以便 SQL Server 可以解析样式 0 下的格式。当您使用样式 105时,出于同样的原因
dd-mm-yyyy
,您必须设置DATEFORMAT
为。DMY
它适用于一种而不适用于另一种的原因是
DATEFORMAT
每种情况下语言的默认设置。请参阅文档中的datetime、
SET LANGUAGE
和Write International Transact-SQL 语句。还有Aaron Bertrand 的SQL Server DateTime 最佳实践。