从 MySQL 日期字段中阻止“0000-00-00”
Posted
技术标签:
【中文标题】从 MySQL 日期字段中阻止“0000-00-00”【英文标题】:Blocking '0000-00-00' from MySQL Date Fields 【发布时间】:2011-04-22 22:57:57 【问题描述】:我有一个数据库,其中旧代码喜欢在 Date 和 DateTime 列中插入“0000-00-00”而不是实际日期。所以我有以下两个问题:
-
我可以在数据库级别上做些什么来阻止它吗?我知道我可以将一列设置为非空,但这似乎并没有阻止这些零值。
检测日期字段中现有零值的最佳方法是什么?我有大约一百个表,每个表有 2-3 个日期列,我不想单独查询它们。
跟进:
默认值已设置为 null。很久以前,默认值为“0000-00-00”。一些代码仍然明确放置“0000-00-00”。我宁愿强制该代码抛出错误,以便隔离并删除它。
【问题讨论】:
我不敢相信 mysql 不支持 CHECK 约束。我打算将其发布为答案,这不是一个选择。越来越多的,我理解 MySQL 的恨。自己从来没用过。 【参考方案1】:我可以在数据库级别做些什么来阻止这个吗?
是的,启用 NO_ZERO_DATE 模式:
SET sql_mode = 'NO_ZERO_DATE';
The behaviour is documented。此外,您可能还希望将模式设置为包括 NO_ZERO_IN_DATE...
还要确保 sql_mode 包含 STRICT_ALL_TABLES 或 STRICT_TRANS_TABLES;没有这些 NO_ZERO_IN_DATE 只会发出警告,但插入仍然成功。
检测日期字段中现有零值的最佳方法是什么?我有大约一百个表,每个表有 2-3 个日期列,我不想单独查询它们。
单独的列意味着必须单独检查它们——对此您无能为力。
【讨论】:
(这仅在插入新数据时有效 - 如果您有一个充满不良数据的数据库,则帮助不大)【参考方案2】:假设您无法轻松修复数据和“SET sql_mode = 'NO_ZERO_DATE';”,您可以在表上创建一个视图...
CREATE VIEW filter AS
SELECT other_column,
CASE
WHEN realtable.dodgy_date = 0 THEN NULL
ELSE realtable.dodgy_date
END AS dodgy_date
FROM realtable;
【讨论】:
【参考方案3】:如果输入的日期无关紧要(即,只要它不为零),您可以更改列定义以使用 NOW() 作为默认值。可能不是一个理想的解决方案,但它确实满足标准: 1) 非空 2) 非零 其实我真的不为这个建议感到骄傲
【讨论】:
【参考方案4】:您可以使列可以为空,并将 NULL
作为默认值,但听起来您已经拥有它并且它不起作用。虽然...它可能是您用来显示数据的工具不喜欢显示NULL
日期...您使用的是什么工具?还是代码检索的数据中出现了“0000-00-00”?
您可以设置一个非 null 且易于识别为默认值的默认值,例如 1900-01-01
(假设您通常不处理接近此日期的日期)。
【讨论】:
【参考方案5】:trigger 可用于强制列的值。
【讨论】:
【参考方案6】:默认设置时间戳可能是您的一个选项,为此使用表更改语句:
ALTER TABLE mytable CHANGE date_update timestamp NOT NULL DEFAULT CURRENT_DATE()
MySQL CURRENT_DATE() documentation at w3c resource
删除零日期并将其替换为例如当前日期:
UPDATE mytable SET date_update = CURRENT_DATE() where date_update = "0000-00-00"
【讨论】:
【参考方案7】:这是我使用的触发器:
delimiter //
CREATE TRIGGER bad_date BEFORE INSERT ON some_table
FOR EACH ROW
BEGIN
IF NEW.the_date='0000-00-00' THEN
SET NEW.the_date= CURDATE();
END IF;
END;//
如果更新是一个问题,添加一个单独的触发器(更新前)来做同样的事情。
【讨论】:
以上是关于从 MySQL 日期字段中阻止“0000-00-00”的主要内容,如果未能解决你的问题,请参考以下文章
仅从日期时间字段(mysql)中提取日期并将其分配给 php 变量