为什么 SQL Server 不让我将“21/04/17”存储为日期?

Phi*_*ins 0 sql t-sql sql-server sqldatatypes

我有一个表,目前所有列都存储为 nvarchar(max),所以我将所有数据类型转换为它们应该是的。我有一列日期,但是当我运行它时:

ALTER TABLE Leavers ALTER COLUMN [Actual_Termination_Date] date;
Run Code Online (Sandbox Code Playgroud)

我得到

"Conversion failed when converting date and/or time from character string".
Run Code Online (Sandbox Code Playgroud)

这是比较正常的,所以我做了以下调查:

SELECT DISTINCT TOP 20 [Actual_Termination_Date]
FROM LEAVERS
WHERE ISDATE([Actual_Termination_Date]) = 0
Run Code Online (Sandbox Code Playgroud)

返回:

NULL
13/04/2017
14/04/2017
17/04/2017
19/04/2017
21/04/2017
23/04/2017
24/04/2017
26/04/2017
28/04/2017
29/03/2017
29/04/2017
30/04/2017
31/03/2017
42795
42797
42813
42817
42820
42825
Run Code Online (Sandbox Code Playgroud)

null 和 excel 样式的日期格式(例如 42795)没有问题,但是我遇到了问题,这些日期显示为完全正常的日期。我通常使用以下修复方法之一来解决此类问题:

SELECT  cast([Actual_Termination_Date] - 2 as datetime)
FROM LEAVERS
WHERE ISDATE([Actual_Termination_Date]) = 0
Run Code Online (Sandbox Code Playgroud)

或者

SELECT  cast(convert(nvarchar,[Actual_Termination_Date], 103) - 2 as datetime)
FROM LEAVERS
WHERE ISDATE([Actual_Termination_Date]) = 0
Run Code Online (Sandbox Code Playgroud)

当这些返回日期时,我会像 expext 一样返回日期,然后我会执行 UPDATE 语句来更改表中的它们,然后转换列类型。但是,我不断收到一条错误消息,告诉我无法转换各种日期,例如:

Conversion failed when converting the nvarchar value '21/04/2017' to data type int.
Run Code Online (Sandbox Code Playgroud)

有什么想法吗?谢谢!

use*_*983 5

可能是因为您的语言设置。为了'21/04/2017'工作,您需要使用该BRITISH语言或其他使用dd/MM/yyyy. 我怀疑您使用的ENGLISH是实际上是美国的。

American 的用法MM/dd/yyyy'21/04/2017'指 2017 年的第 21 个月的第 4 天;显然这是行不通的。

最好的方法是使用一个明确的格式,而不管语言和数据类型。对于 SQL ServeryyyyMMddyyyy-MM-ddThh:mm:ss.nnnnnnn(yyyy-MM-dd并且在使用旧的和数据类型时在 SQL Serveryyyy-MM-dd hh:mm:ss.nnnnnnn不是明确的)。datetimesmalldatetime

否则,你可以使用CONVERT同一个风格的代码:

SELECT CONVERT(date,'21/04/2017', 103)
Run Code Online (Sandbox Code Playgroud)

但是,您的数据的问题在于您具有格式dd/MM/yyyy和整数值中的值。SQL Server 中a的int(非varchar)值为. 另一方面,如果此数据来自 Excel,则值为。我将假设数据来自 Excel,而不是 SQL Server(因为 ACE 驱动程序习惯于将日期读取为数字,因为它们不是“ace”)。42817datetime2017-03-252017-03-23

因此,您首先需要将这些值转换为明确的格式,因此将是yyyyMMdd. 由于我们有 2 种不同类型的值,这有点困难,但仍然可能:

UPDATE dbo.Leavers
SET Actual_Termination_Date = CONVERT(varchar(8), ISNULL(TRY_CONVERT(date, Actual_Termination_Date, 103), DATEADD(DAY, TRY_CONVERT(int, Actual_Termination_Date),'18991230')), 112);
Run Code Online (Sandbox Code Playgroud)

然后你可以改变你的表:

ALTER TABLE dbo.Leavers ALTER COLUMN [Actual_Termination_Date] date;
Run Code Online (Sandbox Code Playgroud)

DB<> Fiddle使用 Micha?Turczyn 的 DML 声明。

  • 谁知道使用标准可以使互操作性变得更容易!?;) (2认同)