带between运算符的Sql查询的奇怪行为

带between运算符的Sql查询的奇怪行为,sql,sql-server,Sql,Sql Server,sql查询中有一个奇怪的错误 查询是这样的 select * from student where dob between '20150820' and '20150828' 但是在数据库中,dob的列是varchar(14),并且是yyyyMMddhhmmss格式,比如说我的行中的数据是(20150827142545)。如果我启动上述查询,它不应该像我在查询中提到的yyyyMMdd格式那样检索任何行。但是它检索的行是昨天的日期(即20150827112535)并且它无法获取具有今天日期(即2

sql查询中有一个奇怪的错误

查询是这样的

select * from student where dob between '20150820' and '20150828'
但是在数据库中,dob的列是varchar(14),并且是yyyyMMddhhmmss格式,比如说我的行中的数据是(20150827142545)。如果我启动上述查询,它不应该像我在查询中提到的yyyyMMdd格式那样检索任何行。但是它检索的行是昨天的日期(即20150827112535)并且它无法获取具有今天日期(即20150828144532)的记录

为什么会发生这种情况

提前感谢您的帮助

您可以这样尝试:

select * from student 
where convert(date,LEFT(dob,8)) between 
      convert(date'20150820')  and convert(date,'20150828'))

正如其他人所评论的,您需要将日期存储为
date
而不是
varchar
,以避免将来出现此类问题。

T-SQL中的between存在问题


但是,如果您想要一个快速的答案,请先转换为date,然后使用>=,您所要做的就是首先将字符串转换为date

select * 
from student 
where dob between convert(date, '20150820') and convert(date, '20150828')

如前所述,您需要使用正确的日期类型,以便在两个日期之间正常工作

select *
from student 
where convert(date,LEFT(dob,8)) between '20150820' and '20150828'
旁注:您不必显式地从文本转换两个日期,因为只要使用明确的日期表示,即ISO标准“YYYYMMDD”或“YYYY-MM-DD”,就可以隐式转换。当然,如果您将值保存在变量中,则使用date | datetime数据类型

declare @startdate date
declare @enddate date

select *
from student 
where convert(date,LEFT(dob,8)) between @startdate and @enddate
旁注2:在表dob列上执行函数会阻止该列上的任何索引在执行计划中被充分利用,并可能导致执行速度减慢(如果可以的话),为表dob列定义正确的数据类型,或者如果性能确实存在问题,则使用持久计算列或实体化视图

旁注3:如果您需要维护数据中的时间部分,即出生日期和时间,请使用以下内容确保捕获所有记录

select *
from student
where
convert(date,LEFT(dob,8)) >= '20150820'
    and convert(date,LEFT(dob,8)) < dateadd(d,1,'20150828')
选择*
来自学生
哪里
转换(日期,左(日期,8))>='20150820'
并转换(日期,左(dob,8))
为什么会发生这种情况?

比较从左到右执行,字符顺序由使用的代码页决定

排序顺序

排序顺序指定数据值的排序方式,从而影响 数据比较的结果。完成了数据的排序 通过排序,可以使用索引对其进行优化


您不需要进行字符串比较,而需要将其转换为日期,这样应该可以工作。为了将来,请不要将日期存储为
VARCHAR(14)
Alter column to date type!没有什么奇怪的事情发生。如果您将日期存储为varchar,则不能期望它的行为与日期类似。感谢您提供的建议。。。。。无法转换数据类型,因为它现在正在生产中@jarlh@Fred对,我同意。。。但是为什么它要给我看昨天的记录呢??这是我真正的问题……谢谢。。。。。但我的问题是,为什么它会用我错误的查询显示昨天日期的记录???@BhanuChowdary:-原因可能是因为在SQL Server中,之间的
是不对称的,日期被作为字符串而不是日期进行比较:-是的..是的。。日期作为字符串进行比较,但查询为什么以及如何提供这些日期之间的记录(不包括查询中指定的日期),以及,甚至字符串都是YYYYMMDDHMMSS格式。但在查询中,我只指定了yyyyMmdd格式。如何在指定日期之间匹配记录???@BhanuChowdary:-这可能是因为如果test_表达式的值大于或等于begin_表达式的值,并且小于或等于end_表达式的值。
因此,在您的示例中,它匹配前8个字符并返回true,因此您得到了结果。谢谢您,爱德华。。。。我知道可以使用convert函数完成…但我的问题是,如果查询类型为varchar,那么查询的行为如何…为什么它会显示那些日期之间的记录,而不包括我在查询中提到的日期..我明白你的问题了,我知道,当比较字符数据时,它将从最左边的字符串开始,当字符串长度不相等时,较长的字符串将被视为后面的字符串。这就是为什么你的第一次约会出现而第二次没有。换句话说,AB在ABC之前,ABC在AC之前,数字12在123之前,123在13之前。回到您的原始数据20150827142545介于20150827[----]和20150828[----]之间,而20150828144532位于20150828[----]之后,因此被排除在结果集中。此外,我认为字符数据的顺序是由使用中的字符集定义的,并且可以发挥大小写敏感度等方面的作用。我正试图找到支持这个的链接