2016-05-13 81 views
0

我想根据我的$ data输入动态搜索数据库中的日期。DATETIME vs LIKE进行动态搜索SQL

日期存储为日期时间,通常显示为例如“2016-05-11”。

随着MySQL数据库我的条款是:

Select * From Table WHERE (Table.date LIKE '$data%') 

因此,如果用户输入“20”的结果将是与20开始。如果用户输入“2016-05”的结果将所有日期是所有以2016-05开始的日期,使我的搜索完美工作。

在Sql Server 2008上部署时,我意识到了两件事。

1)如果我使用LIKE功能这样的

Select * From Table WHERE (Table.date LIKE '%$data$%') 

的功能为“2016”的值工作,而是进入了一个值“2016-”时会返回0的结果。

2)如果我使用的功能DATETIME这样

Select * From Table WHERE (DATEPART(year, Table.date) LIKE(OR)= '$data') 

该函数将返回正确的值时,$数据= 2016,但将返回nil值时$数据=“201”,例如,因此使其不具动态性。

我在做什么错了?

+0

的问题在于输入验证。如果用户可以输入'20',他们也可以输入''fred'或'2016-02-30'。 –

+0

我使用ajax调用,所以如果他们进入弗雷德。他们不会得到结果。那不是问题?我不是吗? – MakDo

回答

0

隐式转换在SQL或大多数其他编程语言中只是坏的,坏的,不好的。

LIKE作用于字符串。如果你想让它在字符串上工作,那么明确确保参数是字符串。这在MySQL和SQL Server中是正确的。

如果你想在一年的使用LIKE,然后用DATENAME()而不是DATEPART()

WHERE DATENAME(year, Table.date) LIKE '$data' 

不过,我建议你考虑使用基于日期的结构,如日期范围的日期。

+0

但是,我的输入是一个字符串!我明确地告诉用户输入YYYY-MM-DD字符串,并且我的搜索相应地发生。所以这不是一个问题!? – MakDo

+1

几乎所有按日期搜索的应用程序都使用日期范围。即使你想出了一个更好的方法来搜索没有人想到的(可疑的)日期,但这是人们所期望的。当我去一家航空公司预订网站并希望按日期搜索时,我不打算在六月份搜索“2016-06-”来搜索航班。另外,如何搜索2016-05-18和2016-05-21之间的日期? –

+1

@MakDo。 。 。然后*显式*使用'date_format()'或'convert()'将日期值转换为一个字符串。顺便说一句,所有这些方法都排除了索引的使用 - 隐式转换和函数调用通常会干扰索引的使用。 –

0

我刚刚意识到我的愚蠢的错误。 我需要使用DATEPART为我的LIKE子句添加通配符。

选择*从表WHERE(DATEPART(year,Table.date)LIKE ='$ data%')。

完美地工作。

但我会喜欢其他建议,以简化将$数据分成YYYY,MM,DD,然后测试每个元素。

0

我会努力保持Table.date免于操纵,所以使用索引。

下界:

CASE LENGTH($data) 
WHEN 8 THEN $data + '01' 
WHEN 7 THEN $data + '-01' 
WHEN 5 THEN $data + '01-01' 
WHEN 4 THEN $data + '-01-01' 
ELSE $data 
END 

上界:

相反,你可以通过添加缺少的部分使用CASE表达式搜索参数转换为日期范围

CASE LENGTH($data) 
WHEN 8 THEN DATEADD(MONTH,$data + '01',1) 
WHEN 7 THEN DATEADD(MONTH,$data + '-01',1) 
WHEN 5 THEN DATEADD(YEAR,$data + '01-01') 
WHEN 4 THEN DATEADD(YEAR,$data + '-01-01') 
ELSE DATEADD(DAY,$data,1) 
END