【问题标题】:Unable to compare datetime variables in stored procedure sql server无法比较存储过程 sql server 中的日期时间变量
【发布时间】:2018-03-15 13:48:37
【问题描述】:

我正在尝试比较存储过程 sql 服务器中的两个日期时间变量。 在下面的代码中,sn-p @createdDate 被用作用户输入,然后与日期时间类型的列进行比较。我无法检查 ''='' 属性

set @sqlquery = 'Select
            v.*,
            vsc.vidhanSabhaConstituencyName, where 1=1 '

set @sqlquery = @sqlquery +'AND v.createdBy ='''+cast(@createdBy as nvarchar(100))+''''

if(@VoterIdNumber is not null)
set @sqlquery = @sqlquery+'AND v.voterIDNumber= '''+@VoterIdNumber+''''

if(@createdDate is not null)
set @sqlquery = @sqlquery+'AND v.dataIsCreated = '''+cast(@createdDate as varchar(100))+''''
else
set @sqlquery = @sqlquery+'AND v.dataIsCreated= '''+cast(getdate() as varchar(100))+'''' 

Execute sp_Executesql @sqlquery

我尝试过强制转换和转换 @createdDate 变量,但没有成功。 它适用于 >=<= 等其他运算符,但不适用于 =

感谢您的帮助

【问题讨论】:

  • 可能不适用于=,因为该值可能精确到秒?如果您不需要精确到秒,最好只使用日期部分。
  • 你试过PRINT @sqlquery;吗?这可能会让比赛没有发生的原因变得很明显。
  • 使用sp_executesql 时,想法是将值作为参数传递,而不是连接所有内容;你应该做exec sp_executesql @sqlquery, N'@createdDate datetime, @createdBy nvarchar(200)', @createdDate, @createdBy;之类的事情,set @sqlquery = @sqlquery + 'AND v.createdBy = @createdBy '之类的事情
  • 感谢您的输入 Marc ,但我需要连接字符串和值,因为需要检查许多值是否为空。当我尝试直接应用 '=' 时,出现以下错误“数据类型 nvarchar 和 date 在 add 运算符中不兼容。”
  • 为什么要将 createdDate 转换为字符串?你应该将它从 c# 作为 DataTime 传递。您还需要将 DateTimes 转换为没有小时、分钟、秒(午夜)的日期,以便比较日期。

标签: c# asp.net sql-server-2008


【解决方案1】:

我只是给你一个例子,这里 SMSDATE 是日期时间,它为我提供输出。尝试在你的程序中实现相同的逻辑

SELECT COUNT(*) FROM tbl_1 WHERE  CONVERT(varchar, SMSDATE,110)  = CONVERT(varchar, GETDATE(),110) 

【讨论】:

  • 不工作,因为我的过程是基于查询连接
【解决方案2】:

首先,您不应该在datetime 上使用cast。请改用convert,以便为结果指定适当的格式。 cast 的输出将取决于您的区域设置。例如,当我在我的 SQL Server 实例上运行 select cast(getdate() as varchar(100)); 时,我得到以下信息:

Mar 15 2018  9:37AM

这个值的精度显然比datetime 的精度要有限得多:任何两个datetime 恰好在同一分钟内出现的值都会被转换为同一个字符串。因此,如果我尝试使用 = 将此值与存储在表的 datetime 字段中的值进行比较,我会发现如果存储的值具有非零秒或毫秒分量,则比较将失败。

如果您必须将datetime 转换为字符串,请使用convert 和最适合您的使用方式的样式参数。例如,如果我运行select convert(varchar(100), getdate(), 126);,我会得到:

2018-03-15T09:43:42.240

这是日期/时间文字格式的更好选择,因为它不会丢弃原始值中的任何数据(例如我的第一个示例如何丢失其秒和毫秒组件)并且无论您的区域设置如何都可以使用.

话虽如此,Marc Gravell 对您的问题有一个非常重要的评论:您应该传入一串参数,而不是尝试连接所有内容。即使您实际想要包含在谓词中的参数数量是可变的,这也将起作用。例如,考虑以下示例:

create table dbo.Test (A int, B datetime);
insert dbo.Test values (1, getdate());
go

declare @A int;
declare @B datetime;

declare @sql nvarchar(max) = 'select * from dbo.Test where 1=1';

if @A is not null
    set @sql = @sql + ' and A = @A';
if @B is not null
    set @sql = @sql + ' and B = @B';

print @sql;
exec sp_executesql @sql, N'@A int, @B datetime', @A = @A, @B = @B;

如果我按照书面形式运行此查询,@A@B 都为空,那么 @sql 的值将是:

select * from dbo.Test where 1=1

如果我将 @A 设置为 1,那么我得到:

select * from dbo.Test where 1=1 and A = @A

如果我还将@B 设置为非空值,那么我会得到:

select * from dbo.Test where 1=1 and A = @A and B = @B

这更容易理解和维护,也更安全。您在原始查询中执行的所有字符串连接只是在乞求 SQL 注入攻击。您可以在this link 阅读有关此主题的内容,或者简单地考虑如果我执行以下操作会对您的查询产生什么影响:

set @createdBy = 'Admin''; drop table dbo.v; --';

这应该足够了,但如果您有任何问题,请随时询问。

【讨论】:

  • 感谢您的意见,乔。我要试试这个
【解决方案3】:

你可以这样试试

声明@date 日期时间
设置@date = '2018-03-13'
select * from user_tbl where cast(createddate as date) = cast(@date as date)
这里,@date 应该是你的 sp 日期参数

【讨论】:

    【解决方案4】:

    我已按照 Marc 和 Aaron 的建议修改了我的存储过程。 下面是我的代码 sn-p 。

    set @sqlquery = N'Select
                v.*,
                vsc.vidhanSabhaConstituencyName,
                lsc.lokSabhaConstituencyName,
                wc.wardName.....''
    
    SET @sqlquery = @sqlquery + N' AND v.createdBy = @createdBy';
            If @VoterIdNumber Is Not Null SET @sqlquery = @sqlquery + N' AND v.voterIDNumber = @VoterIDNumber';
    
            If @createdDate Is Null SET @createdDate = null
                    SET @sqlquery = @sqlquery + N' AND CONVERT(date, v.dataIsCreated) = @createdDate';
    
                    EXEC sp_executesql
        @sqlquery,
        N'@createdBy varchar(50), @VoterIDNumber varchar(50), @createdDate date',
    
                    @createdBy = @createdBy,
                    @VoterIDNumber = @VoterIdNumber,
                    @createdDate = @createdDate
    

    【讨论】:

      猜你喜欢
      • 2017-11-02
      • 2014-09-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-19
      • 2018-07-29
      • 1970-01-01
      • 2017-03-30
      相关资源
      最近更新 更多