【问题标题】:BETWEEN clause in SQLSQL 中的 BETWEEN 子句
【发布时间】:2012-12-14 09:24:26
【问题描述】:

我有一条 SQL 语句来显示两个日期之间的数据。我几乎明白了,但有一个问题。

如果我输入 March 1,2012 to March 7, 2012.. 它应该显示日期介于两者之间的数据.. 但它也会显示 2012 年 3 月以下的所有日期.. 但每当我输入 2012 年 3 月 10 日到 2012 年 3 月 30 日时,SQL完美运行..任何帮助将不胜感激。谢谢

SELECT 
   agentname, noofcalls, qualified, booking, resched, 
   actualbooking, sales, remarks, 
   concat(month,' ',day,',',year) as 'date' 
FROM 
   tblagents
WHERE 
   (month between '" & cbosmonth.Text & "' AND '" & cboemonth.Text & "')
   AND (day between '" & cbosday.Text & "' AND '" & cboeday.Text & "')
   AND (year between '" & cbosyear.Text & "' AND '" & cboeyear.Text & "')"

【问题讨论】:

  • 为什么不将日期存储在单个字段中(适合日期算法类型)?
  • 这看起来像是即将发生的SQL Injection 攻击。
  • @zerkms 你能教我怎么做吗?
  • 你能用数据库版本和使用的应用程序语言编辑问题吗?

标签: sql sql-server vb.net between


【解决方案1】:

您正在对每个“之间”进行字符串比较。每个以 1、2 或 3 开头的数字,无论后面是什么,即 21、26 或 31,如果您将它们视为字符串,它们都小于 7。 1 到 30 有效,因为您只留下 31,并且 30

先做连接,再做中间:

WHERE concat(month,' ',day,',',year) 
      BETWEEN concat(cbosmonth.Text,' ', cbosday.Text,' ',cbosyear.Text)
      AND concat(cboemonth.Text,' ', cboeday.Text,' ',cboeyear.Text)

(检查语法是否正确,我只是从您的问题中复制粘贴,没有尝试过)

顺便说一句,除非您有理由,否则您可能应该将整个日期存储在具有正确数据时间(日期时间、时间戳等)的单个列中,而不是三个单独的列。

【讨论】:

  • 我已经尝试了代码,但我得到了“操作数应包含一列”错误...我的数据库中没有日期列..日期仅来自连接三列...谢谢
  • 您的 SELECT 中有一个日期别名。
  • 啊,我的错,您不能在 WHERE 子句中引用别名,因为它是在确定列值之前执行的。我将编辑我的答案。
【解决方案2】:

这是在数据库中存储日期的错误方式。 将日期列更改为数据类型 date

你可以这样做:

SELECT *
FROM table
WHERE bookingDate between to_date ('2012/03/01', 'yyyy/mm/dd')
AND to_date ('2012/03/07', 'yyyy/mm/dd');

【讨论】:

    【解决方案3】:

    这种方法是错误的。

    为了使日期位于两个间隔日期之间,两个日期之间不必有天数,例如(伪代码)

    • date = May-25-2012; startDate = March-15-2012, endDate = June-01-2012
    • date 显然介于 startDateendDate 之间,但是
    • day(date) 是 25,不在 day(startDate) = 15day(endDate) = 1 之间
    • 另外,由于 15 大于 1,所以它们之间没有数字,所以条件永远为假

    可以为日期的月份部分制作类似的示例(例如date = May-25-2012; startDate = September-15-2010, endDate = Match-01-2015

    您需要获取日、月、年的值,并在应用程序或服务器上构造一个日期,并使用它来比较这些值。


    在 VB 中从文本字段中生成日期

    Dim startDate = new DateTime( 
          Convert.ToInt32(cbosyear.Text), 
          Convert.ToInt32(cbosmonth.Text), 
          Convert.ToInt32(cbosday.Text))
    

    请注意,如果用户输入,这将失败,例如年份值的“一些文本”。您需要添加一些数据验证来实现这一点。

    要从 SQL Server take a look here 中的各个部分创建日期时间,需要解释很多技术。

    此外,您应该始终避免将值粘贴到 sql 字符串中,这会导致 sql 注入问题。你应该这样做:

    Dim command = new SqlCommand()
    command.CommandText = "SELECT .... FROM tblagents where DATEFROMPARTS(year, month, day) between @startDate AND @endDate"
    command.Parameters.AddWithValue("@startDate", startDate)
    command.Parameters.AddWithValue("@endDate", endDate)
    

    【讨论】:

    • 哦,我才意识到你说的。我会尝试构造一个日期。顺便说一句,应用程序语言是 vb.net 和 sql server 作为我的数据库
    猜你喜欢
    • 2017-12-04
    • 1970-01-01
    • 2010-10-08
    • 2012-06-18
    • 2011-06-16
    • 2019-08-31
    • 1970-01-01
    相关资源
    最近更新 更多