将“nvarchar”列数据类型转换为“DateTime”

Moh*_*nan 6 sql sql-server

有谁知道如何在 SQL Server中将列数据类型从“ nvarchar”格式转换为“ datetime”?

前任:

  1. 01-06-2020 12:00:00 AM
  2. 6-17-2020 12:00:00 AM

我试过下面的查询:

ALTER TABLE MyTable ALTER COLUMN UpdatedDate datetime

但是,得到以下错误

nvarchar 数据类型到日期时间数据类型的转换导致值超出范围。

Zoh*_*led 6

好吧,既然您已经了解了它可能带来的问题,我希望您已经学会永远不要将DateTime值存储为字符串。
您应该努力始终使用最合适的可用数据类型。
不过别担心。这是一个常见的错误,Aaron Bertrand 写了一篇关于它的博客文章(嗯,更普遍的问题)——名为“要戒掉的坏习惯:选择错误的数据类型”

因此,您可以这样处理此类事情:(TL;DR;现场演示Rextester

首先,创建并填充示例表(在您以后的问题中保存此步骤):

CREATE TABLE MyTable (
    Id int identity(1,1),
    UpdatedDate nvarchar(30)
);


INSERT INTO MyTable(UpdatedDate) VALUES
('01-06-2020 12:00:00 AM'),
('6-17-2020 12:00:00 AM'),
('02-30-2020 12:00:00 AM'), -- Bad data
('1-06-2020 12:00:00 ZM'),  -- Bad data
('01-06-2020 13:00:00 PM'),
('13-06-2020 13:00:00 PM'),  -- Bad data
('01-06-2020 1:00:00 PM'),
('1-6-2020 1:00:00 AM'),
('Not a date at all...');  -- Bad data
Run Code Online (Sandbox Code Playgroud)

请注意,我添加了一些包含无法转换为DateTime值的数据的行。

然后,第一步是获取转换失败的值列表。

SELECT Id, UpdatedDate
FROM dbo.MyTable
WHERE TRY_CONVERT(DateTime2, UpdatedDate, 110) IS NULL;
Run Code Online (Sandbox Code Playgroud)

这将返回以下记录集(对于此示例数据):

Id  UpdatedDate
3   02-30-2020 12:00:00 AM
4   1-06-2020 12:00:00 ZM
6   13-06-2020 13:00:00 PM
9   Not a date at all...
Run Code Online (Sandbox Code Playgroud)

现在您已经有了列表,您可以决定是否要手动修复它们、删除记录,或者只是忽略这些值,将新UpdatedDate列保留NULL在这些行中。

完成后,您可以向表中添加一个新列,并使用临时名称。我建议使用DateTime2而不是DateTime-它只是一种更好的数据类型。

ALTER TABLE dbo.MyTable 
ADD UpdatedDate_New DateTime2 NULL;
Run Code Online (Sandbox Code Playgroud)

接下来,填充此列(我假设您决定将其保留为 null,因为原始列的数据无法转换为DateTime2):

UPDATE dbo.MyTable
SET  UpdatedDate_New = TRY_CONVERT(DateTime2, UpdatedDate, 110);
Run Code Online (Sandbox Code Playgroud)

现在,从表中删除旧列:

ALTER TABLE dbo.MyTable 
DROP COLUMN UpdatedDate;
Run Code Online (Sandbox Code Playgroud)

最后,重命名新列:

EXEC sp_Rename 'dbo.MyTable.UpdatedDate_New', 'UpdatedDate', 'COLUMN';
Run Code Online (Sandbox Code Playgroud)

验证结果:

SELECT *
FROM dbo.MyTable
Run Code Online (Sandbox Code Playgroud)

结果:

Id  UpdatedDate
1   06.01.2020 00:00:00
2   17.06.2020 00:00:00
3   NULL
4   NULL
5   06.01.2020 13:00:00
6   NULL
7   06.01.2020 13:00:00
8   06.01.2020 01:00:00
9   NULL
Run Code Online (Sandbox Code Playgroud)

我在这个答案中没有解决最后一个问题,那就是原始专栏的依赖关系。您应该检查哪些内容取决于原始列,因为有时您必须根据已更改的列对代码进行调整。


all*_*ran 0

这取决于您的设置dateformat

create table t(dt varchar(10));

insert t(dt) select '20/7/2020';

set dateformat mdy;

alter table t alter column dt datetime ;
--error

set dateformat dmy;

alter table t alter column dt datetime;
-- ok, because the format of the dates in the table is dmy
Run Code Online (Sandbox Code Playgroud)

就您而言,您的值采用月/日/年格式。所以你需要执行set dateformat mdy