404 Not Found

404 Not Found


nginx

数据类型

数据类型

就像收纳盒有不同尺寸——小格子放耳钉、中格子放手表、大格子放围巾——数据库的每列也需要选择合适的"盒子"来存放数据。选对类型,数据既安全又省空间;选错类型,要么浪费存储,要么丢失精度。


1. 核心概念

概念 说明
数值类型 存储整数和小数,包括 INT、BIGINT、DECIMAL、FLOAT 等
字符串类型 存储文本数据,包括 CHAR、VARCHAR、TEXT
日期类型 存储日期和时间,包括 DATE、DATETIME、TIMESTAMP
布尔类型 存储真/假值,SQLite 中用 INTEGER(0/1)表示
NULL 表示"未知"或"缺失",不是空字符串也不是零
类型选择原则 根据数据范围、精度需求和存储效率选择最合适的类型

2. 基本语法

数值类型

类型 说明 范围/精度 适用场景
INTEGER / INT 整数 ±21 亿 ID、数量、年龄
BIGINT 大整数 ±9.2×10¹⁸ 大量数据的 ID、文件大小
DECIMAL(p,s) / NUMERIC(p,s) 精确小数 p 为总位数,s 为小数位 金额、价格(不会丢精度)
FLOAT / REAL 浮点数 约 7 位有效数字 科学计算、近似值
DOUBLE 双精度浮点 约 15 位有效数字 高精度近似计算
SQL
-- DECIMAL 精确存储金额
CREATE TABLE accounts (
    id INTEGER PRIMARY KEY,
    balance DECIMAL(12, 2)  -- 最多 12 位,其中 2 位小数
);

-- FLOAT 近似存储
CREATE TABLE measurements (
    id INTEGER PRIMARY KEY,
    temperature REAL  -- 近似值,可能有微小误差
);
💡 提示:金额永远用 DECIMAL,不要用 FLOAT! FLOAT 是近似存储,0.1 + 0.2 可能等于 0.30000000000000004,这在财务场景中是灾难。

字符串类型

类型 说明 最大长度 适用场景
CHAR(n) 定长字符串 255 字节 固定长度数据(如性别 M/F、状态码)
VARCHAR(n) 变长字符串 65535 字节 姓名、邮箱、标题
TEXT 长文本 无限 文章内容、备注、描述
SQL
CREATE TABLE articles (
    id INTEGER PRIMARY KEY,
    title VARCHAR(200),    -- 标题,最长 200 字符
    status CHAR(1),         -- 状态:D=草稿,P=已发布
    content TEXT             -- 正文,不限长度
);
💡 提示:SQLite 对字符串类型比较宽松,实际上可以存入任意长度的字符串。但为了代码可读性和跨数据库兼容,建议仍然按规范声明类型。

日期类型

类型 说明 格式 适用场景
DATE 日期 YYYY-MM-DD 生日、入职日期
DATETIME 日期时间 YYYY-MM-DD HH:MM:SS 创建时间、预约时间
TIMESTAMP 时间戳 自动管理 记录修改时间、跨时区场景
SQL
CREATE TABLE events (
    id INTEGER PRIMARY KEY,
    event_name TEXT,
    event_date DATE,              -- 只关心日期
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP  -- 自动记录创建时间
);
💡 提示:SQLite 没有专门的日期类型,通常用 TEXT(ISO 8601 格式如 '2024-01-15')或 INTEGER(Unix 时间戳)存储。SQLite 内置的日期函数(如 DATE()DATETIME())可以正确处理这些格式。

布尔类型

类型 说明 存储方式
BOOLEAN 真/假 SQLite 中存储为 INTEGER:0=假,1=真
BIT 位值 MySQL/SQL Server 中使用
SQL
CREATE TABLE users (
    id INTEGER PRIMARY KEY,
    name TEXT,
    is_active BOOLEAN DEFAULT 1  -- 1=启用,0=禁用
);

-- 插入布尔值
INSERT INTO users (name, is_active) VALUES ('张三', TRUE);   -- 存为 1
INSERT INTO users (name, is_active) VALUES ('李四', FALSE);  -- 存为 0

