Administrator
发布于 2025-09-06 / 7 阅读
0
0

MySQL第5课:小数类型详解

MySQL中的小数类型用于存储精确或近似的数值数据,包括浮点数和定点数。正确选择小数类型对数据精度和存储效率至关重要。

1. MySQL小数类型概览

MySQL提供了三种主要的小数类型,每种类型有不同的特点和适用场景:

数据类型

描述

存储需求

特点

适用场景

DECIMAL(M,D)

精确小数

变长存储

精确计算,无精度损失

财务数据、货币计算

FLOAT(M,D)

单精度浮点数

4字节

近似值,有精度损失

科学计算、不需要精确值的场景

DOUBLE(M,D)

双精度浮点数

8字节

近似值,比FLOAT精度高

科学计算、工程应用

2. DECIMAL类型详解

语法和参数

DECIMAL(M, D)
  • M:总位数(精度),范围1-65,默认10

  • D:小数位数(标度),范围0-30,且必须≤M,默认0

存储示例

-- 创建表使用DECIMAL类型
CREATE TABLE products (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(100),
    price DECIMAL(10, 2),        -- 总共10位,2位小数,范围:-99999999.99 到 99999999.99
    weight DECIMAL(8, 3),        -- 总共8位,3位小数
    discount DECIMAL(5, 4)       -- 总共5位,4位小数,如0.1234
);
​
-- 插入数据
INSERT INTO products (name, price, weight, discount)
VALUES 
    ('笔记本电脑', 4599.99, 2.345, 0.15),
    ('手机', 2999.50, 0.189, 0.05),
    ('耳机', 199.00, 0.056, 0.00);

DECIMAL的存储方式

DECIMAL类型以二进制格式存储,但保持十进制的精确性。每4个字节存储9位数字:

  • DECIMAL(10,2):需要5字节存储

  • DECIMAL(20,5):需要9字节存储

3. FLOAT和DOUBLE类型详解

FLOAT类型

-- 单精度浮点数,约7位有效数字
CREATE TABLE scientific_data (
    id INT PRIMARY KEY AUTO_INCREMENT,
    measurement FLOAT(10, 6),    -- 总共10位,6位小数
    temperature FLOAT            -- 不指定精度
);
​
INSERT INTO scientific_data (measurement, temperature)
VALUES 
    (1234.567890, 25.5),
    (0.000123, -10.2);

DOUBLE类型

-- 双精度浮点数,约15位有效数字
CREATE TABLE high_precision_data (
    id INT PRIMARY KEY AUTO_INCREMENT,
    value DOUBLE(20, 10),        -- 总共20位,10位小数
    calculation DOUBLE
);
​
INSERT INTO high_precision_data (value, calculation)
VALUES 
    (1234567890.1234567890, 3.141592653589793),
    (0.0000000001, 2.718281828459045);

4. 如何选择小数类型

选择指南

  1. 需要精确计算(如财务数据):使用DECIMAL

  2. 需要大范围数值(科学计算):使用FLOAT或DOUBLE

  3. 存储空间有限:FLOAT比DECIMAL占用更少空间

  4. 性能要求高:FLOAT/DOUBLE计算比DECIMAL快

实际应用示例

-- 财务应用:使用DECIMAL确保精确性
CREATE TABLE financial_records (
    id INT PRIMARY KEY AUTO_INCREMENT,
    transaction_date DATE,
    amount DECIMAL(15, 2),       -- 足够存储万亿级别的金额
    tax_rate DECIMAL(5, 4)       -- 税率,如0.0825
);
​
-- 科学应用:使用DOUBLE处理极大/极小值
CREATE TABLE scientific_measurements (
    id INT PRIMARY KEY AUTO_INCREMENT,
    distance DOUBLE,             -- 天文距离
    atomic_mass DOUBLE           -- 原子质量
);
​
-- 日常应用:混合使用
CREATE TABLE ecommerce_products (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(100),
    price DECIMAL(10, 2),        -- 精确价格
    rating FLOAT(3, 2),          -- 用户评分,如4.75
    weight DECIMAL(8, 3)         -- 精确重量
);

5. 小数类型的属性和函数

列属性

CREATE TABLE example (
    -- ZEROFILL: 用零填充显示(MySQL 8.0+不推荐)
    value DECIMAL(5, 2) ZEROFILL,
    
    -- UNSIGNED: 无符号值(只适用于DECIMAL)
    positive_value DECIMAL(10, 2) UNSIGNED,
    
    -- 默认值
    price DECIMAL(10, 2) DEFAULT 0.00
);

常用数学函数

-- 四舍五入
SELECT ROUND(123.4567, 2);       -- 123.46
​
-- 向上取整
SELECT CEIL(123.456);            -- 124
​
-- 向下取整
SELECT FLOOR(123.456);           -- 123
​
-- 绝对值
SELECT ABS(-123.45);             -- 123.45
​
-- 取模
SELECT MOD(10.5, 3.2);           -- 1.0
​
--  truncate 截断
SELECT TRUNCATE(123.4567, 2);    -- 123.45

聚合函数

-- 平均值
SELECT AVG(price) FROM products;
​
-- 总和
SELECT SUM(amount) FROM financial_records;
​
-- 最大值/最小值
SELECT MAX(temperature), MIN(temperature) FROM measurements;

