https://www.cnblogs.com/yaochong-chongzi/p/12637681.html
数值类型由2字节,4字节和8字节整数,4字节和8字节浮点数以及可变精度的小数组成。
Name | Storage Size | Description | Range |
---|---|---|---|
smallint | 2 bytes | small-range integer | -32768 to +32767 |
integer | 4 bytes | typical choice for integer | -2147483648 to +2147483647 |
bigint | 8 bytes | large-range integer | -9223372036854775808 to +9223372036854775807 |
decimal | variable | user-specified precision, exact | up to 131072 digits before the decimal point; up to 16383 digits after the decimal point |
numeric | variable | user-specified precision, exact | up to 131072 digits before the decimal point; up to 16383 digits after the decimal point |
real | 4 bytes | variable-precision, inexact | 6 decimal digits precision |
double precision | 8 bytes | variable-precision, inexact | 15 decimal digits precision |
smallserial | 2 bytes | small autoincrementing integer | 1 to 32767 |
serial | 4 bytes | autoincrementing integer | 1 to 2147483647 |
bigserial | 8 bytes | large autoincrementing integer | 1 to 9223372036854775807 |
8.1.1. 整型
与MySQ类似PG中整型也是smallint,integer(int)和bigint类型,并且与MySQL一样基于范围,存储大小和性能之间实现最佳平衡考虑通常使用int(integer)整数类型,MySQL中往往自增主键用bigint,pg中当int类型取值不够时,也会用bigint代替。
如下integer类型插入1.1可以插入进去,但是存的值是整数1,四舍五入精度确实

postgres=# \d products; Table "public.products" Column | Type | Collation | Nullable | Default ------------+---------+-----------+----------+--------- product_no | integer | | | name | text | | | price | numeric | | | postgres=# insert into products values(1.1,'banana',1.2); INSERT 0 1 postgres=# select * from products; product_no | name | price ------------+--------+--------- 1 | Cheese | 1 | Cheese | 1 | Cheese | 1 | Cheese | 10.9890 1 | banana | 1.2

SQL仅指定整数类型integer(或int),smallint和bigint。 类型名称int2,int4和int8是扩展名,有些SQL数据库系统也使用这些扩展名,也就是说pg中int2是smallint的别名。
1 2 3 4 5 6 7 8 | postgres=# create table test (int_c int2); CREATE TABLE postgres=# postgres=# \d test; Table "public.test" Column | Type | Collation | Nullable | Default --------+----------+-----------+----------+--------- int_c | smallint | | | |
8.1.2. 精确浮点型
MySQL中称为精确浮点型,PG中原英文是Arbitrary Precision Numbers,翻译成中文是任意精度数,那么也好理解,decimal可以指定精确度,例如,数字23.5141的精度为6,小数位数为4。可以将整数视为小数位数为零,那么定义的时候即为decimal(6,4)或者NUMERIC(6,4)。实际存储空间类似于varchar(n),两个字节对于每组四个十进制数字,再加上三到八个字节的开销。

postgres=# create table f (money decimal,a float); CREATE TABLE postgres=# insert into f select 1.214151515151321313123213,1.214151515151321313123213; INSERT 0 1 postgres=# select * from f; money | a ----------------------------+------------------ 1.214151515151321313123213 | 1.21415151515132 (1 row) postgres=# \d f; Table "public.f" Column | Type | Collation | Nullable | Default --------+------------------+-----------+----------+--------- money | numeric | | | a | double precision | | |


postgres=# create table a ( a decimal(10,2)); CREATE TABLE postgres=# \d a; Table "public.a" Column | Type | Collation | Nullable | Default --------+---------------+-----------+----------+--------- a | numeric(10,2) | | | postgres=# insert into a values(1.23); INSERT 0 1 postgres=# insert into a values(1.234); INSERT 0 1 postgres=# insert into a values(1.2345); INSERT 0 1 postgres=# insert into a values(1.2); INSERT 0 1 postgres=# select * from a; a ------ 1.23 1.23 1.23 1.20 (4 rows) postgres=# insert into a values(123456789.2); ERROR: numeric field overflow DETAIL: A field with precision 10, scale 2 must round to an absolute value less than 10^8. postgres=# insert into a values(12345678.2); INSERT 0 1 postgres=# select * from a; a ------------- 1.23 1.23 1.23 1.20 12345678.20 (5 rows)

