Sql server 在SQLServer中保存日期

Sql server 在SQLServer中保存日期,sql-server,datetime,Sql Server,Datetime,我有一个传统应用程序,其中输入是日期字符串,即: 06/12/2009 输入的格式始终是字符串,并且是一致的,始终是dd/mm/yyyy 目前,遗留应用程序只是将其插入DateTime字段中。显然,如果服务器的本地化区域性设置发生更改,我们就有一个bug 两个问题: 一: 在这种情况下,在SQLServer中存储日期最安全的方法是什么? 是否有一种格式无论日期和月份的顺序如何都能正确解释? 二: 什么设置确切地决定了SQLServer数据库的区域性,是操作系统设置,还是该数据库的设置,还是什么?

我有一个传统应用程序,其中输入是日期字符串,即:

06/12/2009

输入的格式始终是字符串,并且是一致的,始终是dd/mm/yyyy

目前,遗留应用程序只是将其插入DateTime字段中。显然,如果服务器的本地化区域性设置发生更改,我们就有一个bug

两个问题:

一:

在这种情况下,在SQLServer中存储日期最安全的方法是什么?

是否有一种格式无论日期和月份的顺序如何都能正确解释?

二:

什么设置确切地决定了SQLServer数据库的区域性,是操作系统设置,还是该数据库的设置,还是什么?


cheers

格式
YYYY-MM-DD
是明确的,这意味着SQL Server不会混淆月份 以及将字符串值转换为
DATETIME
的日期。(我从未遇到过使用四位数年份的格式进行隐式转换的问题。)

在SQL Server中存储日期值的“最安全”(也是最方便)的方法是使用DATETIME数据类型

DATETIME
和字符串之间转换时,使用
CONVERT
函数显式指定输入和输出格式

SQL Server 2005关于转换样式参数值的文档:

要将字符串表示形式转换为DATETIME数据类型,请执行以下操作:

select CONVERT(datetime, '2009-06-03', 20)
第一个参数是要转换为的数据类型,第二个参数是要转换的表达式,第三个参数是样式

(样式20是ODBC规范格式=
'YYYY-MM-DD HH:MI:SS'
(24小时时钟)


[跟进]

要将日期时间表达式(例如getdate()转换为
'YYYY-MM-DD'
格式的VARCHAR,请执行以下操作:

select CONVERT(varchar(10), getdate(), 20)
注意,指定varchar(10)只会得到etnire
'YYYY-MM-DD HH:MM:SS'
格式的前10个字符

[/后续行动]



至于什么决定了默认格式,我们将进行研究。我们通过指定格式来避免默认格式引起的问题。

我建议在将所有日期放入数据库时以UTC时间存储。这样会保持一致

像这样存储日期似乎效果很好

YYYY-MM-DD

请参阅。SQL“区域性”是由在会话级别上设置的。SQL Server有自己的日期格式设置,与宿主操作系统无关。这有几个原因:符合ANSI标准,为了防止操作系统更改影响使用宿主在该主机上的数据库的应用程序,尤其是兼容性,SQL早于当前运行的操作系统继续。

在这些问题上,我有点保守,但我更喜欢在表中使用单独的年/月/日字段,而不是使用DBMS特定数据类型的日期字段。这当然需要更多的空间,但缺少歧义和增加的可移植性对我来说是值得的


您付出的代价是,您无法获得免费的日期/时间算术和排序,但您可以自己或通过稍微复杂的“ORDER by”子句轻松完成。请记住,数据不是它的表示形式。在这种情况下,数据是日期或日期时间,无论您如何显示它们。
至于插入/更新/比较日期时间值,我引用BOL:

在比较中指定日期时 或用于插入或更新输入 语句,使用 所有语言的解释都相同 设置:ADO、OLE DB和ODBC 应用程序应该使用ODBC 时间戳、日期和时间转义 条款:
{ts'年-月-日 hh:mm:ss[.fff]'}例如:{ts “1998-09-2410:02:20”}
{d'yyyy-mm-dd'}例如:{d'1998-09-24'}
{t'hh:mm:ss'}例如:{t'10:02:20'}


我可以向您保证,如果您使用此格式,无论您的服务器的语言环境如何,它们都将始终工作

我同意spencer7593的建议,但请注意,使用不带格式的cast或convert可能会产生意外的结果。此T-SQL查询返回12,而不是1

set language British
select month(CAST('2016-01-12' AS datetime))

通常我更喜欢插入为

insert into tbl values('yyyyMMdd')

然后,它将根据db以正确的格式插入。

嘿,斯宾塞,谢谢你提供的信息。在日期时间字段上进行选择时,如何将其转换回通用格式的字符串(YY-mm-dd)?@andy:answer更新以回答后续问题。(我为答案的不完整性道歉…我只是给你一些SQL表达式来进行转换。(对于影响区域/语言环境默认格式的所有问题,我没有一个好的答案。)。(我是一名IT人员,我喜欢我的日期字符串规范CCYYMMDDH24HMISS,这样我就可以对它们进行排序。任何不带世纪和年份的格式,我都使用三个字母的月份缩写,例如2009年6月3日。这避免了歧义。YYYY-MM-DD格式是ISO-8601推荐的格式,无论您的日期格式如何,它都将在SQL Server上工作。)r语言系统设置。使用它!:-)您可以随时从通用格式转换为您需要的任何本地化表示形式。@spencer:哈哈,是的,无需道歉,谢谢您的帮助。刚从修复旧版应用程序中恢复过来…日期处理非常糟糕,代码也是如此…@spencer7593该格式并不明确,这就是为什么我同意您的建议o始终指定格式。隐式和显式强制转换/转换之间的SQL不一致。请尝试以下操作:将语言设置为英国选择月(强制转换(“2016-01-12”为日期时间))ISO-8601标准-始终有效-为什么每个人都不使用该格式?:-)ISO_8601格式的日期(YYYY-MM-DD)无论您的日期格式或语言设置有多糟糕,都将始终在SQL Server上工作。真的,不需要将日、月、年分隔为单独的字段。@Marc:我相信您是对的。对我来说,问题一直在代码和DBMS之间的接口处--我可以从数据库中提取整数