MySQL 中存储金额时,推荐使用 DECIMAL 数据类型,因为它可以精确地表示小数,避免浮点数精度问题。以下是关于存储金额时的建议和注意事项:

推荐的数据类型:DECIMAL

语法

DECIMAL(M, D)
  • M: 数字的总长度(包含整数和小数部分)。
  • D: 小数部分的长度。
  • M 和 D 的取值会影响金额的精度。常见的设置是:
    • 金额以货币为单位:DECIMAL(10, 2),支持最大值为 99999999.99。
    • 金额以分为单位(避免小数操作):DECIMAL(15, 0)

为什么不用浮点数(FLOAT/DOUBLE)?

  1. 浮点数精度问题
    • 浮点类型(FLOATDOUBLE)是近似存储,容易导致计算误差,不适合财务相关数据。
    • 例如,存储和计算 0.1 + 0.2 可能得到 0.30000000000000004
  2. 财务数据要求高精度
    • 金额通常不能容忍误差,因此需要精确存储的 DECIMAL

使用金额字段时的注意事项

  1. 选择合适的精度
    • 根据业务需求设定 M 和 D。例如,如果交易额可能很大,可以选择更大的 M 值。
  2. 默认值的处理
    • 避免使用 NULL,通常可以设置默认值为 0。
    • 示例:DECIMAL(10, 2) NOT NULL DEFAULT 0.00
  3. 索引性能
    • 如果金额字段用于查询条件(如 WHERE amount > 100),建议为其建立索引,但要注意索引的大小。
  4. 避免直接存储小数金额
    • 如果可以,将金额以“最小单位”(如分)存储为整数,然后在应用程序中处理显示(例如 100 表示 1.00 元)。
  5. 数据校验
    • 确保插入或更新时,金额数据符合业务规则(非负、有效范围等)。
    • 可通过 CHECK 约束(MySQL 8.0 及以上支持)实现: CREATE TABLE payments ( amount DECIMAL(10, 2) NOT NULL CHECK (amount >= 0) );

实例

建表示例

CREATE TABLE transactions (
    id INT AUTO_INCREMENT PRIMARY KEY,
    description VARCHAR(255),
    amount DECIMAL(10, 2) NOT NULL DEFAULT 0.00,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

插入数据

INSERT INTO transactions (description, amount) VALUES
('Payment received', 100.25),
('Refund issued', -50.75);

查询示例

SELECT * FROM transactions WHERE amount > 100.00;