代码之家  ›  专栏  ›  技术社区  ›  Sophart

SQL:如何解决“从字符串转换日期和/或时间时转换失败”?

  •  0
  • Sophart  · 技术社区  · 6 年前

    我想将交叉表用于我的人力资源管理系统出勤报告。当我使用这个SQL脚本时,我遇到了这个执行错误

    “(30行受影响)

    消息241,级别16,状态1,行47
    从字符串转换日期和/或时间时转换失败“

    SQL脚本:

    USE [KCLDB]
    GO
    
    /****** Object:  StoredProcedure [hrms].[GET_ATTENDANCEREPORT]    Script Date: 05-Jul-18 10:41:42 AM ******/
    
    SET ANSI_NULLS ON
    GO
    SET QUOTED_IDENTIFIER ON
    GO
    
    ALTER PROCEDURE [hrms].[GET_ATTENDANCEREPORT]   
        @STARTDATE DATE,  
        @ENDDATE DATE  
    AS 
    BEGIN
        WITH DATERANGE AS  
        (  
            SELECT 
                DT = DATEADD(DD, 0, @STARTDATE)  
            WHERE  
                DATEADD(DD, 1, @STARTDATE) <= @ENDDATE  
    
            UNION ALL  
    
            SELECT DATEADD(DD, 1, DT)  
            FROM DATERANGE  
            WHERE DATEADD(DD, 1, DT) <= @ENDDATE  
        )  
        SELECT * 
        INTO #TMP_DATES  
        FROM DATERANGE   
    
        DECLARE @COLUMN VARCHAR(MAX)  
    
        SELECT @COLUMN = ISNULL(@COLUMN + ',', '') + '[' + CAST(CONVERT(DATE , T.DT) AS VARCHAR) + ']' 
        FROM #TMP_DATES T  
    
        DECLARE @Columns2 VARCHAR(MAX)  
        SET @Columns2 = SUBSTRING((SELECT DISTINCT ',ISNULL(['+ CAST(CONVERT(DATE , DT) as varchar )+'],''N/A'') AS ['+CAST(CONVERT(DATE , DT) as varchar )+']' FROM #TMP_DATES GROUP BY DT FOR XML PATH('')),2,8000)
    
        DECLARE @QUERY VARCHAR(MAX)  
        SET @QUERY = 'SELECT UserID, ' + @Columns2 +' FROM   
    (  
    SELECT A.UserID , B.DT AS DATE, A.[Clock], A.[Date] FROM hrms.AttendanceRecord A RIGHT OUTER JOIN #TMP_DATES B ON A.[Date]=B.DT   
    ) X  
    PIVOT   
    (  
    MIN([Clock])  
    FOR [Date] IN (' + @COLUMN + ')  
    ) P   
    WHERE ISNULL(UserID,'''')<>''''  
    '  
    
    EXEC (@QUERY)  
    DROP TABLE #TMP_DATES  
    
    END  
    
    ---Execution Line
    
    EXEC hrms.GET_ATTENDANCEREPORT @STARTDATE = '2018-05-01', @ENDDATE= '2018-05-30'
    
    1 回复  |  直到 6 年前
        1
  •  0
  •   SQLApostle    6 年前

    ALTER PROCEDURE [hrms].[GET_ATTENDANCEREPORT]
        @STARTDATE DATE
        ,@ENDDATE  DATE
    AS
    BEGIN
        WITH
        [DATERANGE]
        AS
        (
            SELECT
                [DT] = DATEADD(DD, 0, @STARTDATE)
            WHERE DATEADD(DD, 1, @STARTDATE) <= @ENDDATE
            UNION ALL
            SELECT
                DATEADD(DD, 1, [DATERANGE].[DT])
            FROM
                [DATERANGE]
            WHERE DATEADD(DD, 1, [DATERANGE].[DT]) <= @ENDDATE
        )
        SELECT
            [DATERANGE].[DT]
        INTO
            [#TMP_DATES]
        FROM
            [DATERANGE]
    
        DECLARE @COLUMN VARCHAR(MAX)
    
        SELECT
            @COLUMN = ISNULL(@COLUMN + ',', '') + '[' + CAST(CONVERT(DATE, [T].[DT]) AS VARCHAR) + ']'
        FROM
            [#TMP_DATES] AS [T]
    
        DECLARE @Columns2 VARCHAR(MAX)
    
        SET @Columns2 = SUBSTRING(
                        (
                            SELECT DISTINCT
                                   ',ISNULL(CONVERT(VARCHAR(20),[' + CAST(CONVERT(DATE, [DT]) AS VARCHAR) + '],120),''N/A'') AS ['
                                   + CAST(CONVERT(DATE, [DT]) AS VARCHAR) + ']'
                            FROM
                                [#TMP_DATES]
                            GROUP BY
                                [DT]
                            FOR XML PATH('')
                        )
                        ,2
                        ,8000
                                 )
    
        DECLARE @QUERY VARCHAR(MAX)
    
        SET @QUERY = 'SELECT UserID, ' + @Columns2
                     + ' FROM   
    (  
    SELECT A.UserID , B.DT AS DATE2, A.[Clock], A.[Date] FROM hrms.AttendanceRecord A RIGHT OUTER JOIN #TMP_DATES B ON A.[Date]=B.DT   
    ) X  
    PIVOT   
    (  
    MIN([Clock])  
    FOR [Date] IN (' + @COLUMN + ')  
    ) P   
    WHERE ISNULL(UserID,'''')<>''''  
    '
    
        EXEC ( @QUERY )
    
        DROP TABLE [#TMP_DATES]
    END
    GO
    ---Execution Line
    EXEC dbo.GET_ATTENDANCEREPORT @STARTDATE = '2018-05-01', @ENDDATE= '2018-05-30'