我正在尝试将包含12,1,2007等个别部分的日期转换为SQL Server 2005中的日期时间。我尝试过以下操作:
CAST(DATEPART(year, DATE)+'-'+ DATEPART(month, DATE) +'-'+ DATEPART(day, DATE) AS DATETIME)
但这会导致错误的日期。将三个日期值转换为正确的日期时间格式的正确方法是什么。
答案 0 :(得分:330)
试试这个:
Declare @DayOfMonth TinyInt Set @DayOfMonth = 13
Declare @Month TinyInt Set @Month = 6
Declare @Year Integer Set @Year = 2006
-- ------------------------------------
Select DateAdd(day, @DayOfMonth - 1,
DateAdd(month, @Month - 1,
DateAdd(Year, @Year-1900, 0)))
它也有效,增加了不进行任何字符串转换的好处,因此它是纯算术处理(非常快)并且它不依赖于任何日期格式 这利用了SQL Server的datetime和smalldatetime值的内部表示是两部分值的事实,第一部分是表示自1900年1月1日以来的天数的整数,第二部分是表示小数部分的小数部分一天(当时)---所以整数值0(零)总是直接翻译成1900年1月1日的午夜...
或者,感谢来自@brinary的建议,
Select DateAdd(yy, @Year-1900,
DateAdd(m, @Month - 1, @DayOfMonth - 1))
2014年10月编辑。正如@cade Roux所述,SQL 2012现在具有内置功能:
DATEFROMPARTS(year, month, day)
做同样的事情。
2016年10月3日编辑,(感谢@bambams注意到这一点,以及@brinary修复它),最后一个解决方案,由@brinary提出。除非首先进行多年添加,否则似乎不适用于闰年
select dateadd(month, @Month - 1,
dateadd(year, @Year-1900, @DayOfMonth - 1));
答案 1 :(得分:229)
SQL Server 2012有一个很棒且期待已久的新DATEFROMPARTS函数(如果日期无效,将引发错误 - 我主要反对基于DATEADD的解决此问题的方法):
http://msdn.microsoft.com/en-us/library/hh213228.aspx
DATEFROMPARTS(ycolumn, mcolumn, dcolumn)
或
DATEFROMPARTS(@y, @m, @d)
答案 2 :(得分:167)
假设y, m, d
都是int
,那么:
CAST(CAST(y AS varchar) + '-' + CAST(m AS varchar) + '-' + CAST(d AS varchar) AS DATETIME)
请参阅my other answer了解SQL Server 2012及更高版本
答案 3 :(得分:116)
或仅使用一个dateadd函数:
DECLARE @day int, @month int, @year int
SELECT @day = 4, @month = 3, @year = 2011
SELECT dateadd(mm, (@year - 1900) * 12 + @month - 1 , @day - 1)
答案 4 :(得分:16)
Sql Server 2012有一个函数,它将根据部分(DATEFROMPARTS)创建日期。对于我们其他人来说,这是我创建的一个db函数,它将从部件中确定日期(感谢@Charles)......
IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = object_id(N'[dbo].[func_DateFromParts]'))
DROP FUNCTION [dbo].[func_DateFromParts]
GO
CREATE FUNCTION [dbo].[func_DateFromParts]
(
@Year INT,
@Month INT,
@DayOfMonth INT,
@Hour INT = 0, -- based on 24 hour clock (add 12 for PM :)
@Min INT = 0,
@Sec INT = 0
)
RETURNS DATETIME
AS
BEGIN
RETURN DATEADD(second, @Sec,
DATEADD(minute, @Min,
DATEADD(hour, @Hour,
DATEADD(day, @DayOfMonth - 1,
DATEADD(month, @Month - 1,
DATEADD(Year, @Year-1900, 0))))))
END
GO
你可以这样称呼它......
SELECT dbo.func_DateFromParts(2013, 10, 4, 15, 50, DEFAULT)
...返回
2013-10-04 15:50:00.000
答案 5 :(得分:12)
尝试CONVERT而不是CAST。
CONVERT允许第三个参数指示日期格式。
格式列表位于:http://msdn.microsoft.com/en-us/library/ms187928.aspx
选择另一个答案作为“正确”答案后更新:
我真的不明白为什么选择的答案明显取决于服务器上的NLS设置,而不会显示此限制。
答案 6 :(得分:8)
您也可以使用
select DATEFROMPARTS(year, month, day) as ColDate, Col2, Col3
From MyTable Where DATEFROMPARTS(year, month, day) Between @DateIni and @DateEnd
自ver.2012和AzureSQL
以来在SQL中运行答案 7 :(得分:6)
使用明确的起点'19000101'
更安全,更整洁create function dbo.fnDateTime2FromParts(@Year int, @Month int, @Day int, @Hour int, @Minute int, @Second int, @Nanosecond int)
returns datetime2
as
begin
-- Note! SQL Server 2012 includes datetime2fromparts() function
declare @output datetime2 = '19000101'
set @output = dateadd(year , @Year - 1900 , @output)
set @output = dateadd(month , @Month - 1 , @output)
set @output = dateadd(day , @Day - 1 , @output)
set @output = dateadd(hour , @Hour , @output)
set @output = dateadd(minute , @Minute , @output)
set @output = dateadd(second , @Second , @output)
set @output = dateadd(ns , @Nanosecond , @output)
return @output
end
答案 8 :(得分:4)
如果您不想保留字符串,这也可以(将其放入函数中):
DECLARE @Day int, @Month int, @Year int
SELECT @Day = 1, @Month = 2, @Year = 2008
SELECT DateAdd(dd, @Day-1, DateAdd(mm, @Month -1, DateAdd(yy, @Year - 2000, '20000101')))
答案 9 :(得分:4)
如果您需要日期和时间部分的日期,我会添加一行解决方案:
select dateadd(month, (@Year -1900)*12 + @Month -1, @DayOfMonth -1) + dateadd(ss, @Hour*3600 + @Minute*60 + @Second, 0) + dateadd(ms, @Millisecond, 0)
答案 10 :(得分:3)
尝试
CAST(STR(DATEPART(year, DATE))+'-'+ STR(DATEPART(month, DATE)) +'-'+ STR(DATEPART(day, DATE)) AS DATETIME)
答案 11 :(得分:2)
对于12以下的SQL Server版本,我建议将CAST
与SET DATEFORMAT
结合使用
-- 26 February 2015
SET DATEFORMAT dmy
SELECT CAST('26-2-2015' AS DATE)
SET DATEFORMAT ymd
SELECT CAST('2015-2-26' AS DATE)
如何创建这些字符串取决于你
答案 12 :(得分:1)
尝试此查询:
SELECT SUBSTRING(CONVERT(VARCHAR,JOINGDATE,103),7,4)AS
YEAR,SUBSTRING(CONVERT(VARCHAR,JOINGDATE,100),1,2)AS
MONTH,SUBSTRING(CONVERT(VARCHAR,JOINGDATE,100),4,3)AS DATE FROM EMPLOYEE1
结果:
2014 Ja 1
2015 Ja 1
2014 Ja 1
2015 Ja 1
2012 Ja 1
2010 Ja 1
2015 Ja 1
答案 13 :(得分:1)
我知道OP要求提供SQL 2005答案,但是问题已经很老了,因此,如果您运行的是SQL 2012或更高版本,则可以使用以下命令:
SELECT DATEADD(DAY, 1, EOMONTH(@somedate, -1))
答案 14 :(得分:0)
我个人喜欢Substring,因为它提供了清理选项和根据需要拆分字符串的能力。假设数据的格式为'dd,mm,yyyy'。
--2012 and above
SELECT CONCAT (
RIGHT(REPLACE(@date, ' ', ''), 4)
,'-'
,RIGHT(CONCAT('00',SUBSTRING(REPLACE(@date, ' ', ''), CHARINDEX(',', REPLACE(@date, ' ', '')) + 1, LEN(REPLACE(@date, ' ', '')) - CHARINDEX(',', REPLACE(@date, ' ', '')) - 5)),2)
,'-'
,RIGHT(CONCAT('00',SUBSTRING(REPLACE(@date, ' ', ''), 1, CHARINDEX(',', REPLACE(@date, ' ', '')) - 1)),2)
)
--2008 and below
SELECT RIGHT(REPLACE(@date, ' ', ''), 4)
+'-'
+RIGHT('00'+SUBSTRING(REPLACE(@date, ' ', ''), CHARINDEX(',', REPLACE(@date, ' ', '')) + 1, LEN(REPLACE(@date, ' ', '')) - CHARINDEX(',', REPLACE(@date, ' ', '')) - 5),2)
+'-'
+RIGHT('00'+SUBSTRING(REPLACE(@date, ' ', ''), 1, CHARINDEX(',', REPLACE(@date, ' ', '')) - 1),2)
以下是数据存储在列中时如何起诉的演示。不用说,它是在应用于列
之前检查结果集的理想选择DECLARE @Table TABLE (ID INT IDENTITY(1000,1), DateString VARCHAR(50), DateColumn DATE)
INSERT INTO @Table
SELECT'12, 1, 2007',NULL
UNION
SELECT'15,3, 2007',NULL
UNION
SELECT'18, 11 , 2007',NULL
UNION
SELECT'22 , 11, 2007',NULL
UNION
SELECT'30, 12, 2007 ',NULL
UPDATE @Table
SET DateColumn = CONCAT (
RIGHT(REPLACE(DateString, ' ', ''), 4)
,'-'
,RIGHT(CONCAT('00',SUBSTRING(REPLACE(DateString, ' ', ''), CHARINDEX(',', REPLACE(DateString, ' ', '')) + 1, LEN(REPLACE(DateString, ' ', '')) - CHARINDEX(',', REPLACE(DateString, ' ', '')) - 5)),2)
,'-'
,RIGHT(CONCAT('00',SUBSTRING(REPLACE(DateString, ' ', ''), 1, CHARINDEX(',', REPLACE(DateString, ' ', '')) - 1)),2)
)
SELECT ID,DateString,DateColumn
FROM @Table