解释此SQL错误“将varchar数据类型转换为datetime数据类型导致值超出范围”

解释此SQL错误“将varchar数据类型转换为datetime数据类型导致值超出范围”,sql,sql-server,Sql,Sql Server,这是我存储的程序;当我执行它时,我得到以下错误 Msg 242,16级,状态3,程序TRN\u Hold\u GetData,第45行 将varchar数据类型转换为datetime数据类型导致值超出范围 XML 17-3-2017中的日期时间可以用两种不同的方式进行解释,其中一种是17个月的第3天无效。确保在XML中使用符合XML标准YYYY-MM-DDThh:MM:ss的显式日期格式,正如Phillip所建议的那样,您确实应该使用通用格式的日期时间字符串。但是,如果您没有控制权,则应正确处理

这是我存储的程序;当我执行它时,我得到以下错误

Msg 242,16级,状态3,程序TRN\u Hold\u GetData,第45行 将varchar数据类型转换为datetime数据类型导致值超出范围


XML 17-3-2017中的日期时间可以用两种不同的方式进行解释,其中一种是17个月的第3天无效。确保在XML中使用符合XML标准YYYY-MM-DDThh:MM:ss的显式日期格式,正如Phillip所建议的那样,您确实应该使用通用格式的日期时间字符串。但是,如果您没有控制权,则应正确处理转换模式:

ALTER PROCEDURE [dbo].[TRN_Hold_GetData] 
    @XMLSearch XML = '<DocumentElement><TRN_Hold_GetData_Custom><HoldId>0</HoldId><FromDate>17-3-2017</FromDate><ToDate>17-2-2017</ToDate></TRN_Hold_GetData_Custom></DocumentElement>'
