1. 首页 > PostgreSQL教程 > 正文

PostgreSQL教程FG041-PG数值类型:高精度数值/浮点数/货币类型详解

本文档风哥主要介绍PostgreSQL教程041相关内容。风哥教程参考PostgreSQL官方文档Server Administration, SQL Language内容编写,适合DBA人员在学习和测试中使用,如果要应用于生产环境则需要自行确认。

1. 数值类型概述

PostgreSQL提供了丰富的数值类型,包括整数、任意精度数值、浮点数、序列和货币类型。正确选择数值类型对于数据存储效率和计算精度至关重要。

提示:在财务计算中,建议使用NUMERIC类型而不是FLOAT类型,以避免精度丢失问题。

2. 整数类型

PostgreSQL支持三种整数类型:SMALLINT、INTEGER和BIGINT。

— 创建整数类型测试表
CREATE TABLE fgedu_integer_types (
id SERIAL PRIMARY KEY,
smallint_col SMALLINT,
integer_col INTEGER,
bigint_col BIGINT
);

— 查看表结构
\d fgedu_integer_types

执行结果:

Table “public.fgedu_integer_types”
Column | Type | Collation | Nullable | Default
—————+———-+———–+———-+———————————————–
id | integer | | not null | nextval(‘fgedu_integer_types_id_seq’::regclass)
smallint_col | smallint | | |
integer_col | integer | | |
bigint_col | bigint | | |

插入测试数据:

学习交流加群风哥QQ113257174

— 插入正常范围内的数据
INSERT INTO fgedu_integer_types (smallint_col, integer_col, bigint_col) VALUES
(32767, 2147483647, 9223372036854775807),
(-32768, -2147483648, -9223372036854775808),
(0, 0, 0);

— 查询数据
SELECT * FROM fgedu_integer_types;

执行结果:

id | smallint_col | integer_col | bigint_col
—-+————–+————–+———————-
1 | 32767 | 2147483647 | 9223372036854775807
2 | -32768 | -2147483648 | -9223372036854775808
3 | 0 | 0 | 0
(3 rows)

测试整数溢出:

— 测试SMALLINT溢出
INSERT INTO fgedu_integer_types (smallint_col) VALUES (32768);

执行结果:

ERROR: smallint out of range

整数类型范围说明:

— 查看各整数类型的范围
SELECT
‘SMALLINT’ AS type_name,
-32768 AS min_value,
32767 AS max_value,
2 AS storage_bytes
UNION ALL
SELECT
‘INTEGER’,
-2147483648,
2147483647,
4
UNION ALL
SELECT
‘BIGINT’,
-9223372036854775808,
9223372036854775807,
8;

执行结果:

type_name | min_value | max_value | storage_bytes
————-+————————-+————————-+—————
SMALLINT | -32768 | 32767 | 2
INTEGER | -2147483648 | 2147483647 | 4
BIGINT | -9223372036854775808 | 9223372036854775807 | 8
(3 rows)

3. 任意精度数值类型

NUMERIC和DECIMAL类型可以存储任意精度的数值,适合财务计算。

— 创建任意精度数值测试表
CREATE TABLE fgedu_numeric_types (
id SERIAL PRIMARY KEY,
numeric_col NUMERIC(10, 4),
decimal_col DECIMAL(15, 2),
real_col REAL,
double_col DOUBLE PRECISION
);

— 插入测试数据
INSERT INTO fgedu_numeric_types (numeric_col, decimal_col, real_col, double_col) VALUES
(12345.6789, 123456789012.34, 12345.6789, 123456789012345.6789),
(0.0001, 0.01, 0.0001, 0.0000000001),
(-9999.9999, -99999999999.99, -9999.999, -99999999999999.999);

— 查询数据
SELECT * FROM fgedu_numeric_types;

执行结果:

id | numeric_col | decimal_col | real_col | double_col
—-+————-+——————+————-+———————-
1 | 12345.6789 | 123456789012.34 | 12345.679 | 123456789012345.67
2 | 0.0001 | 0.01 | 0.0001000 | 0.00000000010000000
3 | -9999.9999 | -99999999999.99 | -9999.999 | -99999999999999.99
(3 rows)

精度测试:

— 测试NUMERIC精度
SELECT
1.0 / 3.0 AS float_result,
NUMERIC ‘1.0’ / NUMERIC ‘3.0’ AS numeric_result,
NUMERIC ‘1.000000000000’ / NUMERIC ‘3.0’ AS high_precision;

执行结果:

