我正在尝试迁移/更新一个旧表,该表允许在假定的“日期”字段中使用可为空的 varchar。我想查找与此格式不匹配的所有行:%e-%b-%y
. 我怎样才能完成这个查询?
**编辑:我应该提到该字段确实包含一些“CANCELLED”、null 或其他字符串值,而不是更常见的 eby 格式。我正在寻找这些行,以便可以将它们更新为我想要的格式 (%e-%b-%y)。
你可以在 MySQL 中使用正则表达式;见http://dev.mysql.com/doc/refman/5.1/en/regexp.html#operator_not-regexp
这是一个表达式,它返回日期字段 (dt) 为空或不匹配的行 1-2 位数字 + 破折号 + 3 个字母字符 + 破折号 + 2 个数字(例如,06-Sep-13)
select * from table_name where dt is null or
dt not rlike '[[:digit:]]{1,2}-[[:alpha:]]{3}-[[:digit:]]{2}';
这是基于Orbling 的评论。您可以执行以下操作:
SELECT * FROM my_table
WHERE DATE_FORMAT(CAST(date_field, DATE), '%e-%b-%y') <> date_field
它的作用是获取 date_field,尝试将其转换为日期,然后将该日期转换回字符串,然后将其与原始字符串进行比较。如果两者不匹配,则报告该行。如果转换失败,您的 MySQL 客户端可能会报告警告,但您可以放心地忽略这些警告。
这是一项非常严格的检查:它将报告您无法通过相应地格式化日期来准确地重新创建原始情况的任何行。特别是,这将抱怨前导零、尾随空格等方面的差异。如果这是一个问题,您可以找到一个不太严格的检查(可能基于日期有效性检查和一些正则表达式),或者做一些简单的模式匹配来识别和更正这些行,以便它们匹配所需的格式。就像查找所有匹配的行并在第一个破折号后__-_-____
引入 a一样。0
另一种方法是尝试使用不同格式恢复尽可能多的日期,如果提取的值无效,则使用STR_TO_DATE()
它将返回,并链接不同的日期格式。NULL
COALESCE()
要仅显示日期不可恢复的行:
SELECT *
FROM table1
WHERE COALESCE(STR_TO_DATE(NULLIF(dt, ''), '%e-%b-%Y'),
STR_TO_DATE(NULLIF(dt, ''), '%e-%b-%y'),
STR_TO_DATE(NULLIF(dt, ''), '%Y-%m-%d'),
STR_TO_DATE(NULLIF(dt, ''), '%m/%d/%Y'),
STR_TO_DATE(NULLIF(dt, ''), '%m/%d/%y')) IS NULL;
要查看转换日期后会得到什么:
SELECT *, COALESCE(STR_TO_DATE(NULLIF(dt, ''), '%e-%b-%Y'),
STR_TO_DATE(NULLIF(dt, ''), '%e-%b-%y'),
STR_TO_DATE(NULLIF(dt, ''), '%Y-%m-%d'),
STR_TO_DATE(NULLIF(dt, ''), '%m/%d/%Y'),
STR_TO_DATE(NULLIF(dt, ''), '%m/%d/%y')) new_date
FROM table1;
笔记:
%y
在两位数之前使用四位数字格式%y
。否则你会得到不正确的日期。如果您有以下示例数据:
| 身份证 | DT | |----|-------------| | 1 | 取消 | | 2 | 2012 年 3 月 2 日 | | 3 | (空) | | 4 | 13 年 8 月 5 日 | | 5 | | | 6 | 2013-09-12 | | 7 | 2013 年 10 月 23 日 | | 8 | 2012 年 8 月 13 日 |
然后第二个查询产生以下输出:
| 身份证 | DT | 新日期 | |----|-------------|------------------------------ ----| | 1 | 取消 | (空) | | 2 | 2012 年 3 月 2 日 | 2012 年 3 月 2 日 00:00:00+0000 | | 3 | (空) | (空) | | 4 | 13 年 8 月 5 日 | 2013 年 8 月 5 日 00:00:00+0000 | | 5 | | (空) | | 6 | 2013-09-12 | 2013 年 9 月 12 日 00:00:00+0000 | | 7 | 2013 年 10 月 23 日 | 2013 年 10 月 23 日 00:00:00+0000 | | 8 | 2012 年 8 月 13 日 | 2012 年 8 月 13 日 00:00:00+0000 |
这是SQLFiddle演示