所以我有一个大表,如果不破坏我的 PHP 应用程序就无法更改。愚蠢地(是的,我知道),例如,我将开始日期和结束日期设置为 VARCHAR,并将数据存储为 '03/04/2013'。
现在我需要能够搜索以查看哪些行当前是“活动的”,这意味着哪些行的开始日期在今天之前并且结束日期在今天之后。
这完全可以通过 SQL 查询实现吗?
所以我有一个大表,如果不破坏我的 PHP 应用程序就无法更改。愚蠢地(是的,我知道),例如,我将开始日期和结束日期设置为 VARCHAR,并将数据存储为 '03/04/2013'。
现在我需要能够搜索以查看哪些行当前是“活动的”,这意味着哪些行的开始日期在今天之前并且结束日期在今天之后。
这完全可以通过 SQL 查询实现吗?
在不破坏应用程序的情况下迁移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
直接使用原始列的地方,同时不会有任何问题。
完成后删除触发器和VARCHAR
列:
DROP TRIGGER `MY_TABLE_VARCHAR_DATE_BI`;
DROP TRIGGER `MY_TABLE_VARCHAR_DATE_BU`;
ALTER TABLE MY_TABLE DROP `VARCHAR_DATE`;
工作SQL 小提琴。
是的,你可以这么做。
尝试这样的事情: -
select date_format(str_to_date('03/04/2013', '%d/%m/%Y'), '%Y%m');
或者可能是这样的:-(我对 03 和 04 感到困惑,只是月份和日期的一个小变化)
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' );
UPDATE `table`
SET `yourColumn` = str_to_date( `yourColumn`, '%d-%m-%Y' );
在不丢失数据的情况下将其转换为日期类型,根据需要添加分钟或秒。从长远来看,它会更容易,但如果你更喜欢涉足 php ..
或者从 varchar 创建一个新的列日期类型。
使用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)