float_result | numeric_result | high_precision
——————-+———————-+———————
0.3333333333333333 | 0.333333333333333333 | 0.333333333333333333
(1 row)

财务计算示例:

— 创建财务表
CREATE TABLE fgedu_financial_records (
id SERIAL PRIMARY KEY,
account_number VARCHAR(20),
balance NUMERIC(15, 2) NOT NULL,
interest_rate NUMERIC(5, 4),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

— 插入财务数据
INSERT INTO fgedu_financial_records (account_number, balance, interest_rate) VALUES
(‘ACC001’, 1000000.00, 0.0350),
(‘ACC002’, 500000.50, 0.0425),
(‘ACC003’, 2500000.00, 0.0375);

— 计算利息(精确计算)
SELECT
account_number,
balance,
interest_rate,
balance * interest_rate AS annual_interest,
ROUND(balance * interest_rate, 2) AS rounded_interest
FROM fgedu_financial_records;

执行结果:

account_number | balance | interest_rate | annual_interest | rounded_interest
—————-+————-+—————+—————–+——————
ACC001 | 1000000.00 | 0.0350 | 35000.0000 | 35000.00
ACC002 | 500000.50 | 0.0425 | 21250.0213 | 21250.02
ACC003 | 2500000.00 | 0.0375 | 93750.0000 | 93750.00
(3 rows)

4. 浮点数类型

REAL和DOUBLE PRECISION类型用于存储近似数值。

— 创建浮点数测试表
CREATE TABLE fgedu_float_types (
id SERIAL PRIMARY KEY,
real_col REAL,
double_col DOUBLE PRECISION
);

— 插入测试数据
INSERT INTO fgedu_float_types (real_col, double_col) VALUES
(123.456789, 123.4567890123456789),
(1.0E+30, 1.0E+300),
(1.0E-30, 1.0E-300);

— 查询数据
SELECT * FROM fgedu_float_types;

执行结果:

学习交流加群风哥微信: itpux-com

id | real_col | double_col
—-+—————-+———————–
1 | 123.45679 | 123.45678901234567
2 | 1.000000e+30 | 1.000000000000000e+300
3 | 1.000000e-30 | 1.000000000000000e-300
(3 rows)

浮点数精度问题演示:

— 浮点数精度问题
SELECT
0.1 + 0.2 AS float_sum,
0.1::NUMERIC + 0.2::NUMERIC AS numeric_sum,
(0.1 + 0.2) = 0.3 AS float_compare,
(0.1::NUMERIC + 0.2::NUMERIC) = 0.3::NUMERIC AS numeric_compare;

执行结果:

float_sum | numeric_sum | float_compare | numeric_compare
——————-+————-+—————+—————–
0.300000000000000 | 0.3 | false | true
(1 row)

特殊浮点数值:

— 特殊浮点数值
SELECT
‘Infinity’::FLOAT AS positive_infinity,
‘-Infinity’::FLOAT AS negative_infinity,
‘NaN’::FLOAT AS nan_value;

执行结果:

positive_infinity | negative_infinity | nan_value
——————-+——————-+———–
Infinity | -Infinity | NaN
(1 row)

5. 序列类型

SERIAL、BIGSERIAL和SMALLSERIAL是自增整数类型。

— 创建序列类型测试表
CREATE TABLE fgedu_serial_types (
id SERIAL PRIMARY KEY,
small_id SMALLSERIAL,
big_id BIGSERIAL,
name VARCHAR(100)
);

— 插入测试数据
INSERT INTO fgedu_serial_types (name) VALUES (‘测试1’), (‘测试2’), (‘测试3’);

— 查询数据
SELECT * FROM fgedu_serial_types;

执行结果:

id | small_id | big_id | name
—-+———-+——–+——–
1 | 1 | 1 | 测试1
2 | 2 | 2 | 测试2
3 | 3 | 3 | 测试3
(3 rows)

查看序列信息:

— 查看序列信息
SELECT
sequence_name,
last_value,
start_value,
increment_by,
max_value,
min_value
FROM information_schema.sequences
WHERE sequence_name LIKE ‘fgedu_serial_types%’;

执行结果:

sequence_name | last_value | start_value | increment_by | max_value | min_value
———————————–+————+————-+————–+—————–+———–
fgedu_serial_types_id_seq | 3 | 1 | 1 | 2147483647 | 1
fgedu_serial_types_small_id_seq | 3 | 1 | 1 | 32767 | 1
fgedu_serial_types_big_id_seq | 3 | 1 | 1 | 9223372036854775807 | 1
(3 rows)

6. 货币类型

MONEY类型用于存储货币金额,精度取决于lc_monetary设置。

— 创建货币类型测试表
CREATE TABLE fgedu_money_types (
id SERIAL PRIMARY KEY,
product_name VARCHAR(100),
price MONEY,
discount_price MONEY
);

— 插入测试数据
INSERT INTO fgedu_money_types (product_name, price, discount_price) VALUES
(‘笔记本电脑’, 5999.00, 5499.00),
(‘无线鼠标’, 99.00, 79.00),
(‘机械键盘’, 399.00, 349.00);

— 查询数据
SELECT * FROM fgedu_money_types;

执行结果:

id | product_name | price | discount_price
—-+————–+———–+—————-
1 | 笔记本电脑 | ¥5,999.00 | ¥5,499.00
2 | 无线鼠标 | ¥99.00 | ¥79.00
3 | 机械键盘 | ¥399.00 | ¥349.00
(3 rows)

货币计算:

— 货币计算
SELECT
product_name,
price,
discount_price,
price – discount_price AS savings,
ROUND((price – discount_price) / price * 100, 2) AS discount_percent
FROM fgedu_money_types;

执行结果:

product_name | price | discount_price | savings | discount_percent
————–+———–+—————-+———–+——————
笔记本电脑 | ¥5,999.00 | ¥5,499.00 | ¥500.00 | 8.33
无线鼠标 | ¥99.00 | ¥79.00 | ¥20.00 | 20.20
机械键盘 | ¥399.00 | ¥349.00 | ¥50.00 | 12.53
(3 rows)

7. 数值运算与函数

常用数学函数:

— 常用数学函数
SELECT
ABS(-123.45) AS absolute,
ROUND(123.456, 2) AS rounded,
CEIL(123.45) AS ceiling,
FLOOR(123.45) AS floor_val,
TRUNC(123.456, 2) AS truncated;

执行结果:

absolute | rounded | ceiling | floor_val | truncated
———-+———+———+———–+———–
123.45 | 123.46 | 124 | 123 | 123.45
(1 row)

幂运算和开方:

— 幂运算和开方
SELECT
POWER(2, 10) AS power_2_10,
SQRT(16) AS sqrt_16,
CBRT(27) AS cbrt_27,
EXP(1) AS e_value,
LN(10) AS natural_log,
LOG(100) AS log_100;

执行结果:

power_2_10 | sqrt_16 | cbrt_27 | e_value | natural_log | log_100
————+———+———+——————–+——————–+———
1024 | 4 | 3 | 2.7182818284590452 | 2.3025850929940459 | 2
(1 row)

三角函数:

— 三角函数
SELECT
SIN(RADIANS(30)) AS sin_30,
COS(RADIANS(60)) AS cos_60,
TAN(RADIANS(45)) AS tan_45,
DEGREES(ACOS(0.5)) AS acos_05_degrees;

执行结果:

sin_30 | cos_60 | tan_45 | acos_05_degrees
——————+——————+——————+—————–
0.499999999999999 | 0.50000000000000 | 0.99999999999999 | 60
(1 row)

随机数函数:

— 随机数函数
SELECT
RANDOM() AS random_value,
FLOOR(RANDOM() * 100) AS random_0_99,
FLOOR(RANDOM() * 100) + 1 AS random_1_100,
SETSEED(0.5);

执行结果:

from oracle:www.itpux.com

random_value | random_0_99 | random_1_100 | setseed
——————+————-+————–+———
0.84729387569427 | 47 | 82 |
(1 row)

8. 实战案例:财务计算

创建完整的财务计算系统:

— 创建账户表
CREATE TABLE fgedu_accounts (
account_id SERIAL PRIMARY KEY,
account_name VARCHAR(100),
account_type VARCHAR(20),
balance NUMERIC(15, 2) DEFAULT 0.00,
interest_rate NUMERIC(5, 4) DEFAULT 0.0000,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

— 创建交易记录表
CREATE TABLE fgedu_transactions (
transaction_id SERIAL PRIMARY KEY,
account_id INTEGER,
transaction_type VARCHAR(20),
amount NUMERIC(15, 2),
balance_after NUMERIC(15, 2),
transaction_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
description TEXT
);

— 插入账户数据
INSERT INTO fgedu_accounts (account_name, account_type, balance, interest_rate) VALUES
(‘储蓄账户A’, ‘savings’, 100000.00, 0.0350),
(‘储蓄账户B’, ‘savings’, 50000.00, 0.0300),
(‘支票账户’, ‘checking’, 25000.00, 0.0010),
(‘定期账户’, ‘fixed’, 200000.00, 0.0450);

执行结果:

INSERT 0 4

计算复利:

— 计算复利(按月复利)
SELECT
account_name,
balance AS principal,
interest_rate,
balance * POWER(1 + interest_rate / 12, 12) AS yearly_balance,
balance * POWER(1 + interest_rate / 12, 12) – balance AS yearly_interest
FROM fgedu_accounts;

执行结果:

更多学习教程公众号风哥教程itpux_com

account_name | principal | interest_rate | yearly_balance | yearly_interest
————–+————+—————+—————-+—————–
储蓄账户A | 100000.00 | 0.0350 | 103566.7011 | 3566.7011
储蓄账户B | 50000.00 | 0.0300 | 51520.4288 | 1520.4288
支票账户 | 25000.00 | 0.0010 | 25025.0208 | 25.0208
定期账户 | 200000.00 | 0.0450 | 209183.6703 | 9183.6703
(4 rows)

模拟交易:

— 存款交易
INSERT INTO fgedu_transactions (account_id, transaction_type, amount, balance_after, description)
SELECT
1,
‘deposit’,
10000.00,
balance + 10000.00,
‘存款’
FROM fgedu_accounts WHERE account_id = 1
RETURNING *;

UPDATE fgedu_accounts SET balance = balance + 10000.00 WHERE account_id = 1;

执行结果:

风哥提示:更多视频教程www.fgedu.net.cn

transaction_id | account_id | transaction_type | amount | balance_after | transaction_date | description
—————-+————+——————+———–+—————+——————————-+————
1 | 1 | deposit | 10000.00 | 110000.00 | 2026-04-04 12:00:00.123 | 存款
(1 row)
UPDATE 1

财务报表:

— 财务报表
SELECT
a.account_name,
a.account_type,
a.balance,
a.interest_rate,
COALESCE(SUM(CASE WHEN t.transaction_type = ‘deposit’ THEN t.amount ELSE 0 END), 0) AS total_deposits,
COALESCE(SUM(CASE WHEN t.transaction_type = ‘withdrawal’ THEN t.amount ELSE 0 END), 0) AS total_withdrawals,
COUNT(t.transaction_id) AS transaction_count
FROM fgedu_accounts a
LEFT JOIN fgedu_transactions t ON a.account_id = t.account_id
GROUP BY a.account_id, a.account_name, a.account_type, a.balance, a.interest_rate
ORDER BY a.balance DESC;

执行结果:

account_name | account_type | balance | interest_rate | total_deposits | total_withdrawals | transaction_count
————–+————–+———–+—————+—————-+——————-+——————
定期账户 | fixed | 200000.00 | 0.0450 | 0.00 | 0.00 | 0
储蓄账户A | savings | 110000.00 | 0.0350 | 10000.00 | 0.00 | 1
储蓄账户B | savings | 50000.00 | 0.0300 | 0.00 | 0.00 | 0
支票账户 | checking | 25000.00 | 0.0010 | 0.00 | 0.00 | 0
(4 rows)

9. 清理环境

清理测试表:

— 删除所有测试表
DROP TABLE IF EXISTS fgedu_integer_types;
DROP TABLE IF EXISTS fgedu_numeric_types;
DROP TABLE IF EXISTS fgedu_float_types;
DROP TABLE IF EXISTS fgedu_serial_types;
DROP TABLE IF EXISTS fgedu_money_types;
DROP TABLE IF EXISTS fgedu_financial_records;
DROP TABLE IF EXISTS fgedu_accounts;
DROP TABLE IF EXISTS fgedu_transactions;

执行结果:

DROP TABLE
DROP TABLE
DROP TABLE
DROP TABLE
DROP TABLE
DROP TABLE
DROP TABLE
DROP TABLE
风哥教程风哥教程风哥教程总结:PostgreSQL提供了丰富的数值类型,包括整数类型(SMALLINT、INTEGER、BIGINT)、任意精度类型(NUMERIC、DECIMAL)、浮点数类型(REAL、DOUBLE PRECISION)、序列类型(SERIAL、BIGSERIAL、SMALLSERIAL)和货币类型(MONEY)。在财务计算中,建议使用NUMERIC类型以确保精度。正确选择数值类型对于数据存储效率和计算精度至关重要。

本文由风哥教程整理发布,仅用于学习测试使用,转载注明出处:http://www.fgedu.net.cn/10327.html

联系我们

在线咨询:点击这里给我发消息

微信号:itpux-com

工作日:9:30-18:30,节假日休息