2013-10-15 17 views
2

所以我有一張大桌子,如果不打破我的PHP應用程序,根本無法改變。愚蠢的是(我知道),我將開始日期和結束日期設置爲VARCHAR,例如數據存儲爲'03/04/2013'。我愚蠢地做了一個日期爲VARCHAR的行,我仍然可以做基於日期的選擇嗎?

現在我需要能夠搜索以查看哪些行當前處於活動狀態,這意味着哪些行在今天之前有開始日期,以及今天之後有結束日期。

這是所有可能的SQL查詢嗎?

+2

[MySQL中的解析日期]的可能重複(http://stackoverflow.com/questions/3296725/parse-date-in-mysql)。你只需要做每個查詢;-) –

+0

檢查[STR_TO_DATE()](http://stackoverflow.com/a/3296730/1029621) –

+0

你可以這樣做,但它會很慢,因爲它不能索引。 – Barmar

回答

0

使用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) 
+1

值得一提的是,這不僅會導致性能下降,因爲您必須轉換列的內容,而且因爲您不會允許MySQL使用列號 –

+0

中的任何潛在索引那 - 在上面的評論中。 – Barmar

+0

@Mark,雖然Barmar的回答在技術上是正確的,並且會得到「完成的工作」......正如他和其他人所提到的那樣,這是非常低效的,從長遠來看會損害您的應用程序。我花時間編寫了一個非常詳細的答案,解決了如何在不破壞PHP代碼的情況下解決問題。請看看它(和其他的stackoverflow社區,請遵循相同的建議hehehe)。 –

2

是的,你可以做到這一點。

嘗試這樣: - 因爲我很困惑與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'); 
+2

值得一提的是,這不僅會導致性能下降,因爲您必須轉換列的內容,而且因爲您不會允許MySQL使用列中的任何潛在索引 –

+0

@MostyMostacho: - 非常好的一點先生! +1 –

0
UPDATE `table` 
SET `yourColumn` = str_to_date(`yourColumn`, '%d-%m-%Y'); 

轉換它做日期類型,而不會丟失你的數據,根據需要it.IT將是從長遠來看更容易添加幾分鐘或幾秒鐘,但如果你喜歡在PHP涉足..

或創建一個新的列日從varchar中輸入一個。

+0

這將打破他的PHP應用程序,該應用程序預計列爲'mm/dd/yyyy'格式。 – Barmar

5

行動計劃,以VARCHAR列遷移到DATE無需中斷應用程序:

  1. 創建新的索引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; 
    
  2. 創建插入/更新觸發器,以各自的價值投你VARCHARDATE和更新你的新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; 
    
  3. 使用DATE列在查詢:

    SELECT * FROM MY_TABLE 
    WHERE `NEW_DATE_COLUMN` BETWEEN 
    CURRENT_DATE AND DATE_ADD(CURRENT_DATE, INTERVAL 1 DAY); 
    
  4. 花點時間,更新您的應用程序,直接使用原來的VARCHAR列的地方,同時nothi ng將被打破。

  5. 當您完成後刪除觸發器和VARCHAR列:

    DROP TRIGGER `MY_TABLE_VARCHAR_DATE_BI`; 
    DROP TRIGGER `MY_TABLE_VARCHAR_DATE_BU`; 
    
    ALTER TABLE MY_TABLE DROP `VARCHAR_DATE`; 
    

工作SQL Fiddle

相關問題