6. 实际应用场景

场景1:电子商务系统

CREATE TABLE orders (
    order_id INT PRIMARY KEY AUTO_INCREMENT,
    user_id INT,
    subtotal DECIMAL(10, 2),     -- 小计
    tax DECIMAL(10, 2),          -- 税费
    discount DECIMAL(10, 2),     -- 折扣
    shipping DECIMAL(10, 2),     -- 运费
    total DECIMAL(10, 2),        -- 总计
    created_at TIMESTAMP
);

-- 计算订单总额
UPDATE orders 
SET total = subtotal + tax + shipping - discount 
WHERE order_id = 1;

场景2:科学数据分析

CREATE TABLE experiment_results (
    id INT PRIMARY KEY AUTO_INCREMENT,
    experiment_name VARCHAR(100),
    measurement1 DOUBLE,
    measurement2 DOUBLE,
    ratio DOUBLE AS (measurement1 / measurement2),  -- 生成列
    standard_deviation DOUBLE,
    created_at TIMESTAMP
);

-- 插入数据
INSERT INTO experiment_results (experiment_name, measurement1, measurement2)
VALUES ('Temperature Study', 12345.6789, 0.000123456);

场景3:库存管理系统

CREATE TABLE inventory (
    product_id INT PRIMARY KEY,
    product_name VARCHAR(100),
    current_stock INT,
    unit_price DECIMAL(10, 2),
    total_value DECIMAL(12, 2) AS (current_stock * unit_price),  -- 自动计算列
    reorder_level INT,
    last_updated TIMESTAMP
);

7. 最佳实践和注意事项

  1. 精度选择:根据实际需要选择适当的精度,不要过度指定

    -- 不好:过度精度
    price DECIMAL(20, 10)
    
    -- 好:适当精度
    price DECIMAL(10, 2)
  2. 避免浮点数比较:浮点数有精度问题,避免直接比较

    -- 可能有问题
    SELECT * FROM products WHERE price = 10.1;
    
    -- 更好的方式
    SELECT * FROM products WHERE ABS(price - 10.1) < 0.0001;
  3. 使用合适的类型

    • 财务数据:始终使用DECIMAL

    • 科学数据:使用FLOAT或DOUBLE

    • 百分比:使用DECIMAL(5,4)表示0.0000到0.9999

  4. 注意存储需求

    • DECIMAL(M,D)的存储需求取决于M值

    • FLOAT固定4字节,DOUBLE固定8字节

  5. 处理除零错误

    -- 可能出错
    SELECT price / 0 FROM products;
    
    -- 安全方式
    SELECT price / NULLIF(quantity, 0) FROM products;

8. 常见问题解决方案

问题1:精度丢失

-- 使用DECIMAL避免精度问题
CREATE TABLE account_balances (
    account_id INT PRIMARY KEY,
    balance DECIMAL(15, 2)  -- 确保财务计算的精确性
);

问题2:范围不足

-- 对于极大或极小的值,使用DOUBLE
CREATE TABLE astronomical_data (
    id INT PRIMARY KEY,
    distance DOUBLE,        -- 存储天文距离
    mass DOUBLE             -- 存储天体质量
);

问题3:性能优化

-- 对于大量计算,考虑使用FLOAT/DOUBLE
CREATE TABLE sensor_readings (
    id INT PRIMARY KEY,
    value FLOAT,            -- 近似值足够,计算更快
    timestamp TIMESTAMP
);

9. 练习项目

项目1:创建财务管理系统

CREATE TABLE financial_system (
    transaction_id INT PRIMARY KEY AUTO_INCREMENT,
    date DATE,
    description VARCHAR(255),
    debit DECIMAL(12, 2),
    credit DECIMAL(12, 2),
    balance DECIMAL(12, 2) AS (credit - debit)
);
​
-- 插入示例数据
INSERT INTO financial_system (date, description, debit, credit)
VALUES 
    ('2023-01-01', '初始资金', 0, 10000.00),
    ('2023-01-02', '购买设备', 2500.00, 0),
    ('2023-01-03', '销售收入', 0, 1500.00);

项目2:创建科学实验记录表

CREATE TABLE lab_experiments (
    experiment_id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(100),
    temperature FLOAT,          -- 温度测量
    pressure DOUBLE,            -- 压力测量
    concentration DECIMAL(10, 6), -- 精确浓度
    result_calculated DOUBLE AS (temperature * pressure / concentration)
);

总结

  • DECIMAL:用于需要精确计算的场景,如财务数据

  • FLOAT:单精度浮点数,适用于不需要精确值的科学计算

  • DOUBLE:双精度浮点数,比FLOAT精度更高

  • 根据数据特点和精度要求选择合适的小数类型

  • 注意浮点数的精度问题,避免直接比较

  • 合理选择精度和标度,平衡存储需求和计算精度

实践建议:分析你的应用场景,确定需要的数据精度和范围。对于财务应用,始终使用DECIMAL;对于科学计算,考虑使用FLOAT或DOUBLE。创建测试表,插入边界值数据,验证数据类型的行为是否符合预期。

通过实际创建表、插入数据和执行计算,你会更好地理解MySQL小数类型的特点和适用场景。


评论