所以我有一張大桌子,如果不打破我的PHP應用程序,根本無法改變。愚蠢的是(我知道),我將開始日期和結束日期設置爲VARCHAR,例如數據存儲爲'03/04/2013'。我愚蠢地做了一個日期爲VARCHAR的行,我仍然可以做基於日期的選擇嗎?
現在我需要能夠搜索以查看哪些行當前處於活動狀態,這意味着哪些行在今天之前有開始日期,以及今天之後有結束日期。
這是所有可能的SQL查詢嗎?
所以我有一張大桌子,如果不打破我的PHP應用程序,根本無法改變。愚蠢的是(我知道),我將開始日期和結束日期設置爲VARCHAR,例如數據存儲爲'03/04/2013'。我愚蠢地做了一個日期爲VARCHAR的行,我仍然可以做基於日期的選擇嗎?
現在我需要能夠搜索以查看哪些行當前處於活動狀態,這意味着哪些行在今天之前有開始日期,以及今天之後有結束日期。
這是所有可能的SQL查詢嗎?
使用STR_TO_DATE
如下:
WHERE STR_TO_DATE(start, '%d/%m/%Y') < DATE(NOW())
AND STR_TO_DATE(end, '%d/%m/%Y') > DATE_ADD(DATE(NOW()), INTERVAL 1 DAY)
值得一提的是,這不僅會導致性能下降,因爲您必須轉換列的內容,而且因爲您不會允許MySQL使用列號 –
中的任何潛在索引那 - 在上面的評論中。 – Barmar
@Mark,雖然Barmar的回答在技術上是正確的,並且會得到「完成的工作」......正如他和其他人所提到的那樣,這是非常低效的,從長遠來看會損害您的應用程序。我花時間編寫了一個非常詳細的答案,解決了如何在不破壞PHP代碼的情況下解決問題。請看看它(和其他的stackoverflow社區,請遵循相同的建議hehehe)。 –
是的,你可以做到這一點。
嘗試這樣: - 因爲我很困惑與03和04
select date_format(str_to_date('03/04/2013', '%d/%m/%Y'), '%Y%m');
或可能是這種:-(只是一個小與月和日變化)
select date_format(str_to_date('03/04/2013', '%m/%d/%Y'), '%Y%m');
或者您也可以嘗試將列轉換回日期,如下所示:
UPDATE `table`
SET `column` = str_to_date(`column`, '%d-%m-%Y');
值得一提的是,這不僅會導致性能下降,因爲您必須轉換列的內容,而且因爲您不會允許MySQL使用列中的任何潛在索引 –
@MostyMostacho: - 非常好的一點先生! +1 –
UPDATE `table`
SET `yourColumn` = str_to_date(`yourColumn`, '%d-%m-%Y');
轉換它做日期類型,而不會丟失你的數據,根據需要it.IT將是從長遠來看更容易添加幾分鐘或幾秒鐘,但如果你喜歡在PHP涉足..
或創建一個新的列日從varchar中輸入一個。
這將打破他的PHP應用程序,該應用程序預計列爲'mm/dd/yyyy'格式。 – Barmar
行動計劃,以VARCHAR
列遷移到DATE
無需中斷應用程序:
創建新的索引DATE
柱,以在各自的值填充它們VARCHAR
列:
-- new column
ALTER TABLE MY_TABLE ADD `NEW_DATE_COLUMN` DATE;
-- index
CREATE INDEX `MY_TABLE_NEW_DATE_IDX` ON MY_TABLE(`NEW_DATE_COLUMN`);
-- initial values
UPDATE MY_TABLE
SET `NEW_DATE_COLUMN` = STR_TO_DATE(`VARCHAR_DATE`, '%d/%m/%Y')
WHERE `NEW_DATE_COLUMN` IS NULL;
創建插入/更新觸發器,以各自的價值投你VARCHAR
列DATE
和更新你的新DATE
列:
-- triggers
DELIMITER //
CREATE TRIGGER `MY_TABLE_VARCHAR_DATE_BI` BEFORE INSERT ON MY_TABLE
FOR EACH ROW
BEGIN
IF NEW.`NEW_DATE_COLUMN` IS NULL AND NEW.`VARCHAR_DATE` IS NOT NULL THEN
SET NEW.NEW_DATE_COLUMN = STR_TO_DATE(NEW.`VARCHAR_DATE`, '%d/%m/%Y');
END IF;
END;
//
CREATE TRIGGER `MY_TABLE_VARCHAR_DATE_BU` BEFORE UPDATE ON MY_TABLE
FOR EACH ROW
BEGIN
IF NEW.`NEW_DATE_COLUMN` IS NULL AND NEW.`VARCHAR_DATE` IS NOT NULL THEN
SET NEW.NEW_DATE_COLUMN = STR_TO_DATE(NEW.`VARCHAR_DATE`, '%d/%m/%Y');
END IF;
END;
//
DELIMITER;
使用DATE
列在查詢:
SELECT * FROM MY_TABLE
WHERE `NEW_DATE_COLUMN` BETWEEN
CURRENT_DATE AND DATE_ADD(CURRENT_DATE, INTERVAL 1 DAY);
花點時間,更新您的應用程序,直接使用原來的VARCHAR
列的地方,同時nothi ng將被打破。
當您完成後刪除觸發器和VARCHAR
列:
DROP TRIGGER `MY_TABLE_VARCHAR_DATE_BI`;
DROP TRIGGER `MY_TABLE_VARCHAR_DATE_BU`;
ALTER TABLE MY_TABLE DROP `VARCHAR_DATE`;
工作SQL Fiddle。
[MySQL中的解析日期]的可能重複(http://stackoverflow.com/questions/3296725/parse-date-in-mysql)。你只需要做每個查詢;-) –
檢查[STR_TO_DATE()](http://stackoverflow.com/a/3296730/1029621) –
你可以這樣做,但它會很慢,因爲它不能索引。 – Barmar