用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版本,我可以推荐将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)
你如何创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