有谁知道如何在 SQL Server中将列数据类型从“ nvarchar”格式转换为“ datetime”?
前任:
01-06-2020 12:00:00 AM6-17-2020 12:00:00 AM我试过下面的查询:
ALTER TABLE MyTable ALTER COLUMN UpdatedDate datetime
但是,得到以下错误
nvarchar 数据类型到日期时间数据类型的转换导致值超出范围。
好吧,既然您已经了解了它可能带来的问题,我希望您已经学会永远不要将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)
我在这个答案中没有解决最后一个问题,那就是原始专栏的依赖关系。您应该检查哪些内容取决于原始列,因为有时您必须根据已更改的列对代码进行调整。
这取决于您的设置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