8.1.3. 浮点类型
real 和double precision类型是不精确的,实际上,这些类型通常是二进制浮点算术的IEEE标准754的实现(分别为单精度和双精度),只要底层处理器,操作系统和编译器支持它即可。存储钱之类的要求精度高的数据再次强调一定要用numeric,real和double 类型可以指定负无穷大,正无穷大值。

postgres=# create table abc (abc real); CREATE TABLE postgres=# \d abc Table "public.abc" Column | Type | Collation | Nullable | Default --------+------+-----------+----------+--------- abc | real | | | postgres=# update abc set abc = '-Infinity'; UPDATE 0 postgres=# select * from abc; abc ----- (0 rows) postgres=# insert into abc values (-10); INSERT 0 1 postgres=# insert into abc values ('-Infinity'); INSERT 0 1 postgres=# insert into abc values ('-Infinity'); INSERT 0 1 postgres=# select * from abc; abc ----------- -10 -Infinity -Infinity (3 rows)

PostgreSQL还支持SQL标准float和float(p)来指定不精确的数字类型。在这里,“p”以二进制数指定最小可接受精度。 PostgreSQL以float(1)到float(24)来表示real类型,而float(25)
到float(53)
表示double precision
。
1 2 3 4 5 6 7 8 | postgres=# create table float_test(a float (10),b float (30)); CREATE TABLE postgres=# \d float_test; Table "public.float_test" Column | Type | Collation | Nullable | Default --------+------------------+-----------+----------+--------- a | real | | | b | double precision | | | |
8.1.4. Serial 类型
MySQL中自增可以指定auto increment关键字,Oracle可以使用序列,PG与Oracle有些类似,本节描述了PostgreSQL特定自增列的方法。
数据类型smallserial,serial和bigserial不是真实类型,而仅仅是创建唯一标识符列的符号方便(类似于某些其他数据库支持的AUTO_INCREMENT属性)。 在当前的实现中,指定:

postgres=# create table test (id serial, money decimal); CREATE TABLE --或者 postgres=# CREATE SEQUENCE product_id_seq AS integer; CREATE SEQUENCE postgres=# CREATE TABLE product (id integer NOT NULL DEFAULT nextval('product_id_seq') primary key,country varchar(20)); CREATE TABLE postgres=# ALTER SEQUENCE product_id_seq OWNED BY product.id; ALTER SEQUENCE postgres=# insert into product(country) values('China'); INSERT 0 1 postgres=# insert into product(country) values('Japan'); INSERT 0 1 postgres=# select * from product; id | country ----+--------- 1 | China 2 | Japan (2 rows) postgres=# select nextval('product_id_seq'); nextval --------- 3 (1 row) postgres=# select nextval('product_id_seq'); nextval --------- 4 (1 row) postgres=# insert into product(country) values('USA'); INSERT 0 1 postgres=# select * from product; id | country ----+--------- 1 | China 2 | Japan 5 | USA (3 rows) postgres=# \d product; Table "public.product" Column | Type | Collation | Nullable | Default ---------+-----------------------+-----------+----------+------------------------------------- id | integer | | not null | nextval('product_id_seq'::regclass) country | character varying(20) | | | Indexes: "product_pkey" PRIMARY KEY, btree (id)

类型名称“ serial”和“ serial4”是等效的:都创建“ integer”类型的列。 类型名称“ bigserial”和“ serial8”的工作方式相同,不同之处在于它们创建了“ bigint”列。 如果您预计在表的生命周期内使用超过231个标识符,则应使用“ bigserial”。 类型名称“ smallserial”和“ serial2”的工作方式相同,只是它们创建了“ smallint”列。删除列时,将自动删除列上对应的序列。 您可以删除序列而不删除列,但是这将强制删除列默认表达式。
8.2. Monetary Types货币类型
money类型(货币类型)以固定的分数精度存储货币金额,见下表。 小数精度由数据库的lc_monetary设置确定。 表中显示的范围假设有两个小数位。 接受的输入格式有多种,包括整数和浮点文字,以及典型的货币格式,例如“ $ 1,000.00”。 输出通常采用后一种形式,但取决于语言环境。

postgres=# create table money_test( id bigint primary key, money money); CREATE TABLE postgres=# \d money_test; Table "public.money_test" Column | Type | Collation | Nullable | Default --------+--------+-----------+----------+--------- id | bigint | | not null | money | money | | | Indexes: "money_test_pkey" PRIMARY KEY, btree (id) postgres=# insert into money_test values (1 ,20); INSERT 0 1 postgres=# select * from money_test; id | money ----+-------- 1 | $20.00 (1 row)

