PostgreSQL教程FG041-PG数值类型:高精度数值/浮点数/货币类型详解
本文档风哥主要介绍PostgreSQL教程041相关内容。风哥教程参考PostgreSQL官方文档Server Administration, SQL Language内容编写,适合DBA人员在学习和测试中使用,如果要应用于生产环境则需要自行确认。
1. 数值类型概述
PostgreSQL提供了丰富的数值类型,包括整数、任意精度数值、浮点数、序列和货币类型。正确选择数值类型对于数据存储效率和计算精度至关重要。
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
执行结果:
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;
执行结果:
—-+————–+————–+———————-
1 | 32767 | 2147483647 | 9223372036854775807
2 | -32768 | -2147483648 | -9223372036854775808
3 | 0 | 0 | 0
(3 rows)
测试整数溢出:
INSERT INTO fgedu_integer_types (smallint_col) VALUES (32768);
执行结果:
整数类型范围说明:
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;
执行结果:
————-+————————-+————————-+—————
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;
执行结果:
—-+————-+——————+————-+———————-
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)
精度测试:
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;
执行结果:
——————-+———————-+———————
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;
执行结果:
—————-+————-+—————+—————–+——————
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
—-+—————-+———————–
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;
执行结果:
——————-+————-+—————+—————–
0.300000000000000 | 0.3 | false | true
(1 row)
特殊浮点数值:
SELECT
‘Infinity’::FLOAT AS positive_infinity,
‘-Infinity’::FLOAT AS negative_infinity,
‘NaN’::FLOAT AS 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;
执行结果:
—-+———-+——–+——–
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%’;
执行结果:
———————————–+————+————-+————–+—————–+———–
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;
执行结果:
—-+————–+———–+—————-
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;
执行结果:
————–+———–+—————-+———–+——————
笔记本电脑 | ¥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;
执行结果:
———-+———+———+———–+———–
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;
执行结果:
————+———+———+——————–+——————–+———
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;
执行结果:
——————+——————+——————+—————–
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
——————+————-+————–+———
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);
执行结果:
计算复利:
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
————–+————+—————+—————-+—————–
储蓄账户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
—————-+————+——————+———–+—————+——————————-+————
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;
执行结果:
————–+————–+———–+—————+—————-+——————-+——————
定期账户 | 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
本文由风哥教程整理发布,仅用于学习测试使用,转载注明出处:http://www.fgedu.net.cn/10327.html