AS 
BEGIN
    DECLARE @HoldId INT = 0,
            @HoldNo VARCHAR(50) = '',
            @Party VARCHAR(100) = '',
            @StoneNo VARCHAR(50) = '',
            @FromDate VARCHAR(50) = '',
            @ToDate VARCHAR(50) = '',
            @HoldStatus VARCHAR(20) = '',
            @FilterQry NVARCHAR(MAX) = '',
            @FinalQry NVARCHAR(MAX) = '' 

    SELECT  
        @HoldNo = doc.col.value('HoldNo[1]', 'VARCHAR(50)'), 
        @Party = doc.col.value('Party[1]', 'VARCHAR(MAX)'),
        @StoneNo = doc.col.value('StoneNo[1]', 'VARCHAR(MAX)'), 
        @FromDate = doc.col.value('FromDate[1]', 'VARCHAR(11)'), 
        @ToDate = doc.col.value('ToDate[1]', 'VARCHAR(11)'), 
        @HoldStatus = doc.col.value('HoldStatus[1]', 'VARCHAR(20)')
    FROM     
        @XMLSearch.nodes('/DocumentElement/TRN_Hold_GetData_Custom') doc(col) 

    SELECT  
        convert(varchar(11), cast(OnHoldDate as datetime), 103), 
        ISNULL(TH.HoldId, '') AS HoldId, 
        ISNULL(TH.HoldNo, '') AS HoldNo, 
        ISNULL(TH.PartyId, '') AS PartyId, 
        ISNULL(MP.Party, '') AS Party, 
        ISNULL(TH.OnHoldDate, '') AS HoldDate, 
        ISNULL(TH.ExpReleaseDays, '') AS ExpReleaseDays, 
        ISNULL(TH.ExpReleaseDate, '') AS ExpReleaseDate, 
        ISNULL(TH.TotalPkt, '') AS TotalPkt, 
        ISNULL(TH.TotalCts, '') AS TotalCts, 
        HOLDSTONE, RELEASESTONE, 
        ISNULL(TH.TotalAmount, '') AS TotalAmount, 
        ISNULL(TH.HoldById, '') AS HoldById, 
        ISNULL(TH.Remark, '') AS Remark, 
        ISNULL(MEmp.firstname, '') + ' ' + ISNULL(MEmp.middlename, '') + ' ' + ISNULL(MEmp.lastname, '') AS HoldUser, 
        ISNULL(MEmp.firstname, '') + ' ' + ISNULL(MEmp.middlename, '') + ' ' + ISNULL(MEmp.lastname, '') AS UnHoldUser
    FROM    
        dbo.TRN_Hold TH WITH ( NOLOCK )
    INNER JOIN 
        ( SELECT SUM(CASE WHEN HoldStatus = 0 THEN 1
                                             ELSE 0
                                        END) AS HOLDSTONE, SUM(CASE WHEN HoldStatus = 1 THEN 1
                                                                    ELSE 0
                                                               END) AS RELEASESTONE, HoldId
                             FROM   TRN_Hold_Detail
                             GROUP BY HoldId ) AS THD ON TH.HoldId = THD.HoldId
                INNER JOIN TRN_Hold_Detail AS HDD WITH ( NOLOCK ) ON HDD.HoldId = THD.HoldId
                INNER JOIN mst_Stone AS MS WITH ( NOLOCK ) ON HDD.StoneId = MS.Stone_id
                LEFT JOIN MST_Party MP ON TH.PartyId = MP.party_id
                LEFT JOIN MST_Employee MEmp ON TH.HoldById = MEmp.employee_id

                WHERE   HoldNo = ( 

                CASE WHEN @HoldNo = '' or @HoldNo is null THEN HoldNo ELSE @HoldNo END ) AND 

                convert(varchar(11),cast(OnHoldDate as datetime),101) 
                between  
                CASE WHEN @FromDate= '' 
                THEN OnHoldDate  
                ELSE convert(varchar(11),@FromDate,101) 
                END  
                AND  
                CASE WHEN @ToDate = '' 
                THEN OnHoldDate 
                ELSE convert(varchar(11),@ToDate,101)      
                END  


                 print @FromDate
                print @ToDate
          --???????????????????????????????????????????????????????????????? 
            --AND ( CASE WHEN convert(varchar(50),cast(@FromDate as datetime),103)= '' 
            --           THEN convert(varchar(50),cast(@FromDate as datetime),103)
            --           ELSE OnHoldDate
            --      END )  >= convert(varchar(50),cast(@FromDate as datetime),103)

            --AND ( CASE WHEN convert(varchar(50),cast(@ToDate as datetime),103) = ''
            --           THEN convert(varchar(50),cast(@ToDate as datetime),103)
            --           ELSE OnHoldDate 
            --      END )  <= convert(varchar(50),cast(@ToDate as datetime),103)  
          --????????????????????????????????????????????????????????????????  


            --AND ( @StoneNo = '' OR ms.Stone_no = @stoneNo )

            --          --realse                   
            --AND  ((@HoldStatus = 'RELEASE' AND  ISNULL(THD.HOLDSTONE, 0) = 0 AND ISNULL(THD.RELEASESTONE, 0) <> 0)
            --             --Hold
            --OR (  @HoldStatus = 'HOLD' AND ISNULL(THD.HOLDSTONE, 0) <> 0 AND ISNULL(THD.RELEASESTONE, 0) = 0) 
            --             --Partial
            --OR (@HoldStatus = 'PARTIAL'  AND ISNULL(THD.HOLDSTONE, 0) <> 0 AND ISNULL(THD.RELEASESTONE, 0) <> 0 )

            --OR @HoldStatus = 'ALL' 
      -- )

              --  print @FromDate
              -- print convert(nvarchar(20), @FromDate ,106)
              --print convert(nvarchar(20), @ToDate ,103) 

            --OnHoldDate between (case when @FromDate ='' then OnHoldDate else @FromDate end) 
            --and (case when @ToDate = '' then OnHoldDate else @ToDate end)
  END

OnHoldDate的值是多少?@mayurgnu我想复制粘贴html解析失败了。传入的XMLSearch变量表面上看起来不是有效的XML,因此不太可能是可测试的。或者添加一个SQL fiddle并参考问题中的内容。为什么要声明像@FromDate这样的变量,而这些变量显然是与日期相关的字符串??您应该始终使用最合适的数据类型—在这里,如果只是日期,则应使用DATE;如果是日期和时间,则应使用DATETIME23
declare @dAsStr varchar(max)  = '17-3-2017'


select convert(datetime, @dAsStr, 105)