-- 查询时使用布尔值
SELECT * FROM users WHERE is_active = 1;
💡 提示:SQLite 中 TRUE 等价于 1,FALSE 等价于 0。但为了代码可读性,建议使用 TRUE/FALSE 而不是直接写数字。

NULL 的含义

NULL 表示"未知"或"缺失",它不是空字符串 '',也不是数字 0,更不是 FALSE

SQL
-- NULL 参与运算的结果都是 NULL
SELECT NULL + 1;        -- 结果:NULL
SELECT NULL || 'hello'; -- 结果:NULL

-- 判断 NULL 必须用 IS / IS NOT
SELECT * FROM employees WHERE department_id IS NULL;     -- ✅ 正确
SELECT * FROM employees WHERE department_id = NULL;      -- ❌ 永远返回空
SELECT * FROM employees WHERE department_id IS NOT NULL; -- ✅ 正确
💡 提示:NULL 是新手最容易踩坑的地方。记住两个规则:①判断 NULL 用 IS,不用 =;②NULL 参与任何运算结果都是 NULL

类型选择最佳实践

场景 推荐类型 原因
主键 ID INTEGER PRIMARY KEY AUTOINCREMENT 整数比字符串快,自增方便
金额/价格 DECIMAL(10,2) 精确存储,无舍入误差
用户名/标题 VARCHAR(100) 变长省空间,限制长度防滥用
文章正文 TEXT 不限长度,适合大文本
日期 DATE / DATETIME 语义明确,内置日期函数支持
是/否标记 BOOLEAN 语义清晰,存储紧凑
枚举状态 CHAR(1)INTEGER 比 ENUM 类型更灵活

3. 示例代码

示例:创建商品表并验证类型约束(难度⭐)

创建一张商品表,体验不同数据类型的行为。

SQL
-- 创建商品表,指定各列类型
CREATE TABLE products_demo (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name VARCHAR(100) NOT NULL,
    price DECIMAL(10, 2) NOT NULL,
    stock INTEGER DEFAULT 0,
    description TEXT,
    is_active BOOLEAN DEFAULT 1,
    created_at DATE
);

-- 插入各种类型的数据
INSERT INTO products_demo (name, price, stock, description, is_active, created_at)
VALUES ('机械键盘', 299.50, 100, '青轴87键机械键盘,适合打字', TRUE, '2024-01-15');

INSERT INTO products_demo (name, price, stock, description, is_active, created_at)
VALUES ('无线鼠标', 89.00, 200, NULL, TRUE, '2024-02-20');

-- 查看数据和类型表现
SELECT name, price, stock, description, is_active, created_at
FROM products_demo;
▶ 试一试

输出

TEXT
name      price    stock  description              is_active  created_at
--------  -------  -----  -----------------------  ---------  ----------
机械键盘  299.50   100    青轴87键机械键盘,适合打字  1          2024-01-15
无线鼠标  89.00    200    (NULL)                    1          2024-02-20

示例:NULL 的运算特性验证(难度⭐⭐)

通过实际查询理解 NULL 的特殊行为。

SQL
-- 创建测试表
CREATE TABLE null_test (
    id INTEGER PRIMARY KEY,
    value INTEGER
);

INSERT INTO null_test VALUES (1, 10);
INSERT INTO null_test VALUES (2, NULL);
INSERT INTO null_test VALUES (3, 20);

-- NULL 参与算术运算
SELECT id, value, value + 100 AS add_result
FROM null_test;
▶ 试一试

输出

TEXT
id  value  add_result
--  -----  ----------
1   10     110
2   (NULL) (NULL)
3   20     120
SQL
-- 判断 NULL:IS vs =
SELECT id, value,
    CASE WHEN value IS NULL THEN '是NULL' ELSE '非NULL' END AS check_result
FROM null_test;

输出

TEXT
id  value  check_result
--  -----  ------------
1   10     非NULL
2   (NULL) 是NULL
3   20     非NULL
SQL
-- NULL 与聚合函数:COUNT 不计 NULL,SUM/AVG 忽略 NULL
SELECT COUNT(value) AS count_val,      -- 2(不计 NULL)
       COUNT(*) AS count_all,          -- 3(计所有行)
       SUM(value) AS sum_val,          -- 30(忽略 NULL)
       AVG(value) AS avg_val           -- 15(30/2,不是30/3)
