如何停止 SQL 服务器交换月份和日期?
How do I stop SQL Server swapping the month and day?
我有以下查询:
DECLARE @someDateTime DATETIME = '2019-12-01 00:00:00.000'; -- 1st December 2019
SELECT @someDateTime;
结果
2019-01-12 00:00:00.000
我预计结果是 2019-12-01 00:00:00.000
(1st 2019 年 12 月)- 月份和日期因某种未知原因互换。
直到最近,我从未遇到过这种格式的问题。
如何以 "YYYY-MM-DD HH:mm:ss.000" 格式输入日期,并在分配给 select 中的 variable/displayed 后保持该格式?
什么设置决定了这种可能已经改变的格式?
可能有用的信息
dbcc useroptions
结果:
Set Option | Value
---------- -----
...
language | British
dateformat | dmy
...
我尝试过的事情:
查询 1
将日期更改为交换后无效的日期
DECLARE @someDateTime DATETIME = '2019-12-20 00:00:00.000';
SELECT @someDateTime;
结果:
Msg 242, Level 16, State 3, Line 4
The conversion of a varchar data type to a datetime data type resulted in an out-of-range value.
查询 2
声明后设置变量
DECLARE @someDateTime DATETIME;
SET @someDateTime = '2019-12-01 00:00:00.000';
SELECT @someDateTime;
结果 - 不受欢迎:
2019-01-12 00:00:00.000
查询 3
将变量插入 table 变量
DECLARE @someDateTime DATETIME = '2019-12-01 00:00:00.000';
DECLARE @someTable TABLE (someDateTimeColumn DATETIME);
INSERT @someTable VALUES (@someDateTime);
SELECT * FROM @someTable
结果 - 不受欢迎:
someDateTimeColumn
------------------
2019-01-12 00:00:00.000
查询 4
将数据直接插入 table 变量
DECLARE @someTable TABLE (someDateTimeColumn DATETIME);
INSERT @someTable VALUES ('2019-12-01 00:00:00.000');
SELECT * FROM @someTable
结果:不希望的
someDateTimeColumn
------------------
2019-01-12 00:00:00.000
查询 5
正在更改输入字符串的格式
DECLARE @someDateTime DATETIME = '01/12/2019';
SELECT @someDateTime;
结果 - 期望
2019-12-01 00:00:00.000
查询 6
正在更改输入字符串的格式
DECLARE @someDateTime DATETIME = '2019-12-01T00:00:00.00';
SELECT @someDateTime;
结果 - 期望:
2019-12-01 00:00:00.000
查询 7
正在更改输入字符串的格式
DECLARE @someDateTime DATETIME = '2019-12-01';
SELECT @someDateTime;
结果 - 不受欢迎:
2019-01-12 00:00:00.000
查询 8
使用SET DATEFORMAT
SET DATEFORMAT ymd
DECLARE @someDateTime DATETIME = '2019-12-01';
SELECT @someDateTime;
结果 - 期望
2019-12-01 00:00:00.000
您可以使用文字格式 YYYYMMDD
,它始终被解释为年-月-日,无论您的 SQL 服务器的区域设置如何:
DECLARE @someDateTime DATETIME = '20191201 00:00:00.000';
一种解决方案是使用完整的 ISO8601 格式,即 2019-12-01T00:00:00.000
,另一种是使用未分隔的日期格式,即 20191201 00:00:00.000
。更好的解决方案是切换到 datetime2
.
datetime2
是在 15 年前(或者是 11 年前)引入的,目的是摆脱 datetime
的怪癖,比如毫秒不准确、任意精度、怪异的算术和......解析特质.例如,datetime2
对ISO8601格式的解析不受DATEFORMAT
影响:
SET DATEFORMAT ydm
DECLARE @someDateTime DATETIME2(0) = '2019-12-01 00:00:00.000'
select @someDateTime
------
2019-12-01 00:00:00
这可以保护您的代码免受不幸的服务器设置修改
阅读来自@SMor 评论的 this 文章、我的同事通过 google 搜索发表的评论,并想起几个月前我做的事情后,我想我已经弄明白了什么是发生了什么以及发生了什么变化。
默认情况下,我的数据库用户设置为:
language | us_english
dateformat | mdy
所以当读取字符串 '2019-12-01'
SQL 服务器期望 mm-dd-yyyy
.
SQL 服务器虽然很聪明。它看到第一部分 2019
并意识到它实际上是年份,因此它将年份移到最后,然后再次尝试。*
它现在 12-01-2019
符合它期望的格式。
当您在 SSMS 中打开帐户属性时,语言下拉列表默认为列表中的第一种语言 (Arabic
)。
几个月前我碰巧在那儿做一些不相关的事情并决定,为了确保我没有不小心将它设置为 Arabic
,我也会更改它。
我选了British
.
我的数据库用户现在设置为:
language | British
dateformat | dmy
所以当读取字符串 '2019-12-01'
SQL 服务器期望 dd-mm-yyyy
.
一旦它改变了年份,它就变成了 12-01-2019
,它被解释为 dd-mm-yyyy
从而给我留下 January 12th 2019 而不是 12 月 1 日st 2019
今天是漫长的一天。
*请注意,这是对我如何理解这个问题的一个相当简单的解释。这可能不是它在现实中的实际运作方式,但可以满足我对这个问题的好奇心。
我有以下查询:
DECLARE @someDateTime DATETIME = '2019-12-01 00:00:00.000'; -- 1st December 2019
SELECT @someDateTime;
结果
2019-01-12 00:00:00.000
我预计结果是 2019-12-01 00:00:00.000
(1st 2019 年 12 月)- 月份和日期因某种未知原因互换。
直到最近,我从未遇到过这种格式的问题。
如何以 "YYYY-MM-DD HH:mm:ss.000" 格式输入日期,并在分配给 select 中的 variable/displayed 后保持该格式?
什么设置决定了这种可能已经改变的格式?
可能有用的信息
dbcc useroptions
结果:
Set Option | Value
---------- -----
...
language | British
dateformat | dmy
...
我尝试过的事情:
查询 1
将日期更改为交换后无效的日期
DECLARE @someDateTime DATETIME = '2019-12-20 00:00:00.000';
SELECT @someDateTime;
结果:
Msg 242, Level 16, State 3, Line 4
The conversion of a varchar data type to a datetime data type resulted in an out-of-range value.
查询 2
声明后设置变量
DECLARE @someDateTime DATETIME;
SET @someDateTime = '2019-12-01 00:00:00.000';
SELECT @someDateTime;
结果 - 不受欢迎:
2019-01-12 00:00:00.000
查询 3
将变量插入 table 变量
DECLARE @someDateTime DATETIME = '2019-12-01 00:00:00.000';
DECLARE @someTable TABLE (someDateTimeColumn DATETIME);
INSERT @someTable VALUES (@someDateTime);
SELECT * FROM @someTable
结果 - 不受欢迎:
someDateTimeColumn
------------------
2019-01-12 00:00:00.000
查询 4
将数据直接插入 table 变量
DECLARE @someTable TABLE (someDateTimeColumn DATETIME);
INSERT @someTable VALUES ('2019-12-01 00:00:00.000');
SELECT * FROM @someTable
结果:不希望的
someDateTimeColumn
------------------
2019-01-12 00:00:00.000
查询 5
正在更改输入字符串的格式
DECLARE @someDateTime DATETIME = '01/12/2019';
SELECT @someDateTime;
结果 - 期望
2019-12-01 00:00:00.000
查询 6
正在更改输入字符串的格式
DECLARE @someDateTime DATETIME = '2019-12-01T00:00:00.00';
SELECT @someDateTime;
结果 - 期望:
2019-12-01 00:00:00.000
查询 7
正在更改输入字符串的格式
DECLARE @someDateTime DATETIME = '2019-12-01';
SELECT @someDateTime;
结果 - 不受欢迎:
2019-01-12 00:00:00.000
查询 8
使用SET DATEFORMAT
SET DATEFORMAT ymd
DECLARE @someDateTime DATETIME = '2019-12-01';
SELECT @someDateTime;
结果 - 期望
2019-12-01 00:00:00.000
您可以使用文字格式 YYYYMMDD
,它始终被解释为年-月-日,无论您的 SQL 服务器的区域设置如何:
DECLARE @someDateTime DATETIME = '20191201 00:00:00.000';
一种解决方案是使用完整的 ISO8601 格式,即 2019-12-01T00:00:00.000
,另一种是使用未分隔的日期格式,即 20191201 00:00:00.000
。更好的解决方案是切换到 datetime2
.
datetime2
是在 15 年前(或者是 11 年前)引入的,目的是摆脱 datetime
的怪癖,比如毫秒不准确、任意精度、怪异的算术和......解析特质.例如,datetime2
对ISO8601格式的解析不受DATEFORMAT
影响:
SET DATEFORMAT ydm
DECLARE @someDateTime DATETIME2(0) = '2019-12-01 00:00:00.000'
select @someDateTime
------
2019-12-01 00:00:00
这可以保护您的代码免受不幸的服务器设置修改
阅读来自@SMor 评论的 this 文章、我的同事通过 google 搜索发表的评论,并想起几个月前我做的事情后,我想我已经弄明白了什么是发生了什么以及发生了什么变化。
默认情况下,我的数据库用户设置为:
language | us_english
dateformat | mdy
所以当读取字符串 '2019-12-01'
SQL 服务器期望 mm-dd-yyyy
.
SQL 服务器虽然很聪明。它看到第一部分 2019
并意识到它实际上是年份,因此它将年份移到最后,然后再次尝试。*
它现在 12-01-2019
符合它期望的格式。
当您在 SSMS 中打开帐户属性时,语言下拉列表默认为列表中的第一种语言 (Arabic
)。
几个月前我碰巧在那儿做一些不相关的事情并决定,为了确保我没有不小心将它设置为 Arabic
,我也会更改它。
我选了British
.
我的数据库用户现在设置为:
language | British
dateformat | dmy
所以当读取字符串 '2019-12-01'
SQL 服务器期望 dd-mm-yyyy
.
一旦它改变了年份,它就变成了 12-01-2019
,它被解释为 dd-mm-yyyy
从而给我留下 January 12th 2019 而不是 12 月 1 日st 2019
今天是漫长的一天。
*请注意,这是对我如何理解这个问题的一个相当简单的解释。这可能不是它在现实中的实际运作方式,但可以满足我对这个问题的好奇心。