从字符串转换日期时间时的转换错误

时间:2018-12-04 20:16:08

标签: sql sql-server

我正在尝试创建一个存储过程。日期列使用varchar数据类型。

我希望能够使用日期作为约束条件来选择数据。

ALTER PROCEDURE [dbo].[spStatusReport]
     @ShipFrom VARCHAR(20) = NULL,
     @ShipTo VARCHAR(20) = NULL,
AS
    SELECT 
        LOCATION, NEXT_DEPT,
        CAST(CONVERT(VARCHAR, REQ_DATE, 104) AS DATETIME) AS REQ_DATE,
        CAST(CONVERT(VARCHAR, SCH, 104) AS DATETIME) AS SCH,
        Tool
    FROM 
        Status_Report 
    WHERE 
        (@ShipFrom IS NULL OR 
         CAST(CONVERT(VARCHAR, SCH, 104) AS DATETIME) >= CAST(CONVERT(VARCHAR, @ShipFrom, 104) AS DATETIME))
        AND (@ShipTo IS NULL OR 
             CAST(CONVERT(VARCHAR, SCH, 104) AS DATETIME) <= CAST(CONVERT(VARCHAR, @ShipTo, 104) AS DATETIME))

当我尝试执行此存储过程时

exec spStatusReport '12/04/2018','NULL'

我希望用户只能传递一个参数ShipFrom或ShipTO或什至两者都传递

  

从字符串转换日期和/或时间时转换失败

3 个答案:

答案 0 :(得分:2)

您传递的是文字字符串 'NULL',而不是值NULL;他们不一样。另外,您应该使用ISO格式作为日期,这样就不会造成歧义。请尝试以下操作之一:

EXEC spStatusReport '20180412',NULL;

EXEC spStatusReport @ShipFrom = '20180412';

编辑:肖恩·兰格(Sean Lange)也在注释中。您的参数应该是date,而不是varchar始终使用适合您数据的数据类型。 varchar远非“一刀切”的数据类型。

答案 1 :(得分:0)

您可以在where子句中执行类似的操作

declare @ShipFrom varchar(20) =NULL,
@ShipTo varchar(20)= NULL

--set @ShipFrom = getdate() - 1
--set @ShipTo = getdate()

select isnull(@ShipFrom,getdate() - 1) , isnull(@ShipTo,getdate())

答案 2 :(得分:0)

我强烈建议您将日期/时间值传递为date / datetime或相关数据类型。

然后,请勿转换为字符串以删除时间分量。 SQL Server具有更好的机制。并且不要将字符串转换为字符串;只是没有道理。

您还可以在适当的地方使用try_convert()

ALTER PROCEDURE [dbo].[spStatusReport] (
     @ShipFrom VARCHAR(20) = NULL,
     @ShipTo VARCHAR(20) = NULL
) AS
BEGIN
    SELECT 
        LOCATION, NEXT_DEPT,
        CAST(CAST(REQ_DATE AS DATE) AS DATETIME)  AS REQ_DATE,
        CAST(CAST(SCH AS DATE) AS DATETIME) AS DATETIME) AS SCH,
        Tool
    FROM Status_Report 
    WHERE (@ShipFrom IS NULL OR 
           TRY_CONVERT(DATE, SCH, 104  >= TRY_CONVERT(DTAE, @ShipFrom, 104)
          ) AND
          (@ShipTo IS NULL OR 
           TRY_CONVERT(DATE, SCH, 104) <= TRY_CONVERT(DATE, @ShipTo, 104) 
         );
END;