🗄️ 第四章 管理数据-避免非法数据的功能
📄 一句话概括

DATE 只存日期(年-月-日),DATETIME 日期带时刻(年-月-日 时:分:秒)——日期要用专门的日期类型存,别用字符串凑合,否则比较先后、算间隔全得靠人肉。

📝 本节和前面几节的关系

4-2 数字、4-3 文字,本节是类型家族的第三族:时间。第三章建表时没放日期列,本节补上——订单表、考勤表都离不开它。核心收获:为什么字符串存日期是个坑。

一、两个类型管两种精度

类型 格式 例
DATE 年-月-日 2026-09-24
DATETIME 年-月-日 时:分:秒 2026-09-24 08:57:12

(MySQL 还有 TIMESTAMP 带时区转换,本课点到为止。)

二、写入:字符串样式的「日期字面量」

写进去的时候长得像字符串(要加引号),但数据库会先检查它是不是合法日期:

INSERT INTO orders (created_at) VALUES ('2026-09-24 08:57:12');  -- 合法
INSERT INTO orders (created_at) VALUES ('2026-13-01');           -- 13 月?报错拦下

这就是 4-1「第一道防线」的又一例:字符串里塞 13 月 不会被察觉,日期类型一眼识破。

三、日期类型的真正威力:会算日期的列

日期类型天生支持:

这些用字符串存都做不到(字符串比大小会得出 2026-9-1 > 2026-10-1 的荒谬结果——逐字符比较,9 > 1)。

四、动手 Demo:日期算术

CREATE TABLE orders (
    id          INT,
    created_at  DATE
);

INSERT INTO orders VALUES (1, '2026-09-20');
INSERT INTO orders VALUES (2, '2026-09-24');

-- 1. 比先后:查 9 月 22 日以后的订单
SELECT * FROM orders WHERE created_at >= '2026-09-22';

-- 2. 算间隔:订单 1 是几天前的事
SELECT julianday('2026-09-24') - julianday('2026-09-20') AS 间隔天数;

第二条查询返回 4——日期类型自己会算账。(julianday 是 SQLite 的写法,MySQL 用 DATEDIFF('2026-09-24','2026-09-20')。)

五、30 秒实验

建 d VARCHAR(20) 表,塞 2026-9-1 和 2026-10-1,执行 SELECT MAX(d)——字符串比较会告诉你「9 月 > 10 月」。再把列改成 DATE 重试,结果立刻正常。一个类型,天壤之别。

六、常见误区

自测三问 1. DATE 和 DATETIME 差在哪?(DATETIME 多存时分秒) 2. 为什么不用字符串存日期?(无法正确比先后/算间隔/校验合法性) 3. `2026-13-01` 塞进 DATE 列会怎样?(报错拦下——类型检查生效)

相关笔记