UNVDB基础之数据类型
数据类型的使用及解释
字符类型
字符类型以文本形式存储数据,nvdb 提供了三种字符数据类型: CHAR
,VARCHAR
,和 TEXT
。
字符类型用法
下面说明了 unvdb 中的三种字符类型的用法:
CHAR(n)
存储固定长度的字符串,长度不足时,使用空白填充。VARCHAR(n)
存储具有长度限制的可变长度文本。VARCHAR
存储没有长度限制的可变长度文本。 它与TEXT
完全相同。TEXT
存储没有长度限制的可变长度文本。
CHAR(n)
和 VARCHAR(n)
最多可存储 n
字符。 VARCHAR
与 TEXT
完全相同。
对于限制了长度的字符类型来说,如果写入的内容超过了限制的长度,unvdb 采用如下的策略:
如果超出长度的部分只有空格,则多余的空格会被截断。
如果超出长度的部分不只是空格,则给出错误提示。
在 unvdb 中,三种字符类型之间没有性能差异,因此你只需要根据的需要选择合适的类型即可。通常您应该使用 TEXT
或者 VARCHAR
。
字符类型示例
这个示例说明了 CHAR
, VARCHAR
以及 TEXT
数据类型是如何工作的。
使用下面的语句创建一个新表用于测试:
CREATE TABLE test_character_type (char_1 CHAR(1),varchar_10 VARCHAR(10),txt TEXT);
CHAR 类型实例
使用下面的语句向表中插入一个新行超出 char_1
列长度的值:
INSERT INTO test_character_type (char_1) VALUES('OK') RETURNING *;
unvdb 发出错误:
ERROR: value too long for type character(1)
这是因为该 char_1
列的数据类型是 CHAR(1)
,我们试图在该列中插入一个包含 2 个字符的字符串: 'OK'
。
使用下面的语句向表中插入一个新行超出 char_1
列长度的值,超出的部分为空格:
INSERT INTO test_character_type (char_1)
VALUES('Y ')
RETURNING *;
char_1 | varchar_10 | txt
--------+------------+-----
Y | |
这里插入成功了。这是因为超出的部分是空格,unvdb自动截断了空格。
VARCHAR 类型实例
使用下面的语句向表中插入一个新行超出 varchar_10
列长度的值:
INSERT INTO test_character_type (varchar_10) VALUES('Hello World') RETURNING *;
unvdb 发出错误:
ERROR: value too long for type character varying(10)
这是因为该 varchar_10
列的数据类型是 VARCHAR(10)
,我们试图在该列中插入一个包含 11 个字符的字符串: 'Hello World'
。
使用下面的语句向表中插入一个新行超出 varchar_10
列长度的值,超出的部分为空格:
INSERT INTO test_character_type (varchar_10) VALUES('HelloWorld ') RETURNING *;
char_1 | varchar_10 | txt
--------+------------+-----
| HelloWorld |
(1 row)
这里插入成功了。这是因为超出的部分是空格,unvdb 自动截断了空格。
TEXT 类型实例
使用下面的语句向表中插入一个新行:
INSERT INTO test_character_type (txt) VALUES('TEXT column can store a string of any length') RETURNING txt;
txt
----------------------------------------------
TEXT column can store a string of any length
(1 row)
对于一个 TEXT
列,您可以插入任意长度的字符串。
整数类型
整数类型将内容存储为整数,unvdb 提供了三种整数数据类型: SMALLINT
,INTEGER
,和 BIGINT
。
下表展示了不同的整数类型的占用的字节数和数值范围:
类型 | 存储大小 | 最小值 | 最大值 |
---|---|---|---|
SMALLINT |
2 字节 | -32,768 | 32,767 |
INTEGER |
4 字节 | -2,147,483,648 | 2,147,483,647 |
BIGINT |
8 字节 | -9,223,372,036,854,775,808 | 9,223,372,036,854,775,807 |
注意,BIGINT
类型占用空间大,并且会降低数据库性能。
整数类型用法
要定义一个整数类型的列,请使用如下语法:
column_name {SMALLINT | INTEGER | BIGINT} column_constrait
注意, INT
是 INTEGER
的同义词,您可以使用 INT
代替 INTEGER
。
要定义一个整数类型的主键列,请使用如下语法:
column_name {SMALLINT | INTEGER | BIGINT} GENERATED ALWAYS AS IDENTITY PRIMARY KEY
要定义一个整数类型的标识列,请使用如下语法:
column_name {SMALLINT | INTEGER | BIGINT} GENERATED ALWAYS AS IDENTITY
要定义一个 SERIAL
列, 请使用如下语法:
column_name SERIAL PRIMARY KEY
注意, SMALLSERIAL
的内部类型为 SMALLINT
,SERIAL
的内部类型为 INTEGER
,BIGSERIAL
的内部类型为 BIGINT
。
整数类型实例
SMALLINT
类型实例
首先,使用下面的语句创建一个测试表:
CREATE TABLE test_smallint(name TEXT NOT NULL,age SMALLINT NOT NULL);
使用下面的语句插入两行数据:
INSERT INTO test_smallint (name, age) VALUES ('Tom', '23'), ('Lucy', 20) RETURNING *;
name | age
------+-----
Tom | 23
Lucy | 20
(2 rows)
注意, 虽然我们为整数列传入了一个字符类型的值 '23'
,unvdb 自动将其转成了数字并存储到数据库。
使用 INTEGER 列作为主键
通常, INTEGER
数据类型的标识列可以作为主键列:
CREATE TABLE test_int_pk(id INTEGER GENERATED ALWAYS AS IDENTITY PRIMARY KEY,name TEXT NOT NULL,age SMALLINT NOT NULL);
这里,id
列是主键列。它的类型是 INTEGER
,并且使用了 GENERATED ALWAYS AS IDENTITY
属性。
使用下面的语句插入和上面例子中相同的两条数据:
INSERT INTO test_int_pk (name, age) VALUES ('Tom', '23'), ('Lucy', 20) RETURNING *;
id | name | age
----+------+-----
1 | Tom | 23
2 | Lucy | 20
(2 rows)
NUMERIC 类型 - 存储高精度的数字
unvdb 提供了 NUMERIC
类型用来存储具有高精度要求的数字类型的数据,比如金额、里程、销量等。
对 NUMERIC
类型的值的计算通常比浮点类型慢,因此,如果对于精度没有要求,则应该使用浮点类型或者整数。
NUMERIC
语法
这是 NUMERIC
类型的语法:
NUMERIC(precision, scale)
NUMERIC(precision)
NUMERIC
说明:
precision
可选的。它是允许存储的数字的总位数,含小数部分的位数。
scale
可选的。小数部分的位数。
例如,数字 1234.567
具有 precision 7
和 scale 3
。
注意, DECIMAL
和 NUMERIC
是等价的。
NUMERIC
取值
NUMERIC
适用于存储含有大量数字的数值。它的小数点前最多 131072 位数字,小数点后最多 16383 位数字。
除了普通的数值之外,浮点类型还有几个特殊值:
'Infinity'
: 无穷大'-Infinity'
: 负无穷大'NaN'
: 非数字
其中, unvdb 支持 'Infinity'
和 '-Infinity'
。
NUMERIC
实例
基本用法
使用下面的语句创建一个表,名称为 test_numeric
:
CREATE TABLE test_numeric (numeric_5_2 NUMERIC(5,2),numeric_i NUMERIC);
使用下面的语句向表中插入一行数据:
INSERT INTO test_numeric (numeric_5_2) VALUES (1234.456) RETURNING numeric_5_2;
ERROR: numeric field overflow
DETAIL: A field with precision 5, scale 2 must round to an absolute value less than 10^3.
这里,因为数字 1234.234
超出了 NUMERIC(5,2)
的范围,因此 给出了一个错误。
下面的语句修改了插入的值,运行它重新尝试插入:
INSERT INTO test_numeric (numeric_5_2) VALUES (234.456) RETURNING numeric_5_2;
numeric_5_2
-------------
234.46
(1 row)
这里,由于 NUMERIC(5,2)
允许的小数位为 2,因此 234.456
被四舍五入为 234.46
。
Infinity 与 NaN
您不能向一个有限范围的 NUMERIC
写入 Infinity
与 -Infinity
, 否则 unvdb 将给出一个错误。比如:
INSERT INTO test_numeric (numeric_5_2) VALUES ('Infinity') RETURNING numeric_5_2;
ERROR: numeric field overflow
DETAIL: A field with precision 5, scale 2 cannot hold an infinite value.
下面的语句向类型为 NUMERIC
的列中写入了 Infinity
:
INSERT INTO test_numeric (numeric_i) VALUES ('Infinity') RETURNING numeric_i;
numeric_i
-----------
Infinity
(1 row)
下面的语句向类型为 NUMERIC
的列中写入了 -Infinity
:
INSERT INTO test_numeric (numeric_i) VALUES ('-Infinity') RETURNING numeric_i;
numeric_i
-----------
-Infinity
(1 row)
向类型为 NUMERIC
的列中写入了 NaN
:
INSERT INTO test_numeric (numeric_5_2) VALUES ('NaN') RETURNING numeric_5_2;
numeric_5_2
-------------
NaN
(1 row)
布尔类型
布尔类型是一种表示真或者假的数据类型。unvdb 数据库支持原生的布尔类型,您可以使用 BOOLEAN
或 BOOL
将一个列的类型定义为布尔值。
BOOLEAN
值
unvdb 对布尔值的处理非常灵活, true
, 'true'
, 't'
, 'yes'
, 'y'
, '1'
都被视为真, false
, 'false'
, 'f'
, 'no'
, 'n'
, '0'
都被视为假。 注意,这里所有的值不区分大小写。除了 true
和 false
,其他的都是字符类型。
unvdb 布尔类型允许 NULL
值。
请注意,在 SQL 标准中,一个布尔值只接受 TRUE
, FALSE
,和 NULL
。
BOOLEAN
实例
请按照以下步骤事件这个实例:
首先,使用以下语句创建一个名字为
test_boolean
的新表 来演示BOOLEAN
类型的用法。CREATE TABLE test_boolean (v VARCHAR NOT NULL,b BOOLEAN NOT NULL);
其次,使用以下语句向
test_boolean
表中插入一些示例数据。其中,我们对布尔值使用各种文字值。INSERT INTO test_boolean (v, b) VALUES (TRUE, TRUE), (FALSE, FALSE), ('t', 't'), ('f', 'f'), ('T', 'T'), ('F', 'F'), ('1', '1'), ('0', '0'), ('y', 'y'), ('n', 'n'), ('Y', 'Y'), ('N', 'N'), ('yes', 'yes'), ('no', 'no'), ('YES', 'YES'), ('NO', 'NO') RETURNING *;
v | b --------+--- true | t false | f t | t f | f T | t F | f 1 | t 0 | f y | t n | f Y | t N | f yes | t no | f YES | t NO | f (16 rows)
这里,我们可以看到,各种文字值都已经转为对应的布尔值了。
使用以下语句根据
BOOLEAN
类型的列检索数据行:SELECT * FROM test_boolean WHERE b = 'Y';
v | b ------+--- true | t t | t T | t 1 | t y | t Y | t yes | t YES | t (8 rows)
这里,我们在
WHERE
条件中对BOOLEAN
列使用了一个字符值'Y'
。该语句返回了所有b
为true
的行。 您还也可以使用't'
,'yes'
,'y'
, 或'1'
等值代替上面语句中的'Y'
。
您可以使用 BOOLEAN
或者 BOOL
保存布尔数据。unvdb 将 true
, 'true'
, 't'
, 'yes'
, 'y'
, '1'
视为真, false
, 'false'
, 'f'
, 'no'
, 'n'
, '0'
视为假。
DATE 数据类型介绍
unvdb支持 DATE
数据类型,以存储日期值。
unvdb DATE
数据类型使用 yyyy-mm-dd
格式存储日期值,并且每个日期值占用 4 个字节。
DATE
语法
要创建一个 DATE
数据类型的列,请使用如下语法:
column_name DATE column_constraint
您可以将 yyyy-mm-dd
格式的文本日期值插入到日期列中。
您可以使用类型转换将一个文本格式的日期值转为日期类型,如下:
'2022-08-30'::DATE
DATE
实例
使用下面的语句创建一个新表,名称为 test_date
:
CREATE TABLE test_date (id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,date_value DATE NOT NULL DEFAULT CURRENT_DATE);
该 test_date
表由两列组成:
该
id
列是标识每行的主键列,它是一个标识列。该
date_value
列是 DATE 数据类型,它不能为 null,并且具有以当前日期为默认值。
插入 DATE 数据
要将数据插入 DATE 列,您必须确保数据采用 yyyy-mm-dd
格式。以下 INSERT
语句向 test_date
表中插入几个新行。
INSERT INTO test_date (date_value)
VALUES
('2022-08-29'),
('2022-08-30'),
('2022-08-31')
RETURNING *;
id | date_value
----+------------
1 | 2022-08-29
2 | 2022-08-30
3 | 2022-08-31
(3 rows)
更新 DATE 数据
要更新 DATE 数据,使用该 UPDATE
语句并传入一个 yyyy-mm-dd
格式的值:
UPDATE test_date SET date_value = '2022-09-01' WHERE id = 3 RETURNING *;
id | date_value
----+------------
3 | 2022-09-01
(1 row)
在 WHERE 条件中使用 DATE 数据
您可以在 WHERE
子句中使用 DATE 列过滤数据。
要查找日期为 2022-08-30
,请使用以下语句:
SELECT * FROM test_date WHERE date_value = '2022-08-30';
id | date_value
----+------------
2 | 2022-08-30
(1 row)
您还可以查找日期小于 2022-09-01
的所有的行,如下:
SELECT * FROM test_date WHERE date_value < '2022-09-01';
id | date_value
----+------------
1 | 2022-08-29
2 | 2022-08-30
(2 rows)
输出指定格式的日期值
unvdb 提供了 TO_CHAR()
函数以按照指定格式输出日期值。 TO_CHAR()
函数接受两个参数。第一个参数是要格式化的日期值,第二个参数是格式。
要以 yyyy/mm/dd
格式显示日期,请使用以下语句:
SELECT
id,
to_char(date_value, 'yyyy/mm/dd')
FROM
test_date;
id | to_char
----+------------
1 | 2022/08/29
2 | 2022/08/30
3 | 2022/09/01
(3 rows)
日期函数
unvdb 提供了很多 日期 相关的函数。
要获取当前的日期,请使用 current_date
:
SELECT current_date;
current_date
--------------
2022-08-31
要计算距离某个日期的年龄,请是 age()
函数:
SELECT age('2001-01-01');
age
-------------------------
21 years 7 mons 30 days
要将一个指定格式的日期字符串转为日期值,请使用 to_date()
函数:
SELECT to_date('2022-08-31', 'YYYY-MM-DD');
to_date
------------
2022-08-31
要获取日期值中的年、月、日部分,请使用 date_part()
函数:
SELECT
date_part('year', current_date) "year",
date_part('month', current_date) "month",
date_part('day', current_date) "day";
year | month | day
------+-------+-----
2022 | 8 | 31
TIME 数据类型介绍
unvdb支持 TIME
数据类型,以存储时间值。
unvdb 存储 TIME
数据类型值使用 8 个字节。TIME
数据类型允许的范围是从 00:00:00
到 24:00:00
。
TIME
数据类型采用以下格式存储
HH:MI:SS.ssssss
其中:
HH
表示小时MI
表示分钟SS
表示秒ssssss
表示小数秒
TIME
语法
要创建一个 TIME
数据类型的列,请使用如下语法:
column_name TIME column_constraint
要将一个实际值插入到时间列中,您可以使用以下格式:
HH:MI:SS[.ssssss]
HHMISS[.ssssss]
MI:SS[.ssssss]
HH:MI
您可以使用类型转换将一个文本格式的时间值转为时间类型,如下:
'2022-08-30'::TIME
TIME
实例
使用下面的语句创建一个新表,名称为 test_time
:
CREATE TABLE test_time (id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,time_value TIME NOT NULL DEFAULT current_time);
该 test_time
表由两列组成:
该
id
列是标识每行的主键列,它是一个标识列。该
time_value
列是TIME
数据类型,它不能为 null,并且具有以当前时间为默认值。
插入 TIME 数据
要将数据插入 TIME 列,您必须确保数据采用正确的格式。以下 INSERT
语句向 test_time
表中插入几个新行。
INSERT INTO test_time (time_value) VALUES('10:10:10'),('10:10:11'),('10:10:12'),('10:10'),('101010'),('10:10:10.111111') RETURNING *;
id | time_value
----+-----------------
1 | 10:10:10
2 | 10:10:11
3 | 10:10:12
4 | 10:10:00
5 | 10:10:10
6 | 10:10:10.111111
(6 rows)
更新 TIME 数据
要更新 TIME 数据,使用该 UPDATE
语句并传入一个正确格式的值:
UPDATE test_time SET time_value = '10:10:09' WHERE id = 1 RETURNING *;
id | time_value
----+------------
1 | 10:10:09
(1 row)
在 WHERE 条件中使用 TIME 数据
您可以在 WHERE
子句中使用 TIME 列过滤数据。
要查找时间为 10:10:10
,请使用以下语句:
SELECT * FROM test_time WHERE time_value = '10:10:10';
id | time_value
----+------------
5 | 10:10:10
(1 row)
您还可以查找时间大于 10:10:10
的所有的行,如下:
SELECT * FROM test_time WHERE time_value > '10:10:10';
id | time_value
----+-----------------
2 | 10:10:11
3 | 10:10:12
6 | 10:10:10.111111
(3 rows)
输出指定格式的时间值
unvdb 提供了 TO_CHAR()
函数以按照指定格式输出时间值。 TO_CHAR()
函数接受两个参数。第一个参数是要格式化的时间值,第二个参数是格式。
要以 yyyy/mm/dd
格式显示时间,请使用以下语句:
SELECT id,to_char(time_value, 'HHMISS') FROM test_time;
id | to_char
----+---------
2 | 101011
3 | 101012
4 | 101000
5 | 101010
1 | 101009
(5 rows)
时间函数
unvdb 提供了很多 时间 相关的函数。
要获取当前的时间,请使用 current_time
:
SELECT current_time;
current_time
-------------------
17:18:49.94353+08
您可以使用 current_time
指定时间的小数秒精度,如下:
SELECT current_time(1);
current_time
---------------
17:19:00.3+08
要获取时间值中的时、分、秒部分,请使用 date_part()
函数:
SELECT date_part('hour', '10:11:12'::time) "hour",date_part('minute', '10:11:12'::time) "minute",date_part('second', '10:11:12'::time) "second";
hour | minute | second
------+--------+--------
10 | 11 | 12
时间戳数据类型
unvdb时间戳类型用来存储日期和时间组合的数据类型。unvdb 支持两种类型的时间戳数据类型,包括 TIMESTAMP
和 TIMESTAMPTZ
:
TIMESTAMP
全写为:TIMESTAMP WITHOUT TIME ZONE
, 用来存储没有时区的时间戳。TIMESTAMPTZ
全写为:TIMESTAMP WITH TIME ZONE
, 用来存储带时区的时间戳。
TIMESTAMP
和 TIMESTAMPTZ
都使用 8 个字节来存储时间戳值。
在 unvdb内部,TIMESTAMPTZ
类型的值被存储为它对应的 UTC 值。当您从数据库中查询 TIMESTAMPTZ
值时,unvdb 会将 UTC 值转换回数据库服务器、用户或当前数据库连接设置的时区的时间值。
时间戳语法
要创建一个不带时区的时间戳类型的列,请使用如下语法:
column_name TIMESTAMP column_constraint
要创建一个带时区的时间戳类型的列,请使用如下语法:
column_name TIMESTAMPTZ column_constraint
时间戳数据类型使用格式: YYYY-MM-DD HH:MI:SS[.ssssss]
。
时间戳实例
使用下面的语句创建一个新表,名称为 test_timestamp
:
CREATE TABLE test_timestamp (id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,timestamp_v TIMESTAMP NOT NULL DEFAULT now(),timestamptz_v TIMESTAMPTZ NOT NULL DEFAULT now());
该 test_timestamp
表由三列组成:
该
id
列是标识每行的主键列,它是一个标识列。该
timestamp_v
列是不带时区的时间戳类型,它不能为 null,并且默认为由now()
函数产生的当前时间。该
timestamptz_v
列是带时区的时间戳类型,它不能为 null,并且默认为由now()
函数产生的当前时间。
插入时间戳数据
要将数据插入时间戳列,您必须确保数据采用正确的格式。以下 INSERT
语句向 test_timestamp
表中插入一个新行。
INSERT INTO test_timestamp (timestamp_v, timestamptz_v)
VALUES
('2022-08-30 10:10:10', '2022-08-30 10:10:10'),
('2022-08-30', '2022-08-30')
RETURNING *;
id | timestamp_v | timestamptz_v
----+---------------------+------------------------
1 | 2022-08-30 10:10:10 | 2022-08-30 10:10:10+08
2 | 2022-08-30 00:00:00 | 2022-08-30 00:00:00+08
(2 rows)
虽然我们在插入时没有为 TIMESTAMPTZ
列指定带有时区的值,但是 unvdb 自动为此列的值添加了时区信息。
要查看当前会话的时区,请使用 SHOW TIMEZONE
语句,如下:
SHOW TIMEZONE;
TimeZone
---------------
Asia/Shanghai
(1 row)
您不能为时间戳类型指定一个时间类型的值,unvdb 将会给出一个错误,如下:
INSERT INTO test_timestamp (timestamp_v, timestamptz_v) VALUES ('10:10:10', '10:10:10') RETURNING *;
ERROR: invalid input syntax for type timestamp: "10:10:10"
LINE 2: VALUES ('10:10:10', '10:10:10')
更新 TIMESTAMP 数据
要更新 TIMESTAMP 数据,使用该 UPDATE
语句并传入一个正确格式的值:
UPDATE
test_timestamp
SET
timestamp_v = '2022-08-30 11:11:11',
timestamptz_v = '2022-08-30 11:11:11'
WHERE id = 1
RETURNING *;
id | timestamp_v | timestamptz_v
----+---------------------+------------------------
1 | 2022-08-30 11:11:11 | 2022-08-30 11:11:11+08
(1 row)
在 WHERE 条件中使用 TIMESTAMP 数据
您可以在 WHERE
子句中使用 TIMESTAMP 列过滤数据。
要查找日期为 2022-08-30
的所有的行,如下:
SELECT * FROM test_timestamp WHERE to_char(timestamp_v, 'YYYY-MM-DD') = '2022-08-30';
id | timestamp_v | timestamptz_v
----+---------------------+------------------------
2 | 2022-08-30 00:00:00 | 2022-08-30 00:00:00+08
1 | 2022-08-30 11:11:11 | 2022-08-30 11:11:11+08
(2 rows)
您还可以查找日期大于 2022-08-30
的所有的行,如下:
SELECT * FROM test_timestamp WHERE timestamp_v > '2022-08-30';
id | timestamp_v | timestamptz_v
----+---------------------+------------------------
1 | 2022-08-30 11:11:11 | 2022-08-30 11:11:11+08
(1 row)
输出指定格式的时间值
unvdb 提供了 TO_CHAR()
函数以按照指定格式输出时间值。 TO_CHAR()
函数接受两个参数。第一个参数是要格式化的时间值,第二个参数是格式。
要以 yyyy/mm/dd
格式显示时间,请使用以下语句:
SELECT id,to_char(timestamp_v, 'YYYY/MM/DD HH24:MI:SS'),to_char(timestamptz_v, 'YYYY/MM/DD HH24:MI:SS TZH') FROM test_timestamp;
id | to_char | to_char
----+---------------------+-------------------------
2 | 2022/08/30 00:00:00 | 2022/08/30 00:00:00 +08
1 | 2022/08/30 11:11:11 | 2022/08/30 11:11:11 +08
(2 rows)
时间戳函数
为了有效地处理时间戳数据,unvdb 提供了一些方便的函数。
要获取当前时间戳,请使用 now()
或者current_timestamp
,如下:
SELECT now(), current_timestamp;
now | current_timestamp
------------------------------+------------------------------
2022-09-02 10:14:14.06204+08 | 2022-09-02 10:14:14.06204+08
除此之外,您还可以使用 transaction_timestamp()
, statement_timestamp()
, localimestamp()
, 或 clock_timestamp()
获取当前的时间戳。
您可以使用 current_timestamp
指定时间戳的小数秒精度,如下:
SELECT current_timestamp, current_timestamp(2);
current_timestamp | current_timestamp
-------------------------------+---------------------------
2022-09-02 10:15:22.670007+08 | 2022-09-02 10:15:22.67+08
要获取时间值中的年、月、日、时、分、秒的值,请使用 date_part()
函数:
SELECT date_part('year', now()) "year",date_part('month', now()) "month",date_part('day', now()) "day",date_part('hour', now()) "hour",date_part('minute', now()) "minute",date_part('second', now()) "second";
year | month | day | hour | minute | second
------+-------+-----+------+--------+-----------
2022 | 9 | 2 | 10 | 17 | 14.520472
INTERVAL 数据类型介绍
INTERVAL
类型用于存储时间间隔值,比如 N 年 N 月 N 日 N 时 N 分 N 秒。时间间隔不是一个时间点,而是一个时间段。
INTERVAL
类型占用 16 个字节的存储空间,其取值范围从 -178000000 years
到 178000000 years
。
INTERVAL
语法
要定义一个unvdb INTERVAL
类型的值,请使用如下法:
@ INTERVAL [ fields ] [ (p) ]
说明:
@
是可选的。fields
定义一个时间段。您可以采用以下两种输入格式:quantity unit [quantity unit...] [direction]
其中,
quantity
是一个数字,可能有符号;unit
是microsecond
,millisecond
,second
,minute
,hour
,day
,week
,month
,year
,decade
,century
,millennium
中的值,或者他们的缩写或者复数形式;direction
可以是ago
或者空。例如:
INTERVAL '1 years 2 months 3 days 4 hours 5 minutes 6 seconds'
ISO 8601 时间间隔格式
P quantity unit [ quantity unit ...] [ T [ quantity unit ...]]
或者
P [ years-months-days ] [ T hours:minutes:seconds ]
其中,
unit
您可以使用以下表中的值:
| 缩写 | 含义 |
| ---- | --------------- |
| `Y` | 年 |
| `M` | 月 (日期部分) |
| `W` | 周 |
| `D` | 天 |
| `H` | 小时 |
| `M` | 分钟 (时间部分) |
| `S` | 秒 |
例如:
```shell
INTERVAL 'P1Y2M3DT4H5M6S'
INTERVAL 'P1-2-3T4:5:6'
```
p
是小数秒的精度。p
的允许范围是从 0 到 6。
比如, interval '1 years 2 months 3 days'
意思是 1 年 2 月零 3 天。
INTERVAL
输出格式
INTERVAL
类型的输出格式可以被设置为 sql_standard
,或 iso_8601
。
您可以使用 SET intervalstyle
命令设置INTERVAL
类型的输出格式。
下面的示例展示了不同的输出格式:
以下代表 6 years 5 months 4 days 3 hours 2 minutes 1 second
四种风格中的区间:
sql_standard
SET intervalstyle = 'sql_standard'; SELECT INTERVAL 'P1Y2M3DT4H5M6S';
interval ------------------ +1-2 +3 +4:05:06
interval ------------------------------- 1 year 2 mons 3 days 04:05:06
iso_8601
SET intervalstyle = 'iso_8601'; SELECT INTERVAL 'P1Y2M3DT4H5M6S';
interval ---------------- P1Y2M3DT4H5M6S
unvdb 区间相关的运算符和函数
算数运算
您可以将算术运算符(+
、 -
)应用于区间值,例如:
SELECT INTERVAL '1 day 12h 50m' + INTERVAL '10m';
?column?
----------------
1 day 13:00:00
您可以将算术运算符(+
、 -
)应用于时间值和区间值,例如:
SELECT
current_timestamp "Now",
current_timestamp - INTERVAL '10m'
AS "Ten minutes ago";
-[ RECORD 1 ]---+------------------------------
Now | 2022-09-02 16:08:29.933843+08
Ten minutes ago | 2022-09-02 15:58:29.933843+08
从 unvdb 间隔中提取数据
你可以使用 date_part()
函数从一个间隔值的提取指定的字段。下面语句提取间隔值中天数、小时数和分钟数:
SELECT date_part('day', INTERVAL '2 days 10 minutes') "day",date_part('hour', INTERVAL '2 days 10 minutes') "hour",date_part('minutes', INTERVAL '2 days 10 minutes') "minutes";
day | hour | minutes
-----+------+---------
2 | 0 | 10
转换时间值
unvdb 提供三个函数用于转换时间值:
justify_days()
将超过 30 天的天数转为月数。justify_hours()
]将超过 24 小时的小时数转为天数。justify_interval()
将超过 24 小时的小时数转为天数,并且将超过 30 天的天数转为月数。
比如:
SELECT justify_days(INTERVAL '1 year 40 days');
justify_days
----------------------
1 year 1 mon 10 days
SELECT justify_hours(INTERVAL '60 hours');
justify_hours
-----------------
2 days 12:00:00
SELECT justify_interval(INTERVAL '6000 hours');
justify_interval
------------------
8 mons 10 days
Array数组数据类型
unvdb 允许您使用数组数据类型存储一个多值的集合,比如,一些业余爱好,几个昵称等。
数组用法
和其他很多语言一样,在 unvdb 中,使用 data_type[]
表示一个数组类型,其中 data_type
是数组中元素的数据类型。比如, TEXT
的数组类型是 TEXT[]
, INTEGER
的数组类型是 INTEGER[]
, BOOLEAN
的数组类型是 BOOLEAN[]
,等等。
构造 unvdb 数组
要表示一个数组数据,您可以使用以下两种方法:
使用
ARRAY()
构造函数构造一个数组:ARRAY(elem1, elem2, ...)
比如,
ARRAY(1, 2, 3)
是一个整数数组。使用花括号构造一个 unvdb 数组:
'{elem1, elem2, ...}'::data_type[]
比如:
'{1, 2, 3}'::integer[]
是一个整数数组。
访问 unvdb 数组元素
要访问 unvdb 数组中的元素,您可以使用数组下标。默认情况下,unvdb 对数组元素使用从 1 开始的编号。这意味着第一个数组元素的下标是 1, 第二个数组元素的下表是 2,…。
定义 unvdb 数组列
要在 unvdb 数据库中定义一个数组列,请使用如下语法:
column_name data_type[] column_constraint
数组实例
为演示 unvdb 数组类型的用法,请使用以下 CREATE TABLE
语句创建 user_hobbies
表,其中 hobbies
列定义为文本数组。
CREATE TABLE user_hobbies (id INTEGER GENERATED ALWAYS AS IDENTITY PRIMARY KEY,name VARCHAR(50),hobbies TEXT[]);
其中, hobbies
列是一个一维数组,其中包含用户的各种业余爱好。
插入 unvdb 数组值
以下语句使用 ARRAY()
构造函数构造了一个文本数组,并向 user_hobbies
表中插入一个新行:
INSERT INTO user_hobbies (name, hobbies) VALUES ('Tom', ARRAY['Football', 'Basketball']) RETURNING *;
id | name | hobbies
----+------+-----------------------
1 | Tom | {Football,Basketball}
(1 row)
以下语句使用花括号构造了一个文本数组,并向 user_hobbies
表中插入一个新行:
INSERT INTO user_hobbies (name, hobbies)
VALUES ('Tim','{"Piano", "Violin", "Cello"}')
RETURNING *;
id | name | hobbies
----+------+----------------------
2 | Tim | {Piano,Violin,Cello}
(1 row)
查询数组数据
您可以使用 SELECT
语句查询数组数据,如下所示:
SELECT name,hobbies FROM user_hobbies;
name | hobbies
------+-----------------------
Tom | {Football,Basketball}
Tim | {Piano,Violin,Cello}
(2 rows)
您可以使用下标访问数组元素。比如,要获取用户的第一个业余爱好,请使用如下的语句:
SELECT name,hobbies[1] FROM user_hobbies;
name | hobbies
------+----------
Tom | Football
Tim | Piano
(2 rows)
在 unvdb 数组中搜索
要从 unvdb 数组中搜索是否包含某个指定的元素,请使用 ANY()
运算符。比如,要查找那些业余爱好为足球的同学,请使用以下查询:
SELECT name,hobbies FROM user_hobbies WHERE 'Football' = ANY (hobbies);
name | hobbies
------+-----------------------
Tom | {Football,Basketball}
(1 row)
修改 unvdb 数组
unvdb 允许使用数组下标修改数组中的每个元素,比如:
UPDATE user_hobbies SET hobbies[2] = 'Baseball' WHERE ID = 1 RETURNING *;
id | name | hobbies
----+------+---------------------
1 | Tom | {Football,Baseball}
(1 row)
您也可以更新整个数组,比如:
UPDATE user_hobbies SET hobbies = '{"Baseball"}' WHERE ID = 1 RETURNING *;
id | name | hobbies
----+------+------------
1 | Tom | {Baseball}
(1 row)
数组函数
unvdb 提供了很多数组相关的函数。下面是几个常用的 unvdb 数组函数:
array_append()
: 将指定的元素追加到指定的数组。array_cat()
: 将两个指定的数组合并为一个数组。array_length()
: 返回指定的数组中指定维度的长度。array_prepend()
: 将指定的元素添加到指定的数组的开头。array_replace()
: 在指定的数组中使用一个新元素替换指定的元素。array_to_string()
: 将数组中的所有元素使用分隔符连接起来。unnest()
:将指定的数组展开为一个行的集合。
例如:要将 hobbies
数组中的每一个业余爱好扩展为一行,请使用如下语句:
SELECT name,unnest(hobbies) FROM user_hobbies;
name | unnest
------+----------
Tim | Piano
Tim | Violin
Tim | Cello
Tom | Baseball
(4 rows)
JSON 数据类型介绍
本文介绍了在 unvdb 中如何使用 JSON 类型以及一些用于处理 JSON 数据的有用的函数。
JSON 是一种通用的、轻量级的数据传输格式,它可以表示复杂的、结构化的数据,但同时也易于阅读和编写。
JSON 简介
JSON 定义了以下几种类型的值:
对象
数组
字符串
数字
true
false
null
JSON 对象是一个键值对的组合。键是字符串类型的文本,值可以是上面定义的几种类型的任何一种。
JSON 数组是一些值的组合。其中的值可以是任意的以上一种类型的值。
一个 JSON 值可以是以上任意类型的值。
比如,以下是一些纯值的 JSON 值:
"a"
"abc"
"Hello World"
1
1.23
123.456
true
false
null
以下是一个 JSON 对象的示例:
{
"x": "Hollo World",
"y": { "a": 1, "b": true },
"z": [1, "a", true, false, null],
"o": null
}
以下是一个 JSON 数组的示例:
[1, "a", { "a": 1, "b": true }, [1, "a", true, false, null], null]
通常情况下,我们在传输数据的时使用 JSON 对象和 JSON 数组。
JSON 介绍
unvdb 支持两种 JSON 类型: JSON
和 JSONB
。他们的处理效率不同。 JSON
按文本保存输入数据,保留原始数据中的空格,重复键。 JSONB
则按照二进制保存输入数据,他会删除没必要的空格以及重复的键。
JSON 文本转为 JSON 类型
要将一个字符串的 JSON 文本转为 JSON 类型的值,您可以使用如下两种方法:
使用
JSON()
构造函数将 JSON 文本转为 JSON 类型的值:
json('[1, 2, 3]')
使用类型转换将 JSON 文本转为 JSON 类型的值:
'{"a": [1, 2, 3]}'::json
JSON 操作符
unvdb 提供了用于 JSON 数据的操作符,如下:
->
: 获取 JSON 数组的元素或者 JSON 对象中的字段,返回值为 JSON 类型的值。->>
: 获取 JSON 数组的元素或者 JSON 对象中的字段,返回值为文本。#>
: 获取指定路径的值,返回值为 JSON 类型的值。#>>
: 获取指定路径的值,返回值为文本。
JSON 实例
使用下面的语句创建一个新表,名称为 login_logs
:
CREATE TABLE login_logs (id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,detail JSON NOT NULL);
该 login_logs
表由两列组成:
该
id
列是标识每行的主键列,它是一个标识列。该
detail
是 JSON 数据类型。
插入 JSON 数据
要将数据插入 JSON 列,您必须确保数据采用有效的 JSON 格式。以下 INSERT
语句向 login_logs
表中插入几个新行。
INSERT INTO login_logs (detail)
VALUES
('{ "name": "Tom", "address": {"ip": "192.168.1.23","country": "US"}}'),
('{ "name": "Tim", "address": {"ip": "192.168.1.24","country": "US"}}'),
('{ "name": "Jim", "address": {"ip": "192.168.1.25","country": "UK"}}');
这里, detail
列中的 JSON 值是 JSON 对象,其中包含两个键:
name
是登陆用户的名称。address
是登陆用户的地址,它也是一个 JSON 对象,包含了两个成员:
ip
是登陆用户的 IP 地址。country
是登陆用户所在的国家。
查询 JSON 数据
要查询 JSON 数据,请使用该 SELECT
语句:
SELECT * FROM login_logs;
id | detail
----+---------------------------------------------------------------------
1 | { "name": "Tom", "address": {"ip": "192.168.1.23","country": "US"}}
2 | { "name": "Tim", "address": {"ip": "192.168.1.24","country": "US"}}
3 | { "name": "Jim", "address": {"ip": "192.168.1.25","country": "UK"}}
(3 rows)
如果您想显示 JSON 对象内部的字段,请使用 ->
和 ->>
操作符。 ->
返回的值是 JSON 类型, ->>
返回的值是文本类型。
以下查询分别使用两个运算符 ->
和 ->>
以 JSON 的形式获取所有登陆用户的名称:
SELECT detail -> 'name' AS name_json,detail ->> 'name' AS name_text FROM
login_logs;
name_json | name_text
-----------+-----------
"Tom" | Tom
"Tim" | Tim
"Jim" | Jim
(3 rows)
要获取所有登陆用的国家和 IP,请使用下面的语句:
SELECT detail -> 'address' ->> 'country' as country,detail -> 'address' ->> 'ip' as ip FROM login_logs;
country | ip
---------+--------------
US | 192.168.1.23
US | 192.168.1.24
UK | 192.168.1.25
(3 rows)
首先 detail -> 'address'
将地址作为 JSON 对象返回。然后 detail -> 'address' ->> 'country'
将所有国家作为文本返回。
在 WHERE 条件中使用 JSON 运算符
您可以在 WHERE
子句中使用 JSON 运算符来过滤返回的行。
例如,要找出所有来自 US 的登陆用户,清使用以下查询:
SELECT detail ->> 'name' AS name,detail -> 'address' ->> 'country' AS country FROM login_logs WHERE detail -> 'address' ->> 'country' = 'US';
name | country
------+---------
Tom | US
Tim | US
(2 rows)
unvdb JSON 函数
unvdb 提供了很多 JSON 相关的函数,如下:
array_to_json()
: 将一个 SQL 数组转为 JSON 数组并返回。json_array_elements()
: 将顶层 JSON 数组扩展为一个 JSON 值的集合。json_array_length()
: 返回一个指定的 JSON 数组的长度。json_build_array()
: 从可变的参数列表中创建一个可能是异构类型的 JSON 数组。json_each()
: 将一个指定的 JSON 对象扩展为一个键值对的集合。json_extract_path()
: 从一个指定的 JSON 值中提取指定的路径的值。json_object_keys()
: 返回指定的 JSON 对象中的顶层键的集合。json_object()
: 从一个文本数组构建一个 JSON 对象,或者从两个分别作为键和值的数组构建一个 JSON 对象。json_to_record()
: 将指定的最顶层的 JSON 对象扩展为一个在 AS 子句中定义的具有符合类型的行。json_to_recordset()
: 将指定的最顶层的 JSON 数组(元素为对象)扩展为一个在 AS 子句中定义的具有符合类型的行的集合。json_typeof()
: 以字符串的形式返回指定的 JSON 值的类型。row_to_json()
: 将一个 SQL 复合类型的值转为 JSON 对象并返回。to_json()
: 将一个 SQL 值转为 JSON 值并返回。
UUID 数据类型介绍
UUID 是一种通用唯一标识符,它由 32 为十六进制数字以及连字符组成。
与 SERIAL
,标识列,和 序列 相比, UUID 具有全局的唯一性,而不是数据库中的唯一性。 UUID 更适合在集群环境中作为唯一标识符。
unvdb 支持 UUID 数据类型,以存储 UUID 数据。
生成 UUID 值
要在 unvdb 中生成 UUID,请使用 gen_random_uuid()
函数,如下:
SELECT gen_random_uuid();
gen_random_uuid
--------------------------------------
d1f7b7c1-c0b6-4707-aa17-5055b09b3ae8
(1 row)
gen_random_uuid()
函数生成一个 v4 版本的 UUID,要生成其他版本的 UUID,请使用 uuid-ossp
模块,并使用它的函数:
uuid_generate_v1()
uuid_generate_v1mc()
uuid_generate_v3()
uuid_generate_v4()
uuid_generate_v5()
有关 UUID 生成函数的更多信息,请查看[uuid-ossp模块文档。
unvdb UUID 实例
在本示例中,您将创建一个 fruits
表,其主键是 UUID 数据类型。
使用以下语句创建 fruits
表:
CREATE TABLE fruits (id UUID DEFAULT gen_random_uuid() PRIMARY KEY,name VARCHAR NOT NULL);
在 fruits
表中, id
列的数据类型是 UUID
,并且由 gen_random_uuid()
函数提供默认值。
使用下面的语句插入一些数据到 fruits
表中:
INSERT INTO fruits (name) VALUES ('Apple'),('Peach'),('Banana') RETURNING *;
id | name
--------------------------------------+--------
980dd890-f7fe-4fff-999d-873516108b2e | Apple
617c7809-cec6-44aa-9ce3-59a988e5bf35 | Peach
98edf248-42a2-496d-9b4a-16472f6f0a00 | Banana
(3 rows)
如您所见,该 id
列已由 gen_random_uuid()
函数生成的 UUID 值填充。
unvdb HSTORE 数据类型介绍
HSTORE
数据类型用于存储键值对类型的数据。
unvdb 允许您使用 HSTORE
类型存储键值对数据类型,类似于 JSON 对象。
unvdb HSTORE
数据类型很适合存储无规则的字典值,比如电子产品的属性,服装的规格等。
unvdb HSTORE
数据类型在 hstore 模块中实现。要使用 unvdb HSTORE
类型,请使用如下语句启用 unvdb hstore 扩展:
CREATE EXTENSION hstore;
unvdb HSTORE
语法
要创建一个 HSTORE
数据类型的列,请使用如下语法:
column_name HSTORE column_constraint
HSTORE
数据类型的值采用如下的格式:
"key1=>value1"[, "key2=>value2", ...]
这里:
"key1=>value1"
是一个键值对。 如果键和值中不包含空格,可以省略双引号。多个键值对之间使用逗号分隔。
键和值都是文本值。
HSTORE
实例
使用下面的语句创建一个新表,名称为 product
:
CREATE TABLE product (id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,product_name VARCHAR NOT NULL,attributes HSTORE);
product
表存储一个在线商城的产品,它由三列组成:
id
列是标识每行的主键列,它是一个标识列。product_name
列存储产品的名称,它的类型是VARCHAR
。attributes
列是HSTORE
数据类型,它不能为 null。
产品的属性是多样的,很适合使用 HSTORE
数据类型,比如:
电脑产品具有 CPU,内存,硬盘,品牌,外观等属性
服装产品具有 季节,款式,性别,品牌,颜色等属性。
插入 HSTORE
数据
要将数据插入 HSTORE
列,您必须确保数据采用正确的格式。以下 INSERT
语句向 product
表中插入几个新行。
INSERT INTO product (product_name, attributes) VALUES ('Computer A', 'CPU=>2.5, Memory=>16G, Disk=>1T'),('Shirt B', 'Season=>Spring, Style=>Business, Color=>White') RETURNING *;
id | product_name | attributes
----+--------------+-----------------------------------------------------------
1 | Computer A | "CPU"=>"2.5", "Disk"=>"1T", "Memory"=>"16G"
2 | Shirt B | "Color"=>"White", "Style"=>"Business", "Season"=>"Spring"
(2 rows)
查询 HSTORE
数据
要查询 HSTORE
数据,请使用如下 SELECT
语句:
SELECT * FROM product;
id | product_name | attributes
----+--------------+-----------------------------------------------------------
1 | Computer A | "CPU"=>"2.5", "Disk"=>"1T", "Memory"=>"16G"
2 | Shirt B | "Color"=>"White", "Style"=>"Business", "Season"=>"Spring"
(2 rows)
如果要查询 HSTORE
数据特定的键值,请使用 ->
运算符或者 column_name['key_name']
语法,如下:
SELECT id,product_name,attributes -> 'Memory' memory,attributes['Disk'] disk FROM product;
id | product_name | memory | disk
----+--------------+--------+--------
1 | Computer A | 16G | 1T
2 | Shirt B | <null> | <null>
(2 rows)
要在 WHERE
条件中使用 HSTORE
数据的键值,请使用 column_name['key_name']
语法:
SELECT * FROM product WHERE attributes['Memory'] = '16G';
id | product_name | attributes
----+--------------+---------------------------------------------
1 | Computer A | "CPU"=>"2.5", "Disk"=>"1T", "Memory"=>"16G"
(1 row)
要检查 HSTORE
数据中是否包含一个特定的键值,请使用 ?
运算符,如下:
SELECT * FROM product WHERE attributes ? 'Color';
id | product_name | attributes
----+--------------+-----------------------------------------------------------
2 | Shirt B | "Color"=>"White", "Style"=>"Business", "Season"=>"Spring"
(1 row)
或者使用 IS NOT NULL
运算符,如下:
SELECT * FROM product WHERE attributes['Color'] IS NOT NULL;
id | product_name | attributes
----+--------------+-----------------------------------------------------------
2 | Shirt B | "Color"=>"White", "Style"=>"Business", "Season"=>"Spring"
(1 row)
将键值对添加到 HSTORE
数据
要将键值对添加到 HSTORE
数据,使用该 UPDATE
语句:
UPDATE product SET attributes['Brand'] = 'HP' WHERE id = 1 RETURNING *;
id | product_name | attributes
----+--------------+------------------------------------------------------------
1 | Computer A | "CPU"=>"2.5", "Disk"=>"1T", "Brand"=>"HP", "Memory"=>"16G"
(1 row)
删除 HSTORE
数据中的键值对
要从 HSTORE
数据中删除已有的键值对,使用 UPDATE
语句 和 delete()
函数:
UPDATE product SET attributes = delete(attributes, 'brand') WHERE id = 1 RETURNING *;
id | product_name | attributes
----+--------------+---------------------------------------------
1 | Computer A | "CPU"=>"2.5", "Disk"=>"1T", "Memory"=>"16G"
(1 row)
更新 HSTORE
数据中的键值
要更新 HSTORE
数据中的键值,使用该 UPDATE
语句:
UPDATE product SET attributes['Brand'] = 'Dell' WHERE id = 1 RETURNING *;
id | product_name | attributes
----+--------------+--------------------------------------------------------------
1 | Computer A | "CPU"=>"2.5", "Disk"=>"1T", "Brand"=>"Dell", "Memory"=>"16G"
(1 row)
枚举数据类型
枚举类型是是一组有序的常量值的集合。比如,您可以使用枚举类型用作订单的状态值。
如果没有枚举类型,您可能使用整数 1, 2, 3 ...
或者字符串表示,但是很容易带来错误,比如书写错误等。用了枚举类型之后,数据库可以保证不能输入错误的值。
创建 unvdb 枚举值
要使用枚举值,您需要使用 CREATE TYPE
语句创建一个自定义的枚举值。
这里是创建枚举类型的语法:
CREATE TYPE name AS ENUM (
label_1
[, label_2, ... ]
);
其中,
name
是要创建的枚举类型的名称。label_1
,label_2
是枚举类型中的常量值。
枚举类型实例
首先,使用下面的语句创建一个表示星期的枚举类型:
CREATE TYPE my_week AS ENUM ('Monday','Tuesday','Wednesday','Thursday','Friday','Saturday','Sunday');
然后,使用下面的语句创建一个每天销售明细表,
CREATE TABLE week_day_sales (id integer GENERATED ALWAYS AS IDENTITY PRIMARY KEY,week_day my_week NOT NULL,sales integer NOT NULL);
然后,使用下面的语句插入几个新行:
INSERT INTO week_day_sales (week_day, sales)
VALUES
('Monday', 110),
('Tuesday', 120),
('Wednesday', 130),
('Thursday', 140),
('Friday', 150),
('Saturday', 160),
('Sunday', 170),
('Monday', 210),
('Tuesday', 220),
('Wednesday', 230),
('Thursday', 240),
('Friday', 250),
('Saturday', 260),
('Sunday', 270);
如果您向枚举列插入一个错误的值,unvdb 将给出一个错误:
INSERT INTO week_day_sales (week_day, sales) VALUES ('Error', 110);
ERROR: invalid input value for enum my_week: "Error"
LINE 2: VALUES ('Error', 110);
下面的语句检索 week_day_sales
表的所有的行:
SELECT * FROM week_day_sales;
id | week_day | sales
----+-----------+-------
1 | Monday | 110
2 | Tuesday | 120
3 | Wednesday | 130
4 | Thursday | 140
5 | Friday | 150
6 | Saturday | 160
7 | Sunday | 170
8 | Monday | 210
9 | Tuesday | 220
10 | Wednesday | 230
11 | Thursday | 240
12 | Friday | 250
13 | Saturday | 260
14 | Sunday | 270
(14 rows)
要按照枚举类型的值的顺序排序,请使用下面的语句:
SELECT * FROM week_day_sales ORDER BY week_day;
id | week_day | sales
----+-----------+-------
1 | Monday | 110
8 | Monday | 210
2 | Tuesday | 120
9 | Tuesday | 220
3 | Wednesday | 130
10 | Wednesday | 230
4 | Thursday | 140
11 | Thursday | 240
5 | Friday | 150
12 | Friday | 250
6 | Saturday | 160
13 | Saturday | 260
7 | Sunday | 170
14 | Sunday | 270
(14 rows)
枚举函数
unvdb 提供了几个用于枚举类型的函数:
enum_first()
函数返回由参数指定的枚举类型的第一个枚举值。enum_last()
函数返回由参数指定的枚举类型的最后一个枚举值。enum_range()
函数返回由参数指定的枚举类型的所有枚举值,或者指定的范围内的枚举值。
范围 (Range) 数据类型介绍
范围 (Range) 是表示某些元素类型的值的区间的数据类型。比如 一个整数的范围可以表示一组人的年龄的范围, 以及一个时间的范围可以表示一个会议室被保留的时间段。
范围值是一个区间值,使用 [
, ]
, (
, )
表示:
[
表示范围的开始,包含起始值。]
表示范围的结束,包含结束值。(
表示范围的开始,不包含起始值。)
表示范围的结束,不包含结束值。
下面是是几个范围的示例:
[a,b]
-a
和b
之间的值,包含a
和b
。(a,b)
-a
和b
之间的值,不包含a
和b
。[a,b)
-a
和b
之间的值,包含a
,不包含b
。(a,b]
-a
和b
之间的值,不包含a
,包含b
。[a,)
-a
和 大于a
的值。(a,)
- 大于a
的值。(,b]
-b
和 小于b
的值。(,b)
- 小于b
的值。
Multirange 类型,它是 Range 类型的集合。表示方法为: { range_1, range_2, ...}
。
每一个 Range 类型都有其对应的 Multirange 类型。
unvdb 内置的 Range 类型
下表展示了 unvdb内置的范围类型:
Range | 说明 | Multirange |
---|---|---|
int4range |
integer 的范围 |
int4multirange |
int8range |
bigint 的范围 |
int8multirange |
numrange |
numeric 的范围 |
nummultirange |
tsrange |
timestamp without time zone 的范围 |
tsmultirange |
tstzrange |
timestamp with time zone 的范围 |
tstzmultirange |
daterange |
date 的范围 |
datemultirange |
Range 运算符和函数
下表展示了 unvdb 一些用于范围类型的运算符:
运算符 | 说明 |
---|---|
@> |
检查第一个操作数(范围)是否包含第二个操作数(范围或者元素) |
<@ |
检查第二个操作数(范围)是否包含第一个操作数(范围或者元素) |
&& |
检查两个范围是否有重合的部分 |
<< |
检查第一个范围是否在第二个范围的左侧 |
>> |
检查第一个范围是否在第二个范围的右侧 |
&< |
检查第一个范围是否延伸到第二个范围的右侧 |
&> |
检查第一个范围是否延伸到第二个范围的左侧 |
-|- |
检查两个范围是否是相邻的 |
+ |
计算两个范围的合集 |
* |
计算两个范围的交集 |
- |
计算两个范围的差集 |
这些操作数同样适合 Multirange 类型的数据。
同时, unvdb 为 Range 和 Multirange 数据类型提供了许多有用的[\函数,如下:
isempty()
函数检查一个给定的范围值是否为空。lower_inc()
)函数检查一个给定范围的下限是否是包含在内的。lower_inf()
函数检查一个给定范围的下限是否是无限。lower()
函数返回一个给定范围或者多值范围的下限值。multirange()
函数返回一个包含了给定范围的多值范围。range_merge()
函数计算包含了所有范围或者整个多值范围的最小范围。unnest()
函数将一个多值范围值展开为范围值的集合。upper_inc()
函数检查一个给定范围的上限是否是包含在内的。upper_inf()
函数检查一个给定范围的上限是否是无限。upper()
函数返回一个给定范围或者多值范围的上限。
Range 实例
下面是一些 unvdb Range 和 Multirange 的实例。
要检查一个范围是否包含另一个范围,请使用以下语句:
SELECT '[1,9]'::int4range @> '[3,9]'::int4range;
?column?
----------
t
要检查一个范围是否包含一个值,请使用以下语句:
SELECT '[1,9]'::int4range @> 3;
?column?
----------
t
要检查一个 Multirange 值是否包含一个范围值,请使用以下语句:
SELECT '{[1,5], [7, 9]}'::int4multirange @> '[3,4]'::int4range;
?column?
----------
t
自定义范围
除了使用 unvdb内置的范围类型,您还可以使用 CREATE TYPE
语句创建自己的范围类型。
这是创建自定义范围类型的语法:
CREATE TYPE name AS RANGE (
SUBTYPE = subtype
[ , SUBTYPE_OPCLASS = subtype_operator_class ]
[ , COLLATION = collation ]
[ , CANONICAL = canonical_function ]
[ , SUBTYPE_DIFF = subtype_diff_function ]
[ , MULTIRANGE_TYPE_NAME = multirange_type_name ]
)
假设,您要创建一个时间 (time
) 的范围类型 my_time_range
,请使用以下语句:
CREATE TYPE my_time_range AS RANGE (SUBTYPE = time);
下面的语句使用了刚刚创建的范围类型 my_time_range
:
SELECT my_time_range('10:00:00','12:00:00') @> '11:00:00'::time;
?column?
----------
t
用户自定义类型教程
unvdb 允许您使用 CREATE DOMAIN
和 CREATE TYPE
语句创建用户定义数据类型。
使用
CREATE DOMAIN
您能基于已有的类型创建一个子类型,并可以为其添加一些约束,目前支持 3 中约束:NULL
,NOT NULL
,CHECK
。使用
CREATE TYPE
您能创建复合类型,枚举类型,或RANGE
类型。
CREATE DOMAIN
语法
CREATE DOMAIN
语句用于创建一个域。 域是具有可选约束的数据类型。
要基于一个现有的数据类型创建一个域,请按照如下语法使用 CREATE DOMAIN
语句:
CREATE DOMAIN name [ AS ] data_type
[ COLLATE collation ]
[ DEFAULT expression ]
[ { NOT NULL | NULL | CHECK (expression) } ]
name
要创建的域(子类型)的名称。
data_type
域的基础数据类型。
collation
域的排序规则,它是可选的。
DEFAULT expression
使用此数据类型的列的默认值。
CHECK (expression)
使用此数据类型的列的
CHECK
约束。
比如,要创建一个默认值为空字符串且不能为 NULL 的 TEXT
类型 not_null_text
,请使用以下语句:
CREATE DOMAIN not_null_text
AS TEXT
DEFAULT '';
下面的 CREATE TABLE
语句使用此 not_null_text
类型:
CREATE TABLE test_domain (
col1 not_null_text,
col2 not_null_text
);
CREATE TYPE
unvdb CREATE TYPE
语句用于创建一个复合类型,枚举类型,或 RANGE
类型。
语法
以下语法使用 CREATE DOMAIN
语句用于创建一个复合类型:
CREATE TYPE name AS (
field_name1 data_type
[, field_name2 data_type, ...]
);
以下语法使用 CREATE DOMAIN
语句用于创建一个枚举类型:
CREATE TYPE name AS ENUM (
label_1
[, label_2, ... ]
);
以下语法使用 CREATE DOMAIN
语句用于创建一个 RANGE
类型:
CREATE TYPE name AS RANGE (
SUBTYPE = subtype
[ , SUBTYPE_OPCLASS = subtype_operator_class ]
[ , COLLATION = collation ]
[ , CANONICAL = canonical_function ]
[ , SUBTYPE_DIFF = subtype_diff_function ]
[ , MULTIRANGE_TYPE_NAME = multirange_type_name ]
);
创建复合类型实例
使用下面的语句创建一个自定义类型:
CREATE TYPE address as (country TEXT, city TEXT);
上面的语句创建了一个名字为 address
自定义类型,它有两个字段: country
和 city
字段,他们都是 TEXT
类型。
下面的语句将一个复杂的 JSON 对象转为 SQL 行:
SELECT * FROM json_to_record('{"name": "Tom", "age": 20, "address": {"country": "CN", "city": "BeiJing"}}') AS x(name TEXT, age INT, address address);
name | age | address
------+-----+--------------
Tom | 20 | (CN,BeiJing)
(1 row)
创建枚举类型实例
使用 CREATE TYPE
语句创建一个枚举类型 my_color
:
CREATE TYPE my_color AS ENUM ('yellow','red','blue','green','white','black');
使用 enum_first()
函数 返回 my_color
中的第一个枚举值:
SELECT enum_first(null::my_color);
enum_first
------------
yellow
使用 unvdb enum_last()
函数返回 my_color
中的最后一个枚举值:
SELECT enum_last(null::my_color);
enum_last
-----------
black
unvdb 允许您使用 CREATE DOMAIN
和 CREATE TYPE
语句创建用户定义数据类型。
使用 CREATE DOMAIN
您能基于已有的类型创建一个子类型,并可以为其添加 NULL
, NOT NULL
, 或 CHECK
约束。
使用 CREATE TYPE
您能创建复合类型,枚举类型,或 RANGE
类型。