Name | Storage Size | Description | Range |
---|---|---|---|
money | 8 bytes | currency amount | -92233720368547758.08 to +92233720368547758.07 |
由于此数据类型的输出对语言环境敏感,因此将“ money”数据加载到具有“ lc_monetary”不同设置的数据库中可能不起作用。 为了避免出现问题,在将转储恢复到新数据库之前,请确保“ lc_monetary”具有与转储数据库中相同或相等的值。
set lc_monetary='zh_CN'; show lc_monetary;
可以将“ numeric”,“ int”和“ bigint”数据类型的值强制转换为“ money”。 从“ real”和“ double precision”数据类型的转换可以通过首先转换为“ numeric”来完成,例如:
postgres=# SELECT '12.34'::float8::numeric::money; money -------- $12.34 (1 row)
但是,不建议这样做。 由于可能会舍入错误,因此不应使用浮点数来处理资金。
可以将“ money”值转换为“ numeric”而不会损失精度。 转换为其他类型可能会失去精度,并且必须分两个阶段完成:
SELECT '52093.89'::money::numeric::float8;
将“货币”值除以整数值的过程是将小数部分截断为零。 要获得四舍五入的结果,请除以浮点值,或将“ money”值转换为“ numeric”,然后除以,然后再返回至“ money”。 (最好避免使用后者,以免损失精度。)将“货币”值除以另一个“货币”值时,结果是“双精度”(即纯数字,而不是货币);
8.3.字符串类型
Name | Description |
---|---|
character varying(n) , varchar(n) | variable-length with limit |
character(n) , char(n) | fixed-length, blank padded |
text | variable unlimited length |
PostgreSQL提供了“text”文本类型,该类型存储任何长度的字符串。
短字符串(最多126个字节)的存储要求是1个字节加上实际字符串,如果是'character',则包括空格。较长的字符串的开销为4个字节,而不是1个字节。较长的字符串由系统自动压缩,因此对磁盘的物理需求可能会更少。非常长的值也存储在后台表中,这样它们就不会干扰对较短列值的快速访问。在任何情况下,可以存储的最长字符串约为1 GB。 (数据类型声明中允许n 的最大值小于该值。更改此值无用,因为对于多字节字符编码,字符和字节数可以如果您希望存储没有特定上限的长字符串,请使用不带长度说明符的“文本”或“字符变化”,而不是设置任意长度限制。)
这三种类型之间没有性能差异,除了使用空白填充类型时增加了存储空间,只不过存在长度受限,尽管在其他一些数据库系统中,“ char(n)”具有性能上的优势,但在PostgreSQL中却没有这种优势。实际上,“char(n)”通常是三个字符中最慢的一个,因为它会增加存储成本。在大多数情况下,应改用“text”或“varchar”。

postgres=# CREATE TABLE test1 (a character(4)); CREATE TABLE postgres=# postgres=# INSERT INTO test1 VALUES ('ok'); INSERT 0 1 postgres=# SELECT a, char_length(a) FROM test1; -- (1) a | char_length ------+------------- ok | 2 (1 row) postgres=# CREATE TABLE test2 (b varchar(5)); CREATE TABLE postgres=# INSERT INTO test2 VALUES ('ok'); INSERT 0 1 postgres=# postgres=# INSERT INTO test2 VALUES ('good '); INSERT 0 1 postgres=# postgres=# INSERT INTO test2 VALUES ('too long'); ERROR: value too long for type character varying(5) INSERT INTO test2 VALUES ('too long'::varchar(5)); -- explicit truncation SELECT b, char_length(b) FROM test2; b | char_length -------+------------- ok | 2 good | 5 too l | 5

PostgreSQL中还有另外两种定长字符类型。名称类型仅存在于内部系统目录中,用于存储标识符,不适合普通用户使用。 目前,它的长度定义为64个字节(63个可用字符加终止符),但应使用C源代码中的常量“ NAMEDATALEN”来引用。 该长度是在编译时设置的(因此对于特殊用途可以调整); 默认的最大长度可能会在将来的版本中更改。 “ char”类型(请注意引号)与“ char(1)”不同之处在于它仅使用一个字节的存储空间。 在系统目录中内部使用它作为一种简单的枚举类型。
Name | Storage Size | Description |
---|---|---|
"char" | 1 byte | single-byte internal type |
name | 64 bytes | internal type for object names |