我有一个nvarchar(50)
字段 (DateHr),它以以下格式保存日期和时间:(yy/mm/dd hh:mm:ss
例如12/04/11 16:49:23
,应该转换为April 11, 2012 4:49 PM
)。
我很难尝试以这种格式管理日期值。
我想知道是否可以创建一个列作为DateTime
数据类型并使用这个新字段。
我有一个nvarchar(50)
字段 (DateHr),它以以下格式保存日期和时间:(yy/mm/dd hh:mm:ss
例如12/04/11 16:49:23
,应该转换为April 11, 2012 4:49 PM
)。
我很难尝试以这种格式管理日期值。
我想知道是否可以创建一个列作为DateTime
数据类型并使用这个新字段。
为什么不只是有一个观点?
CREATE VIEW dbo.View_MyTable
AS
SELECT
DateHr,
DateHr2 = CONVERT(VARCHAR(24), CONVERT(DATETIME, '20' + DateHr), 100)),
DateHrProper = CONVERT(DATETIME, '20' + DateHr)
FROM dbo.MyTable;
现在您的查询可以是:
SELECT DateHr2 FROM dbo.View_MyTable
WHERE DateHrProper >= '20120412'
AND DateHrProper < '20120413';
这样您就不必弄乱表的架构,并且只有在需要时才可以研究持久计算列方法。如果您确实添加了计算列,我会将其添加为日期时间列,而不是作为同一日期的不同字符串表示形式。在输出而不是存储中做你的“让它漂亮”的东西。
编辑如果您可以通过存储过程控制对表的写入(强烈推荐),并且您不让用户运行临时插入/更新,那么您可以更改基本类型而不必担心他们可能会胡说八道进入。例如:
UPDATE dbo.MyTable
SET DateHr = CONVERT(DATETIME, '20' + DateHr);
-- assuming there are no rows left where `ISDATE(DateHr) = 0`,
-- but you'll have to test that:
ALTER TABLE dbo.MyTable ALTER COLUMN DateHr DATETIME;
GO
ALTER PROCEDURE dbo.ProcThatUpdatesMyTable
@key INT,
@DateHr NVARCHAR(50)
AS
BEGIN
SET NOCOUNT ON;
IF ISDATE('20' + @DateHr) = 0
BEGIN
RAISERROR('Please enter a valid date.', 11, 1);
RETURN;
END
UPDATE dbo.MyTable
SET DateHr = CONVERT(DATETIME, '20' + @DateHr)
WHERE key = @key;
END
GO
现在您的查询,您想要April 11, 2012 4:49 PM
作为输出的位置 - 不幸的是,在 SQL Server 中没有一种本地方法可以轻松地转换为该格式。您可以使用各种字符串操作来做到这一点,例如:
;WITH x AS
(
SELECT
d = DATENAME(MONTH, DateHr) + ' '
+ CONVERT(VARCHAR(2), DAY(DateHr)) + ', '
+ CONVERT(CHAR(5), YEAR(DateHr)),
t = CONVERT(CHAR(26), DateHr, 109)
FROM dbo.blab
)
SELECT d = d + LEFT('0' + RIGHT(t, 13), 5) + ' ' + RIGHT(t, 2) FROM x;
这非常接近您想要的输出:
April 11, 2012 04:49 PM
如果需要,您可以进行更多的字符串操作以删除小时的前导 0。
在客户端上进行格式化要好得多。从好的方面来说,您可以在 SQL Server 2012 中使用新FORMAT()
功能轻松做到这一点:
SELECT FORMAT(DateHr, 'MMMM dd, yyyy h:mm tt')
FROM dbo.MyTable;
结果:
April 11, 2012 4:49 PM
当然,我会再次提到,最终的解决方案是不让您的用户首先输入自由文本日期格式。我向您保证,有人会输入 4 月 5 日,他们的意思是 5 月 4 日,或者 2011 年 12 月,他们的意思是 2012 年 11 月。让他们从下拉菜单或日历控件中进行选择,您可以在安全的地方完全监督传递给 SQL Server 的字符串格式而不是依赖于当天的心情,将确保您始终知道日期是用户选择的日期(即使他们的区域格式可能不是您所期望的)。
做这个:
SELECT CONVERT(VARCHAR(20), cast('2012/04/11 16:49:23' as datetime), 100)
这很奇怪,但两个演员都是必要的
编辑:
create table test_date
(
DateHr varchar(50),
DateHr2 AS (CONVERT(VARCHAR(20), cast('20'+ DateHr as datetime), 100))
)
insert into test_date values ('12/04/11 16:49:23')
select * from test_date
12/04/11 16:49:23 Apr 11 2012 4:49PM
一种选择是计算列。例如,
declare @t table(s nvarchar(50), dt as convert(varchar(30),case isdate(s) when 1 then cast(s as datetime) end,121))
insert into @t(s) values ('12/04/11 16:49:23')
update @t set s='20'+s where ISDATE(s)=1 and LEN(s)<19 --prepend w/century
insert into @t(s) values ('john') --demonstrate bad date string handling here
select * from @t;
结果:
s dt
-------------------------------------------------- ------------------------------
2012/04/11 16:49:23 2012-04-11 16:49:23.000
john NULL
编辑:添加对错误日期值的处理
编辑:自定义日期 24 小时格式 - yyyy-mm-dd hh:mi:ss.mmm(24h)
编辑:根据需要在原始日期前加上世纪
或者,您可以在计算列中添加世纪:
declare @t table(s nvarchar(50), dt as convert(varchar(30),case isdate('20'+s) when 1 then cast('20'+s as datetime) end,121))
insert into @t(s) values ('12/04/11 16:49:23')
insert into @t(s) values ('john') --demonstrate bad date string handling here
select * from @t;
结果:
s dt
-------------------------------------------------- ------------------------------
12/04/11 16:49:23 2012-04-11 16:49:23.000
john NULL