Sql 从字符串转换日期时间时发生转换错误

Sql 从字符串转换日期时间时发生转换错误,sql,sql-server,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 D

我正在尝试创建一个存储过程。日期列使用
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))
我希望用户只能传递ShipFrom或ShipTO或两者中的一个参数,但我得到了这个错误

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


您传递的是文本字符串
'NULL'
而不是值
NULL
;他们不一样。此外,您应该使用ISO格式的日期,这样它就不会模棱两可。请尝试以下操作之一:

EXEC spStatusReport '20180412',NULL;

EXEC spStatusReport @ShipFrom = '20180412';

编辑:肖恩·兰格的评论也是对的。您的参数应该是
date
,而不是
varchar
始终使用适合您的数据的数据类型
varchar
远远不是“一刀切”的数据类型。

您传递的是文本字符串
'NULL'
而不是值
NULL
;他们不一样。此外,您应该使用ISO格式的日期,这样它就不会模棱两可。请尝试以下操作之一:

EXEC spStatusReport '20180412',NULL;

EXEC spStatusReport @ShipFrom = '20180412';

编辑:肖恩·兰格的评论也是对的。您的参数应该是
date
,而不是
varchar
始终使用适合您的数据的数据类型
varchar
远远不是“一刀切”的数据类型。

您可以在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())

您可以在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())

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

然后,不要转换为字符串来删除时间组件。SQLServer有更好的机制。不要将字符串转换为字符串;这根本没有道理

您也可以在适当的情况下使用
try\u 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;
ALTER过程[dbo].[spStatusReport](
@ShipFrom VARCHAR(20)=空,
@ShipTo VARCHAR(20)=空
)作为
开始
挑选
地点,下一个部门,
CAST(CAST(要求日期为日期)为要求日期,
转换(转换(SCH为日期)为日期时间)为日期时间)为SCH,
工具
从状态报告
其中(@ShipFrom为NULL或
TRY_CONVERT(日期,SCH,104>=TRY_CONVERT(DTAE,@ShipFrom,104)
)及
(@ShipTo为空或

尝试转换(日期,SCH,104)我强烈建议您将日期/时间值作为
DATE
/
datetime
或相关数据类型传递

然后,不要转换为字符串来删除时间组件。SQL Server有更好的机制。不要将字符串转换为字符串;这根本没有意义

您也可以在适当的情况下使用
try\u 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;
ALTER过程[dbo].[spStatusReport](
@ShipFrom VARCHAR(20)=空,
@ShipTo VARCHAR(20)=空
)作为
开始
挑选
地点,下一个部门,
CAST(CAST(要求日期为日期)为要求日期,
转换(转换(SCH为日期)为日期时间)为日期时间)为SCH,
工具
从状态报告
其中(@ShipFrom为NULL或
TRY_CONVERT(日期,SCH,104>=TRY_CONVERT(DTAE,@ShipFrom,104)
)及
(@ShipTo为空或

尝试转换(日期,SCH,104)。如果SHIPTO参数为null,则可以设置默认参数,如getdate();如果SHIPFROM为null,则可以设置默认参数,如getdate()-1您的参数是varchar而不是dates。这使得这比需要的要痛苦得多。从使用正确的数据类型开始。我甚至没有注意到
varchar
声明。/facepalm您可以检查下面的示例代码;如果其中一个或两个参数都为NULL,则设置默认值。您可以在开始时使用IF st检查这一点atement。确保使用BEGIN、END来封装IF-语句。如果SHIPTO param为null,则可以设置默认参数,如getdate();如果SHIPFROM为null,则可以设置类似(getdate()-1)的默认参数您的参数是varchar而不是dates。这使得这比需要的要痛苦得多。从使用正确的数据类型开始。我甚至没有注意到
varchar
声明。/facepalm您可以检查下面的示例代码;如果其中一个或两个参数都为NULL,则设置默认值。您可以在开始时使用IF st检查这一点atement。确保使用BEGIN、END来封装IF语句。我实际上是使用一个C#web应用程序来执行此操作的,执行查询的过程就是这样default@Saahar不,C没有。它肯定不会传递值
NULL
的文本字符串
'NULL'
。这听起来像是你的C代码的问题,不是吗我实际上是使用一个C#web应用程序来执行这项操作,以执行这样的查询过程default@Saahar不,C没有。它肯定不会传递值
NULL
的文本字符串
'NULL'
。这听起来像是你的C代码的问题,而不是SQL。