Stored procedures 在存储过程中使用DateTime作为参数,转换失败

Stored procedures 在存储过程中使用DateTime作为参数,转换失败,stored-procedures,sql-server-2012,Stored Procedures,Sql Server 2012,我创建了一个存储过程,它将一个DATETIME作为其输入参数。当我试图以MM-DD-YYYY或YYYY-MM-DD的格式传递日期时,我得到了错误 从字符串转换日期和/或时间时,转换失败 我测试的日期是2010-01-01,如果我把它直接插入存储过程中的select语句中,就可以了。要使用DATETIME作为参数,我必须做什么 这是我的密码: CREATE PROC dbo.WSL_ProjectSearchByDate @param1 DATETIME --Search Date AS

我创建了一个存储过程,它将一个
DATETIME
作为其输入参数。当我试图以
MM-DD-YYYY
YYYY-MM-DD
的格式传递日期时,我得到了错误

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

我测试的日期是
2010-01-01
,如果我把它直接插入存储过程中的select语句中,就可以了。要使用
DATETIME
作为参数,我必须做什么

这是我的密码:

CREATE PROC dbo.WSL_ProjectSearchByDate
    @param1 DATETIME --Search Date
AS
    SET NOCOUNT ON;

    DECLARE @STMT NVARCHAR(MAX)

    SET @STMT =
        'SELECT project AS Project,
                project_desc AS Description
                status_gl AS Status
        FROM dbo.PJPROJ WITH (NOLOCK)
        WHERE crtd_datetime >= ' + @param1 + '
        OR lupd_datetime >= ' + @param1 + ';';

编辑:我完全知道这不是使用动态SQL的最佳实践,我对此没有任何发言权,这个问题不是关于动态SQL的优点以及我是否应该使用它。这就是我被指示构建存储过程的方式,因此我正在这样做。

将参数类型更改为
VARCHAR
,并在动态SQL中添加引号:

...
@param1 VARCHAR(10) --Search Date
...
WHERE crtd_datetime >= ''' + @param1 + '''
OR lupd_datetime >= ''' + @param1 + ''';';
...
WHERE crtd_datetime >= ''' + CONVERT(VARCHAR, @param1, 120) + '''
OR lupd_datetime >= ''' + CONVERT(VARCHAR, @param1, 120) + ''';';
或-

构造动态SQL时,对参数应用
CONVERT

...
@param1 VARCHAR(10) --Search Date
...
WHERE crtd_datetime >= ''' + @param1 + '''
OR lupd_datetime >= ''' + @param1 + ''';';
...
WHERE crtd_datetime >= ''' + CONVERT(VARCHAR, @param1, 120) + '''
OR lupd_datetime >= ''' + CONVERT(VARCHAR, @param1, 120) + ''';';
各种设置(语言、日期格式)仅影响在SQL Server Management Studio中向您显示日期时间的方式,或者在您尝试将字符串转换为日期时间时如何解析日期时间

SQL Server支持多种格式-请参阅。大多数格式取决于您的设置,因此,这些设置有时可能有效,有时无效

解决此问题的方法是使用SQL Server支持的(稍作调整的)ISO-8601日期格式,无论您的SQL Server语言和日期格式设置如何,此格式始终有效

SQL Server支持的有两种风格:

  • YYYYMMDD
    仅适用于日期(无时间段);注意:无破折号,这非常重要
    YYYY-MM-DD
    独立于SQL Server中的日期格式设置,在所有情况下都将工作
或:

  • 日期和时间的
    YYYY-MM-DDTHH:MM:SS
    -此处注意:此格式有破折号(但可以省略),并且在
    DATETIME
    的日期和时间部分之间有一个固定的
    T
    分隔符
这对SQL Server 2000及更新版本有效

如果您使用SQL Server 2008或更高版本以及
日期
数据类型(仅
日期
-
日期时间
!),那么您确实也可以使用
YYYY-MM-DD
格式,这也适用于SQL Server中的任何设置

不要问我为什么这个话题如此棘手,有些令人困惑——事实就是这样。但是使用
YYYYMMDD
格式,您应该可以使用任何版本的SQL Server以及SQL Server中的任何语言和日期格式设置

对于SQL Server 2008及更新版本,如果只需要日期部分,建议使用
DATE
;如果同时需要日期和时间,建议使用
DATETIME2(n)
。如果可能的话,您应该尝试逐步淘汰
DATETIME
数据类型

因此,在您的具体案例中,尝试以下方法:

CREATE PROC dbo.WSL_ProjectSearchByDate
    @param1 DATETIME2(0) --Search Date 
    -- @param1 DATETIME2(0) -- or use this, if you really only care about DATE - no time portion
AS
    SET NOCOUNT ON;

    SELECT 
        project AS Project,
        project_desc AS Description
        status_gl AS Status
    FROM 
        dbo.PJPROJ 
    WHERE 
        crtd_datetime >= @param1
        OR lupd_datetime >= @param1;

为什么要使用动态sql?您是从什么代码执行存储过程的?@zoharpel,因为专家指示我这样做。该过程最终将由VB.Net Web服务调用,但现在我只是通过SSMS和
EXEC
语句进行测试。您提供的代码不需要使用动态sql,因此除非有更多的sql,否则我怀疑所谓的专家是否真的知道他们的东西。不管怎样,.Net日期时间直接映射到sql server日期时间,所以您真的不需要担心格式。专家需要一些推回。简单地说,动态sql在这里是错误的方法。我支持我的评论:动态sql在这里是错误的方法。不管这是否是你的选择,如果你被迫继续沿着这条路走下去,Chris下面的回答应该足够了(尽管投了反对票)。有些事告诉我你对发的牌不太满意。祝你好运!更新后,您认为还需要将参数类型更改为
VARCHAR
。不过我不想使用
VARCHAR
作为输入参数。这个问题是关于如何使
DATETIME
参数工作的。在创建动态SQL时,您可以接受
VARCHAR
参数,或者显式地
CONVERT
DATETIME
参数转换为
VARCHAR
。这不是不必要的对话吗?获取一个字符串并转换为DateTime,或者获取一个日期时间并再次转换为字符串并转换为DateTime。。。对