FROM null_test;

输出

TEXT
count_val  count_all  sum_val  avg_val
---------  ---------  -------  -------
2          3          30       15.0

4. 常见应用场景

场景一:设计用户注册表

根据业务需求选择合适的类型:

SQL
CREATE TABLE users (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    username VARCHAR(50) NOT NULL UNIQUE,     -- 用户名,唯一且非空
    email VARCHAR(100) NOT NULL UNIQUE,       -- 邮箱
    password_hash CHAR(64) NOT NULL,          -- SHA256 哈希,固定 64 字符
    age INTEGER CHECK (age >= 0 AND age <= 150),  -- 年龄,合理范围校验
    balance DECIMAL(12, 2) DEFAULT 0.00,      -- 账户余额,精确到分
    bio TEXT,                                  -- 个人简介,不限长度
    is_verified BOOLEAN DEFAULT 0,            -- 是否验证邮箱
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

场景二:处理 NULL 的默认值

COALESCE 函数为 NULL 提供默认值:

SQL
-- 查询员工信息,部门为空时显示"未分配"
SELECT e.name,
       COALESCE(d.name, '未分配') AS department,
       COALESCE(e.salary, 0) AS salary
FROM employees e
LEFT JOIN departments d ON e.department_id = d.id;

❓ 常见问题

Q DECIMAL(10,2) 和 FLOAT 都能存小数,有什么区别?
A DECIMAL 是精确存储,适合金额等不能有误差的场景;FLOAT 是近似存储,计算速度快但有微小误差。简单记:钱用 DECIMAL,科学计算用 FLOAT
Q CHAR 和 VARCHAR 怎么选?
A 如果数据长度固定(如性别 M/F、MD5 哈希),用 CHAR 更高效;如果长度不固定(如姓名、标题),用 VARCHAR 更省空间。实际开发中 VARCHAR 用得更多。
Q NULL 和空字符串 '' 有什么区别?
A NULL 表示"不知道/没有值",空字符串表示"知道值是什么,值是空的"。比如"中间名"列,外国人可能没有中间名(NULL),中国人可能有中间名但为空字符串('')。在聚合函数中,COUNT(列) 不计 NULL 但会计空字符串。
Q SQLite 的类型系统和其他数据库有什么不同?
A SQLite 使用动态类型系统,列的类型声明更像是"建议"而非强制约束。你可以往 INTEGER 列插入字符串(虽然不推荐)。MySQL、PostgreSQL 等是严格类型系统,类型不匹配会报错。为了代码可移植性,建议按规范使用类型。

📖 小节

  • 数值类型:整数用 INT/BIGINT,精确小数用 DECIMAL(金额必选),近似值用 FLOAT
  • 字符串类型:固定长度用 CHAR,变长用 VARCHAR,大文本用 TEXT
  • 日期类型:DATE 存日期,DATETIME 存日期时间,TIMESTAMP 自动管理
  • 布尔类型:BOOLEAN 存储 TRUE/FALSE,SQLite 中实际为 INTEGER 0/1
  • NULL 表示"未知",判断用 IS NULL 而非 = NULL,NULL 参与运算结果仍为 NULL
  • 类型选择原则:根据数据范围、精度需求、存储效率综合考虑,金额必用 DECIMAL

📝 作业

练习 1(⭐)

设计一个"图书馆借阅"表,包含以下字段,选择合适的数据类型:

  • 借阅 ID(主键)
  • 书名(最长 200 字符)
  • ISBN(固定 13 位)
  • 借阅人姓名
  • 借出日期
  • 应还日期
  • 是否归还
  • 备注(可为空)

练习 2(⭐⭐)

创建上题的表并插入 5 条数据,然后编写查询:

  1. 查询所有未归还的借阅记录
  2. 查询备注为 NULL 的记录
  3. 计算所有未归还记录的数量(注意 NULL 的处理)

下一课

👉 06-practice-basics - 实战:基础查询综合

Web-Tutorial.com

Web-Tutorial 技术团队

由多位开发者共同维护的编程教程平台。每篇教程由对应领域的开发者编写和审核,确保内容准确可靠。如发现任何问题,欢迎向我们反馈。

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