关于sql server:使用T-SQL从日期和年份创建日期

Create a date from day month and year with T-SQL

我正在尝试将包含单个部分(如12、1、2007)的日期转换为SQL Server 2005中的日期时间。我尝试了以下方法:

1
CAST(DATEPART(YEAR, DATE)+'-'+ DATEPART(MONTH, DATE) +'-'+ DATEPART(DAY, DATE) AS DATETIME)

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


试试这个:

2

它也可以工作,不进行任何字符串转换的额外好处,所以它是纯算术处理(非常快),并且不依赖于任何日期格式。这是基于这样一个事实:SQL Server的datetime和smalldatetime值的内部表示是由两部分组成的值,第一部分是一个整数,表示自1900年1月1日以来的天数,第二部分是一个小数部分,表示一天的小数部分(对于时间而言)--因此整数值0(零)总是直接翻译成1900年1月1日午夜的早晨……

或者,多亏了@brinary的建议,

1
2
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提出。除非先执行年份添加,否则在闰年似乎不起作用。

1
2
SELECT dateadd(MONTH, @MONTH - 1,
     dateadd(YEAR, @Year-1900, @DayOfMonth - 1));


SQL Server 2012有一个出色的、期待已久的新datefromparts函数(如果日期无效,则会引发错误-我主要反对基于dateadd的此问题解决方案):

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

1
DATEFROMPARTS(ycolumn, mcolumn, dcolumn)

1
DATEFROMPARTS(@y, @m, @d)


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

1
CAST(CAST(y AS VARCHAR) + '-' + CAST(m AS VARCHAR) + '-' + CAST(d AS VARCHAR) AS DATETIME)

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


或者只使用一个dateadd函数:

1
2
3
4
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)创建日期。对于我们中的其他人,这里有一个我创建的数据库函数,它将根据部件确定日期(谢谢@charles)…

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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

你可以这样称呼它…

1
SELECT dbo.func_DateFromParts(2013, 10, 4, 15, 50, DEFAULT)

回报…

1
2013-10-04 15:50:00.000

尝试转换而不是强制转换。

convert允许第三个参数指示日期格式。

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

选择另一个答案作为"正确"答案后更新:

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


您也可以使用

1
2
SELECT DATEFROMPARTS(YEAR, MONTH, DAY) AS ColDate, Col2, Col3
FROM MyTable WHERE DATEFROMPARTS(YEAR, MONTH, DAY) BETWEEN @DateIni AND @DateEnd

从2012年版开始在SQL和AzureSQL中工作


使用明确的起点"19000101"更安全、更整洁。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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


如果您同时需要日期和时间部分的日期时间,我会添加一个单行解决方案:

1
SELECT dateadd(MONTH, (@YEAR -1900)*12 + @MONTH -1, @DayOfMonth -1) + dateadd(ss, @HOUR*3600 + @MINUTE*60 + @SECOND, 0) + dateadd(ms, @Millisecond, 0)

如果您不想让字符串远离它,这也会起作用(将其放入函数中):

1
2
3
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')))

尝试

1
CAST(STR(DATEPART(YEAR, DATE))+'-'+ STR(DATEPART(MONTH, DATE)) +'-'+ STR(DATEPART(DAY, DATE)) AS DATETIME)


对于低于12的SQL Server版本,我建议结合使用CASTSET DATEFORMAT

1
2
3
4
5
6
-- 26 February 2015
SET DATEFORMAT dmy
SELECT CAST('26-2-2015' AS DATE)

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

如何创建这些字符串取决于您自己。


尝试这个查询:

1
2
3
    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

结果:

1
2
3
4
5
6
7
2014    Ja    1
2015    Ja    1
2014    Ja    1
2015    Ja    1
2012    Ja    1
2010    Ja    1
2015    Ja    1

我个人更喜欢子字符串,因为它提供了清理选项和根据需要拆分字符串的能力。假设数据的格式为"dd,mm,yyyy"。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
--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)

这里演示了如果数据存储在列中,如何起诉它。不用说,在应用到列之前检查结果集是理想的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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