2016-05-13 79 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