用T-SQL创build一个date

我试图将个别部分,如12,1,2007date转换为SQL Server 2005中的date时间。我已经尝试了以下:

CAST(DATEPART(year, DATE)+'-'+ DATEPART(month, DATE) +'-'+ DATEPART(day, DATE) AS DATETIME) 

但是这会导致错误的date。 将三个date值转换为适当的date时间格式的正确方法是什么?

假设y, m, d都是int ,那么:

 CAST(CAST(y AS varchar) + '-' + CAST(m AS varchar) + '-' + CAST(d AS varchar) AS DATETIME) 

请参阅SQL Server 2012及更高版本的其他答案

尝试这个:

 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))) 

它工作得很好,增加了不做任何string转换的好处,所以它是纯粹的算术处理(速度非常快),它不依赖于任何date格式。这利用了SQL Server的datetime和smalldatetime值的内部表示是两个部分值的第一部分是一个整数,表示自1900年1月1日以来的天数,第二部分是小数部分表示一天的小数部分(时间)—所以整数值0(零)总是直接翻译成1900年1月1日的午夜上午…

或者,感谢@brinary的build议,

 Select DateAdd(yy, @Year-1900, DateAdd(m, @Month - 1, @DayOfMonth - 1)) 

2014年10月编辑。正如@cade Roux所述,SQL 2012现在具有内置function:
DATEFROMPARTS(year, month, day)
那是做同样的事情。

编辑2016年10月3日,(感谢@bambams注意到这一点,@BRINARY修复它),最后的解决scheme,由@brinary提出。 似乎不适用于闰年,除非首先执行年份增加

 select dateadd(month, @Month - 1, dateadd(year, @Year-1900, @DayOfMonth - 1)); 

SQL Server 2012有一个美妙的和期待已久的新的DATEFROMPARTS函数(如果date无效,会引发一个错误 – 我主要反对基于DATEADD的解决scheme):

http://msdn.microsoft.com/en-us/library/hh213228.aspx

 DATEFROMPARTS(ycolumn, mcolumn, dcolumn) 

要么

 DATEFROMPARTS(@y, @m, @d) 

或者只使用一个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) 

Sql Server 2012有一个函数,将根据部分( DATEFROMPARTS )创builddate。 对于我们其余的人来说,这里是我创build的一个db函数,它将决定部件的date(谢谢@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 

尝试CONVERT而不是CAST。

CONVERT允许第三个参数指示date格式。

格式列表在这里: http : //msdn.microsoft.com/en-us/library/ms187928.aspx

更新后的另一个答案被选为“正确的”答案:

我不明白为什么select的答案显然取决于服务器上的NLS设置,而没有指出这个限制。

使用明确的起点“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 

你也可以使用

 select DATEFROMPARTS(year, month, day) as ColDate, Col2, Col3 From MyTable Where DATEFROMPARTS(year, month, day) Between @DateIni and @DateEnd 

从2012年开始使用SQL和AzureSQL

如果你不想保留string,这也可以工作(把它放到一个函数中):

 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'))) 

如果您需要date和时间部分的date时间,我将添加一行解决scheme:

 select dateadd(month, (@Year -1900)*12 + @Month -1, @DayOfMonth -1) + dateadd(ss, @Hour*3600 + @Minute*60 + @Second, 0) + dateadd(ms, @Millisecond, 0) 

尝试

 CAST(STR(DATEPART(year, DATE))+'-'+ STR(DATEPART(month, DATE)) +'-'+ STR(DATEPART(day, DATE)) AS DATETIME) 

对于低于12的SQL Server版本,我可以推荐将CASTSET DATEFORMAT结合使用

 -- 26 February 2015 SET DATEFORMAT dmy SELECT CAST('26-2-2015' AS DATE) SET DATEFORMAT ymd SELECT CAST('2015-2-26' AS DATE) 

你如何创build这些string取决于你

试试这个查询:

  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 

我个人更喜欢Substring,因为它提供了清理选项,并根据需要分割string。 假设数据的格式为“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