首页 文章

使用T-SQL从日期和年份创建日期

提问于
浏览
243

我试图将日期与单个部分(如12,1,2007)转换为SQL Server 2005中的日期时间 . 我尝试了以下内容:

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

但这会导致错误的日期 . 将三个日期值转换为正确的日期时间格式的正确方法是什么 .

14 回答

  • 162

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

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

    有关SQL Server 2012及更高版本,请参阅my other answer

  • 4

    试试这个:

    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值的内部表示是两个的事实part值的第一部分是一个整数,表示自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));
    
  • 8

    SQL Server 2012有一个很棒且期待已久的新DATEFROMPARTS函数(如果日期无效,将引发错误 - 我主要反对基于DATEADD的解决此问题的方法):

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

    DATEFROMPARTS(ycolumn, mcolumn, dcolumn)
    

    要么

    DATEFROMPARTS(@y, @m, @d)
    
  • 3

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

    Sql Server 2012有一个函数,它将根据部分创建日期(DATEFROMPARTS) . 对于我们其他人来说,这是我创建的数据库函数,它将确定部件的日期(感谢@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
    
  • 1

    尝试CONVERT而不是CAST .

    CONVERT允许第三个参数指示日期格式 .

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

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

    我真的不明白为什么选择的答案显然取决于服务器上的NLS设置,而没有指明此限制 .

  • 2

    你也可以使用

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

    自ver.2012和AzureSQL以来在SQL中工作

  • 220

    使用明确的起点'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
    
  • 12

    如果您不想保留字符串,这也可以(将其放入函数中):

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

    如果您需要日期时间 from both date and time parts ,我会添加一个单行解决方案:

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

    尝试

    CAST(STR(DATEPART(year, DATE))+'-'+ STR(DATEPART(month, DATE)) +'-'+ STR(DATEPART(day, DATE)) AS DATETIME)
    
  • 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)
    

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

  • 4

    试试这个查询:

    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
    
  • 6

    我个人喜欢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
    

相关问题