使用T-SQL从日、月和年创建一个日期

我正在尝试将2007年12月1日等单独部分的日期转换为SQL Server 2005中的日期时间。我尝试过以下方法:

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

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

441845 次浏览

尝试CONVERT而不是CAST。

CONVERT允许使用第三个参数表示日期格式。

格式列表如下:http://msdn.microsoft.com/en-us/library/ms187928.aspx

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

我真的不明白为什么选择的答案明显依赖于服务器上的NLS设置,而没有说明这一限制。

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

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

请参见SQL Server 2012及以上版本的我的另一个答案

如果你不想把字符串排除在外,这也可以(把它放到一个函数中):

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

试试这个:

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日的午夜早晨…< / p >

或者,感谢@brinary的建议,

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

编辑2014年10月。正如@cade Roux所指出的,SQL 2012现在有一个内置函数:
DATEFROMPARTS(year, month, day) < br >

编辑2016年10月3日,(感谢@bambams注意到这一点,@brinary修复了它),最后的解决方案,由@brinary提出。除非先执行年份加法,否则似乎对闰年不起作用

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

或者只使用一个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函数(如果日期无效,它将引发错误-我对基于dateadd的解决方案的主要反对意见):

http://msdn.microsoft.com/en-us/library/hh213228.aspx < a href = " http://msdn.microsoft.com/en-us/library/hh213228.aspx " > < / >

DATEFROMPARTS(ycolumn, mcolumn, dcolumn)

DATEFROMPARTS(@y, @m, @d)

使用显式起点'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

试一试

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

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

如果你需要datetime 从日期和时间两个部分,我添加了一行解决方案:

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

对于低于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)

如何创建这些字符串取决于你

试试这个问题:

    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,因为它提供了清理选项,并能够根据需要分割字符串。假设数据的格式是'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

你也可以使用

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

工作在SQL自ver。2012和azureql

我知道OP正在询问SQL 2005的答案,但这个问题已经很老了,所以如果你正在运行SQL 2012或以上版本,你可以使用以下命令:

SELECT DATEADD(DAY, 1, EOMONTH(@somedate, -1))
< p >参考: https://learn.microsoft.com/en-us/sql/t-sql/functions/eomonth-transact-sql?view=sql-server-2017&viewFallbackFrom=sql-server-previousversions < / p >