1. 引言

1.1. 编写目的

提供了与 Oracle 数据库兼容的特性。 这些特性使您能够轻松迁移到 LightDB 并减少重新配置应用程序的成本。 下表列出了与 Oracle 数据库兼容的特性。

1.2. 预期读者

数据库管理员 开发工程师 测试工程师 技术支持工程师 解决方案架构师 产品经理 技术架构师

1.3. 参考文献

《LightDB-X参考手册》《oracle 官方文档》

2. GUC参数

2.1. lightdb_syntax_compatible_type

含义:

该参数显示了当前实例安装时指定的兼容模式,当创建库时不指定兼容模式,则创建出来的库兼容模式即遵循该参数。

参数:

实例级别,有效值为oracle、mysql、off,lightdb安装时默认值为off(即postgres模式);

示例:

lightdb@testdb1=# show lightdb_syntax_compatible_type ;
        lightdb_syntax_compatible_type
        --------------------------------
        Oracle
        (1 row)

        lightdb@testdb1=#
        lightdb@testdb1=# create database db1;
        NOTICE:  auto create user "db1" success
        CREATE DATABASE
        lightdb@testdb1=#
        lightdb@testdb1=# \c db1
        You are now connected to database "db1" as user "lightdb".
        compatible type: oracle

2.2. lightdb_dblevel_syntax_compatible_type

含义:

该参数显示了当前库的兼容模式,通过在创建库时指定参数LIGHTDB_SYNTAX_COMPATIBLE_TYPE来设置兼容模式。不同兼容模式的库可以在同一实例下共存。

参数:

库级别,有效值为oracle、mysql、off。

示例:

lightdb@testdb1=# show lightdb_dblevel_syntax_compatible_type ;
        lightdb_dblevel_syntax_compatible_type
        ----------------------------------------
        MySql
        (1 row)

        lightdb@testdb1=#
        lightdb@testdb1=# create database db2 with LIGHTDB_SYNTAX_COMPATIBLE_TYPE = oracle;
        NOTICE:  auto create user "db2" success
        CREATE DATABASE
        lightdb@testdb1=#
        lightdb@testdb1=# \c db2
        You are now connected to database "db2" as user "lightdb".
        compatible type: oracle
        lightdb@db2=#
        lightdb@db2=# show lightdb_dblevel_syntax_compatible_type ;
        lightdb_dblevel_syntax_compatible_type
        ----------------------------------------
        Oracle
        (1 row)

2.3. lightdb_ascii_zero_store_value

含义:

当兼容模式被设置为oracle或mysql,且该参数设置为非零ASCII码值, ASCII 码值 E’0’ 以及 CHR(0) 的值等于 ASCII 码值?lightdb_ascii_zero_store_value,如果通过JDBC的绑定参数与服务端交互,文本类型的参数中ASCII码值 ‘0’ 由 ASCII 码值?lightdb_ascii_zero_store_value?在服务器端被替换,libpq同样场景下,值替换发生在libpq这一端。 注意,如果ASCII码值 ‘0’ 由 ASCII 码值?lightdb_ascii_zero_store_value替换,替换后此值在系统中的行为与 ASCII 码值?lightdb_ascii_zero_store_value?相同,比如,比较操作,concat函数调用,length函数调用,等其它接受字符输入参数的函数。

参数:

库级别,取值范围为0到32,包含0,32,数据库创建时指定,创建成功后不能被修改;

示例:

create?database?oradb?with?lightdb_ascii_zero_store_value 20 lightdb_syntax_compatible_type?'oracle';

        lightdb@oradb=#?create?table?t00(a?char(1), b?char(2));
        CREATE?TABLE
        lightdb@oradb=#?insert?into?t00(a,b)?values(E'\0',E'\0');
        INSERT?0 1
        lightdb@oradb=#?insert?into?t00(a,b)?values(chr(0),chr(0));
        INSERT?0 1
        lightdb@oradb=#
        lightdb@oradb=#?select?*?from?t00;
        ??a?? |?? b
        ----+-------
        ?\x14 | \x14
        ?\x14 | \x14
        (2?rows)

        lightdb@oradb=#?select?*?from?t00?where?a=E'\0';
        ??a?  ? |?? b
        ------+-------
        ?\x14 | \x14
        ?\x14 | \x14
        (2?rows)
        ?
        lightdb@oradb=#?UPDATE?t00?SET?b='a'?where?a=E'\0'?LIMIT 1;
        UPDATE?1
        lightdb@oradb=#?select?*?from?t00;
        ??a?? |?? b
        ------+-------
        ?\x14 | \x14
        ?\x14 | a
        (2?rows)
        ?
        lightdb@oradb=#?delete?from?t00?where?a=E'\0';
        DELETE?2
        lightdb@oradb=#?select?*?from?t00;
        ?a | b
        ---+---
        (0?rows)

2.4. lightdb_oracle_sql_mode

含义:

用于是否使能当执行一条select语句时默认显示大写列名;

参数:

会话级别,true/on(生效执行select语句时默认显示大写列名),false/off(lightdb原生行为,执行select语句时默认显示小写列名),默认值为off;

3. 数据类型

数据库操作的每个值都有一个数据类型。值的数据类型将一组固定的属性与该值关联。这些属性导致lightdb将一种数据类型的值与另一种数据类型的值区别对待。下表根据Oracle的数据类型,对字符类型、数值类型、长数据类型、日期时间类型,ROW数据类型,大对象类型和XMLType的兼容性情况,进行概览展示。

3.1. 字符类型

3.1.1. VARCHAR2(len [byte|char])

类型说明:变长字符串,最多可包含len个字符。 对于len,请指定大于0的整数。 如果省略len,则字符串可以是任意长度。 自23.1版本以来,LightDB实现了此语法,以兼容Oracle的varchar2类型。 在len后面的关键字byte或char是可选的,仅与Oracle语法兼容, 内部实现与只有len而没有byte或char关键字的实现相同。

通用规则:

  • VARCHAR2是一种字符数据类型。请指定长度所需的字符数。

  • 字符串长度可变。指定的值将被存储为原样。 此数据类型的上限约为1GB。

示例:

lightdb@postgres=# create table t1(name varchar2(10));
CREATE TABLE
lightdb@postgres=#
lightdb@postgres=# \d+ t1
                                                                        Table "public.t1"
Column |     Type     | Collation | Nullable | Default | Storage | Stats target | Description
--------+--------------+-----------+----------+---------+---------+--------------+-------------
name   | varchar2(10) |           |          |         | plain   |              |
Access method: heap
lightdb@postgres=#
lightdb@postgres=# create table t2(name varchar2(10 byte));
CREATE TABLE
lightdb@postgres=#
lightdb@postgres=# \d+ t2
                                                                        Table "public.t2"
Column |     Type     | Collation | Nullable | Default | Storage | Stats target | Description
--------+--------------+-----------+----------+---------+---------+--------------+-------------
name   | varchar2(10) |           |          |         | plain   |              |
Access method: heap

lightdb@postgres=#
lightdb@postgres=# create table t3(name varchar2(10 char));
CREATE TABLE
lightdb@postgres=#
lightdb@postgres=# \d+ t3
                                                                        Table "public.t3"
Column |     Type     | Collation | Nullable | Default | Storage | Stats target | Description
--------+--------------+-----------+----------+---------+---------+--------------+-------------
name   | varchar2(10) |           |          |         | plain   |              |
Access method: heap

3.1.2. NVARCHAR2(len)

类型说明:变长国家字符字符串,最多可包含len个字符。 对于len,请指定大于0的整数。 如果省略len,则字符串可以是任意长度。

通用规则:

  • NVARCHAR2是一种国家字符数据类型。请指定长度所需的字符数。

  • 字符串长度可变。指定的值将被存储为原样。 此数据类型的上限约为1GB。

3.1.3. VARCHAR(size)【暂不支持】

类型说明:oracle 官方建议使用VARCHAR2代替此字段类型

3.1.4. CHAR [(size [BYTE | CHAR])]

类型说明:长度为size大小字节或字符的固定长度字符数据。最大大小为2000字节或字符。默认和最小大小为1字节。 BYTE和CHAR具有与VARCHAR2相同的语义。

3.1.5. NCHAR[(size)]【暂不支持】

类型说明:固定长度字符数据的长度为字符大小。字节数最多可以是AL16UTF16编码大小的两倍,UTF8编码大小的三倍。最大大小由国家字符集定义决定,上限为2000字节。默认和最小大小为1个字符。

3.2. 数值类型

3.2.1. NUMBER [ (p [, s]) ]【暂不支持】

类型说明:具有精度p和刻度s的数字。精度p的取值范围为1到38。刻度范围从-84到127。精度和比例都是十进制数字。NUMBER的取值范围是1 ~ 22个字节。

3.2.2. FLOAT [(p)]【暂不支持】

类型说明:具有精度p的NUMBER数据类型的子类型。FLOAT值在内部表示为NUMBER。精度p的取值范围是1到126位二进制数字。FLOAT值需要1 ~ 22个字节。

3.2.3. BINARY_FLOAT

类型说明:BINARY_FLOAT是一种32位单精度浮点数的数据类型。每个BINARY_FLOAT值需要4个字节。

3.2.4. BINARY_DOUBLE

类型说明:BINARY_DOUBLE是一种64位双精度浮点数的数据类型。每个BINARY_DOUBLE值需要8个字节。

3.3. 长数据类型

3.3.1. LONG 【暂不支持】

类型说明:可变长度的字符数据,最大可达2gb,或231 -1字节

3.4. 日期时间类型

3.4.1. DATE

类型说明:存储日期和时间DATE是一种日期/时间数据类型。日期和时间存储在DATE中。时区不会被存储。

通用规则:

  • DATE是一种日期/时间数据类型。

  • 日期和时间存储在DATE中。时区不会被存储。

3.4.2. TIMESTAMP [(fsp)] WITH TIME 【暂不支持】

类型说明:TIMESTAMP的所有值以及时区位移值,其中fsp是SECOND datetime字段小数部分的位数。取值范围为0 ~ 9。默认值是6。大小固定为13字节。此数据类型包含日期时间字段YEAR、MONTH、DAY、HOUR、MINUTE、SECOND、TIMEZONE_HOUR和TIMEZONE_MINUTE。它具有小数秒和明确的时区。

3.4.3. TIMESTAMP [(fsp)] WITH LOCAL TIME 【暂不支持】

类型说明:对时区信息敏感的TIMESTAMP的另一个变体。它与TIMESTAMP WITH TIME ZONE的不同之处在于,存储在数据库中的数据被规范化为数据库时区,而时区信息不作为列数据的一部分存储。当用户检索数据时,Oracle返回用户本地会话时区的数据

3.4.4. INTERVAL YEAR [(year_precision)] TO MONTH【暂不支持】

类型说明:以年和月为单位存储一段时间,其中year_precision是YEAR datetime字段中的位数。取值范围为0 ~ 9。默认值是2。大小固定为5字节。

3.4.5. INTERVAL DAY [(day_precision)] TO SECOND[(fsp)]【暂不支持】

类型说明:以天、小时、分和秒为单位存储一段时间,其中 day_precision是DAY datetime字段的最大位数。取值范围为0 ~ 9。默认值是2。 fsp是SECOND字段小数部分的位数。取值范围为0 ~ 9。默认值是6。 大小固定为11字节。

3.5. ROW

3.5.1. RAW(len)

类型说明:存储可变长度的二进制数据。外部表示为十六进制。 len 只是为了与 Oracle 兼容,没有实际作用。 二进制数据可以是任意长度。

通用规则:

  • RAW 是一个可变长度的十六进制数据类型。

  • 十六进制字符串长度可变。指定的值将被存储为二进制数据。此数据类型的上限约为 1GB。

3.6. 大对象类型

3.6.1. BFILE 【暂不支持】

类型说明:包含存储在数据库外部的大型二进制文件的定位器。允许字节流I/O访问驻留在数据库服务器上的外部lob。最大大小为4gb。

3.6.2. BLOB

类型说明:用于存储二进制大对象。最大大小为(4gb - 1) *(数据库块大小)。BLOB 是 BYTEA 的别名。

3.6.3. CLOB

类型说明:包含单字节或多字节字符的字符大对象。支持固定宽度和可变宽度字符集,两者都使用数据库字符集。最大大小为(4gb - 1) *(数据库块大小)。 CLOB 是 TEXT 的别名。

3.6.4. NCLOB 【暂不支持】

类型说明:用于存储Unicode字符的大对象。固定宽度字符集和可变宽度字符集都支持,两者都使用数据库国家字符集。最大大小为(4gb - 1) *(数据库块大小)。

3.7. XMLType

3.7.1. XMLType

类型说明:XMLType是一个对象类型,可以用来存储XML数据。

通用规则:

  • XMLType是xml数据类型。

  • 支持oracle.XMLType和pg_catalog.xml之间的隐式转换。

示例:

lightdb@postgres=# create database test_oracle lightdb_syntax_compatible_type oracle;
CREATE DATABASE

lightdb@postgres=# \c test_oracle
You are now connected to database "test_oracle" as user "lightdb".
compatible type: oracle

lightdb@test_oracle=# select dbms_output.serveroutput(true);
serveroutput
--------------

(1 row)


lightdb@test_oracle=# CREATE TABLE xml_table (id NUMBER, xml_column XMLType );
CREATE TABLE

lightdb@test_oracle=# INSERT INTO xml_table (id, xml_column) VALUES (1, XMLType('<root><name>John</name></root>'));
INSERT 0 1

lightdb@test_oracle=# DECLARE
lightdb@test_oracle$#   v_clob CLOB;
lightdb@test_oracle$# BEGIN
lightdb@test_oracle$#   SELECT XMLType.getClobVal(xml_column)
lightdb@test_oracle$#   INTO v_clob
lightdb@test_oracle$#   FROM xml_table
lightdb@test_oracle$#   WHERE id = 1;
lightdb@test_oracle$#   DBMS_OUTPUT.PUT_LINE('CLOB value: ' || v_clob);
lightdb@test_oracle$# END;
lightdb@test_oracle$# /
CLOB value: <root><name>John</name></root>
DO

lightdb@test_oracle=# DECLARE
lightdb@test_oracle$#   xml_data XMLType;
lightdb@test_oracle$#   clob_data CLOB;
lightdb@test_oracle$# BEGIN
lightdb@test_oracle$#   xml_data := XMLType('<root><name>John Doe</name></root>');
lightdb@test_oracle$#   clob_data := xml_data.getClobVal();
lightdb@test_oracle$#   DBMS_OUTPUT.PUT_LINE(clob_data);
lightdb@test_oracle$# END;
lightdb@test_oracle$# /
<root><name>John Doe</name></root>
DO

lightdb@test_oracle=# SELECT XMLType.getClobVal(xml_column) from xml_table;
getclobval
--------------------------------
<root><name>John</name></root>
(1 row)

4. 函数类型

4.1. 数值函数

4.1.1. ABS(n)

函数作用:计算数值n的绝对值

语法:

ABS(bigint) returns bigint
ABS(double precision) returns double precision
ABS(integer) returns integer
ABS(numeric) returns numeric
ABS(real) returns real
ABS(smallint) returns smallint

示例:

lightdb@testdb=# select ABS(-11) from dual;
abs
-----
11
(1 row)

4.1.2. ACOS(n)

函数作用:计算n的反余弦值。

语法:

ACOS(double precision) return double precision

示例:

lightdb@testdb=# select ACOS(0.5) from dual;
        acos
--------------------
1.0471975511965979
(1 row)

4.1.3. ASIN(n)

函数作用:计算n的反正弦值

语法:

ASIN(double precision) return double precision

4.1.4. ATAN(n)

函数作用:计算n的四象限反正切值

语法:

ATAN(double precision) return double precision

示例:

lightdb@testdb=# select ATAN(0.5) from dual;
        atan
--------------------
0.4636476090008061
(1 row)

4.1.5. ATAN2(n1,n2)

函数作用:计算n1,n2的四象限反正切值

语法:

ATAN2(double precision, double precision) RETURN double precision

示例:

lightdb@testdb=# select ATAN2(0.5,0.5) from dual;
        atan2
--------------------
0.7853981633974483
(1 row)

4.1.6. BITAND

函数作用:执行按位 AND 操作。

语法:

BITAND(int1 integers, int2 integers) returns bigint

示例:

    SELECT BITAND(5,3) FROM DUAL;
 bitand
-------
      1
(1 row)

4.1.7. CEIL(n)

函数作用:计算大于等于n的最小整数

语法:

CEIL(double precision) RETURN double precision
CEIL(numeric) RETURN numeric

示例:

lightdb@testdb=# select ceil(1.1) from dual;
ceil
------
        2
(1 row)

4.1.8. COS(n)

函数作用:计算n的COS(n)函数值

语法:

COS(double precision) RETURN double precision

示例:

lightdb@testdb=# select COS(1.1) from dual;
                cos
--------------------
0.4535961214255773
(1 row)

4.1.9. COSH

函数作用:计算一个数字的双曲余弦。

语法:

COSH(num numeric) returns double precision

示例:

SELECT COSH(2.236) FROM DUAL;
        cosh
-----------------
4.7313591000247
(1 row)

4.1.10. EXP(e)

函数作用:计算e的n次方

语法:

EXP(double precision) returns double precision

示例:

lightdb@testdb=# select exp(1.1) from dual;
                exp
--------------------
3.0041660239464331
(1 row)

4.1.11. FLOOR(n)

函数作用:计算等于或小于n的最大整数

语法:

FLOOR(double precision) RETURN double precision
FLOOR(numeric) RETURN numeric

示例:

lightdb@testdb=# select floor(1.1) from dual;
floor
-------
        1
(1 row)

4.1.12. LN(n)

函数作用:计算n的自然对数。

语法:

LN(double precision) RETURN double precision
LN(numeric) RETURN numeric

示例:

lightdb@testdb=# select ln(1.1) from dual;
                ln
---------------------
0.09531017980432486
(1 row)

4.1.13. MOD(n1,n2)

函数作用:返回n2除以n1的余数。如果n1为0,则返回n2。

语法:

    MOD(n2 bigint, n1 bigint) returns bigint
MOD(n2 integer, n1 integer) returns integer
MOD(n2 numeric, n1 numeric) returns numeric
MOD(n2 smallint, n1 smallint) returns smallint

示例:

SELECT mod(5,2) FROM DUAL;
        mod
-----------
        1

4.1.14. NANVL(n1,n2)

函数作用:如果输入值n2是NaN(不是数字),则指示Oracle数据库返回一个备选值n1。如果n2不是NaN,那么Oracle返回n2。

语法:

NANVL(double precision, character varying) RETURN double precision
NANVL(double precision, double precision) RETURN double precision
NANVL(numeric, character varying ) RETURN numeric
NANVL(numeric, numeric) RETURN numeric
NANVL(real, character varying) RETURN real
NANVL(real, real) RETURN real

示例:

lightdb@testdb=# select nanvl(1,1) from dual;
nanvl
-------
        1
(1 row)

4.1.15. POWER(n1,n2)

函数作用:计算n2的n1次方

语法:

POWER(double precision, double precision) RETURN double precision
POWER(numeric, numeric) RETURN numeric

示例:

lightdb@testdb=# select power(1,4) from dual;
power
-------
        1
(1 row)

4.1.16. REMAINDER(n1,n2)

函数作用:计算n2除以n1的余数

语法:

REMAINDER(numeric, numeric) RETURN numeric

示例:

lightdb@testdb=# select remainder(1,4) from dual;
remainder
-----------
        1
(1 row)

4.1.17. ROUND (number,n)

函数作用:ROUND返回小数点右边四舍五入到整数位的n。如果省略整数,则n四舍五入到零位。如果整数为负数,则n在小数点左边四舍五入。 N可以是任何数字数据类型,也可以是可以隐式转换为数字数据类型的任何非数字数据类型。如果省略整数,则函数返回与n的数字数据类型相同的数据类型的值ROUND(n, 0)。如果包含整数,则函数返回NUMBER。

语法:

ROUND(double precision) RETURN double precision
ROUND(numeric) RETURN numeric

示例:

lightdb@testdb=# select round(1,3) from dual;
round
-------
1.000
(1 row)

4.1.18. ROUND_TIES_TO_EVEN (n,integer)

函数作用:ROUND_TIES_TO_EVEN是一个舍入函数,它接受两个参数:n和integer。该函数根据以下规则返回四舍五入到整数位的n: 如果integer为正数,则n四舍五入到小数点右边的整数位。 如果未指定整数,则n四舍五入到0位。 如果integer为负数,则n四舍五入到小数点左边的整数位。

语法:

ROUND_TIES_TO_EVEN(n numeric, places integer DEFAULT 0) RETURN numeric

示例:

lightdb@testdb=# select sign(2) from dual;
sign
------
        1
(1 row)

4.1.19. SIN(n)

函数作用:计算n的sin(n)函数值

语法:

SIN(double precision) RETURN double precision

示例:

lightdb@testdb=# select sin(0.5) from dual
lightdb@testdb-# ;
                sin
-------------------
0.479425538604203
(1 row)

4.1.20. SINH

函数作用:计算一个数的双曲正弦值

语法:

SINH(num numeric) returns double precision

示例:

SELECT SINH(1.414) FROM DUAL;
        sinh
-----------------
1.93460168824956
(1 row)

4.1.21. SQRT(n)

函数作用:计算n的平方根

语法:

SQRT(double precision) RETURN double precision
SQRT(numeric) RETURN numeric

示例:

lightdb@testdb=# select SQRT(9) from dual;
sqrt
------
        3
(1 row)

4.1.22. TAN(n)

函数作用:计算n的tan(n)函数值。

语法:

TAN(double precision) RETURN double precision

示例:

lightdb@testdb=# select TAN(9) from dual;
                tan
----------------------
-0.45231565944180985
(1 row)

4.1.23. TANH

函数作用:TANH(num numeric) returns double precision。

语法:

TANH(num numeric) returns double precision

示例:

SELECT TANH(3) FROM DUAL;
        tanh
-----------------
0.995054753686731
(1 row)

4.1.24. TRUNC (number,n)

函数作用:计算number截断小数点后n位的值。

语法:

TRUNC(double precision) RETURN double precision
TRUNC(numeric) RETURN numeric

示例:

lightdb@testdb=# select trunc(0.5) from dual;
trunc
-------
        0
(1 row)

4.1.25. WIDTH_BUCKET(expr,minexpr,maxexpr,buckets)

函数作用:在[minexpr,maxexpr)之间为expr做buckets数量的桶计算,并返回计算结果。

语法:

WIDTH_BUCKET(anyelement, anyarray) RETURN integer
WIDTH_BUCKET(double precision, double precision, double precision, integer) RETURN integer
WIDTH_BUCKET(numeric, numeric, numeric, integer) RETURN integer

4.2. 字符串函数

4.2.1. CHR(n)

函数作用:返回具有与n等效二进制值的字符,作为数据库字符集中的VARCHAR2值,或者(如果指定USING NCHAR_CS)国家字符集中的VARCHAR2值。。

语法:

CHR(integer) RETURN text

示例:

lightdb@testdb=# select CHR(2) from dual;
chr
------
\x02
(1 row)

4.2.2. CONCAT(char1,char2)

函数作用:返回char1连接char2的字符集。char1和char2可以是任何数据类型CHAR、VARCHAR2、NCHAR、NVARCHAR2、CLOB或NCLOB。

语法:

CONCAT(VARIADIC "any") RETURN text

示例:

lightdb@testdb=# select CONCAT(13,14) from dual;
concat
--------
1314
(1 row)

4.2.3. INITCAP(char)

函数作用:返回char,其中每个单词的第一个字母为大写,其他所有字母为小写。

语法:

INITCAP(text) RETURN text

示例:

lightdb@testdb=# select INITCAP('12wer') from dual;
initcap
---------
12wer
(1 row)

4.2.4. LOWER(text)

函数作用:返回text,且所有字母都是小写。

语法:

LOWER(text) RETURN text

示例:

lightdb@testdb=# select LOWER('QSFS') from dual;
lower
-------
qsfs
(1 row)

4.2.5. LPAD

函数作用:使用一系列的字符填充一个字符串,使其达到指定的长度。。

语法:

LPAD(str text, len integer) returns text
LPAD(str text, len integer, paddingStr text) returns text

一般规则:

  • LPAD 函数将在字符串 str 的开始处反复填充填充字符 paddingStr,直到字符串达到长度 len,然后返回结果。

  • 如果字符串是 CHAR 类型,则填充字符将添加到字符串中,而不会删除尾随空格。

  • 在结果字符串中,全角字符被认为长度为2,半角字符被认为长度为1。如果一个全角字符不能被包含在结果字符串中,因为只有一个半角字符的空间可用,那么该字符串将用单字节空格填充。

  • 返回值的数据类型是 TEXT。

示例:

    SELECT LPAD('abc',10,'a') FROM DUAL;
lpad
------------
 aaaaaaaabc
(1 row)

4.2.6. LTRIM

函数作用:从字符串的开头删除指定的字符。。

语法:

    LTRIM(str text) returns text
LTRIM(str text, trimChars text) returns text

一般规则:

  • LTRIM 函数返回一个从字符串 str 的开头删除了 trimChars 的字符串。

  • 如果指定了多个修剪字符,则删除与修剪字符匹配的所有字符。如果省略了 trimChars,则删除所有前导半角空格。

  • 返回值的数据类型是 TEXT。

示例:

    SELECT LTRIM('aabcab','ab') FROM DUAL;
 ltrim
-------
 cab
(1 row)

4.2.7. NCHR(number)【暂不支持】

函数作用:返回在国家字符集中与number具有二进制等价的字符,返回的值总是NVARCHAR2。。

4.2.8. NLS_INITCAP(char)【暂不支持】

函数作用:返回char,每个单词的第一个字母为大写,其他所有字母为小写。单词由空格或非字母数字字符分隔。

4.2.9. NLS_LOWER(char)【暂不支持】

函数作用:返回char,所有字母都是小写.

4.2.10. NLS_UPPER(char)【暂不支持】

函数作用:返回char,所有字母都大写.

4.2.11. NLSSORT()

函数作用:返回表示区域设置(COLLATE)的词法顺序的字节字符串。。

语法:

    NLSSORT(str text) returns bytea
NLSSORT(str text, locale text) returns bytea

一般规则:

  • NLSSORT用于在区域设置(COLLATE)的排序顺序中进行比较和排序,该区域设置与默认区域设置不同。

  • 可以为区域设置指定的值根据数据库服务器的操作系统而异。

  • 如果省略了区域设置,则需要使用set_nls_sort预先设置区域设置。要使用set_nls_sort设置区域设置,请执行SELECT语句。

  • 返回值的数据类型是BYTEA。

示例:

    SELECT col1,col2 FROM t3 ORDER BY NLSSORT(col2,'da_DK.UTF8');
 col1 |    col2
------+------------
 2001 | abcdef
 1001 | aabcababc
 3001 | aacbaab
(3 row)

4.2.12. REGEXP_REPLACE

函数作用:返回与调用函数中指定的模式匹配的字符串。

语法:

    REGEXP_REPLACE(string text, pattern text, replace_string text, startPos integer,
occurrence integer, flags text) returns text

一般规则:

  • REGEXP_REPLACE 返回修改后的源字符串,其中源字符串中出现的 POSIX 正则表达式模式会被替换为指定的替换字符串。 如果未找到匹配项或查询的出现次数超过了匹配项的数量,则返回未修改的源字符串。

搜索和替换从指定的起始位置 startPos 开始,在 string 中进行,默认从 string 的开头开始。 * startPos 是一个正整数,不允许使用负值从 string 的末尾开始搜索。 * occurrence 是一个正整数,表示应搜索和替换 string 中 pattern 的哪个出现次数。默认值为 0,表示替换 string 中所有的 pattern。 * flags 是一个字符表达式,可让您更改函数的默认匹配行为。有关详细信息,请参见 REGEXP_COUNT。

示例:

SELECT regexp_replace('512.123.4567 612.123.4567', '([[:digit:]]{3})\.([[:digit:]]{3})\.([[:digit:]]{4})', '(\1) \2-\3') FROM DUAL;
        regexp_replace
-------------------------------
 (512) 123-4567 (612) 123-4567
(1 row)

SELECT oracle.REGEXP_REPLACE('number   your     street,    zipcode  town, FR', '( ){2,}', ' ', 9);
             regexp_replace
----------------------------------------
 number   your street, zipcode town, FR
(1 row)

SELECT oracle.REGEXP_REPLACE('number   your     street,    zipcode  town, FR', '( ){2,}', ' ', 9, 2);
               regexp_replace
---------------------------------------------
 number   your     street, zipcode  town, FR
(1 row)

4.2.13. REGEXP_SUBSTR()

函数作用:返回与调用函数中指定的模式匹配的字符串。

语法:

REGEXP_SUBSTR(string text, pattern text) returns text
REGEXP_SUBSTR(string text, pattern text, startPos integer) returns text
REGEXP_SUBSTR(string text, pattern text, startPos integer, occurrence integer) returns text
REGEXP_SUBSTR(string text, pattern text, startPos integer, occurrence integer, flags text) returns text
REGEXP_SUBSTR(string text, pattern text, startPos integer, occurrence integer, flags text, group int) returns text

一般规则:

  • REGEXP_SUBSTR返回与将POSIX正则表达式模式与字符串匹配所得到的匹配子字符串。如果未找到匹配,则该函数返回NULL。 如果参数中有一个为空,则返回 NULL,但 ‘flags’ 参数可以为空。

搜索从字符串中指定的起始位置startPos开始,默认从字符串的开头开始。 * startPos是一个正整数,不允许使用负值从字符串的末尾开始搜索。 * occurrence是一个正整数,表示在字符串中搜索第几个模式。 默认值为1,表示在字符串中搜索第一个模式。 * flags是一个字符表达式,它允许您更改函数的默认匹配行为。有关详细信息,请参见REGEXP_COUNT。 * 对于具有捕获组的模式,*group*是一个正整数,表示应由函数返回模式中的哪个捕获组。捕获组可以嵌套,它们按照它们在模式中左括号出现的顺序进行编号。 如果group为零,则返回与模式匹配的整个子字符串的位置。 如果group值超过模式中捕获组的数量,则函数返回NULL。 空的group值返回NULL。 group的默认值为零。

示例:

SELECT REGEXP_SUBSTR('number of your street, zipcode town, FR', ',[^,]+') FROM DUAL;
 regexp_substr
----------------
 , zipcode town
(1 row)

SELECT regexp_substr('number of your street, zipcode town, FR', ',[^,]+', 24) FROM DUAL;
 regexp_substr
---------------
 , FR
(1 row)

SELECT regexp_substr('number of your street, zipcode town, FR', ',[^,]+', 1, 2) FROM DUAL;
 regexp_substr
---------------
 , FR
(1 row)

SELECT regexp_substr('1234567890 1234567890', '(123)(4(56)(78))', 1, 1, 'i', 0) FROM DUAL;
 regexp_substr
---------------
 12345678
(1 row)

4.2.14. REPLACE()

函数作用:返回将每个 search_string 的出现替换为 replacement_string 的字符串。

语法:

    REPLACE(string text, pattern text) returns text
REPLACE(string text, pattern text, replace_string text) returns text
REPLACE(string uuid, pattern text, replace_string text) returns text

一般规则:

  • 如果省略或为 null,则将删除 search_string 的所有出现。如果 search_string 为 null,则返回 string。

示例:

SELECT REPLACE('abcdAbcdasd', 'a') FROM DUAL;
replace
-----------
bcdAbcdsd
(1 row)

SELECT REPLACE('abcdAbcdasd', 'a','c') FROM DUAL;
replace
-------------
cbcdAbcdcsd
(1 row)

SELECT REPLACE('abcdAbcdasd', NULL,'c') FROM DUAL;
replace
-------------
abcdAbcdasd
(1 row)

SELECT REPLACE('abcdAbcdasd', 'a',NULL) FROM DUAL;
replace
-----------
bcdAbcdsd
(1 row)

4.2.15. RPAD()

函数作用:使用一系列字符将字符串右侧填充到指定的长度。

语法:

    RPAD(str text, len integer) returns text
RPAD(str text, len integer, paddingStr text) returns text

一般规则:

  • RPAD 返回在使用填充字符 paddingStr 反复填充字符串 str 的末尾直到字符串达到长度 len 后的结果。

  • 如果字符串是 CHAR 类型,则添加填充字符时不会删除尾随空格。

  • 在结果字符串中,全角字符被认为长度为 2,半角字符长度为 1。如果由于只有一个半角字符的空间可用而无法包含全角字符,则使用单字节空格填充字符串。

  • 返回值的数据类型为 TEXT。

示例:

       SELECT RPAD('abc',10,'a') FROM DUAL;
       rpad
   ------------
    abcaaaaaaa
   (1 row)

RTRIM()

语法:

    RTRIM(str text) returns text
RTRIM(str text, trimChars text) returns text

一般规则:

  • RTRIM 返回从字符串 str 末尾删除 trimChars 后的字符串。

  • 如果指定了多个修剪字符,则删除与修剪字符匹配的所有字符。如果省略了 trimChars,则删除所有尾随半角空格。

  • 返回值的数据类型为 TEXT。

示例:

SELECT RTRIM('aabcab','ab') FROM DUAL;
rtrim
-------
aabc
(1 row)

4.2.16. SUBSTR()

函数作用:使用字符指定位置和长度提取字符串的一部分。

语法:

    SUBSTR(str text, startPos integer) returns text
SUBSTR(str text, startPos integer, len integer) returns text

一般规则:

  • SUBSTR从字符串str的位置startPos开始提取并返回一个子字符串,长度为len个字符。

  • 当startPos为正数时,它将是从字符串开头算起的字符数。

  • 当startPos为0时,它将被视为1。

  • 当startPos为负数时,它将是从字符串末尾算起的字符数。

  • 当未指定len时,将返回字符串末尾的所有字符。如果len小于1,则返回NULL。

  • 对于startPos和len,请指定整数或NUMERIC类型。如果指定了包含小数位的数字,则将其截断为整数。

  • 返回值的数据类型是TEXT。

示例:

SELECT SUBSTR('ABCDEFG',3,4) "Substring" FROM DUAL;
 Substring
-----------
 CDEF
(1 row)

SELECT SUBSTR('ABCDEFG',-5,4) "Substring" FROM DUAL;
 Substring
-----------
 CDEF
(1 row)

4.2.17. TRANSLATE(expr,from_string,to_string)

函数作用:返回expr,并将from_string中每个字符的所有出现替换为to_string中对应的字符。expr中不在from_string中的字符不会被替换。参数from_string可以包含比to_string更多的字符。在这种情况下,from_string末尾的额外字符在to_string中没有对应的字符。如果这些额外的字符出现在expr中,那么它们将从返回值中删除。

语法:

TRANSLATE(text, text, text) return text

示例:

lightdb@testdb=# select TRANSLATE('1','2','3') from dual;
translate
-----------
1
(1 row)

4.2.18. ASCIl(char)

函数作用:返回char的第一个字符在数据库字符集中的十进制表示形式。char的数据类型为char、VARCHAR2、NCHAR或NVARCHAR2。

4.2.19. INSTR()

函数作用:返回字符串中子字符串的位置。

语法:

INSTR(str1 text, str2 text) returns integer
INSTR(str1 text, str2 text, startPos integer) returns integer
INSTR(str1 text, str2 text, startPos integer, occurrences integer) returns integer

一般规则:

  • INSTR 函数在字符串 str1 中搜索子字符串 str2,并返回第一次出现的字符位置(以字符计数)。

  • 搜索从字符串 str1 的指定起始位置 startPos 开始。

  • 当 startPos 为 0 或负数时,起始位置将从 str1 结尾左侧的指定字符数开始,INSTR 函数将从该点向后搜索。

  • 如果没有指定起始位置,则从 str1 的开头开始搜索。

  • 如果指定了 occurrences,则返回 str2 的第 n 次出现在 str1 中的位置。只能指定正数。

  • 如果未指定 occurrences,则返回找到的第一个出现位置的起始位置。

  • 如果在 str1 中未找到 str2,则返回 0。

  • 对于 startPos 和 occurrences,请指定 SMALLINT 或 INTEGER 类型。

  • 返回值的数据类型为 INTEGER。

示例:

SELECT INSTR('ABCACBCAAC','BC') FROM DUAL;
 instr
-------
     2
(1 row)

SELECT INSTR('ABCACBCAAC','BC',-1,2) FROM DUAL;
 instr
-------
     2
(1 row)

4.2.20. LENGTH()

函数作用:返回字符串中字符的数量。

语法:

LENGTH(str text) returns integer

一般规则:

  • LENGTH 返回字符串 str 中字符的数量。

  • 如果字符串是 CHAR 类型,尾随空格也会计入长度。

  • 返回值的数据类型是 INTEGER。

示例:

SELECT col2,LENGTH(col2) FROM t1 WHERE col1 = '1001';
    col2    | length
------------+--------
 AAAAA      |     10
(1 row)

4.2.21. REGEXP_COUNT()

函数作用:在字符串中搜索正则表达式,并返回匹配项的计数。

语法:

REGEXP_COUNT(string text, pattern text) returns integer
REGEXP_COUNT(string text, pattern text, startPos integer) returns integer
REGEXP_COUNT(string text, pattern text, startPos integer, flags text) returns integer

示例:

SELECT REGEXP_COUNT('a'||CHR(10)||'d', 'a.d') FROM DUAL;
 regexp_count
--------------
            0
(1 row)

SELECT REGEXP_COUNT('a'||CHR(10)||'d', 'a.d', 1, 'm') FROM DUAL;
 regexp_count
--------------
            0
(1 row)

SELECT REGEXP_COUNT('a'||CHR(10)||'d', 'a.d', 1, 'n') FROM DUAL;
 regexp_count
--------------
            1
(1 row)

SELECT REGEXP_COUNT('a'||CHR(10)||'d', '^d$', 1, 'm') FROM DUAL;
 regexp_count
--------------
            1
(1 row)

4.2.22. REGEXP_INSTR()

函数作用:返回在字符串中找到模式匹配的开始或结束位置。

语法:

    REGEXP_INSTR(string text, pattern text) returns integer
REGEXP_INSTR(string text, pattern text, startPos integer) returns integer
REGEXP_INSTR(string text, pattern text, startPos integer, occurrence integer) returns integer
REGEXP_INSTR(string text, pattern text, startPos integer, occurrence integer) returns integer
REGEXP_INSTR(string text, pattern text, startPos integer, occurrence integer, return_opt integer) returns integer
REGEXP_INSTR(string text, pattern text, startPos integer, occurrence integer, return_opt integer, flags text) returns integer
REGEXP_INSTR(string text, pattern text, startPos integer, occurrence integer, return_opt integer, flags text) returns integer
REGEXP_INSTR(string text, pattern text, startPos integer, occurrence integer, return_opt integer, flags text, group integer) returns integer

示例:

SELECT REGEXP_INSTR('1234567890', '(123)(4(56)(78))') FROM DUAL;
 regexp_instr
--------------
            1
(1 row)

SELECT REGEXP_INSTR('1234567890', '(4(56)(78))', 3) FROM DUAL;
 regexp_instr
--------------
            4
(1 row)

SELECT REGEXP_INSTR('123 123456 1234567, 1234567 1234567 12', '[^ ]+', 1, 6) FROM DUAL;
 regexp_instr
--------------
           37

(1 row)

SELECT REGEXP_INSTR('199 Oretax Prayers, Riffles Stream, CA', '[S|R|P][[:alpha:]]{6}', 3, 2, 1) FROM DUAL;
 regexp_instr
--------------
           28
(1 row)

4.2.23. INSTRB()

函数作用:INSTRB 函数使用字节搜索字符串中的子字符串,并返回第一个指定出现的子字符串字节所在字符串的位置。

语法:

INSTRB( p_source text, p_search text, p_position int4  default 1, p_occurrence  int4  default 1) RETURNS integer

一般规则:

  • INSTRB 函数在字符串 p_source 中搜索子字符串 p_search,并返回第一次出现的子字符串字节所在字符串的位置(以字节计数)。

  • 搜索从字符串 p_source 的指定起始位置 p_position 开始。

  • 当 p_position 为 0 或负数时,将引发错误。这与 Oracle 不同,在 Oracle 中,p_position 将从 p_source 结尾左侧的指定字节数开始,INSTRB 函数将从该点向后搜索。

  • 如果未指定起始位置,则从 p_source 的开头开始搜索。

  • 如果指定了 p_occurrence,则返回 p_search 的第 n 次出现在 p_source 中的位置。只能指定正数。

  • 如果未指定 occurrences,则返回找到的第一个出现位置的起始位置。

  • 如果在 p_source 中未找到 p_search,则返回 0。

  • 返回值的数据类型为 INTEGER。

示例:

SELECT INSTRB('hhh测试onhx', 'on') FROM DUAL;
instrb
--------
        10
(1 row)

SELECT INSTRB('hhh测试onhx on xxxx', 'on', 7, 2) FROM DUAL;
instrb
--------
        15
(1 row)

4.2.24. LENGTHB()

函数作用:返回字符串的字节数。

语法:

LENGTHB(str text) returns integer

一般规则:

  • LENGTHB 返回字符串 str 中的字节数。

  • 如果字符串是 CHAR 类型,尾随空格也会计入长度。

  • 返回值的数据类型是 INTEGER。

示例:

SELECT col2,LENGTHB(col2) FROM t1 WHERE col1 = '1001';
     col2      | lengthb
---------------+---------
 AAAAA         |      10
(1 row)

SELECT col2,LENGTHB(col2) FROM t1 WHERE col1 = '1004';
     col2      | lengthb
---------------+---------
 ***           |      16
(1 row)

4.2.25. REGEXP_LIKE()

函数作用:在查询的WHERE子句中使用,使得查询返回与给定模式匹配的行。

语法:

    REGEXP_LIKE(string text, pattern text) returns boolean
REGEXP_LIKE(string text, pattern text, flags text) returns boolean

一般规则:

  • REGEXP_LIKE类似于LIKE条件,但它执行正则表达式匹配,而不是LIKE执行的简单模式匹配。

  • 返回一个布尔值,当模式匹配字符串时为true,否则为false。 如果参数中有一个为空,则返回 NULL,但 ‘flags’ 参数可以为空。

  • flags是一个字符表达式,它允许您更改函数的默认匹配行为。有关详细信息,请参见REGEXP_COUNT。

示例:

SELECT REGEXP_LIKE('a'||CHR(10)||'d', 'a.d', 'm') FROM DUAL;
 regexp_like
-------------
 f
(1 row)

SELECT REGEXP_LIKE('a'||CHR(10)||'d', 'a.d', 'n') FROM DUAL;
 regexp_like
-------------
 t
(1 row)

4.2.26. SUBSTRB()

函数作用:使用字节指定位置和长度提取字符串的一部分。

语法:

    SUBSTRB(str text, startPos integer) returns varchar2
SUBSTRB(str text, startPos integer, len integer) returns varchar2

一般规则:

  • SUBSTR从字符串str的字节位置startPos开始提取并返回一个子字符串,长度为len个字节。

  • 当startPos为0或负数时,提取从起始位置减1并向左移动相应位置数后找到的位置开始。

  • 当未指定len时,将返回字符串末尾的所有字节。

  • 如果未提取字符串或len小于1,则返回空字符串。

  • 对于startPos和len,请指定SMALLINT或INTEGER类型。

  • 返回值的数据类型是VARCHAR2。

示例:

SELECT SUBSTRB('aaabbbccc',4,3) FROM DUAL;
 substrb
-----------
 bbb
(1 row)

SELECT SUBSTRB('aaabbbccc',-2,6) FROM DUAL;
 substrb
-----------
 aaa
(1 row)

4.3. 日期时间函数

4.3.1. ADD_MONTHS()

函数作用:对日期添加月份。

语法:

    ADD_MONTHS(date DATE, months INTEGER) returns DATE
ADD_MONTHS(date TIMESTAMP WITH TIME ZONE, months INTEGER) returns TIMESTAMP

一般规则:

  • ADD_MONTHS返回date加上months。

  • 对于date,请指定DATE或TIMESTAMP WITH TIME ZONE类型。

  • 对于months,请指定SMALLINT或INTEGER类型。

  • 如果months指定为负值,则从日期中减去月数。

  • 返回值的数据类型是DATE或TIMESTAMP。

示例:

SELECT ADD_MONTHS(DATE'2016/05/01',3) FROM DUAL;
     add_months
---------------------
 2016-08-01 00:00:00
(1 row)

4.3.2. CURRENT_DATE()【暂不支持】

函数作用:返回会话时区中的当前日期。

4.3.3. CURRENT_TIMESTAMP()【暂不支持】

函数作用:返回会话时区的当前日期和时间,返回数据类型为[TIMESTAMP WITH time zone]。

4.3.4. DBTIMEZONE()

函数作用:返回数据库时区的值。

语法:

DBTIMEZONE() returns text

一般规则:

  • DBTIMEZONE返回数据库的时区值。

  • 返回值的数据类型为TEXT。

示例:

SELECT DBTIMEZONE() FROM DUAL;
 dbtimezone
------------
 GMT
(1 row)

4.3.5. EXTRACT (datetime)【暂不支持】

函数作用:从日期时间或间隔表达式中提取并返回指定日期时间时间字段的值

4.3.6. FROM_TZ【暂不支持】

函数作用:将时间戳值和时区转换为timestamp WITH time zone值

4.3.7. LAST_DAY

函数作用:返回指定日期所在月份的最后一天。

语法:

    LAST_DAY(date DATE) returns DATE
LAST_DAY(date TIMESTAMPTZ) returns TIMESTAMPTZ

一般规则:

  • LAST_DAY返回指定日期所在月份的最后一天。

  • 对于date,请指定DATE或TIMESTAMPTZ类型。

  • 返回值的数据类型为DATE或TIMESTAMPTZ。

示例:

SELECT LAST_DAY(DATE'2016/02/01') FROM DUAL;
last_day
---------------------
 2016-02-29 00:00:00
(1 row)

4.3.8. LOCALTIMESTAMP【暂不支持】

函数作用:TIMESTAMP数据类型的值返回会话时区的当前日期和时间。

4.3.9. MONTHS_BETWEEN()

函数作用:返回两个日期之间的月数。

语法:

    MONTHS_BETWEEN(date1 DATE, date2 DATE) returns NUMERIC
MONTHS_BETWEEN(date1 TIMESTAMP WITH TIME ZONE, date2 TIMESTAMP WITH TIME ZONE) returns NUMERIC

一般规则:

  • MONTHS_BETWEEN返回date1和date2之间月份的差异。

  • 对于date1和date2,请指定DATE或TIMESTAMPTZ类型。

  • 如果date2比date1早,返回值将为负数。

  • 如果两个日期是同一天,或者这两个日期都是它们所属月份的最后一天,则返回一个整数。 如果这两个日期的天数不同,则将一个月视为31天,并返回一个值,该值加上日期差的除以31的结果。

  • 返回值的数据类型为DATE或NUMERIC。

示例:

SELECT MONTHS_BETWEEN(DATE'2016/03/15', DATE'2015/11/15') FROM DUAL;
 months_between
----------------
  4
(1 row)

4.3.10. NEW_TIME(date,timezone1,timezone2)

函数作用:当时区timezone1中的日期和时间为date时,NEW_TIME返回时区timezone2中的日期和时间。

4.3.11. NEXT_DAY

函数作用:返回指定日期之后的第一个特定星期几的日期。

语法:

NEXT_DAY(date DATE, dayOfWk TEXT) returns DATE
NEXT_DAY(date DATE, dayOfWk INTEGER) returns DATE
NEXT_DAY(date TIMESTAMP WITH TIME ZONE, dayOfWk TEXT) returns TIMESTAMP
NEXT_DAY(date TIMESTAMP WITH TIME ZONE, dayOfWk INTEGER) returns TIMESTAMP

一般规则:

  • NEXT_DAY 返回符合条件的日期,即在指定日期 date 之后的第一个 dayOfWk 的实例。

  • 对于 date,请指定为 DATE 或 TIMESTAMPTZ WITH TIME ZONE 类型。

  • 指定表示星期几的数字值或字符串。

示例:

SELECT NEXT_DAY(DATE'2016/05/01', 'Friday') FROM DUAL;
next_day
---------------------
 2016-05-06 00:00:00
(1 row)

4.3.12. NUMTODSINTERVAL(n,’日、秒’)

函数作用:将n转换为一个从日到秒的时间间隔

语法:

NUMTODSINTERVAL(double precision, text) RETURNS int

4.3.13. NUMTOYMINTERVAL(n,’年、月’)

函数作用:将数字n转换为一个从年到月的时间间隔

语法:

NUMTOYMINTERVAL(numeric, text) RETURNS interval

4.3.14. ORA_DST_AFFECTED【暂不支持】

函数作用:该函数接受一个datetime表达式作为参数,该表达式解析为TIMESTAMP WITH TIME ZONE值或包含TIMESTAMP WITH TIME ZONE值的VARRAY对象

4.3.15. ORA_DST_CONVERT【暂不支持】

函数作用:该函数允许您为指定的日期时间表达式指定错误处理。

4.3.16. ORA_DST_ERROR【暂不支持】

函数作用:该函数将datetime表达式作为参数,该表达式解析为TIMESTAMP WITH TIME ZONE值或包含TIMESTAMP WITH TIME ZONE值的VARRAY对象,并指示datetime值是否会导致使用新时区数据时出现错误

4.3.17. ROUND

函数作用:对日期进行四舍五入。

语法:

    ROUND(date DATE) returns DATE
ROUND(date DATE, fmt TEXT) returns DATE
ROUND(date TIMESTAMP WITH TIME ZONE) returns TIMESTAMP WITH TIME ZONE
ROUND(date TIMESTAMP WITH TIME ZONE, fmt TEXT) returns TIMESTAMP WITH TIME ZONE
ROUND(date TIMESTAMP WITHOUT TIME ZONE) returns TIMESTAMP WITHOUT TIME ZONE
ROUND(date TIMESTAMP WITHOUT TIME ZONE, fmt TEXT) returns TIMESTAMP WITHOUT TIME ZONE

一般规则:

  • ROUND 函数返回按格式模型 fmt 指定的单位进行四舍五入的日期。

  • 对于 date,请指定为 DATE 或 TIMESTAMPTZ 类型。

  • 以字符串形式指定格式模型。

示例:

SELECT ROUND(TIMESTAMP'2016/06/20 18:00:00','DAY') FROM DUAL;
round
------------------------
 2016-06-19 00:00:00+09
(1 row)

4.3.18. SESSIONTIMEZONE

函数作用:返回会话的时区。

语法:

SESSIONTIMEZONE() returns text

一般规则:

  • SESSIONTIMEZONE 返回会话之间的时区值。

  • 返回值的数据类型为TEXT。

示例:

SELECT SESSIONTIMEZONE() FROM DUAL;
 sessiontimezone
-----------------
 Japan
(1 row)

4.3.19. SYS_EXTRACT_UTC【暂不支持】

函数作用:从带有时区偏移量或时区地区名称的日期时间值中提取UTC(协调世界时,即格林威治标准时间)。

4.3.20. SYSDATE

函数作用:返回系统日期。

语法:

SYSDATE() returns oracle.date

一般规则:

  • SYSDATE返回系统日期。

  • 返回值的数据类型是orafce的DATE类型。

示例:

    SELECT SYSDATE() FROM DUAL;
 sysdate
---------------------
 2016-06-22 08:06:51
(1 row)

4.3.21. SYSTIMESTAMP()【暂不支持】

函数作用:返回数据库所在系统的系统日期,包括小数秒数和时区。返回类型是TIMESTAMP WITH TIME ZONE。

4.3.22. TO_CHAR (datetime,fmt)

函数作用:将DATE、TIMESTAMP、TIMESTAMP WITH TIME ZONE、TIMESTAMP WITH LOCAL TIME ZONE、interval DAY TO SECOND或interval YEAR TO MONTH数据类型中的日期时间或间隔值转换为VARCHAR2数据类型的值,格式由日期格式fmt指定

语法:

TO_CHAR(timestamp without time zone, text, text) RETURNS text

4.3.23. TO_TIMESTAMP(char,fmt)

函数作用:将char转换为TIMESTAMP数据类型的值。 对于char,可以指定任何表达式(fmt),计算结果为char、VARCHAR2、NCHAR或NVARCHAR2数据类型的字符串。 可选的DEFAULT return_value ON CONVERSION ERROR子句允许您指定在将char转换为TIMESTAMP时发生错误时该函数返回的值。

语法:

TO_TIMESTAMP(double precision) return timestamp with time zone
TO_TIMESTAMP(text, text) return timestamp with time zone

4.3.24. TO_TIMESTAMP_TZ(char)【暂不支持】

函数作用:将char转换为TIMESTAMP WITH TIME ZONE数据类型的值

4.3.25. TO_YMINTERVAL(char)【暂不支持】

函数作用:将其参数转换为INTERVAL MONTH to YEAR数据类型的值

4.3.26. TRUNC

函数作用:截取日期部分。

语法:

TRUNC(date DATE) returns DATE
TRUNC(date DATE, fmt TEXT) returns DATE
TRUNC(date TIMESTAMP WITH TIME ZONE) returns TIMESTAMP WITH TIME ZONE
TRUNC(date TIMESTAMP WITH TIME ZONE, fmt TEXT) returns TIMESTAMP WITH TIME ZONE
TRUNC(date TIMESTAMP WITHOUT TIME ZONE) returns TIMESTAMP WITHOUT TIME ZONE
TRUNC(date TIMESTAMP WITHOUT TIME ZONE, fmt TEXT) returns TIMESTAMP WITHOUT TIME ZONE

一般规则:

  • TRUNC返回按格式模型fmt指定的单位截断的日期。

  • 对于date,请指定DATE或TIMESTAMP类型。

  • 将格式模型指定为字符串。可以指定的值与ROUND相同。

  • 如果省略fmt,则按天截断日期。

  • 如果在日期中指定了LightDB的DATE类型,则返回值的数据类型将是该DATE类型。 如果在日期中指定了TIMESTAMP类型,则返回值的数据类型为TIMESTAMP WITH TIME ZONE, 无论是否使用时区。

示例:

SELECT TRUNC(TIMESTAMP'2016/08/10 15:30:00','DDD') FROM DUAL;
         trunc
------------------------
 2016-08-10 00:00:00+09
(1 row)

4.3.27. TZ_OFFSET

函数作用:返回时区偏移量。

语法:

TZ_OFFSET(text) returns text

一般规则:

  • 您可以输入一个有效的时区区域名称,或一个距UTC的时区偏移量(仅返回该偏移量本身)。

  • 要获取time_zone_name的有效值列表,请查询pg_timezone_names的name列。

示例:

SELECT TZ_OFFSET('Asia/Shanghai') FROM DUAL;
tz_offset
-----------
08:00:00
(1 row)
(1 row)

4.4. 强制转换函数

4.4.1. CAST【暂不支持】

函数作用:允许将一种类型的内置数据类型或集合类型的值转换为另一种内置数据类型或集合类型

4.4.2. CHARTOROWID【暂不支持】

函数作用:将CHAR、VARCHAR2、NCHAR、NVARCHAR2数据类型的值转换为ROWID数据类型

4.4.3. COMPOSE(char)【暂不支持】

函数作用:字符值char作为参数,并返回对其应用Unicode规范组合的结果,如Unicode标准定义D117中所述。如果参数的字符集不是Unicode字符集之一,则COMPOSE返回未经修改的参数

4.4.4. DECOMPOSE 【暂不支持】

函数作用:分解将一个字符值字符串作为其第一个参数,并返回将其中一个Unicode分解应用于该字符串的结果

4.4.5. RAWTONHEX 【暂不支持】

函数作用:将raw转换为包含其十六进制表示的字符值

4.4.6. ROWIDTOCHAR【暂不支持】

函数作用:将rowid值转换为VARCHAR2数据类型

4.4.7. ROWIDTONCHAR【暂不支持】

函数作用:将rowid值转换为NVARCHAR2数据类型

4.4.8. TIMESTAMP_TO_SCN【暂不支持】

函数作用:接受一个时间戳值作为参数,并返回与该时间戳相关联的近似系统更改号(SCN)

4.4.9. TO_BINARY_DOUBLE(expr)【暂不支持】

函数作用:将expr转换为双精度浮点数。

4.4.10. TO_BINARY_FLOAT(expr)【暂不支持】

函数作用:将expr转换为单精度浮点数。

4.4.11. TO_BLOB (bfile)【暂不支持】

函数作用:将bfile值转换为BLOB值

4.4.12. TO_DSINTERVAL【暂不支持】

函数作用:将其参数转换为INTERVAL DAY to SECOND数据类型的值

4.4.13. TO_LOB【暂不支持】

函数作用:列long_column中的LONG或LONG RAW值转换为LOB值

4.4.14. TO_NCHAR (character)【暂不支持】

函数作用:将字符串、CHAR、VARCHAR2、CLOB或NCLOB值转换为国家字符集

4.4.15. TO_NCHAR (datetime)【暂不支持】

函数作用:将DATE、TIMESTAMP、TIMESTAMP WITH TIME ZONE、TIMESTAMP WITH LOCAL TIME ZONE、interval MONTH TO YEAR或interval DAY TO SECOND数据类型中的日期时间或间隔值从数据库字符集转换为国家字符集

4.4.16. TO_NCLOB【暂不支持】

函数作用:将LOB列或其他字符串中的CLOB值转换为NCLOB值

4.4.17. TO_TIMESTAMP_TZ(char)【暂不支持】

函数作用:将char转换为TIMESTAMP WITH TIME ZONE数据类型的值。

4.4.18. TO_YMINTERVAL【暂不支持】

函数作用:将其参数转换为INTERVAL MONTH to YEAR数据类型的值

4.4.19. BIN_TO_NUM

函数作用:BIN_TO_NUM 将位向量转换为其等效数字。

语法:

BIN_TO_NUM(VARIADIC integer []) returns int

一般规则:

  • 此函数的每个参数表示位向量中的一位。

  • 此函数以任何整数数据类型或任何可隐式转换为整数的非整数数据类型作为参数。

  • BIN_TO_NUM 在数据仓库应用程序中很有用,用于使用分组集从物化视图中选择感兴趣的组。

示例:

SELECT BIN_TO_NUM(1,0,1,0) FROM DUAL;
bin_to_num
------------
        10
(1 row)

4.4.20. CONVERT

函数作用:CONVERT将一个字符字符串从一个字符集转换为另一个字符集。

语法:

CONVERT(str TEXT,dest_char_set TEXT,source_char_set TEXT DEFAULT 'utf8') returns TEXT

一般规则:

  • str参数是要转换的值。

  • dest_char_set参数是将str转换为的字符集的名称。

  • source_char_set参数是数据库中存储str的字符集的名称。默认值为数据库字符集。

  • 目标字符集和源字符集参数都可以是文字或包含字符集名称的列。

  • 为了在字符转换中实现完全对应,目标字符集必须包含源字符集中定义的所有字符的表示。如果目标字符集中不存在某个字符,则会出现替换字符。替换字符可以作为字符集定义的一部分进行定义。

示例:

SELECT CONVERT('娴??', 'gbk', 'utf8') from dual; FROM DUAL;
convert
---------
测试
(1 row)

4.4.21. NUMTOYMINTERVAL

函数作用:NUMTOYMINTERVAL将数字转换为INTERVAL YEAR TO MONTH文字。

语法:

NUMTOYMINTERVAL(n numeric, interval_unit text) returns interval

一般规则:

  • interval_unit的值指定n的单位,并且必须解析为以下字符串值之一:’YEAR’,’MONTH’。

  • interval_unit不区分大小写。

示例:

SELECT NUMTOYMINTERVAL(1,'YEAR') FROM DUAL;
numtoyminterval
-----------------
1 year
(1 row)

4.4.22. TO_BLOB(raw)

函数作用:TO_BLOB(raw)将RAW值转换为BLOB值。

语法:

TO_BLOB(raw) returns blob

示例:

SELECT TO_BLOB(UTL_RAW.CAST_TO_RAW('测试')) FROM DUAL;
        to_blob
----------------
\xe6b58be8af95
(1 row)

4.4.23. TO_CHAR

函数作用:将一个值转换为字符串。

语法:

TO_CHAR(num SMALLINT) returns TEXT
TO_CHAR(num INTEGER) returns TEXT
TO_CHAR(num BIGINT) returns TEXT
TO_CHAR(num REAL) returns TEXT
TO_CHAR(num DOUBLE PRECISION) returns TEXT
TO_CHAR(num NUMERIC) returns TEXT
TO_CHAR(date TIMESTAMP) returns TEXT
TO_CHAR(TEXT) returns TEXT

一般规则:

  • TO_CHAR将特定的数字或日期/时间值转换为字符串。

  • 对于num,请指定数字数据类型。

  • 对于date,请指定DATE或TIMESTAMP类型。 另外,您必须事先为nls_date_format变量设置日期/时间格式。 以下是使用SET语句进行设置的示例。

示例:

SELECT TO_CHAR(123.45) FROM DUAL;
 to_char
---------
 123.45
(1 row)

4.4.24. TO_CLOB

函数作用:将字符字符串或数值转换为CLOB值。

语法:

TO_CLOB(str TEXT) returns CLOB

一般规则:

  • TO_CLOB 转换值为CLOB值.

示例:

CREATE TABLE testorafce_to_clob (
        col_char CHAR(10),
        col_varchar2 VARCHAR2(20),
        col_varchar VARCHAR(20),
        col_nchar NCHAR(10),
        col_nvarchar2 NVARCHAR2(20),
        col_smallint smallint,
        col_integer integer,
        col_bigint bigint,
        col_decimal decimal,
        col_numeric numeric,
        col_real real,
        col_double double precision,
        col_clob CLOB,
        col_raw raw(10)
);

INSERT INTO testorafce_to_clob (col_char, col_varchar2, col_varchar, col_nchar, col_nvarchar2, col_smallint, col_integer, col_bigint, col_decimal, col_numeric, col_real, col_double, col_clob, col_raw)
VALUES ('ABC1', 'Hello', 'world', 'hello', 'world', 1, 2, 3, 4, 5, 6, 7, 'This is a CLOB', 'AB');

INSERT INTO testorafce_to_clob (col_char, col_varchar2, col_varchar, col_nchar, col_nvarchar2, col_smallint, col_integer, col_bigint, col_decimal, col_numeric, col_real, col_double, col_clob, col_raw)
VALUES ('ABC2', 'Hello', 'world', 'hello', 'world', 1, 2, 3, 4, 5, 6, 7, 'This is a CLOB', '1');

INSERT INTO testorafce_to_clob (col_char, col_varchar2, col_varchar, col_nchar, col_nvarchar2, col_smallint, col_integer, col_bigint, col_decimal, col_numeric, col_real, col_double, col_clob, col_raw)
VALUES ('ABC3', 'Hello', 'world', 'hello', 'world', 1, 2, 3, 4, 5, 6, 7, to_clob('This is a CLOB'), '1AB456789');

SELECT  to_clob(col_char) AS clob_char,
                to_clob(col_varchar2) AS clob_varchar2,
                to_clob(col_varchar) AS col_varchar,
                to_clob(col_nchar) AS clob_nchar,
                to_clob(col_nvarchar2) AS clob_nvarchar2,
                to_clob(col_clob) AS clob_clob,
                to_clob(col_smallint) AS col_smallint,
                to_clob(col_integer) AS col_integer,
                to_clob(col_bigint) AS col_bigint,
                to_clob(col_decimal) AS col_decimal,
                to_clob(col_numeric) AS col_numeric,
                to_clob(col_real) AS col_real,
                to_clob(col_double) AS col_double,
                to_clob(col_raw) AS clob_nclob
                FROM testorafce_to_clob order by col_char asc;

clob_char  | clob_varchar2 | col_varchar | clob_nchar | clob_nvarchar2 |   clob_clob    | col_smallint | col_integer | col_bigint | col_decimal | col_numeric | col_real | col_double | clob_nclob
------------+---------------+-------------+------------+----------------+----------------+--------------+-------------+------------+-------------+-------------+----------+------------+------------
ABC1       | Hello         | world       | hello      | world          | This is a CLOB | 1            | 2           | 3          | 4           | 5           | 6        | 7          | AB
ABC2       | Hello         | world       | hello      | world          | This is a CLOB | 1            | 2           | 3          | 4           | 5           | 6        | 7          | 01
ABC3       | Hello         | world       | hello      | world          | This is a CLOB | 1            | 2           | 3          | 4           | 5           | 6        | 7          | 01AB456789
(3 rows)

4.4.25. TO_DATE

函数作用:根据指定的格式将字符串转换为日期。

语法:

    TO_DATE(str TEXT) returns TIMESTAMP
TO_DATE(str TEXT, fmt TEXT) returns TIMESTAMP

一般规则:

  • TO_DATE将字符串str根据指定的格式fmt转换为日期。

  • 指定一个表示日期/时间的字符串。

  • 指定所需的日期/时间格式。如果省略,则使用nls_date_format变量中指定的格式。 如果未设置nls_date_format变量,则使用现有的日期/时间输入解释。 以下是使用SET语句进行设置的示例。

示例:

SELECT TO_DATE('2016/12/31','YYYY/MM/DD') FROM DUAL;
 to_date
---------------------
 2016-12-31 00:00:00
(1 row)

4.4.26. TO_MULTI_BYTE

函数作用:将单字节字符串转换为多字节字符串。

语法:

TO_MULTI_BYTE(str TEXT) returns TEXT

一般规则:

  • TO_MULTI_BYTE将字符串str中的半角字符转换为全角字符,并返回转换后的字符串。

  • 指定一个表示日期/时间的字符串。

  • 指定所需的日期/时间格式。如果省略,则使用nls_date_format变量中指定的格式。 如果未设置nls_date_format变量,则使用现有的日期/时间输入解释。 以下是使用SET语句进行设置的示例。

示例:

SELECT TO_MULTI_BYTE('abc123') FROM DUAL;
 to_multi_byte
---------------
   ******
(1 row)

4.4.27. TO_NUMBER

函数作用:根据指定的格式将值转换为数字。

语法:

TO_NUMBER(str TEXT) returns NUMERIC
TO_NUMBER(num NUMERIC) returns NUMERIC
TO_NUMBER(num NUMERIC, fmt NUMERIC) returns NUMERIC

一般规则:

  • TO_NUMBER将指定的值按照指定的格式fmt转换为数字值。

  • 对于num,指定一个数字数据类型。

  • 对于str,指定一个表示数字值的字符串。 数字值必须由可转换字符组成。

  • 指定所需的数字数据格式。 指定的数字值将被处理为数据类型表达式。

  • 返回值的数据类型是 NUMERIC。

示例:

SELECT TO_NUMBER(-130.5) FROM DUAL;
 to_number
-----------
    -130.5
(1 row)

4.4.28. HEXTORAW(char)

函数作用:将char、VARCHAR2、NCHAR或NVARCHAR2数据类型中包含十六进制数字的char转换为原始值。

语法:

HEXTORAW(lt_catalog.varchar2) returns text
HEXTORAW(text) returns text
HEXTORAW(varchar2) returns text

一般规则:

  • TO_SINGLE_BYTE将字符串str中的全角字符转换为半角字符,并返回转换后的字符串。

  • 只有可以显示为半角的全角字母数字字符、空格和符号才能被转换。

  • 返回值的数据类型为TEXT。

示例:

   SELECT TO_SINGLE_BYTE('******') FROM DUAL;
 to_single_byte
----------------
 xyz999
(1 row)

4.4.29. ASCIISTR

函数作用:ASCIISTR以一个字符串或解析为字符串的表达式作为其参数,并返回数据库字符集中字符串的ASCII版本。

语法:

ASCIISTR(str TEXT) returns TEXT

一般规则:

  • 非ASCII字符被转换为形式xxxx,其中xxxx表示UTF-16代码单元。

  • 返回值的数据类型为TEXT。

示例:

SELECT ASCIISTR('AB?CDE') FROM DUAL;
 asciistr
----------------
 AB\00C4CDE
(1 row)

4.4.30. NUMTODSINTERVAL(n,text)

函数作用:将n转换为一个从日到秒的时间间隔。参数n可以是任何NUMBER值或可以隐式转换为NUMBER值的表达式。参数text的数据类型可以是CHAR、VARCHAR2、NCHAR或NVARCHAR2。text的值指定n的单位

语法:

NUMTODSINTERVAL(double precision, text ) returns interval

4.4.31. RAWTOHEX(raw)

函数作用:将raw转换为包含其十六进制表示的字符值。

语法:

RAWTOHEX(row) returns row
RAWTOHEX(text) returns text

4.4.32. TO_TIMESTAMP(raw)

函数作用:将char转换为TIMESTAMP数据类型的值

语法:

TO_TIMESTAMP(text,text) returns timestamp with time zone
TO_TIMESTAMP(double precision) returns timestamp with time zone

4.4.33. UNISTR(text)

函数作用:将文本文本或解析为字符数据的表达式作为参数,并以国家字符集的形式返回它

语法:

UNISTR(text) returns text

4.5. 聚合函数

4.5.1. APPROX_COUNT(expr)【暂不支持】

函数作用:返回表达式的近似计数

4.5.2. APPROX_COUNT_DISTINCT(expr)【暂不支持】

函数作用:返回expr中包含不同值的大概行数

4.5.3. APPROX_COUNT_DISTINCT_AGG【暂不支持】

函数作用:将一列详细信息作为输入,其中包含有关不同值的近似计数的信息,并使您能够对这些计数执行聚合。

4.5.4. APPROX_COUNT_DISTINCT_DETAIL(expr)【暂不支持】

函数作用:计算关于包含expr不同值的行的大概数目的信息,并返回一个称为detail的BLOB值,该值以特殊格式包含该信息

4.5.5. APPROX_PERCENTILE_AGG【暂不支持】

函数作用:将包含近似百分位信息的详细信息列作为其输入,并使您能够执行该信息的聚合

4.5.6. APPROX_PERCENTILE_DETAIL(expr)【暂不支持】

函数作用:计算expr值的近似百分位信息,并返回一个称为detail的BLOB值,该值以特殊格式包含该信息

4.5.7. APPROX_RANK【暂不支持】

函数作用:返回一组值中的近似值

4.5.8. APPROX_SUM(expr)【不兼容】

函数作用:返回expr的近似和。如果提供MAX_ERROR作为第二个参数,则该函数返回实际和近似和之间的最大误差

4.5.9. COLLECT【暂不支持】

函数作用:它将任意类型的列作为参数,并从所选的行中创建输入类型的嵌套表。要从该函数获得准确的结果,必须在CAST函数中使用它

4.5.10. GROUPING【暂不支持】

函数作用:将超聚合行与常规分组行区分开来

4.5.11. GROUPING_ID【暂不支持】

函数作用:返回与行关联的GROUPING位向量对应的数字

4.5.12. JSON_ARRAYAGG【暂不支持】

函数作用:它将一列SQL表达式作为输入,将每个表达式转换为JSON值,并返回包含这些JSON值的单个JSON数组。

4.5.13. JSON_OBJECTAGG【暂不支持】

函数作用:它将一个属性键值对作为输入。通常,属性键、属性值或两者都是SQL表达式的列

4.5.14. STATS_KS_TEST【暂不支持】

函数作用:它比较两个样本以测试它们是来自相同的总体还是来自具有相同分布的总体

4.5.15. STATS_MODE【暂不支持】

函数作用:接受一组值作为参数,并返回出现频率最高的值

4.5.16. STATS_MW_TEST【暂不支持】

函数作用:检验两个总体具有相同分布函数的零假设和两个分布函数不同的备择假设

4.5.17. STATS_ONE_WAY_ANOVA【暂不支持】

函数作用:通过比较两种不同的方差估计来检验(对于组或变量)的均值差异的统计显著性

4.5.18. SYS_OP_ZONE_ID【暂不支持】

函数作用:接受row作为参数,并返回一个zone ID

4.5.19. SYS_XMLAGG(expr)【暂不支持】

函数作用:聚合expr表示的所有XML文档或片段,并生成单个XML文档

4.5.20. TO_APPROX_COUNT_DISTINCT【暂不支持】

函数作用:接受一个包含近似不同值计数信息的细节作为输入,并将其转换为NUMBER值

4.5.21. TO_APPROX_PERCENTILE【暂不支持】

函数作用:将包含近似百分位数信息、百分位数值和排序规范的详细信息作为其输入,并返回相对于排序规范而言属于该百分位数值的近似插值值

4.5.22. AVG(expr)

函数作用:返回expr的平均值

语法:

AVG(bigint) returns numeric
AVG(double precision) returns double precision
AVG(integer) returns numeric
AVG(interval) returns interval
AVG(numeric) returns text
AVG(real) returns double precision
AVG(smallint) returns numeric

4.5.23. CORR(double precision, double precision)

函数作用:返回一组数字对的相关系数

语法:

CORR(double precision, double precision) returns double precision

4.5.24. COUNT

函数作用:查询返回的行数

语法:

COUNT("any" ) returns bigint

4.5.25. COVAR_POP

函数作用:返回一组数字对的总体协方差

语法:

COVAR_POP(double precision, double precision ) returns double precision

4.5.26. COVAR_SAMP

函数作用:返回一组数字对的样本协方差

语法:

COVAR_SAMP(double precision, double precision ) returns double precision

4.5.27. CUME_DIST

函数作用:计算一组值中一个值的累积分布。CUME_DIST返回的值范围是>0到<=1。这些值总是计算为相同的累积分布值

语法:

CUME_DIST( VARIADIC "any" ORDER BY VARIADIC "any") returns double precision

4.5.28. DENSE_RANK(NUMBER)

函数作用:在一组有序的行中计算一行的秩,并以NUMBER的形式返回秩。排名是从1开始的连续整数。最大的秩值是查询返回的唯一值的个数。在发生并列时,不会跳过等级值。具有相同排名标准值的行将获得相同的排名。此函数对于top-N和bottom-N报告非常有用

语法:

DENSE_RANK( VARIADIC "any" ORDER BY VARIADIC "any") returns bigint

4.5.29. MAX(anyarray)

函数作用:返回anyarray的最大值

语法:

MAX(anyarray) returns anyarray
MAX(anyenum) returns anyenum
MAX(bigint) returns bigint
MAX(character) returns character
MAX(date) returns date

4.5.30. MIN(anyarray)

函数作用:返回anyarray的最小值

语法:

MIN(anyarray) returns anyarray
MIN(anyenum) returns anyenum
MIN(bigint) returns bigint
MIN(character) returns character
MIN(date) returns date

4.5.31. PERCENT_RANK

函数作用:返回的值范围是0到1,包括0到1。任何集合中的第一行的PERCENT_RANK为0。返回值是NUMBER。

语法:

PERCENT_RANK(VARIADIC "any" ORDER BY VARIADIC "any" )

4.5.32. PERCENTILE_CONT

函数作用:逆分布函数,它假设一个连续分布模型。它接受一个百分位数值和一个排序规范,并返回一个相对于排序规范而言属于该百分位数值的插值值。空值在计算中被忽略。

语法:

PERCENTILE_CONT(double precision)
PERCENTILE_CONT(double precision[])
PERCENTILE_CONT(interval)
PERCENTILE_CONT(interval[])

4.5.33. PERCENTILE_DISC

函数作用:逆分布函数,它假设一个离散分布模型。它接受一个百分位数值和一个排序规范,并从集合中返回一个元素。空值在计算中被忽略。

语法:

PERCENTILE_DISC(anyelement)
PERCENTILE_DISC(anyarray)

4.5.34. RANK

函数作用:计算一个值在一组值中的排名。返回类型是整数。

语法:

RANK(VARIADIC "any" ORDER BY VARIADIC "any")

4.5.35. STDDEV

函数作用:计算expr的样本标准差,expr是一组数字.

语法:

STDDEV(bigint) return bigint
STDDEV(double precision) return double precision
STDDEV(integer) return integer
STDDEV(numeric) return numeric
STDDEV(real) return real

4.5.36. STDDEV

函数作用:计算expr的样本标准差,expr是一组数字.

语法:

STDDEV(bigint) return bigint
STDDEV(double precision) return double precision
STDDEV(integer) return integer
STDDEV(numeric) return numeric
STDDEV(real) return real

4.5.37. STDDEV_POP(expr)

函数作用:计算expr的总体标准差并返回总体方差的平方根

语法:

STDDEV_POP(bigint) return bigint
STDDEV_POP(double precision) return double precision
STDDEV_POP(integer) return integer
STDDEV_POP(numeric) return numeric
STDDEV_POP(real) return real

4.5.38. STDDEV_SAMP(expr)

函数作用:计算expr的累积样本标准差并返回样本方差的平方根

语法:

STDDEV_SAMP(bigint) return bigint
STDDEV_SAMP(double precision) return double precision
STDDEV_SAMP(integer) return integer
STDDEV_SAMP(numeric) return numeric
STDDEV_SAMP(real) return real

4.5.39. SUM(expr)

函数作用:返回expr值的和,expr可以为:bigint,double precision,integer,numeric,smallint

语法:

SUM(bigint) return bigint
SUM(double precision) return double precision
SUM(integer) return integer
SUM(numeric) return numeric
SUM(real) return real

4.5.40. VAR_POP

函数作用:返回一组数字在丢弃该集合中的空值后的总体方差

语法:

VAR_POP(bigint) return bigint
VAR_POP(double precision) return double precision
VAR_POP(integer) return integer
VAR_POP(numeric) return numeric
VAR_POP(real) return real

4.5.41. VAR_SAMP

函数作用:返回一组数字在丢弃该集合中的空值后的样本方差

语法:

VAR_SAMP(bigint) return bigint
VAR_SAMP(double precision) return double precision
VAR_SAMP(integer) return integer
VAR_SAMP(numeric) return numeric
VAR_SAMP(real) return real

4.5.42. VARIANCE(expr)

函数作用:方差返回expr的方差。您可以将它用作聚合函数或分析函数。 Oracle数据库计算expr的方差如下: 如果expr中的行数= 1,则为0 如果expr中的行数> 1,则为VAR_SAMP 如果指定DISTINCT,则只能指定analytic_clause子句的query_partition_clause子句。order_by_clause子句和windowing_clause子句是不允许的。

语法:

VARIANCE(bigint) return bigint
VARIANCE(double precision) return double precision
VARIANCE(integer) return integer
VARIANCE(numeric) return numeric
VARIANCE(real) return real

4.5.43. XMLAGG(XML)

函数作用:它接受一组XML片段并返回一个聚合的XML文档。

语法:

XMLAGG(xml) return xml

4.6. 分析函数

4.6.1. CLUSTER_DETAILS【暂不支持】

函数作用:返回选择中每一行的集群详细信息

4.6.2. CLUSTER_DISTANCE【暂不支持】

函数作用:返回选择中每一行的集群距离

4.6.3. CLUSTER_ID【暂不支持】

函数作用:返回选择中每一行的最高概率集群的标识符

4.6.4. CLUSTER_PROBABILITY【暂不支持】

函数作用:返回选择中每一行的概率。概率是指概率最大的集群或指定的cluster_id

4.6.5. CLUSTER_SET【暂不支持】

函数作用:为选择的每一行返回一组集群ID和概率对

4.6.6. FEATURE_DETAILS【暂不支持】

函数作用:返回选择中每行的特性详细信息。返回值是一个XML字符串

4.6.7. FEATURE_ID【暂不支持】

函数作用:返回选择中每行的最高值特性的标识符

4.6.8. FEATURE_SET【暂不支持】

函数作用:选择的每一行返回一组特征ID和特征值对

4.6.9. PREDICTION_SET【暂不支持】

函数作用:返回一组预测,其中包含选择中每行的概率或成本

4.6.10. LAG

函数作用:它提供了在没有自连接的情况下同时访问表的多行。给定从查询返回的一系列行和游标的位置,LAG提供对位于该位置之前的给定物理偏移位置的行的访问。

语法:

LAG(anyelement, integer, anyelement) RETURN anyelement
LAG(anyelement, integer, anyelement) RETURN anyelement
LAG(anyelement, integer, anyelement) RETURN anyelement

4.6.11. LISTAGG

函数作用:对于指定的度量,LISTAGG在ORDER BY子句中指定的每个组中排序数据,然后连接度量列的值

语法:

LISTAGG(text, text) return text
LISTAGG(text) return text

4.7. JSON函数

4.7.1. JSON_QUERY()【暂不支持】

函数作用:数据中选择并返回一个或多个值json,然后返回这些值。

4.7.2. JSON_TABLE()【暂不支持】

函数作用:创建JSON数据的关系视图。它将JSON数据计算的结果映射到关系行和列

4.7.3. JSON_VALUE()【暂不支持】

函数作用:在JSON数据中查找指定的标量JSON值,并将其作为SQL值返回。

4.7.4. JSON_ARRAY()【暂不支持】

函数作用:将一系列SQL标量表达式或一个集合类型实例(VARRAY或NESTED TABLE)作为其输入。

4.7.5. JSON_ARRAYAGG()【暂不支持】

函数作用:将一列SQL表达式作为输入,将每个表达式转换为JSON值,并返回包含这些JSON值的单个JSON数组。

4.7.6. JSON_DATAGUIDE()【暂不支持】

函数作用:接受JSON数据的表列作为输入,并将数据指南作为CLOB返回。

4.7.7. JSON_OBJECT(text[])

函数作用:参数为一个键值对序列或一个对象类型实例作为其输入。集合类型不能传递给JSON_OBJECT。它返回一个JSON对象,其中包含每个键值对的对象成员

语法:

JSON_OBJECT(text[]) RETURN json
JSON_OBJECT(text[],text[]) RETURN json

4.7.8. json_object_agg()

函数作用:它将一个属性键值对作为输入。通常,属性键、属性值或两者都是SQL表达式的列。该函数为每个键值对构造一个对象成员,并返回包含这些对象成员的单个JSON对象。

语法:

json_object_agg( "any", "any") RETURN json

4.8. 比较函数

4.8.1. GREATEST(exp1…expn)【暂不支持】

函数作用:返回包含一个或多个表达式的列表中的最大值。

4.8.2. LEAST(exp1…expn)【暂不支持】

函数作用:返回包含一个或多个表达式的列表中的最小值

4.9. 分层函数

4.9.1. SYS_CONNECT_BY_PATH()【暂不支持】

函数作用:仅在分层查询中有效。它返回列值从根到节点的路径,由CONNECT by条件返回的每一行用字符分隔列值

4.10. 环境和标识符函数

4.10.1. CON_DBID_TO_ID【暂不支持】

函数作用: 指定一个NUMBER值或任何可以隐式转换为NUMBER的值。

4.10.2. CON_GUID_TO_ID【暂不支持】

函数作用: 将容器GUID(全局唯一标识符)作为参数并返回容器ID

4.10.3. CON_NAME_TO_ID【暂不支持】

函数作用:接受一个容器名作为参数,并返回容器ID。

4.10.4. CON_UID_TO_ID【暂不支持】

函数作用: 将容器UID(唯一标识符)作为参数,并返回容器ID。

4.10.5. ORA_INVOKING_USER【暂不支持】

函数作用: 返回调用当前语句或视图的数据库用户名。

4.10.6. ORA_INVOKING_USERID【暂不支持】

函数作用:返回调用当前语句或视图的数据库用户的标识符。

4.10.7. SYS_TYPEID【暂不支持】

函数作用:返回操作数最具体类型的类型id。此值主要用于标识可替换列下面的类型区分列。

4.10.8. UID【暂不支持】

函数作用: 返回一个唯一标识会话用户(登录的用户)的整数。

4.10.9. SYS_CONTEXT

函数作用:返回当前时刻与上下文命名空间关联的参数的值。

语法:

SYS_CONTEXT(namespace text, parameter text, length integer DEFAULT 256) return text

4.10.10. USERENV()

函数作用:返回关于当前会话的信息。此信息可以用于编写一个应用程序特定的审计跟踪表或确定特定于语言的角色目前使用的会话。

语法:

USERENV(parameter text) return text

4.11. 编码和解码函数

4.11.1. DECODE(expr)

函数作用:将expr逐个与每个搜索值进行比较。如果expr等于一个搜索,那么Oracle数据库返回相应的结果。如果没有找到匹配,那么Oracle返回默认值

语法:

DECODE("any", "any", date  )  RETURN date
DECODE("any", "any", date, VARIADIC "any"  )  RETURN character varying
DECODE(integer, integer, numeric, integer, numeric, integer )  RETURN integer
DECODE(numeric, integer, numeric, integer, numeric, integer, numeric)  RETURN numeric
DECODE(text, numeric, integer, integer)  RETURN integer
DECODE(text, text, text, text, text, text, text)  RETURN text

4.11.2. DUMP(expr)

函数作用:返回一个字符类型值,其中包含数据类型、字节长度和expr的内部表示。返回的结果总是在数据库字符集中

语法:

DUMP("any")  RETURN date
DUMP("any", integer)  RETURN character varying
DUMP(text)  RETURN integer
DUMP(text, integer)  RETURN numeric

4.11.3. ORA_HASH()

函数作用:它计算给定表达式的哈希值。

语法:

ORA_HASH(p_data anyelement, p_buckets integer DEFAULT 0, p_seed integer DEFAULT 0) return integer

4.11.4. STANDARD_HASH()【暂不支持】

函数作用:使用国家标准技术局定义和标准化的几种哈希算法来计算给定表达式的哈希值。该函数可以用于身份验证或数据完整性,例如签名,校验和、指纹。

4.11.5. VSIZE(expr)

函数作用:返回expr的大小(字节)数

语法:

VSIZE("any") RETUN integer

5. SQL语句类型

5.1. DDL语句

DDL语句

类型

概要

详细说明链接

是否支持

DDL

创建一个分析视图

CREATE ANALYTIC VIEW

暂不支持

DDL

创建属性维度

CREATE ATTRIBUTE DIMENSION

暂不支持

DDL

并提供了一套完整的增强审计特性

CREATE AUDIT POLICY (Unified Auditing)

暂不支持

DDL

创建集群

CREATE CLUSTER

暂不支持

DDL

重新创建控制文件

CREATE CONTROLFILE

暂不支持

DDL

创建一个新数据库

CREATE DATABASE

支持

DDL

创建数据库链接

CREATE DATABASE LINK

暂不支持

DDL

创建一个维度

CREATE DIMENSION

暂不支持

DDL

创建目录对象

CREATE DIRECTORY

暂不支持

DDL

指定Oracle数据库为您管理该组。

CREATE DISKGROUP

暂不支持

DDL

创建一个新版本作为现有版本的子版本

CREATE EDITION

暂不支持

DDL

创建闪回归档

CREATE FLASHBACK ARCHIVE

暂不支持

DDL

建独立的存储函数或调用规范

CREATE FUNCTION

暂不支持

DDL

创建一个层次结构

CREATE HIERARCHY

暂不支持

DDL

定义一个新索引

CREATE INDEX

支持

DDL

创建一个INDEXTYPE

CREATE INDEXTYPE

暂不支持

DDL

创建包含JAVA源、类或资源的模式对象

CREATE JAVA

暂不支持

DDL

创建连接组

CREATE INMEMORY JOIN GROUP

暂不支持

DDL

创建与操作系统共享库关联的模式对象

CREATE LIBRARY

暂不支持

DDL

创建PDB锁定配置文件

CREATE LOCKDOWN PROFILE

暂不支持

DDL

定义一个新的物化视图

CREATE MATERIALIZED VIEW

支持

DDL

创建物化视图日志

CREATE MATERIALIZED VIEW LOG

暂不支持

DDL

创建一个zone map

CREATE MATERIALIZED ZONEMAP

暂不支持

DDL

定义一个新的操作符

CREATE OPERATOR

支持

DDL

创建存储的大纲

CREATE OUTLINE

暂不支持

DDL

存储包创建规范

CREATE PACKAGE

暂不支持

DDL

创建存储包的主体

CREATE PACKAGE BODY

暂不支持

DDL

创建文本参数文件是获取数据库正在使用的当前参数设置列表

CREATE PFILE

暂不支持

DDL

创建可插拔数据库

CREATE PLUGGABLE DATABASE

暂不支持

DDL

定义一个新的过程

CREATE PROCEDURE

支持

DDL

创建一个概要文件,它是对数据库资源的一组限制

CREATE PROFILE

暂不支持

DDL

创建还原点,还原点是一个与数据库的时间戳或SCN相关联的名称

CREATE RESTORE POINT

暂不支持

DDL

定义一个新的数据库角色

CREATE ROLE

支持

DDL

创建回滚段

CREATE ROLLBACK SEGMENT

暂不支持

DDL

定义一个新模式

CREATE SCHEMA

支持

DDL

定义一个新的序列发生器

CREATE SEQUENCE

支持

DDL

从传统的纯文本初始化参数文件或从当前的系统范围设置创建服务器参数文件

CREATE SPFILE

暂不支持

DDL

创建同义词

CREATE SYNONYM

暂不支持

DDL

定义一个新表

CREATE TABLE

支持

DDL

定义一个新的表空间

CREATE TABLESPACE

支持

DDL

创建表空间集

CREATE TABLESPACE SET

暂不支持

DDL

定义一个新触发器

CREATE TRIGGER

支持

DDL

定义一种新的数据类型

CREATE TYPE

支持

DDL

定义或实现对象类型规范中定义的成员方法。

CREATE TYPE BODY

暂不支持

DDL

定义一个新的数据库角色

CREATE USER

支持

DDL

定义一个新视图

CREATE VIEW

支持

DDL

修改一个分析视图

ALTER ANALYTIC VIEW

暂不支持

DDL

修改属性维度

ALTER ATTRIBUTE DIMENSION

暂不支持

DDL

修改增强审计特性

ALTER AUDIT POLICY (Unified Auditing)

暂不支持

DDL

修改集群

ALTER CLUSTER

暂不支持

DDL

更改一个数据库

ALTER DATABASE

支持

DDL

修改数据库链接

ALTER DATABASE LINK

暂不支持

DDL

修改一个维度

ALTER DIMENSION

暂不支持

DDL

修改目录对象

ALTER DIRECTORY

暂不支持

DDL

允许对磁盘组或磁盘组中的磁盘执行许多操作。

ALTER DISKGROUP

暂不支持

DDL

修改一个新版本作为现有版本的子版本

ALTER EDITION

暂不支持

DDL

修改闪回归档

ALTER FLASHBACK ARCHIVE

暂不支持

DDL

修改独立的存储函数或调用规范

ALTER FUNCTION

暂不支持

DDL

修改一个层次结构

ALTER HIERARCHY

暂不支持

DDL

更改一个索引的定义

ALTER INDEX

支持

DDL

修改一个INDEXTYPE

ALTER INDEXTYPE

暂不支持

DDL

修改连接组

ALTER INMEMORY JOIN GROUP

暂不支持

DDL

修改与操作系统共享库关联的模式对象

ALTER LIBRARY

暂不支持

DDL

修改PDB锁定配置文件

ALTER LOCKDOWN PROFILE

暂不支持

DDL

更改一个物化视图的定义

ALTER MATERIALIZED VIEW

支持

DDL

修改物化视图日志

ALTER MATERIALIZED VIEW LOG

暂不支持

DDL

修改一个zone map

ALTER MATERIALIZED ZONEMAP

暂不支持

DDL

更改一个操作符的定义

ALTER OPERATOR

支持

DDL

修改存储的大纲

ALTER OUTLINE

暂不支持

DDL

修改存储包创建规范

ALTER PACKAGE

暂不支持

DDL

修改存储包的主体

ALTER PACKAGE BODY

暂不支持

DDL

修改文本参数文件是获取数据库正在使用的当前参数设置列表

ALTER PFILE

暂不支持

DDL

修改可插拔数据库

ALTER PLUGGABLE DATABASE

暂不支持

DDL

更改一个过程的定义

ALTER PROCEDURE

支持

DDL

修改一个概要文件,它是对数据库资源的一组限制

ALTER PROFILE

暂不支持

DDL

修改还原点,还原点是一个与数据库的时间戳或SCN相关联的名称

ALTER RESTORE POINT

暂不支持

DDL

更改一个数据库角色

ALTER ROLE

支持

DDL

更改现有序列的增量、最小值和最大值、缓存数和行为

ALTER SEQUENCE

支持

DDL

修改现有同义词。

ALTER SYNONYM

不支持

DDL

动态修改Oracle数据库实例

ALTER SYSTEM

支持

DDL

修改非分区表、分区表、表分区或表子分区的定义

ALTER TABLE

支持

DDL

修改一个现有的表空间或它的一个或多个数据文件或临时文件。

ALTER TABLESPACE

支持

DDL

修改一个已存在的表空间集的属性。

ALTER TABLESPACE SET

不支持

DDL

启用、禁用或编译数据库触发器。

ALTER TRIGGER

支持

DDL

添加或删除成员属性或方法。

ALTER TYPE

支持

DDL

更改数据库用户的身份验证或数据库资源特征

ALTER USER

支持

DDL

显式地重新编译无效的视图或修改视图约束。

ALTER VIEW

支持

DDL

将默认统计信息或统计类型与列、独立函数、包、类型、域索引或索引类型解除关联

DISASSOCIATE STATISTICS

暂不支持

DDL

删除一个分析视图

DROP ANALYTIC VIEW

暂不支持

DDL

修改属性维度

DROP ATTRIBUTE DIMENSION

暂不支持

DDL

修改属性维度

DROP AUDIT POLICY (Unified Auditing)

暂不支持

DDL

从数据库中删除上下文名称空间。

DROP CONTEXT

暂不支持

DDL

删除数据库

DROP DATABASE

暂不支持

DDL

删除数据库链接

DROP DATABASE LINK

暂不支持

DDL

删除一个维度

DROP DIMENSION

暂不支持

DDL

删除目录对象

DROP DIRECTORY

暂不支持

DDL

删除一个新版本作为现有版本的子版本

DROP EDITION

暂不支持

DDL

删除闪回归档

DROP FLASHBACK ARCHIVE

暂不支持

DDL

删除一个INDEXTYPE

DROP INDEXTYPE

暂不支持

DDL

删除连接组

DROP INMEMORY JOIN GROUP

暂不支持

DDL

删除包含JAVA源、类或资源的模式对象

DROP JAVA

暂不支持

DDL

删除与操作系统共享库关联的模式对象

DROP LIBRARY

暂不支持

DDL

删除PDB锁定配置文件

DROP LOCKDOWN PROFILE

暂不支持

DDL

删除物化视图日志

DROP MATERIALIZED VIEW LOG

暂不支持

DDL

删除一个zone map

DROP MATERIALIZED ZONEMAP

暂不支持

DDL

删除存储的大纲

DROP OUTLINE

暂不支持

DDL

删除可插拔数据库

DROP PLUGGABLE DATABASE

暂不支持

DDL

删除一个概要文件,它是对数据库资源的一组限制

DROP PROFILE

暂不支持

DDL

删除还原点,还原点是一个与数据库的时间戳或SCN相关联的名称

DROP RESTORE POINT

暂不支持

DDL

删除回滚段

DROP ROLLBACK SEGMENT

暂不支持

DDL

删除同义词

DROP SYNONYM

暂不支持

DDL

删除表空间集

DROP TABLESPACE SET

暂不支持

DDL

删除集群

DROP CLUSTER

暂不支持

DDL

移除一个数据库

DROP DATABASE

支持

DDL

移除一个函数

DROP FUNCTION

支持

DDL

删除层次结构。

DROP HIERARCHY

不支持

DDL

移除一个索引

DROP INDEX

支持

DDL

移除一个物化视图

DROP MATERIALIZED VIEW

支持

DDL

移除一个操作符

DROP OPERATOR

支持

DDL

移除一个过程

DROP PROCEDURE

支持

DDL

移除一个数据库角色

DROP ROLE

支持

DDL

移除一个序列

DROP SEQUENCE

支持

DDL

移除一个表

DROP TABLE

支持

DDL

移除一个表空间

DROP TABLESPACE

支持

DDL

移除一个触发器

DROP TRIGGER

支持

DDL

移除一个数据类型

DROP TYPE

支持

DDL

删除对象类型、数组或嵌套表类型的主体。

DROP TYPE BODY

不支持

DDL

创建一个分析视图

DROP PACKAGE

暂不支持

DDL

移除一个数据库角色

DROP USER

支持

DDL

移除一个视图

DROP VIEW

支持

DDL

定义访问特权

GRANT

支持

DDL

移除访问特权

REVOKE

支持

DDL

清空一个表或者一组表

TRUNCATE

支持

DDL

创建一个分析视图

AUDIT

暂不支持

DDL

回收站中删除表或索引,并释放与该对象关联的所有空间

PURGE

暂不支持

DDL

重命名表、视图、序列或私有同义词

RENAME

暂不支持

DDL

将数据库返回到过去的时间或系统更改号(SCN)

FLASHBACK DATABASE

暂不支持

DDL

恢复表的早期状态

FLASHBACK TABLE

暂不支持

5.1.1. CREATE DATABASE

创建一个新数据库

语法:

CREATE DATABASE name
        [ [ WITH ] [ OWNER [=] user_name ]
                [ TEMPLATE [=] template ]
                [ ENCODING [=] encoding ]
                [ LOCALE [=] locale ]
                [ LC_COLLATE [=] lc_collate ]
                [ LC_CTYPE [=] lc_ctype ]
                [ TABLESPACE [=] tablespace_name ]
                [ ALLOW_CONNECTIONS [=] allowconn ]
                [ CONNECTION LIMIT [=] connlimit ]
                [ IS_TEMPLATE [=] istemplate ] ]
                [ LIGHTDB_SYNTAX_COMPATIBLE_TYPE [=] compa_type ] ]
                [ LIGHTDB_MYSQL_LOWER_CASE_TABLE_NAMES [=] mysql_lower_case ] ]
                [ LIGHTDB_ASCII_ZERO_STORE_VALUE [=] ascii_zero_store_value ] ]

描述:

  • CREATE DATABASE创建一个新的LightDB数据库。

  • 要创建一个数据库,你必须是一个超级用户或者具有特殊的CREATEDB特权。见CREATE ROLE。

  • 默认情况下,新数据库将通过克隆标准系统数据库template1被创建。可以通过写TEMPLATE name指定一个不同的模板。特别地,通过写TEMPLATE template0你可以创建一个原始的数据库(其中没有用户定义的对象存在并且系统对象没有被更改),它将只包含你的LightDB版本所预定义的标准对象。如果你希望避免拷贝任何可能被加入到template1中的本地安装对象,这将有所帮助。

参数:

  • name

    要创建的数据库名。

  • user_name

    将拥有新数据库的用户的角色名,或者用DEFAULT来使用默认值(即,执行该命令的用户)。要创建一个被另一个角色拥有的数据库,你必须是该角色的一个直接或间接成员,或者是一个超级用户。

  • template

    要从其创建新数据库的模板名称,或者用DEFAULT来使用默认模板(template1)。

  • encoding

    要在新数据库中使用的字符集编码。指定一个字符串常量(例如’SQL_ASCII’),或者一个整数编码编号,或者DEFAULT来使用默认的编码(即,模板数据库的编码)。

  • locale

    这是一个同时设置LC_COLLATE和LC_CTYPE的快捷方式。 如果指定此参数,您不能指定这些参数中的任何一个。

tip

其他语言环境设置 lc_messages, lc_monetary, lc_numeric, and lc_time不是每个数据库固定的, 也不是由该命令设置的。 如果要将它们设置为特定数据库的默认值,则可以使用 ALTER DATABASE… SET.

  • lc_collate

    要在新数据库中使用的排序规则顺序(LC_COLLATE)。这会影响应用到字符串的排序顺序,例如在带 ORDER BY 的查询中,以及文本列上索引所使用的顺序。默认是使用模板数据库的排序规则顺序。附加限制见下文。

  • lc_ctype

    要在新数据库中使用的字符分类(LC_CTYPE)。这会影响字符的类别,如小写、大写和数字。默认是使用模板数据库的字符分类。附加限制见下文。

  • tablespace_name

    将与新数据库相关联的表空间名称,或者DEFAULT来使用模板数据库的表空间。这个表空间将是在这个数据库中创建的对象的表空间。详见CREATE TABLESPACE。

  • allowconn

    如果为假,则没有人能连接到这个数据库。默认为真,表示允许连接(除了 被其他机制约束以外,例如GRANT/REVOKE CONNECT)。

  • connlimit

    这个数据库允许多少并发连接。-1 (默认值)表示没有限制。

  • istemplate

    如果为真,则任何具有CREATEDB特权的用户都可以从 这个数据库克隆。如果为假(默认),则只有超级用户或者该数据库的拥有者 可以克隆它。

  • compa_type

    如果值是oracle,那么这个数据库可以使用oracle的一些功能。 如果值是mysql,那么这个数据库可以使用mysql的一些功能。 如果这些值处于禁用状态,则此数据库无法使用上述功能。 默认值由lightdb_syntax_compatible_type指定

  • mysql_lower_case

    在Mysql兼容模式下,是否开启表名全小写特性。mysql_lower_case的取值为(1,true,on,0,false,off)中的一个,默认值是1。(1,true,on):开启 (0,false,off):不开启

  • ascii_zero_store_value

    Lightdb 23.3引入了一个新的数据库级别GUC参数lightdb_ascii_zero_store_value。 此参数取值范围为0到32,包含0,32。数据库创建时设定,之后不能修改。

可选的参数可以被写成任何顺序,不用按照上面说明的顺序。

示例:

要创建一个新数据库:

CREATE DATABASE lusiadas;

要在一个默认表空间salesspace中创建一个被用户salesapp拥有的新数据库sales:

CREATE DATABASE sales OWNER salesapp TABLESPACE salesspace;

要用不同的语言环境创建数据库music:

CREATE DATABASE music
LOCALE 'sv_SE.utf8'
TEMPLATE template0;

在这个例子中,如果指定的语言环境与template1中的语言环境不同, 则需要TEMPLATE template0子句。(如果不是,则明确指定区域设置是多余的。) 要用不同的语言环境和不同的字符集编码创建数据库music2:

    CREATE DATABASE music2
LOCALE 'sv_SE.iso885915'
ENCODING LATIN9
TEMPLATE template0;

指定的区域设置和编码设置必须匹配,否则会报告错误。 请注意,区域名称是特定于操作系统的, 因此上述命令可能无法在任何地方以相同的方式工作。 在创建数据库testdb之前,查询数据库列表和用户列表:

lightdb@postgres=# \l
                                                                                           List of databases
  Name    |  Owner  | Encoding |   Collate   |    Ctype    |  Access privileges
-----------+---------+----------+-------------+-------------+---------------------
lt_test   | lightdb | UTF8     | zh_CN.UTF-8 | zh_CN.UTF-8 |
postgres  | lightdb | UTF8     | zh_CN.UTF-8 | zh_CN.UTF-8 |
template0 | lightdb | UTF8     | zh_CN.UTF-8 | zh_CN.UTF-8 | =c/lightdb         +
          |         |          |             |             | lightdb=CTc/lightdb
template1 | lightdb | UTF8     | zh_CN.UTF-8 | zh_CN.UTF-8 | =c/lightdb         +
          |         |          |             |             | lightdb=CTc/lightdb
(4 rows)

lightdb@postgres=#
lightdb@postgres=# \du
                                                                List of roles
Role name |                         Attributes                         | Member of
-----------+------------------------------------------------------------+-----------
lightdb   | Superuser, Create role, Create DB, Replication, Bypass RLS | {}

lightdb@postgres=#

oracle兼容模式下创建数据库:

lightdb@postgres=# create database testdb with lightdb_syntax_compatible_type oracle;
NOTICE:  auto create user "testdb" success
CREATE DATABASE
lightdb@postgres=#

然后查询数据库和用户列表:

lightdb@postgres=# \l
                        List of databases
  Name    |  Owner  | Encoding |   Collate   |    Ctype    |  Access privileges
-----------+---------+----------+-------------+-------------+---------------------
lt_test   | lightdb | UTF8     | zh_CN.UTF-8 | zh_CN.UTF-8 |
postgres  | lightdb | UTF8     | zh_CN.UTF-8 | zh_CN.UTF-8 |
template0 | lightdb | UTF8     | zh_CN.UTF-8 | zh_CN.UTF-8 | =c/lightdb         +
          |         |          |             |             | lightdb=CTc/lightdb
template1 | lightdb | UTF8     | zh_CN.UTF-8 | zh_CN.UTF-8 | =c/lightdb         +
          |         |          |             |             | lightdb=CTc/lightdb
testdb    | lightdb | UTF8     | zh_CN.UTF-8 | zh_CN.UTF-8 | =Tc/lightdb        +
          |         |          |             |             | lightdb=CTc/lightdb+
          |         |          |             |             | testdb=CTc/lightdb
(5 rows)

lightdb@postgres=#
lightdb@postgres=# \du
                                                                List of roles
Role name |                         Attributes                         | Member of
-----------+------------------------------------------------------------+-----------
lightdb   | Superuser, Create role, Create DB, Replication, Bypass RLS | {}
testdb    |                                                            | {}

lightdb@postgres=#

5.1.2. CREATE INDEX

定义一个新索引

语法:

CREATE [ UNIQUE ] INDEX [ CONCURRENTLY ] [ [ IF NOT EXISTS ] [schema_name.]name ] ON [ ONLY ] table_name [ USING method ]
        ( { column_name | ( expression ) } [ COLLATE collation ] [ opclass [ ( opclass_parameter = value [, ... ] ) ] ] [ ASC | DESC ] [ NULLS { FIRST | LAST } ] [ LOCAL | GLOBAL ] [, ...] )
        [ INCLUDE ( column_name [, ...] ) ]
        [ WITH ( storage_parameter [= value] [, ... ] ) ]
        [ COMPRESS | NOCOMPRESS | LOGGING | NOLOGGING | COMPRESS LOGGING | COMPRESS NOLOGGING | NOCOMPRESS LOGGING | NOCOMPRESS NOLOGGING | LOGGING COMPRESS | LOGGING NOCOMPRESS | NOLOGGING COMPRESS | NOLOGGING NOCOMPRESS ]
        [ TABLESPACE tablespace_name ]
        [ WHERE predicate ]

描述:

  • CREATE INDEX在指定关系的指定列上构建 一个索引,该关系可以是一个表或者一个物化视图。索引主要被用来提升 数据库性能(不过不当的使用会导致性能变差)。

  • 索引的键域被指定为列名或者写在圆括号中的表达式。如果索引方法支持 多列索引,可以指定多个域。

  • 一个索引域可以是一个从表行的一列或者更多列值进行计算的表达式。 这种特性可以被用来获得对基于基本数据某种变换的数据的快速访问。 例如,一个在upper(col)上计算的索引可以允许子句 WHERE upper(col) = ‘JIM’使用索引。

  • LightDB提供了索引方法 B-树、哈希、GiST、SP-GiST、GIN 以及 BRIN。用户也可以定义自己的索引 方法,但是相对较复杂。

  • 当WHERE子句存在时,会创建一个 部分索引。部分索引只包含表中一部分行的项, 通常索引这一部分会比表的其他部分更有用。例如,如果有一个表包含了 已付和未付订单,其中未付订单占了整个表的一小部分并且是经常被使用 的部分,可以通过只在这一部分上创建一个索引来改进性能。另一种可能 的应用是使用带有UNIQUE的 WHERE在表的一个子集上强制唯一性。

  • WHERE子句中使用的表达式只能引用底层表的列,但 它可以引用所有列而不仅仅是被索引的列。当前, WHERE中也禁止使用子查询和聚集表达式。同样的 限制也适用于表达式索引中的表达式域。

  • 所有在索引定义中使用的函数和操作符必须是“不可变的”, 就是说它们的结果必须仅依赖于它们的参数而不受外在因素(例如另 一个表的内容和当前的时间)的影响。这种限制确保了索引的行为是 良定的。要在一个索引表达式或者WHERE子句中 使用用户定义的函数,记住在创建函数时把它标记为不可变。

  • LightDB支持在创建索引后立即自动收集统计信息。 可以设置lightdb_enable_indexautoanalyze配置变量来决定是否自动收集统计信息。

参数:

  • UNIQUE

    导致系统在索引被创建时(如果数据已经存在)或者加入数据时 检查重复值。会导致重复项的数据插入或者更新尝试将会产生一 个错误。 当唯一索引被应用在分区边上时会有额外的限制,请参考CREATE TABLE。

  • CONCURRENTLY

    当使用了这个选项时,LightDB在构建索引时 不会取得任何会阻止该表上并发插入、更新或者删除的锁。而标准的索引 构建将会把表锁住以阻止对表的写(但不阻塞读),这种锁定会持续到索 引创建完毕。在使用这个选项时有多个需要注意的地方 ? 请见 Building Indexes Concurrently。 对于临时表,CREATE INDEX始终是非并发的,因为没有其他会话可以访问它们,并且创建非并发索引的成本更低。

  • IF NOT EXISTS

    如果一个同名关系已经存在则不要抛出错误。这种情况下会发出一个提示。 注意着并不保证现有的索引与将要创建的索引有任何相似。当 IF NOT EXISTS被指定时,需要指定索引名。

  • INCLUDE

    可选的INCLUDE子句指定一个列的列表,其中的列将被包括在索引中作为非键列。非键列不能作为索引扫描的条件,并且该索引所强制的任何唯一性或者排除约束都不会考虑它们。不过,只用索引的扫描可以返回非键列的内容而无需访问该索引的基表,因为在索引项中就能直接拿到它们。因此,非键列的增加允许查询使用只用索引的扫描,否则就无法使用。 保守地向索引中增加非键列是明智的,特别是很宽的列。如果一个索引元组超过索引类型允许的最大尺寸,数据插入将会失败。在任何情况下,非键列都会重复来自索引基表的数据并且让索引的尺寸膨胀,因此可能会拖慢搜索。此外,B树重复数据删除永远不会与具有非关键列的索引一起使用。 INCLUDE子句中列出的列不需要合适的操作符类,甚至数据类型没有为给定的访问方法定义操作符类的列都可以包括在这个子句中。不支持把表达式作为被包括列,因为它们不能被用在只用索引的扫描中。 当前,有B-树、GiST和SP-GiST索引访问方法支持这一特性。 在这些索引中,INCLUDE子句中列出的列的值被包括在对应于堆元组的叶子元组中,但是不包括在用于树导航的上层索引项中。

  • name

    要创建的索引名称。这里不能包括模式名,因为索引总是被创建在其基表所在 的模式中。如果索引名称被省略,LightDB将基于基 表名称和被索引列名称选择一个合适的名称。

  • ONLY

    如果该表是分区表,指示不要在分区上递归创建索引。默认会递归创建索引。

  • table_name

    要被索引的表的名称(可以被模式限定)。

  • method

    要使用的索引方法的名称。可以选择 btree、hash、 gist、spgist、 gin以及brin。 默认方法是btree。

  • column_name

    一个表列的名称。

  • expression

    一个基于一个或者更多个表列的表达式。如语法中所示,表达式通常必须 被写在圆括号中。不过,如果该表达式是一个函数调用的形式,圆括号可 以被省略。

  • collation

    要用于该索引的排序规则的名称。默认情况下,该索引使用被索引列 的排序规则或者被索引表达式的结果排序规则。当查询涉及到使用非 默认排序规则的表达式时,使用非默认排序规则的索引就能排上用场。

  • opclass

    一个操作符类的名称。详见下文。

  • opclass_parameter

    运算符类参数的名称。详情请见下文。

  • ASC

    指定上升排序(默认)。

  • DESC

    指定下降排序。

  • NULLS FIRST

    指定把空值排序在非空值前面。在指定DESC时, 这是默认行为。

  • NULLS LAST

    指定把空值排序在非空值后面。在没有指定DESC时, 这是默认行为。

  • storage_parameter

    索引方法相关的存储参数的名称。详见 Index Storage Parameters。

  • tablespace_name

    在其中创建索引的表空间。如果没有指定,将会使用 default_tablespace。或者对临时表上的索引使用 temp_tablespaces。

  • predicate

    部分索引的约束表达式。

  • local

    Oracle兼容语法,不支持函数。有必要将配置更改为Oracle兼容模式。

  • global

    Oracle兼容语法,不支持函数。有必要将配置更改为Oracle兼容模式。

  • COMPRESS LOGGING

    为了兼容Oracle数据库语法,新增了四个非保留关键字COMPRESS, LOGGING, NOCOMPRESS, NOLOGGING。 这四个关键字仅是语法糖,没有实现实际的功能。这四个关键字是可选的,如果必须要使用,请放在TABLESPACE关键字之前。

  • schema_name

    为了兼容Oracle数据库语法,CREATE INDEX语句支持为索引名称指定schema_name。这个功能仅是语法糖。

索引存储参数

可选的WITH子句为索引指定存储参数。每一种索引方法都有自己的存储参数集合。B-树、哈希、GiST以及SP-GiST索引方法都接受这个参数:

  • fillfactor (integer)

    索引的填充因子是一个百分数,它决定索引方法将尝试填充索引页面的充满程度。 对于B-树,在初始的索引构建过程中,叶子页面会被填充至该百分数,当在索引右端扩展索引 (增加新的最大键值)时也会这样处理。如果页面后来被完全填满,它们就会被分裂, 导致在磁盘上的索引结构上产生碎片。 B-树使用了默认的填充因子 90,但是也可以选择为 10 到 100 的任何整数值。

B-树索引还接受这个参数:

备注

通过ALTER INDEX关闭deduplicate_items 可以防止将来的插入触发重复数据删除,但本身不会使现有的发布列表元组使用标准的元组表示。

GiST还额外接受这个参数:

  • buffering (enum)

    当OFF时,缓冲被禁用,当ON时,它被启用, 当AUTO时,它最初被禁用,但当索引大小达到 effective_cache_size时,会立即启用。 默认值为AUTO。 请注意,如果排序构建是可能的,则除非指定了buffering=ON, 否则将使用排序构建而不是缓冲构建。

GIN索引接受不同的参数:

  • fastupdate (boolean)

    它是一个布尔参数:ON启用快速更新, OFF禁用之。默认是 ON。

备注

通过ALTER INDEX关闭fastupdate 会阻止未来的更新进入到待处理索引项列表中,但它不会自己处理之前的 待处理项。可以使用VACUUM或者调用 gin_clean_pending_list确保处理完待处理列表的项。

  • gin_pending_list_limit (integer)

    自定义gin_pending_list_limit参数。这个值 要以千字节来指定。

BRIN索引接受不同的参数:

  • pages_per_range (integer)

    定义用于每一个BRIN索引项的块范围由多少个表块组成。默认是128。

  • autosummarize (boolean)

    定义是否只要在下一个页面上检测到插入就为前面的页面范围运行概要操作。

并发构建索引

创建索引可能会干扰数据库的常规操作。通常 LightDB会锁住要被索引的表,让它不能被写入, 并且用该表上的一次扫描来执行整个索引的构建。其他事务仍然可以读取表 , 但是如果它们尝试在该表上进行插入、更新或者删除,它们会被阻塞直到索引 构建完成。如果系统是一个生产数据库,这可能会导致严重的后果。索引非常 大的表可能会需要很多个小时,而且即使是较小的表,在构建索引过程中阻塞 写入者一段时间在生产系统中也是不能接受的。 LightDB支持构建索引时不阻塞写入。这种方法通过 指定CREATE INDEX的CONCURRENTLY选项 实现。当使用这个选项时,LightDB必须执行该表的 两次扫描,此外它必须等待所有现有可能会修改或者使用该索引的事务终止。因此这种 方法比起标准索引构建过程来说要做更多工作并且需要更多时间。不过,由于它 允许在构建索引时继续普通操作,这种方式对于在生产环境中增加新索引很有用。 当然,由索引创建带来的额外 CPU 和 I/O 开销可能会拖慢其他操作。 在并发索引构建中,索引实际上在一个事务中被录入到系统目录,然后在两个 事务中发生两次表扫描。在每一次表扫描之前,索引构建必须等待已经修改了 表的现有事务终止。在第二次扫描之后,索引构建必须等待任何持有早于第二 次扫描的快照(见Chapter 13)的事务终止,如果所涉及的索引 是部分的或具有非简单列引用的列,则还包括在其他表上构建并发索引的任何阶段 所使用的事务。 然后该索引最终能被标记为准备好使用,并且CREATE INDEX命令终止。 不过即便那样,该索引也不是立刻可以用于查询:在最坏的情况下,只要早于 索引构建开始时存在的事务存在,该索引就无法使用。 如果在扫描表示出现问题,例如死锁或者唯一索引中的唯一性被违背, CREATE INDEX将会失败,但留下一个“不可用” 的索引。这个索引会被查询所忽略,因为它可能不完整。不过它仍将消耗更新 开销。ltsql的d命令将把这类索引报告为 INVALID:

lightdb@postgres=# \d tab
        Table "public.tab"
Column |  Type   | Collation | Nullable | Default
--------+---------+-----------+----------+---------
col    | integer |           |          |
Indexes:
        "idx" btree (col) INVALID

这种情况下推荐的恢复方法是删除该索引并且尝试再次执行CREATE INDEX CONCURRENTLY。 (另一种可能性是用REINDEX INDEX CONCURRENTLY重建该索引)。 并发构建一个唯一索引时需要注意的另一点是,当第二次表扫描开始时,唯一约束 已经被强制在其他事务上。这意味着在该索引变得可用之前,其他查询中可能就会 报告该约束被违背,或者甚至在索引构建最终失败的情况中也是这样。还有,如果在 第二次扫描时发生失败,“无效的”索引也会继续强制它的唯一性约束。 表达式索引和部分索引的并发构建也被支持。在这些表达式计算过程中发生的 错误可能导致和上述唯一约束违背类似的行为。 常规索引构建允许在同一个表上同时构建其他常规索引,但是在一个表上同时 只能有一个并发索引构建发生。在两种情况下,在索引被构建时不允许表的模式修改。另一个不同是,一个常规CREATE INDEX 命令可以在一个事务块中执行,但是 CREATE INDEX CONCURRENTLY不行。 当前不支持在分区表上并发生成索引。 然而,你可以在每个分区上单独的并发构建索引,然后最终以非并发的方式创建分区索引,以减少对分区表的写入被锁定的时间。 在这种情况下,生成分区索引仅是元数据操作。

注解

关于索引何时能被使用、何时不被使用以及什么情况下它们有用的信息请 见Chapter 11。

当前,只有 B-树、GiST、GIN 和 BRIN 索引方法支持多键列索引。 是否可以有多个键列与是否可以将INCLUDE列添加到索引无关。 索引最多可以有32列,包括INCLUDE列。 (可以在构建LightDB时修改这个限制)。 当前只有 B-树支持唯一索引。

为索引的每一列可以指定一个带可选参数的操作符类。该操作符 类标识要被该索引用于该列的操作符。例如,一个四字节整数上的 B-树索引 会使用int4_ops类。这个操作符类包括了用于四字节整数 的比较函数。实际上,通常列数据类型的默认操作符类就足够了。对某些数据 类型指定操作符类的主要原因是,可能会有多于一种有意义的顺序。例如, 我们可能想用绝对值或者实数部分对复数类型排序。我们可以通过为该数据 类型定义两个操作符类来做到,并且在创建索引时选择其中合适的类。

当在一个分区表上调用CREATE INDEX时,默认的行为是递归到所有的分区上以确保它们都具有匹配的索引。每一个分区首先会被检查是否有一个等效的索引存在,如果有则该索引将被挂接为被创建索引的一个分区索引,而被创建的索引将成为其父索引。如果不存在匹配的索引,则会创建一个新的索引并且自动进行挂接。如果命令中没有指定索引名称,每个分区中的新索引的名称将被自动决定。如果指定了ONLY选项,则不会进行递归,并且该索引会被标记为无效(一旦所有的分区都得到该索引,ALTER INDEX … ATTACH PARTITION可以把该索引标记为有效)。不过,要注意不管是否指定这一选项,未来使用CREATE TABLE … PARTITION OF创建的任何分区将自动有一个匹配的索引,不管有没有指定ONLY。

对于支持有序扫描的索引方法(当前只有 B-树),可以指定可选子句ASC、 DESC、NULLS FIRST以及NULLS LAST 来修改索引的排序顺序。由于一个有序索引能前向或者反向扫描,通常创建一个 单列DESC索引没什么用处 ? 一个常规索引已经提供了排序 顺序。这些选项的价值是可以创建多列索引,让它的排序顺序匹配有混合排序要求 的查询,例如SELECT … ORDER BY x ASC, y DESC。如果你想要在依靠索引避免排序步骤的查询中支持 “空值排序低”这种行为,NULLS选项就能派上用场,默认 的行为是“空值排序高”。

系统定期收集表中所有列的统计信息。新创建的非表达式索引可以立即使用 这些统计数据来确定索引的有用性。对于新的表达式索引,需要运行 ANALYZE 或等待autovacuum守护程序分析表以 生成这些索引的统计信息。

对于大多数索引方法,索引的创建速度取决于 maintenance_work_mem的设置。较大的值将会减少 索引创建所需的时间,当然不要把它设置得超过实际可用的内存量(那会迫使 机器进行交换)。

LightDB可以在构建索引时利用多个CPU以更快地处理表行。这种特性被称为并行索引构建。对于支持并行构建索引的索引方法(当前只有B-树),maintenance_work_mem指定每次索引构建操作整体可用的最大内存量,而不管启动了多少工作者进程。一般来说,一个代价模型(如果有)自动判断应该请求多少工作者进程。

增加maintenance_work_mem可以让并行索引构建受益,而等效的串行索引构建将无法受益或者得到很小的益处。注意maintenance_work_mem可能会影响请求的工作者进程的数量,因为并行工作者必须在总的maintenance_work_mem预算中占有至少32MB的份额。还必须有32MB的份额留给领袖进程。增加max_parallel_maintenance_workers可以允许使用更多的工作者,这将降低索引创建所需的时间,只要索引构建不是I/O密集型的。当然,还需要有足够的CPU计算能力,否则工作者们会闲置。

通过ALTER TABLE为parallel_workers设置一个值直接控制着CREATE INDEX会对表请求多少并行工作者进程。这会完全绕过代价模型,并且防止maintenance_work_mem对请求多少并行工作者产生影响。通过ALTER TABLE将parallel_workers设置为0将禁用所有情况下的并行索引构建。

tip

在把parallel_workers用于调优一次索引构建之后,你可能想要重置parallel_workers。这可以避免对查询计划的无意更改,因为parallel_workers影响所有的并行表扫描。

虽然带有CONCURRENTLY选项的CREATE INDEX支持并行构建并且没有特殊的限制,但只有第一次表扫描会实际以并行方式执行。

使用DROP INDEX可以移除一个索引。

与任何长时间运行的事务一样,表上的CREATE INDEX会影响 其他表上的并发VACUUM可以删除哪些元组。 除此之外,对于非部分且不索引任何表达式的索引,还可以使用 CONCURRENTLY选项进行操作。

以前的LightDB发行也有一种 R-树 索引方法。这种方法已经被移除,因为它比起 GiST 方法来说没有什么明显的 优势。如果指定了USING rtree,CREATE INDEX 将会把它解释为USING gist,以便把旧的数据库转换成 GiST。

示例:

在表films中的列title上创建一个 B-树索引:

CREATE UNIQUE INDEX title_idx ON films (title);

要在表films的列title上创建一个唯一的B-树索引并且包括列director和rating:

CREATE UNIQUE INDEX title_idx ON films (title) INCLUDE (director, rating);

要创建禁用重复数据删除的 B 树索引:

CREATE INDEX title_idx ON films (title) WITH (deduplicate_items = off);

在表达式lower(title)上创建一个索引来允许高效的大小写 无关搜索:

CREATE INDEX ON films ((lower(title)));

创建一个具有非默认排序规则的索引:

CREATE INDEX title_idx_german ON films (title COLLATE "de_DE");

创建一个具有非默认空值排序顺序的索引:

CREATE INDEX title_idx_nulls_low ON films (title NULLS FIRST);

创建一个具有非默认填充因子的索引:

CREATE UNIQUE INDEX title_idx ON films (title) WITH (fillfactor = 70);

创建一个禁用快速更新的GIN索引:

CREATE INDEX gin_idx ON documents_table USING GIN (locations) WITH (fastupdate = off);

在表films中的列code上创建一个而索引并且 把索引放在表空间indexspace中:

CREATE INDEX code_idx ON films (code) TABLESPACE indexspace;

在一个点属性上创建一个 GiST 索引,这样我们可以在转换函数的结果 上有效地使用 box 操作符:

    CREATE INDEX pointloc
ON points USING gist (box(location,location));
    SELECT * FROM points WHERE box(location,location) && '(0,0),(1,1)'::box;

创建一个表而不排斥对表的写操作:

CREATE INDEX CONCURRENTLY sales_quantity_index ON sales_table (quantity);

创建本地或全局索引

CREATE INDEX index_local ON sales_table (quantity) LOCAL;
CREATE INDEX index_global ON sales_table (quantity) GLOBAL;

使用COMPRESS/NOCOMPRESS/LOGGING/NOLOGGING选项来创建一个索引。

create table comp_log_test(id int);
create index idx_id on comp_log_test(id) nologging compress tablespace pg_default;

在创建索引时使用schema_name前缀。

create table t1(id int);
create index hahaha.index_t1_id on t1(id);

5.1.3. CREATE MATERIALIZED VIEW

定义一个新的物化视图

语法:

CREATE MATERIALIZED VIEW [ IF NOT EXISTS ] table_name
        [ (column_name [, ...] ) ]
        [ USING method ]
        [ WITH ( storage_parameter [= value] [, ... ] ) ]
        [ TABLESPACE tablespace_name ]
        AS query
        [ WITH [ NO ] DATA ]

描述:

  • CREATE MATERIALIZED VIEW定义一个查询的物化视图。 在该命令被发出时,查询会被执行并且被用来填充该视图(除非使用了 WITH NO DATA),并且后来可能会用 REFRESH MATERIALIZED VIEW进行刷新。

  • CREATE MATERIALIZED VIEW类似于 CREATE TABLE AS,不过它还会记住被用来初始化该视图的查询, 这样它可以在后来被命令刷新。一个物化视图有很多和表相同的属性,但是不支持 临时物化视图。

参数:

  • IF NOT EXISTS

    如果已经存在一个同名的物化视图时不要抛出错误。这种情况下会发出一个 提示。注意这不保证现有的物化视图与即将创建的物化视图相似。

  • table_name

    要创建的物化视图的名称(可以被模式限定)。

  • column_name

    新物化视图中的一个列名。如果没有提供列名,会从查询的输出列名来得到。

  • USING method

    此可选子句指定用于存储新具体化视图内容的表访问方法;该方法需要是TABLE类型的访问方法。 详细信息请参考 Chapter 57。如果未指定此选项,则为新具体化视图选择默认表访问方法。 详细信息请参考 default_table_access_method 。

  • WITH ( storage_parameter [= value] [, … ] )

    这个子句为新的物化视图指定可选的存储参数,详见CREATE TABLE的 Storage Parameters。所有CREATE TABLE支持的参数CREATE MATERIALIZED VIEW也支持。 详见CREATE TABLE。

  • TABLESPACE tablespace_name

    tablespace_name是 要把新物化视图创建在其中的表空间的名称。如果没有指定, 将查阅default_tablespace。

  • query

    一个SELECT、 TABLE 或者VALUES命令。 这个查询将在一个安全受限的操作中运行。 特别地,对本身会创建临时表的函数的调用将会失败。

  • WITH [ NO ] DATA

    这个子句指定物化视图是否在创建时被填充。如果不是,该物化视图将被标记为 不可扫描并且在REFRESH MATERIALIZED VIEW被使用前不能被查询。

5.1.4. CREATE PROCEDURE

定义一个新的过程

语法:

CREATE [ OR REPLACE ] PROCEDURE
        name ( [ [ argmode ] [ argname ] argtype [ { DEFAULT | = } default_expr ] [, ...] ] )
        { LANGUAGE lang_name
                | TRANSFORM { FOR TYPE type_name } [, ... ]
                | [ EXTERNAL ] SECURITY INVOKER | [ EXTERNAL ] SECURITY DEFINER
                | SET configuration_parameter { TO value | = value | FROM CURRENT }
                | AS 'definition'
                | AS 'obj_file', 'link_symbol'
        } ...

描述:

  • CREATE PROCEDURE定义一个新的过程。CREATE OR REPLACE PROCEDURE将会创建一个新过程或者替换一个已有的定义。为了能够定义过程,用户必须具有所使用的语言上的USAGE特权。

  • 如果这个命令中包括了一个方案名称,则该过程将被创建在该方案中。否则过程将被创建在当前的方案中。新过程的名称不能匹配同一方案中具有相同输入参数类型的任何现有过程或函数。不过,具有不同参数类型的过程和函数可以共享同一个名称(这被称为重载)。

  • 要替换一个已有过程的当前定义,请使用CREATE OR REPLACE PROCEDURE。不能用这种方式更改过程的名称或者参数类型(如果尝试这样做,实际上会创建一个新的、不同的过程)。

  • 当CREATE OR REPLACE PROCEDURE被用来替换一个现有的过程时,该过程的拥有关系和权限保持不变。所有其他的过程属性会被赋予这个命令中指定的或者暗示的值。必须拥有(包括成为拥有角色的成员)该过程才能替换它。

  • 创建过程的用户将成为该过程的拥有者。

  • 为了能够创建一个过程,用户必须具有参数类型上的USAGE特权。

参数:

  • name

    要创建的过程的名称(可以是被方案限定的)。

  • argmode

    参数的模式可以是:IN、OUT、 INOUT或者VARIADIC。 如果省略,则默认为IN。

  • argname

    参数的名称。

  • argtype

    过程的参数(如果有)的数据类型(可以是被方案限定的)。参数类型可以是基础类型、组合类型或者域类型,或者可以引用一个表列的类型。

    根据具体的实现语言,还可能可以指定“伪类型”,例如cstring。伪类型表示实际的参数类型没有完全确定,或者是位于普通SQL数据类型的集合之外。

    写上table_name.column_name%TYPE可以引用某个列的类型。使用这种特性有时可以让过程不受表定义改变的影响。

  • default_expr

    没有指定参数时要被用作默认值的表达式。这个表达式必须符合该参数的参数类型。跟在有默认值的参数后面的输入参数也都必须有默认值。

  • lang_name

    用于实现该过程的语言名称。它可以是sql、c、 internal或者一种用户定义的过程语言的名称,例如plpgsql。 如果指定了sql_body,则默认值为sql。 将名称包裹在单引号内的方式已经被废弃,并且要求大小写匹配。

  • TRANSFORM { FOR TYPE type_name } [, … ] }

    列出对过程的调用应该应用哪些Transform。Transform负责在SQL类型和语言相关的数据类型之间进行转换,请参考CREATE TRANSFORM。过程语言实现通常采用硬编码的方式保存内建类型的知识,因此它们无需在这里列出。但如果一种过程语言实现不知道如何处理一种类型并且没有提供Transform,它将回退到默认的行为来转换数据类型,但是这依赖于其实现。

  • [EXTERNAL] SECURITY INVOKER

  • [EXTERNAL] SECURITY DEFINER

    SECURITY INVOKER指示过程以调用它的用户的特权来执行。这是默认方式。SECURITY DEFINER指定过程以拥有它的用户的特权来执行。

    为了符合SQL标注,允许使用EXTERNAL关键词,但它是可选的,因为和SQL中不同,这个特性适用于所有的过程而不仅仅是外部过程。

    SECURITY DEFINER过程不能执行事务控制语句(例如COMMIT和ROLLBACK,具体取决于实现的语言)。

  • configuration_parameter

  • value

    SET子句导致在进入该过程时指定的配置参数被设置为指定的值,并且在过程退出时恢复到之前的值。SET FROM CURRENT把CREATE PROCEDURE执行时该参数的当前值保存为在进入该过程时要应用的值。

    如果对过程附加一个SET子句,那么在该过程中为同一个变量执行的SET LOCAL命令的效果就被限制于该过程:在过程退出时还是会恢复到该配置参数的以前的值。不过,一个普通的SET命令(没有LOCAL)会重载这个SET子句,很像它对一个之前的SET LOCAL命令所做的事情:这样一个命令的效果将持续到过程退出之后,除非当前事务被回滚。

    如果对过程附加一个SET子句,则该过程不能执行事务控制语句(例如COMMIT和ROLLBACK,具体取决于实现的语言)。

    有关允许的参数名和值的更多信息请参考SET和Chapter 17。

  • definition

    一个定义该过程的字符串常量,其含义取决于语言。它可以是一个内部的过程名、一个对象文件的路径、一个SQL命令或者以一种过程语言编写的文本。

    在编写过程的定义字符串时,使用美元引用而不是普通的单引号语法常常会很有帮助。如果没有美元引用,过程定义中的任何单引号或者反斜线必须以双写的方式进行转义。

  • obj_file, link_symbol

    当C语言源码中的过程名与SQL过程的名称不同时,这种形式的AS子句被用于动态可装载的C语言过程。字符串obj_file是包含已编译好的C过程的共享库文件名,并且被按照LOAD命令的方式解析。字符串link_symbol是该过程的链接符号,也就是该过程在C语言源代码中的名称。如果链接符号被省略,则会被假定为与正在被定义的SQL过程的名称相同。

    当重复的CREATE PROCEDURE调用引用同一个对象文件时,只会对每一个会话装载该文件一次。要卸载或者重新载入该文件(可能是在开发期间),应该开始一个新的会话。

示例:

CREATE PROCEDURE insert_data(a integer, b integer)
LANGUAGE SQL
AS $$
INSERT INTO tbl VALUES (a);
INSERT INTO tbl VALUES (b);
$$;

CALL insert_data(1, 2);

5.1.5. CREATE ROLE

定义一个新的数据库角色

语法:

CREATE ROLE name [ [ WITH ] option [ ... ] ]

where option可以是:

        SUPERUSER | NOSUPERUSER
        | CREATEDB | NOCREATEDB
        | CREATEROLE | NOCREATEROLE
        | INHERIT | NOINHERIT
        | LOGIN | NOLOGIN
        | REPLICATION | NOREPLICATION
        | BYPASSRLS | NOBYPASSRLS
        | CONNECTION LIMIT connlimit
        | [ ENCRYPTED ] PASSWORD 'password' | PASSWORD NULL
        | VALID UNTIL 'timestamp'
        | IN ROLE role_name [, ...]
        | IN GROUP role_name [, ...]
        | ROLE role_name [, ...]
        | ADMIN role_name [, ...]
        | USER role_name [, ...]
        | SYSID uid

描述:

  • CREATE ROLE向LightDB数据库集簇增加一个新的角色。一个角色是一个实体,它可以拥有数据库对象并且拥有数据库特权。根据一个角色如何被使用,它可以被考虑成一个“用户”、一个“组”或者两者。要使用这个命令,你必须具有CREATEROLE特权或者成为一个数据库超级用户。

  • 注意角色是定义在数据库集簇层面上的,并且因此在集簇中的所有数据库中都可用。

参数:

  • name

    新角色的名称。

  • SUPERUSER

  • NOSUPERUSER

    这些子句决定新角色是否是一个“超级用户”,它可以越过数据库内的所有访问限制。超级用户状态很危险并且只应该在确实需要时才用。要创建一个新超级用户,你必须自己是一个超级用户。如果没有指定,默认值是NOSUPERUSER。

  • CREATEDB

  • NOCREATEDB

    这些子句定义一个角色创建数据库的能力。如果指定了CREATEDB,被定义的角色将被允许创建新的数据库。指定NOCREATEDB将否定一个角色创建数据库的能力。如果没有指定,默认值是NOCREATEDB。

  • CREATEROLE

  • NOCREATEROLE

    这些子句决定一个角色是否被允许创建新的角色(也就是执行CREATE ROLE)。一个带有CREATEROLE特权的角色也能修改和删除其他角色。如果没有指定,默认值是NOCREATEROLE。

  • INHERIT

  • NOINHERIT

    如果新的角色是其他角色的成员,这些子句决定新角色是否从那些角色中“继承”特权,把新角色作为成员的角色称为新角色的父角色。一个带有INHERIT属性的角色能够自动使用已经被授予给其直接或间接父角色的任何数据库特权。如果没有INHERIT,在另一个角色中的成员关系只会把SET ROLE的能力授予给那个其他角色,只有在这样做后那个其他角色的特权才可用。如果没有指定,默认值是INHERIT。

  • LOGIN

  • NOLOGIN

    这些子句决定一个角色是否被允许登录,也就是在客户端连接期间该角色是否能被 给定为初始会话认证名称。一个具有LOGIN属性的角色可以被 考虑为一个用户。没有这个属性的角色对于管理数据库特权很有用,但是却不是 用户这个词的通常意义。如果没有指定,默认值是NOLOGIN, 不过当CREATE ROLE被通过 CREATE USER调用时默认值会是LOGIN。

  • REPLICATION

  • NOREPLICATION

    这些子句决定一个角色是否为复制角色。角色必须具有这个属性(或者成为一个超级用户)才能以复制模式(物理复制或者逻辑复制)连接到服务器以及创建或者删除复制槽。一个具有REPLICATION属性的角色是一个具有非常高特权的角色,并且只应被用于确实需要复制的角色上。如果没有指定,默认值是NOREPLICATION。 您必须是超级用户才能创建具有REPLICATION属性的新角色。

  • BYPASSRLS

  • NOBYPASSRLS

    这些子句决定是否一个角色可以绕过每一条行级安全性(RLS)策略。 默认是NOBYPASSRLS。 您必须是超级用户才能创建具有BYPASSRLS属性的新角色。

    注意 lt_dump 将默认把row_security设置为OFF, 以确保一个表的所有内容被转储出来。如果运行 lt_dump 的用户不具有适当的权限,将会返回一个错误。 但是,超级用户和被转储表的拥有者总是可以绕过 RLS。

  • CONNECTION LIMIT connlimit

    如果角色能登录,这指定该角色能建立多少并发连接。-1(默认值)表示无限制。注意这个限制仅针对于普通连接。预备事务和后台工作者连接都不受这一限制管辖。

  • [ ENCRYPTED ] PASSWORD ‘password’

  • PASSWORD NULL

    设置角色的口令(口令只对具有LOGIN属性的角色有用,但是不管怎样你还是可以为没有该属性的角色定义一个口令)。如果你没有计划使用口令认证,你可以忽略这个选项。如果没有指定口令,口令将被设置为空并且该用户的口令认证总是会失败。也可以用PASSWORD NULL显式地写出一个空口令。

    Note

    指定一个空字符串也将把口令设置为空,但是在LightDB版本10之前是不能这样做的。在早期的版本中,是否可以使用空字符串取决于认证方法和确切的版本,而libpq在任何情况下都将拒绝使用空字符串。为了避免混淆,应该避免指定空字符串。

    口令总是以加密的方式存放在系统目录中。ENCRYPTED关键词没有实际效果,它只是为了向后兼容性而存在。加密的方法由配置参数password_encryption决定。如果当前的口令字符串已经是MD5加密或者SCRAM加密的格式,那么不管password_encryption的值是什么,口令字符串还是原样存储(因为系统无法解密以不同格式加密的口令字符串)。这种方式允许在转储/恢复时重载加密的口令。

  • VALID UNTIL ‘timestamp’

    VALID UNTIL机制设置一个日期和时间,在该时间点之后角色的口令将会失效。如果这个子句被忽略,那么口令将总是有效。

  • IN ROLE role_name

    IN ROLE子句列出一个或多个现有的角色,新角色将被立即作为新成员加入到这些角色中(注意没有选项可以把新角色作为一个管理员加入,需要用一个单独的GRANT命令来完成)。

  • IN GROUP role_name

    IN GROUP是IN ROLE的一种已废弃的拼写方式。

  • ROLE role_name

    ROLE子句列出一个或者多个现有角色,它们会被自动作为成员加入到新角色中(这实际上新角色变成了一个“组”)。

  • ADMIN role_name

    ADMIN子句与ROLE相似,但是被提及的角色被使用WITH ADMIN OPTION加入到新角色中,让它们能够把这个角色中的成员关系授予给其他人。

  • USER role_name

    USER子句是ROLE子句的一个已废弃的拼写方式。

  • SYSID uid

    SYSID子句会被忽略,但是会为了向后兼容,还是会接受它。

示例:

创建一个能登录但是没有口令的角色:

CREATE ROLE jonathan LOGIN;

创建一个有口令的角色:

CREATE USER davide WITH PASSWORD 'jw8s0F4';

(CREATE USER和CREATE ROLE完全相同,除了它带有LOGIN)。

创建一个角色,它的口令有效期截止到 2004 年底。在进入 2005 年第一秒时,该口令会失效。

CREATE ROLE miriam WITH LOGIN PASSWORD 'jw8s0F4' VALID UNTIL '2005-01-01';

创建一个能够创建数据库并且管理角色的角色:

CREATE ROLE admin WITH CREATEDB CREATEROLE;

5.1.6. CREATE SCHEMA

定义一个新模式

语法:

CREATE SCHEMA schema_name [ AUTHORIZATION role_specification ] [ schema_element [ ... ] ]
CREATE SCHEMA AUTHORIZATION role_specification [ schema_element [ ... ] ]
CREATE SCHEMA IF NOT EXISTS schema_name [ AUTHORIZATION role_specification ]
CREATE SCHEMA IF NOT EXISTS AUTHORIZATION role_specification

其中 role_specification 可以是:

        user_name
| CURRENT_USER
| SESSION_USER

描述:

  • CREATE SCHEMA输入一个新模式到当前数据库中。 该模式名必须与当前数据库中任何现有模式的名称不同。

  • 一个模式本质上是一个名字空间:它包含命令对象(表、数据类型、函数以及操作符), 对象可以与在其他模式中存在的对象重名。可以通过用模式名作为一个前缀 “限定”命名对象的名称来访问它们,或者通过把要求的模式包括 在搜索路径中来访问命名对象。一个指定非限定对象名的 CREATE命令在当前模式(搜索路径中的第一个模式,由函数 current_schema决定)中创建对象。

  • CREATE SCHEMA中可以选择包括子命令用以在 新模式中创建对象。这些子命令实际被当做独立的在创建该模式后被发出的命令 一样,除非使用AUTHORIZATION子句,所有被创建的对象都会 由该用户拥有。

参数:

  • schema_name

    要创建的一个模式名。如果省略, user_name将被用作模式名。 该名称不能以pg_开始,因为这样的名称是用作系统模式的。

  • user_name

    将拥有新模式的用户的角色名。如果省略,默认为执行该命令的用户。要 创建由另一个角色拥有的角色,你必须是那个角色的一个直接或者间接成员, 或者是一个超级用户。

  • schema_element

    要在该模式中创建的对象的定义 SQL 语句。当前,只有CREATE TABLE、CREATE VIEW、CREATE INDEX、CREATE SEQUENCE、CREATE TRIGGER以及GRANT被接受为 CREATE SCHEMA中的子句。其他类型的对象可以在模式被 创建之后用单独的命令创建。

  • IF NOT EXISTS

    如果一个具有同名的模式已经存在,则什么也不做(不过发出一个提示)。 使用这个选项时不能包括 schema_element子命令。

示例:

创建一个模式:

CREATE SCHEMA myschema;

为用户joe创建一个模式,该模式也将被命名为 joe:

CREATE SCHEMA AUTHORIZATION joe;

创建一个被用户joe拥有的名为test的模式, 除非已经有一个名为test的模式(不管joe 是否拥有该已经存在的模式)。

CREATE SCHEMA IF NOT EXISTS test AUTHORIZATION joe;

创建一个模式并且在其中创建一个表和视图:

CREATE SCHEMA hollywood
  CREATE TABLE films (title text, release date, awards text[])
  CREATE VIEW winners AS
      SELECT title, release FROM films WHERE awards IS NOT NULL;

注意子命令不以分号结束。

下面是达到相同结果的等效的方法:

CREATE SCHEMA hollywood;
CREATE TABLE hollywood.films (title text, release date, awards text[]);
CREATE VIEW hollywood.winners AS
        SELECT title, release FROM hollywood.films WHERE awards IS NOT NULL;

5.1.7. CREATE SEQUENCE

定义一个新的序列发生器

语法:

CREATE [ TEMPORARY | TEMP ] SEQUENCE [ IF NOT EXISTS ] name
        [ AS data_type ]
        [ INCREMENT [ BY ] increment ]
        [ MINVALUE minvalue | NO MINVALUE ] [ MAXVALUE maxvalue | NO MAXVALUE ]
        [ START [ WITH ] start ] [ CACHE cache ] [ [ NO ] CYCLE ]
        [ OWNED BY { table_name.column_name | NONE } ]
        [ NOORDER ]
        [ ORDER ]
        [ NOCACHE ]
        [ NOCYCLE ]
        [ NOMAXVALUE ]

描述:

  • CREATE SEQUENCE创建一个新的序列数 发生器。这涉及到用名称name创建并且初始化 一个新的特殊的单行表。该发生器将由发出该命令的用户所拥有。

  • 如果给出一个模式名称,则该序列将将被创建在指定的模式中。否则它会被创建在当前模式中。临时序列存在于一个特殊的模式中,因此在创建临时序列时不能给出模式名。序列名称必须与同一模式中任何其他序列、表、索引、 视图或者外部表的名称不同。

  • 在序列被创建后,可以使用函数 nextval、 currval以及 setval来操作该序列.

  • 尽管无法直接更新一个序列,可以使用这样的查询:

SELECT * FROM name;

来检查一个序列的参数以及当前状态。特别地,序列的 last_value域显示被任意会话最后一次取得的值(当然, 在被打印时该值可能已经过时了,因为可能有其他会话正在执行 nextval调用)。

参数:

  • TEMPORARY or TEMP

    如果被指定,只会为这个会话创建序列对象,并且在会话退出时自动 删除它。当临时序列存在时,已有的同名永久序列(在这个会话中) 会变得不可见,不过可以用模式限定的名称来引用同名永久序列。

  • IF NOT EXISTS

    如果已经存在一个同名的关系时不要抛出错误。这种情况下会发出一个 提示。注意这不保证现有的关系与即将创建的序列相似 ? 它甚至可能 都不是一个序列。

  • name

    要创建的序列的名称(可以是模式限定的)。

  • data_type

    可选的子句AS data_type 制定序列的数据类型。有效类型是 smallint、integer、 和bigint。默认是bigint。 数据类型决定了序列的默认最小和最大值。

  • increment

    可选的子句INCREMENT BY increment指定为了 创建新值会把哪个值加到当前序列值上。一个正值将会创造一个上升 序列,负值会创造一个下降序列。默认值是 1。

  • minvalue

  • NO MINVALUE

    可选的子句MINVALUE minvalue决定一个序列 能产生的最小值。如果没有提供这个子句或者指定了 NO MINVALUE,那么会使用默认值。 升序序列的默认值为1。降序序列的默认值为数据类型的最小值。

  • maxvalue

NO MAXVALUE

可选的子句MAXVALUE maxvalue决定该序列 的最大值。如果没有提供这个子句或者指定了 NO MAXVALUE,那么将会使用默认值。 升序序列的默认值是数据类型的最大值。降序序列的默认值是-1。

如果maxvalue的值大于INT64_MAX(9223372036854775807),则设置maxvalue为sequence类型所对应的最大值。

  • start

    可选的子句START WITH start 允许序列从任何 地方开始。对于上升序列和下降序列来说,默认的开始值分别是 minvalue和 maxvalue。

  • cache

    可选的子句CACHE cache指定要预分配多少 个序列数并且把它们放在内存中以便快速访问。最小值为 1 (一次只生成 一个值,即没有缓存),默认值也是 1。

  • CYCLE

  • NO CYCLE

    对于上升序列和下降序列,CYCLE选项允许序列 在分别达到maxvalue和minvalue时回卷。如果达到 该限制,下一个产生的数字将分别是minvalue和maxvalue。

    如果指定了NO CYCLE,当序列到达其最大值 后任何nextval调用将返回一个错误。如果 CYCLE和NO CYCLE都没有 被指定,则默认为NO CYCLE。

  • OWNED BY table_name.column_name

  • OWNED BY NONE

    OWNED BY选项导致序列被与一个特定的表列关联 在一起,这样如果该列(或者整个表)被删除,该序列也将被自动删除。 指定的表必须和序列具有相同的拥有者并且在同一个模式中。默认选项 OWNED BY NONE指定该序列不与某个列关联。

  • NOORDER

  • ORDER

  • NOCACHE

  • NOCYCLE

    为了兼容Oracle数据库语法,CREATE SEQUENCE语句支持 NOORDER/ORDER/NOCACHE/NOCYCLE 关键字。这些关键字仅是语法糖。

  • NOMAXVALUE

    为了兼容Oracle数据库语法,CREATE SEQUENCE语句支持 NOMAXVALUE 关键字。内部逻辑和NO MAXVALUE相同。

示例:

创建一个称作serial的上升序列,从 101 开始:

CREATE SEQUENCE serial START 101;

从这个序列中选取下一个数字:

SELECT nextval('serial');

nextval
---------
        101

再从这个序列中选取下一个数字:

SELECT nextval('serial');

nextval
---------
        102

在一个INSERT命令中使用这个序列:

INSERT INTO distributors VALUES (nextval('serial'), 'nothing');

在一次COPY FROM后更新新列值:

BEGIN;
COPY distributors FROM 'input_file';
SELECT setval('serial', max(id)) FROM distributors;
END;

使用ORDER/NOORDER/NOCACHE/NOCYCLE选项来创建sequence。

create sequence lt_seq_test5 start 100 ORDER nocache NOCYCLE;
create sequence lt_seq_test6 start 100 NOCACHE NOORDER nocycle;

创建序列时支持声明 NOMAXVALUE

create sequence s1 nomaxvalue;
\d+ s1
                                                        Sequence "public.s1"
Type  | Start | Minimum |       Maximum       | Increment | Cycles? | Cache
--------+-------+---------+---------------------+-----------+---------+-------
bigint |     1 |       1 | 9223372036854775807 |         1 | no      |     1

创建序列时支持声明 MAXVALUE

create sequence s2 maxvalue 100000;
\d+ s2
Sequence "public.s2"
Type  | Start | Minimum | Maximum | Increment | Cycles? | Cache
--------+-------+---------+---------+-----------+---------+-------
bigint |     1 |       1 |  100000 |         1 | no      |     1

语句支持 order / noorder / nocycle / nocache 关键字

create sequence lt_seq_test1 order start 100;
create sequence lt_seq_test3 start 100 nocycle;
create sequence lt_seq_test5 start 100 ORDER nocache NOCYCLE;
alter sequence lt_seq_test1 nocache nocycle noorder;

5.1.8. CREATE TABLE

定义一个新表

语法:

CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXISTS ] table_name ( [
{ column_name data_type [ COLLATE collation ] [ column_constraint [enable|disable] [ ... ] ] [ COMMENT column_comment ]
        | table_constraint
        | LIKE source_table [ like_option ... ] }
        [, ... ]
] )[ INHERITS ( parent_table [, ... ] ) ]
[ lt_partition_option ]
[ USING method ]
[ WITH ( storage_parameter [= value] [, ... ] ) | WITHOUT OIDS ]
[ ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP } ]
[ lt_table_options ]

CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXISTS ] table_name
        OF type_name [ (
{ column_name [ WITH OPTIONS ] [ column_constraint [enable|disable] [ ... ] ]
        | table_constraint }
        [, ... ]
) ]
[ lt_partition_option ]
[ USING method ]
[ WITH ( storage_parameter [= value] [, ... ] ) | WITHOUT OIDS ]
[ ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP } ]
[ TABLESPACE tablespace_name ]

CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXISTS ] table_name
        PARTITION OF parent_table [ (
{ column_name [ WITH OPTIONS ] [ column_constraint [enable|disable] [ ... ] ]
        | table_constraint }
        [, ... ]
) ] { FOR VALUES partition_bound_spec | DEFAULT }
[ PARTITION BY { RANGE | LIST | HASH } ( { column_name | ( expression ) } [ COLLATE collation ] [ opclass ] [, ... ] ) ]
[ PARTITIONS partitions_value ]
[ INTERVAL interval_value ]
[ USING method ]
[ WITH ( storage_parameter [= value] [, ... ] ) | WITHOUT OIDS ]
[ ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP } ]
[ TABLESPACE tablespace_name ]

其中 lt_partition_option 是:

{
PARTITION BY { RANGE | LIST | HASH } ( { column_name | ( expression ) } [ COLLATE collation ] [ opclass ] [, ... ] )
[ PARTITIONS partitions_value ]
[ INTERVAL interval_value ] |
PARTITION BY partition_type (column)
        [ SUBPARTITION BY partition_type (column) ]
        [ SUBPARTITIONS subpartitions_value ]
                [ SUBPARTITION TEMPLATE ( template_spec ) ]
        [...]
        ( partition_spec )
                | [ SUBPARTITION BY partition_type (column) ]
                [...]
        ( partition_spec
        [ ( subpartition_spec
                [(...)]
                ) ]
        )
}

并且 lt_table_options 是:

{ TABLESPACE tablespace_name |
WITH UPDATE CURRENT_TIMESTAMP |
WITH PRIMRAY KEY [ smallserial | serial | bigserial ] |
{ DISTRIBUTED BY [HASH | APPEND](column) [ distribute_option ... ] | DISTRIBUTED REPLICATED } |
COMMENT = table_comment |
{ COMPRESS | NOCOMPRESS } |
{ LOGGING | NOLOGGING } |
STORAGE(value) |
ENGINE = { INNODB | MYISAM } |
DEFAULT CHARSET = value |
COLLATE = value |
NESTED TABLE column_name STORE AS nested_table_name [...]
}

并且 column_constraint 是:

[ CONSTRAINT constraint_name ]
{ NOT NULL |
NULL |
CHECK ( expression ) [ NO INHERIT ] |
DEFAULT default_expr |
ON UPDATE CURRENT_TIMESTAMP |
AUTO_INCREMENT |
GENERATED ALWAYS AS ( generation_expr ) STORED |
GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY [ ( sequence_options ) ] |
UNIQUE index_parameters |
PRIMARY KEY index_parameters |
REFERENCES reftable [ ( refcolumn ) ] [ MATCH FULL | MATCH PARTIAL | MATCH SIMPLE ]
        [ ON DELETE referential_action ] [ ON UPDATE referential_action ] }
[ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]

并且 table_constraint 是:

[ CONSTRAINT constraint_name ]
{ CHECK ( expression ) [ NO INHERIT ] |
UNIQUE ( column_name [, ... ] ) index_parameters |
PRIMARY KEY ( column_name [, ... ] ) index_parameters |
EXCLUDE [ USING index_method ] ( exclude_element WITH operator [, ... ] ) index_parameters [ WHERE ( predicate ) ] |
FOREIGN KEY ( column_name [, ... ] ) REFERENCES reftable [ ( refcolumn [, ... ] ) ]
        [ MATCH FULL | MATCH PARTIAL | MATCH SIMPLE ] [ ON DELETE referential_action ] [ ON UPDATE referential_action ] }
[ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]

并且 like_option 是:

{ INCLUDING | EXCLUDING } { COMMENTS | CONSTRAINTS | DEFAULTS | GENERATED | IDENTITY | INDEXES | STATISTICS | STORAGE | SEQUENCES | ALL }

and partition_bound_spec is:

IN ( partition_bound_expr [, ...] ) |
FROM ( { partition_bound_expr | MINVALUE | MAXVALUE } [, ...] )
TO ( { partition_bound_expr | MINVALUE | MAXVALUE } [, ...] ) |
WITH ( MODULUS numeric_literal, REMAINDER numeric_literal )

UNIQUE、PRIMARY KEY以及EXCLUDE约束中的index_parameters是:

[ INCLUDE ( column_name [, ... ] ) ]
[ WITH ( storage_parameter [= value] [, ... ] ) ]
[ USING INDEX TABLESPACE tablespace_name ]

一个EXCLUDE约束中的exclude_element是:

{ column_name | ( expression ) } [ opclass ] [ ASC | DESC ] [ NULLS { FIRST | LAST } ]
where partition_type is:
        LIST
| RANGE
| HASH
where partition_spec is:
partition_element [, ...]
and partition_element is:
DEFAULT PARTITION name
| [PARTITION name] VALUES ( list_value [,...] )
| [PARTITION name]
        START ([datatype] start_value ) [INCLUSIVE | EXCLUSIVE]
        [ END ([datatype] end_value ) [INCLUSIVE | EXCLUSIVE] ]
        [ EVERY ([datatype] [number | INTERVAL] interval_value ) ]
| [PARTITION name]
        END ([datatype] end_value ) [INCLUSIVE | EXCLUSIVE]
        [ EVERY ([datatype] [number | INTERVAL] interval_value ) ]
| [PARTITION name]
        FROM ([datatype] from_value ) [INCLUSIVE | EXCLUSIVE]
        [ TO ([datatype] to_value ) [INCLUSIVE | EXCLUSIVE] ]
        [ EVERY ([datatype] [number | INTERVAL] interval_value ) ]
| [PARTITION name]
        TO ([datatype] to_value ) [INCLUSIVE | EXCLUSIVE]
        [ EVERY ([datatype] [number | INTERVAL] interval_value ) ]
| [PARTITION name] VALUES WITH ( MODULUS numeric_literal, REMAINDER numeric_literal )
| [PARTITION name] VALUES LESS THAN ( { partition_value | MAXVALUE } )
| [PARTITION name]
[ TABLESPACE tablespace ]
[ NOCOMPRESS | COMPRESS ]
where subpartition_spec or template_spec is:
subpartition_element [, ...]
and subpartition_element is:
DEFAULT SUBPARTITION name
| [SUBPARTITION name] VALUES ( list_value [,...] )
| [SUBPARTITION name]
        START ([datatype] start_value ) [INCLUSIVE | EXCLUSIVE]
        [ END ([datatype] end_value ) [INCLUSIVE | EXCLUSIVE] ]
        [ EVERY ([datatype] [number | INTERVAL] interval_value ) ]
| [SUBPARTITION name]
        END ([datatype] end_value ) [INCLUSIVE | EXCLUSIVE]
        [ EVERY ([datatype] [number | INTERVAL] interval_value ) ]
| [SUBPARTITION name]
        FROM ([datatype] from_value ) [INCLUSIVE | EXCLUSIVE]
        [ TO ([datatype] to_value ) [INCLUSIVE | EXCLUSIVE] ]
        [ EVERY ([datatype] [number | INTERVAL] interval_value) ]
| [SUBPARTITION name]
        TO ([datatype] to_value ) [INCLUSIVE | EXCLUSIVE]
        [ EVERY ([datatype] [number | INTERVAL] interval_value ) ]
| [SUBPARTITION name] VALUES WITH ( MODULUS numeric_literal, REMAINDER numeric_literal )
[ NOCOMPRESS | COMPRESS ]
where distribute_option is:
        SHARD_COUNT(int_value)
        | COLOCATE_WITH('string_value')

描述:

  • CREATE TABLE将在当前数据库中创建一个新的、初始为空的表。该表将由发出该命令的用户所拥有。

  • 如果给定了一个模式名(例如CREATE TABLE myschema.mytable …),那么该表被创建在指定的模式中。否则它被创建在当前模式中。临时表存在于一个特殊的模式中,因此在创建一个临时表时不能给定一个模式名。该表的名称必须与同一个模式中的任何其他表、序列、索引、视图或外部表的名称区分开。

  • CREATE TABLE也会自动地创建一个数据类型来表示对应于该表一行的组合类型。因此,表不能用同一个模式中任何已有数据类型的名称。

  • lt_table_options 中的任何选项都可以以任何顺序指定。

  • 可选的约束子句指定一个插入或更新操作要成功,新的或更新过的行必须满足的约束(测试)。一个约束是一个 SQL 对象,它帮助以多种方式定义表中的合法值集合。

  • 有两种方式来定义约束:表约束和列约束。一个列约束会作为列定义的一部分定义。一个表约束定义不与一个特定列绑定,并且它可以包含多于一个列。每一个列约束也可以被写作一个表约束,列约束只是一种当约束只影响一列时方便书写的记号习惯。

  • 当指定column_comment后便会在该列上添加注释。相似地,在表定义的最后指定table_comment将添加该表的注释。

  • 要能创建一个表,你必须分别具有所有列类型或OF子句中类型的USAGE特权。

参数:

  • TEMPORARY or TEMP

    如果指定,该表被创建为一个临时表。 临时表会被在会话结束时自动被删除,或者也可以选择在当前事务结束时删除(见下文的ON COMMIT)。 默认搜索路径首先包括临时模式,因此当临时表存在时,不会为新计划选择同名的已有的永久表,除非它们使用模式限定的名称进行引用。 在一个临时表上创建的任何索引也自动地变为临时的。

    自动清理守护进程不能访问并且因此也不能清理或分析临时表。由于这个原因,应该通过会话的 SQL 命令执行合适的清理和分析操作。例如,如果一个临时表将要被用于复杂的查询,最好在把它填充完毕后在其上运行ANALYZE。

    可以选择将GLOBAL或LOCAL写在TEMPORARY或TEMP的前面。这当前在LightDB中没有区别并且已被废弃,见Compatibility。

  • UNLOGGED

    如果指定,该表被创建为一个不受日志记录的表。被写入到不做日志的表中的数据不会被写到预写式日志中(见Chapter 27),这让它们比普通表快非常多。不过,它们在崩溃时是不安全的:一个不做日志的表在一次崩溃或非干净关闭之后会被自动地截断。一个不做日志的表中的内容也不会被复制到后备服务器中。在一个不做日志的表上创建的任何索引也会自动地不被日志记录。

  • IF NOT EXISTS

    如果一个同名关系已经存在,不要抛出一个错误。在这种情况下会发出一个提示。注意这不保证现有的关系是和将要被创建的表相似的东西。

  • table_name

    要被创建的表名(可以选择用模式限定)。 请注意:ORACLE模式下创建分区表时,分区表的名字限制为30字符长。

  • table_comment

    将被创建的表注释内容。

  • OF type_name

    创建一个类型化的表,它的结构取自于指定的组合类型(名字可以选择用模式限定)。一个类型化的表和它的类型绑定在一起,例如如果类型被删除,该表也将被删除(用DROP TYPE … CASCADE)。

    当一个类型化的表被创建时,列的数据类型由底层的组合类型决定而没有在CREATE TABLE命令中直接指定。但是CREATE TABLE命令可以对表增加默认值和约束,并且可以指定存储参数。

  • column_name

    列的名称会在新表中被建立。

    值得注意的是,如果当前数据库在初始化时指定为mysql模式,同时在lightdb.conf中将 ‘lightdb_sql_mode’设置包含’uppercase_identifier’规则,那么列名不能够出现多次, 即使它们大小写不同。该特性将与mysql保持一致,但不同于常规下的lightdb对待列名大小 写敏感,也就是说常规下lightdb仅仅禁止列名完全相等。

    考虑到oracle模式中的类似情况,与mysql模式略有不同。如果guc参数’lightdb_oracle_sql_mode’ 在oracle会话内设置为’true’,那么即使对列标签使用别名,select语句的执行结果亦为大写。因此 仅有对该列名使用双引号包裹,才可使得显示保持原样。设置’lightdb_oracle_sql_mode’为false, 那么该功能会被禁用并恢复默认模式。

  • column_comment

    将被创建的表中列的注释内容。

  • data_type

    列的数据类型. 这可以包括数组 规格. 有关LightDB支持数据类型的详细信息, 请参考Chapter 8.

  • COLLATE collation

    COLLATE子句为该列(必须是一种可排序数据类型)赋予一个排序规则。 如果没有指定,将使用该列数据类型的默认排序规则。

  • INHERITS ( parent_table [, … ] )

    可选的INHERITS子句指定一个表的列表, 新表将从其中自动地继承所有列。 父表可以是普通表或者外部表。

    INHERITS的使用在新的子表和它的父表之间创建一种持久的关系。 对于父表的模式修改通常也会传播到子表, 并且默认情况下子表的数据会被包括在对父表的扫描中。

    如果在多个父表中存在同名的列,除非父表中每一个这种列的数据类型都能匹配, 否则会报告一个错误。如果没有冲突,那么重复列会被融合来形成新表中的一个单一列。 如果新表中的列名列表包含一个也是继承而来的列名,该数据类型必须也匹配继承的列, 并且列定义会被融合成一个。如果新表显式地为列指定了任何默认值, 这个默认值将覆盖来自该列继承声明中的默认值。 否则,任何父表都必须为该列指定相同的默认值,或者会报告一个错误。

    CHECK约束本质上也采用和列相同的方式被融合: 如果多个父表或者新表定义中包含相同的命名CHECK约束, 这些约束必须全部具有相同的检查表达式,否则将报告一个错误。 具有相同名称和表达式的约束将被融合成一份拷贝。 一个父表中的被标记为NO INHERIT的约束将不会被考虑。 注意新表中一个未命名的CHECK约束将永远不会被融合, 因为那样总是会为它选择一个唯一的名字。

    列的STORAGE设置也会从父表复制过来。

    如果父表中的列是标识列,那么该属性不会被继承。 如果需要,可以将子表中的列声明为标识列。

  • PARTITION BY { RANGE | LIST | HASH } ( { column_name | ( expression ) } [ opclass ] [, …] )

    可选的PARTITION BY子句指定了对表进行分区的策略。 这样创建的表称为分区表。 带括号的列或表达式的列表构成表的分区键。 使用范围或哈希分区时,分区键可以包含多个列或表达式(最多32个,但在构建 LightDB时可以更改此限制), 但对于列表分区,分区键必须由单个列或表达式组成。

    范围和列表分区需要 btree 运算符类,而哈希分区需要哈希运算符类。 如果没有运算符类被显式指定,将使用相应类型的默认运算符类; 如果不存在默认运算符类,则将引发错误。 使用哈希分区时,所使用的运算符类必须实现支持功能 2。

    分区表被分成多个子表(称为分区),它们是使用单独的CREATE TABLE命令创建的。 分区表本身是空的。插入到表中的数据行将根据分区键中的列或表达式的值路由到分区。 如果没有现有的分区与新行中的值匹配,则会报告错误。

    分区表不支持EXCLUDE约束; 但是,你可以在各个分区上定义这些约束。

    有关表分区的更多讨论。 ORACLE模式下创建分区时,分区名与子分区名均限制为30字符长。

  • PARTITION OF parent_table { FOR VALUES partition_bound_spec | DEFAULT }

    将表创建为指定父表的分区。 该表建立时,可以使用FOR VALUES创建为特定值的分区, 也可以使用DEFAULT创建默认分区。父表中存在的任何索引、 约束和用户定义的行级触发器都将克隆到新分区上。

    partition_bound_spec 必须对应于父表的分区方法和分区键,并且必须不能与该父表的任何现有分区重叠。 具有IN的形式用于列表分区, 具有FROM和TO的形式用于范围分区, 具有WITH的形式用于哈希分区。

    partition_bound_expr是任何无变量表达式(不允许子查询、窗口函数、聚合函数和集返回函数)。 它的数据类型必须与相应分区键列的数据类型相匹配。 表达式在表创建时只计算一次,因此它甚至可以包含易失性表达式,如CURRENT_TIMESTAMP。

    在创建列表分区时,可以指定NULL来表示分区允许分区键列为空。 但是,给定父表不能有多于一个这样的列表分区。无法为范围分区指定 NULL。

    创建范围分区时,由FROM指定的下限是一个包含范围, 而用TO指定的上限是排除范围。也就是说, 在FROM列表中指定的值是该分区的相应分区键列的有效值, 而TO列表中的值不是。请注意, 必须根据按行比较的规则来理解此语句。 例如,给定PARTITION BY RANGE (x,y),分区范围 FROM (1, 2) TO (3, 4)允许x=1与任何y>=2, x=2与任何非空y,和x=3与任何y<4。

    在创建范围分区以指示列值没有下限或上限时,可以使用特殊值MINVALUE 和MAXVALUE。例如,使用FROM (MINVALUE) TO (10) 定义的分区允许任何小于10的值,并且使用FROM (10) TO (MAXVALUE) 定义的分区允许任何大于或等于10的值。

    创建涉及多个列的范围分区时,将MAXVALUE作为下限的一部分并将 MINVALUE作为上限的一部分也是有意义的。例如,使用 FROM (0, MAXVALUE) TO (10, MAXVALUE) 定义的分区允许第一个分区键列大于0且小于或等于10的任何行。类似地, 使用FROM (‘a’, MINVALUE) TO (‘b’, MINVALUE)定义的分区 允许第一个分区键列以”a”开头的任何行。

    请注意,如果MINVALUE或MAXVALUE用于分区边界的一列, 则必须为所有后续列使用相同的值。例如,(10, MINVALUE, 0) 不是有效的边界;你应该写(10, MINVALUE, MINVALUE)。

    还要注意,某些元素类型,如timestamp,具有“无穷”的概念, 这只是另一个可以存储的值。这与MINVALUE和MAXVALUE不同, 它们不是可以存储的实际值,而是它们表示值无界的方式。MAXVALUE 可以被认为比任何其他值(包括“无穷”)都大的值,MINVALUE 可以被认为是比任何其他值(包括“负无穷”)都小的值。因此, 范围FROM (‘infinity’) TO (MAXVALUE)不是空的范围; 它只允许存储一个值? “infinity”。

    如果指定了DEFAULT,则表将创建为父表的默认分区。此选项不适用于哈希分区表。 不适合给定父级表的任何其他分区的分区键值将路由到默认分区。

    当一个表已有DEFAULT 分区并且要对它添加新分区时, 必须扫描默认分区以验证它不包含可能属于新分区的任何行。 如果默认分区包含大量行,则速度可能会很慢。 如果默认分区是外表或者它具有可证明的不可能包含能放置在新分区中的行的约束,则将略过扫描

    当创建哈希分区时,必须指定模数和余数。 模数必须是正整数,余数必须是小于模数的非负整数。 通常情况下,当初始设置哈希分区表时,应选择一个与分区数相等的模数,并为每个表分配相同的模数和不同的余数(请参阅下方示例)。 不过,并不要求每个分区都具有相同的模数,只要求哈希分区表里面的分区中出现的每个模数都是下一个较大模数的因数。 这允许以增量的方式增加分区数量而不需要一次移动所有数据。 例如,假设你有一个包含 8 个分区的哈希分区表,每个分区有模数8,但发现有必要将分区数增加到 16 个。 您可以拆分其中一个模数-8分区,然后创建两个新的模数-16分区来覆盖键空间的相同部分(一个的余数等于被拆分的分区的余数,另一个的余数等于该值加 8),而后用数据重新填充他们。 然后,你可以对每一个余数-8分区重复此操作过程,直到没有剩余。 虽然这其中的每个步骤都可能会导致大量的数据移动操作,它仍然要好于建一个全新的表并一次移动全部数据。

    分区必须与其所属的分区表的字段名和类型相同。 对分区表字段名或类型的修改,将自动传播到所有分区。 CHECK约束将自动被每一个分区继承,但是单独的分区可以指定额外的CHECK约束;与父表相同名称和条件的额外约束将被父表约束合并。 可以为每个分区分别指定默认值。但是请注意,在通过分区表插入元组时不会应用分区的默认值。

    插入分区表中的行将自动路由到正确的分区。如果不存在合适的分区,则会发生错误。

    像TRUNCATE这样的操作通常会影响一个表及其所有继承子级,这些操作将级联到所有分区, 但也可能在单个分区上执行。请注意,使用DROP TABLE 删除分区需要在父表上采用ACCESS EXCLUSIVE锁。

  • LIKE source_table [ like_option … ]

    LIKE指定新表将从哪一个表自动地复制所有的列名、数据类型以及它们的非空约束。

    和INHERITS不同,新表和原始表在创建完成之后是完全分离的。对原始表的更改将不会被应用到新表,并且不可能在原始表的扫描中包括新表的数据。

    同样与INHERITS不同,用LIKE拷贝的列和约束不会和相似的命名列及约束融合。如果显式指定了相同的名称或者在另一个LIKE子句中指定了相同的名称,将会发出一个错误。

    可选的like_option子句指定要复制的原始表的附加属性。 指定 INCLUDING 复制该属性, 指定 EXCLUDING 忽略该属性。EXCLUDING为默认值。 如果对同一类型的对象指定了多个规范,则使用最后一个规范。可用的选项包括:

    • INCLUDING COMMENTS

      复制的列、约束和索引的注释将被复制。默认行为是去除注释,从而导致新表中复制的列和约束没有注释。

    • INCLUDING CONSTRAINTS

      CHECK约束将被复制。 列约束和表约束之间没有区别。非空约束始终复制到新表。

    • INCLUDING DEFAULTS

      复制列定义的默认表达式将被复制。否则,不会复制默认表达式,从而导致新表中复制的列具有空默认值。 注意,复制调用数据库修改函数的默认值,例如nextval,可能在原始表和新表之间创建功能联系。

    • INCLUDING GENERATED

      列定义的任何生成表达式将被复制。 默认情况下,新列将是常规基本列。

    • INCLUDING IDENTITY

      已复制列定义的任何标识规范都将被复制。为新表的每个标识列创建一个新序列,与与旧表关联的序列分开。

    • INCLUDING INDEXES

      原始表上的索引、PRIMARY KEY、 UNIQUE和 EXCLUDE约束将被建立在新表上。 根据默认规则选择新索引和约束的名称,而不考虑原始的命名。(此行为可避免新索引可能出现重复名称失败。)

    • INCLUDING STATISTICS

    扩展统计信息将复制到新表。

    • INCLUDING STORAGE

      已复制列定义的STORAGE设置将被复制。 默认行为是排除STORAGE设置,从而导致新表中已复制列具有类型规定的默认设置。 关于STORAGE设置的更多信息。

    • INCLUDING SEQUENCES

      使用INCLUDING DEFAULTS选项进行转移。 当旧表的列使用序列类型(serial, smallserial, bigserial)之一创建时, 为新表的每个序列列创建一个新序列,与旧表相关联的序列是独立的。

    • INCLUDING ALL

      INCLUDING ALL 是选择所有可用的单独选项的缩写形式。 (它能被用于在INCLUDING ALL之后写单独的EXCLUDING子句,以选择部分指定选项之外的所有选项。)

      LIKE子句也能被用来从视图、外部表或组合类型拷贝列定义。不适合的选项(例如来自视图的INCLUDING INDEXES)会被忽略。

  • CONSTRAINT constraint_name

    一个列约束或表约束的可选名称。如果该约束被违背,约束名将会出现在错误消息中,这样类似列必须为正的约束名可以用来与客户端应用沟通有用的约束信息(指定包含空格的约束名时需要用到双引号)。如果没有指定约束名,系统将生成一个。

  • NOT NULL

    该列不允许包含空值。当指定空值时lightdb将会抛出错误并使本次插入失败。但在mysql模式下,如果该列在创建时绑定自增序列或为serial类型亦或是生成列,那么插入空值将会转换成设置默认值,即插入对应序列所生成的默认值。

  • NULL

    该列允许包含空值。这是默认情况。

    这个子句只是提供与非标准 SQL 数据库的兼容。在新的应用中不推荐使用。

  • CHECK ( expression ) [ NO INHERIT ]

    CHECK指定一个产生布尔结果的表达式,一个插入或更新操作要想成功,其中新的或被更新的行必须满足该表达式。计算出 TRUE 或 UNKNOWN 的表达式就会成功。只要任何一个插入或更新操作的行产生了 FALSE 结果,将报告一个错误异常并且插入或更新不会修改数据库。一个被作为列约束指定的检查约束只应该引用该列的值,而一个出现在表约束中的表达式可以引用多列。

    当前,CHECK表达式不能包含子查询,也不能引用当前行的列之外的变量。可以引用系统列tableoid,但不能引用其他系统列。

    一个被标记为NO INHERIT的约束将不会传播到子表。

    当一个表有多个CHECK约束时,检查完NOT NULL约束后,对于每一行会以它们名称的字母表顺序来进行检查(版本 9.5 之前的LightDB对于CHECK约束不遵从任何特定的引发顺序)。

  • DEFAULT default_expr

    DEFAULT子句为出现在其定义中的列赋予一个默认数据。该值是可以使用变量的表达式(特别是,不允许用对其他列的交叉引用)。子查询也是不允许的。 默认值表达式的数据类型必须匹配列的数据类型。

    默认值表达式将被用在任何没有为该列指定值的插入操作中。如果一列没有默认值,那么默认值为空值。

  • ON UPDATE CURRENT_TIMESTAMP

    TIMESTAMP ON UPDATE CURRENT_TIMESTAMP列可以自动初始化并更新为当前时间戳。 对于表中的任何TIMESTAMP列,您可以将当前时间戳分配为默认值、ON UPDATE CURRENT_TIMESTAMP,或两者都分配。 但不建议同时使用默认值和ON UPDATE CURRENT_TIMESTAMP,因为ON UPDATE CURRENT_TIMESTAMP已经包含了默认的当前时间戳语义。

    ON UPDATE CURRENT_TIMESTAMP只能用于TIMESTAMP类型的列,不能用于其他类型的列。

  • AUTO_INCREMENT

    该子句创建一个自增列。该列无法被写入,它将隐式附加一个序列,并且新行中的该列将自动分配从序列中分配的值。这样的列隐式为 NOT NULL。

    该子句等同于GENERATED ALWAYS AS IDENTITY

  • GENERATED ALWAYS AS ( generation_expr ) STORED

    此子句将列创建为generated column。 列无法被写入,读取时将返回指定表达式的结果。

    关键字STORED表示将在写入时计算列并将存储在磁盘上。

    生成表达式可以引用表中的其他列,但不能引用其他生成的列。使用的任何函数和运算符都必须是不可改变的。不允许引用其他表。

  • GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY [ ( sequence_options ) ]

    该子句将列创建为标识列。 它将拥有一个隐式序列附加到它,并且新行中的列将自动从分配给它的序列中获取值。 这样的列为隐式NOT NULL。

    子句ALWAYS和BY DEFAULT确定如何在 INSERT和UPDATE命令中明确处理用户指定的值。

    在INSERT命令中,如果选择了ALWAYS,则仅当 INSERT 语句指定OVERRIDING SYSTEM VALUE时 才接受用户指定的值。除此之外,在该列插入空值将会隐式调用相应的序列以达到插入默认值的目的。 如果选择BY DEFAULT,则用户指定的值优先。 有关详细信息,请参阅INSERT。(在COPY命令中, 无论此设置如何,始终使用用户指定的值。)

    在UPDATE命令中,如果选择了ALWAYS, 则将列更新为除DEFAULT之外的任何值都将被拒绝。 如果选择BY DEFAULT,则该列可以正常更新。 (UPDATE命令没有OVERRIDING子句。)

    可选的sequence_options子句可用于覆盖序列的选项。 有关详细信息,请参见CREATE SEQUENCE。

  • UNIQUE (列约束)

  • UNIQUE ( column_name [, … ] ) [ INCLUDE ( column_name [, …]) ] (表约束)

    UNIQUE约束指定一个表中的一列或多列组成的组包含唯一的值。 唯一表约束的行为与唯一列约束的行为相同,只是表约束能够跨越多列。 约束因此强制在这些列中的至少一列的任何两行必须不同。

    对于一个唯一约束的目的来说,空值不被认为是相等的。

    每一个唯一表约束将命名一个列的集合,并且它与该表上任何其他唯一或主键约束所命名的列集合都不相同。 (否则,冗余的唯一约束将被丢弃。)

    在为多级分区层次结构建立唯一约束时, 目标分区表的分区键中的所有列,以及那些由它派生的所有分区表, 必须被包含在约束定义中。

    添加唯一约束将自动在使用于约束的列或列组上创建唯一的 btree索引。

    可选 INCLUDE子句向该索引添加一个或多个列是简单的“payload”:在它们上面唯一性是不强制的,并且该索引不能基于这些列搜索。 然而它们可以通过一个仅对索引的扫描检索。 请注意虽然约束在包含的列上是非强制的,但是它仍然依赖于它们。 因此,这样的列上的某些操作(例如DROP COLUMN)可能会导致级联约束和索引删除。

  • PRIMARY KEY (列约束)

  • PRIMARY KEY ( column_name [, … ] ) [ INCLUDE ( column_name [, …]) ] (表约束)

    PRIMARY KEY约束指定表的一个或者多个列只能包含唯一(不重复)、非空的值。一个表上只能指定一个主键,可以作为列约束或表约束。

    主键约束所涉及的列集合应该不同于同一个表上定义的任何唯一约束的列集合(否则,该唯一约束是多余的并且会被丢弃)。

    PRIMARY KEY强制的数据约束可以看成是UNIQUE和NOT NULL的组合, 然而,把一组列标识为主键也为模式设计提供了元数据,因为主键标识其他表可以依赖这一个列集合作为行的唯一标识符。

    当放到分区表上时,PRIMARY KEY 约束共享前面描述的UNIQUE 约束的限制。

    添加PRIMARY KEY约束将自动在用于约束的列或列组上创建唯一的 btree 索引。

    可选 INCLUDE子句向该索引添加一个或多个列是简单的“payload”:唯一性对它们是非强制的,并且该索引不能基于这些列搜索。 然而它们可以通过一个仅对索引的扫描检索。 注意虽然包含的列的约束的唯一性是非强制的,但仍依赖于它们。 因此,这样的列上的某些操作(例如DROP COLUMN)可能会导致级联约束和索引删除。

  • EXCLUDE [ USING index_method ] ( exclude_element WITH operator [, … ] ) index_parameters [ WHERE ( predicate ) ]

    EXCLUDE子句定一个排除约束,它保证如果任意两行在指定列或表达式上使用指定操作符进行比较,不是所有的比较都将会返回TRUE。如果所有指定的操作符都测试相等,这就等价于一个UNIQUE约束,尽管一个普通的唯一约束将更快。不过,排除约束能够指定比简单相等更通用的约束。例如,你可以使用&&操作符指定一个约束,要求表中没有两行包含相互覆盖的圆。

    排除约束使用一个索引实现,这样每一个指定的操作符必须与用于索引访问方法index_method的一个适当的操作符类相关联。操作符被要求是交换的。每一个exclude_element可以选择性地指定一个操作符类或者顺序选项,这些在CREATE INDEX中有完整描述。

    访问方法必须支持amgettuple(见Chapter 58),目前这意味着GIN无法使用。尽管允许,但是在一个排除约束中使用 B-树或哈希索引没有意义,因为它无法做得比一个普通唯一索引更出色。因此在实践中访问方法将总是GiST或SP-GiST。

    predicate允许你在该表的一个子集上指定一个排除约束。在内部这会创建一个部分索引。注意在为此周围的圆括号是必须的。

  • REFERENCES reftable [ ( refcolumn ) ] [ MATCH matchtype ] [ ON DELETE referential_action ] [ ON UPDATE referential_action ] (column constraint)

  • FOREIGN KEY ( column_name [, … ] ) REFERENCES reftable [ ( refcolumn [, … ] ) ] [ MATCH matchtype ] [ ON DELETE referential_action ] [ ON UPDATE referential_action ] (表约束)

    这些子句指定一个外键约束,它要求新表的一列或一个列的组必须只包含能匹配被引用表的某个行在被引用列上的值。 如果refcolumn列表被忽略,将使用reftable的主键。 被引用列必须是被引用表中一个非可延迟唯一约束或主键约束的列。 用户必须在被引用的表(或整个表,或特定的引用列)上拥有REFERENCES权限。 增加的外键约束需要SHARE ROW EXCLUSIVE 锁定引用的表。 注意外键约束不能在临时表和永久表之间定义。

    被插入到引用列的一个值会使用给定的匹配类型与被引用表的值进行匹配。 有三种匹配类型:MATCH FULL、MATCH PARTIAL以及MATCH SIMPLE(这是默认值)。 MATCH FULL将不允许一个多列外键中的一列为空,除非所有外键列都是空;如果它们都是空,则不要求该行在被引用表中有一个匹配。 MATCH SIMPLE允许任意外键列为空,如果任一为空,则不要求该行在被引用表中有一个匹配。 MATCH PARTIAL现在还没有被实现(当然,NOT NULL约束能被应用在引用列上来组织这些情况发生)。

    另外,当被引用列中的数据被改变时,在这个表的列中的数据上可以执行特定的动作。ON DELETE指定当被引用表中一个被引用行被删除时要执行的动作。同样,ON UPDATE指定当被引用表中一个被引用列被更新为新值时要执行的动作。如果该行被更新,但是被引用列并没有被实际改变,不会做任何动作。除了NO ACTION检查之外的引用动作不能被延迟,即便该约束被声明为可延迟的。对每一个子句可能有以下动作:

    • NO ACTION

      产生一个错误指示删除或更新将会导致一个外键约束违背。如果该约束被延迟,并且仍存在引用行,这个错误将在约束检查时被产生。这是默认动作。

    • RESTRICT

      产生一个错误指示删除或更新将会导致一个外键约束违背。这个动作与NO ACTION形同,不过该检查不是可延迟的。

    • CASCADE

      删除任何引用被删除行的行,或者把引用列的值更新为被引用列的新值。

    • SET NULL

      将引用列设置为空。

    • SET DEFAULT

      设置引用列为它们的默认值(如果该默认值非空,在被引用表中必须有一行匹配该默认值,否则该操作将会失败)。

如果被引用列被频繁地更改,最好在引用列上加上一个索引,这样与外键约束相关的引用动作能够更高效地被执行。

  • DEFERRABLE

  • NOT DEFERRABLE

    这个子句控制该约束是否能被延迟。 一个不可延迟的约束将在每一次命令后立刻被检查。 可延迟约束的检查将被推迟到事务结束时进行(使用SET CONSTRAINTS命令)。 NOT DEFERRABLE是默认值。 当前,只有UNIQUE、PRIMARY KEY、EXCLUDE以及REFERENCES(外键)约束接受这个子句。 NOT NULL以及CHECK约束是不可延迟的。 注意在包括ON CONFLICT DO UPDATE子句的INSERT语句中,可延迟约束不能被用作冲突裁判者。

  • INITIALLY IMMEDIATE

  • INITIALLY DEFERRED

    如果一个约束是可延迟的,这个子句指定检查该约束的默认时间。 如果该约束是INITIALLY IMMEDIATE,它会在每一个语句之后被检查。 这是默认值。 如果该约束是INITIALLY DEFERRED,它只会在事务结束时被检查。 约束检查时间可以用SET CONSTRAINTS命令修改。

  • USING method

    此可选子句指定用于存储新表内容的表访问方法;该方法需要的是类型TABLE的访问方法。详见 Chapter 57 。 如果未指定此选项,则为新表选择默认表访问方法。详见default_table_access_method。

  • WITH UPDATE CURRENT_TIMESTAMP

    该子句为表指定了一个可选的隐含的 “ltaut” 列。 ltaut 列可以像 TIMESTAMP ON UPDATE CURRENT_TIMESTAMP 列一样自动初始化并更新为当前时间戳。 它可以自动初始化并更新为当前时间戳。 如果使用了 WITH UPDATE CURRENT_TIMESTAMP,则不允许使用 ON UPDATE CURRENT_TIMESTAMP,反之亦然。

    请注意,在创建分布式表时不支持使用 WITH UPDATE CURRENT_TIMESTAMP。

  • WITH PRIMARY KEY [ smallserial | serial | bigserial ]

    该子句为表指定了一个可选的隐含的 “ltapk” 列。 “ltapk” 列可以自动递增,并且可以指定为主键约束。 如果表已经有了主键,则不允许使用 WITH PRIMARY KEY。

    在使用 CREATE TABLE、CREATE TABLE AS 或 SELECT INTO 创建表时, 不允许将 “ltapk” 作为新表的显式列名。 (除非在 CREATE TABLE 中使用 like_option 时包括 INDEXES 和 DEFAULTS)

    请注意,在创建分布式表时不支持使用 WITH PRIMARY KEY。

  • DISTRIBUTED REPLICATED

    该子句创建引用表,请确保 Canopy 扩展已准备就绪。

    请注意,只有哈希分布类型支持创建分布式表,不支持创建只读表和临时表。如果您要创建分布式表,则仅在分布列是主键的一部分时才强制执行主键约束。

  • DISTRIBUTED BY [HASH | APPEND](column) [ distribute_option … ]

    该子句创建一个分布式表,请确保 Canopy 扩展已准备就绪。 分布列为 “column”,分布类型为 “hash” 或 “append”,默认为 “hash”。

    distribute_option 可以指定 shard_count 选项或 colocate_with 选项。shard_count 是可选的,用于选择要分发的表的分片。 colocate_with 是可选的,是当前分布式表将与之共存的表。 可能的值包括 “default”,”none” 以启动新的共存组,或另一个表的名称,该表将与之共存。

    请注意,只有哈希分布类型支持创建分布式表,不支持创建只读表和临时表。如果您要创建分布式表,则仅在分布列是主键的一部分时才强制执行主键约束。

  • WITH ( storage_parameter [= value] [, … ] )

    这个子句为一个表或索引指定可选的存储参数,详见Storage Parameters 。 为了向后兼容性,表的WITH子句还可以包括OIDS=FALSE以便指定新表的行不应包含 OIDs (对象标识符),OIDS=TRUE不再受支持。

  • WITHOUT OIDS

    这是向后兼容的语法,用于声明表WITHOUT OIDS,不再支持创建表WITH OIDS。

  • ON COMMIT

    临时表在一个事务块结束时的行为由ON COMMIT控制。三种选项是:

  • PRESERVE ROWS

    在事务结束时不采取特殊的动作。这是默认行为。

  • DELETE ROWS

    在每一个事务块结束时将删除临时表中的所有行。 实质上,在每一次提交时会完成一次自动的TRUNCATE。 当应用于分区表上时,这不会级联到它的分区。

  • DROP

    在当前事务块结束时将删除临时表。 当在分区表上使用时,这个操作会删除他的分区,而在具有继承子级的表上使用时,它将删除依赖的子级。

  • COMPRESS

  • LOGGING

    为了兼容Oracle数据库语法,新增了四个非保留关键字COMPRESS, LOGGING, NOCOMPRESS, NOLOGGING。 这四个关键字仅是语法糖,没有实现实际的功能。这四个关键字是可选的,如果必须要使用,请放在TABLESPACE关键字之前。

  • STORAGE

    为了兼容Oracle数据库语法,CREATE TABLE语句支持STORAGE关键字。STORAGE关键字后面括号内的内容是被忽略的。 STORAGE关键字是可选的,如果一定要使用,请在COMPRESS LOGGING关键字和TABLESPACE关键字之间使用。

  • ENGINE

    ENGINE 关键字只是为了在语法上兼容 MYSQL 数据库

    • INNODB

    大小写不敏感

    • IMYISAM

    大小写不敏感

  • IDEFAULT CHARSET = …

    关键字 DEFAULT CHARSET 只是为了在语法上兼容 MYSQL 数据库。 注意: DEFAULT CHARACTER SET 还没有被 lightdb 支持。

  • ICOLLATE = …

    关键字 COLLATE 只是为了在语法上兼容 MYSQL 数据库。

  • ITABLESPACE tablespace_name

    tablespace_name是新表要创建于其中的表空间名称。如果没有指定,将参考default_tablespace,或者如果表是临时的则参考temp_tablespaces。 对于分区表,由于表本身不需要存储,指定表空间将 default_tablespace作为默认表空间覆盖,在未显式指定其他表空间时用于任何新创建的分区。

  • IUSING INDEX TABLESPACE tablespace_name

    这个子句允许选择与一个UNIQUE、PRIMARY KEY或者EXCLUDE约束相关的索引将被创建在哪个表空间中。如果没有指定,将参考default_tablespace,或者如果表是临时的则参考temp_tablespaces。

  • IPARTITIONS partitions_value

    Oracle 兼容的语法用于创建哈希分区。需要将配置更改为 Oracle 兼容模式。

  • ISUBPARTITIONS subpartitions_value

    Oracle 兼容的语法用于创建哈希子分区。 目前,仅支持将范围作为主分区、列表作为子分区和哈希作为子分区。 需要将配置更改为 Oracle 兼容模式。

  • IINTERVAL interval_value

    Oracle 兼容的语法用于创建范围分区。 支持两个时间转换函数:NUMTOYMINTERVAL() 和 NUMTODSINTERVAL()。目前,仅支持时间间隔分区。 需要将配置更改为 Oracle 兼容模式。

  • INESTED TABLE column_name STORE AS nested_table_name

    Oracle 兼容语法用于创建带嵌套表类型的表。 目前仅做语法兼容,在未来可能做功能支持。

  • Inable

  • Idisable

    为了兼容Oracle数据库的语法,执行create table语句时列约束支持enable/disable关键字。这个功能仅仅是语法糖。

存储参数

WITH子句能够为表或与一个UNIQUE、PRIMARY KEY或者EXCLUDE约束相关的索引指定存储参数。 用于索引的存储参数已经在CREATE INDEX中介绍过。 当前可用于表的存储参数在下文中列出。 如下文所示,对于很多这类参数,都有一个名字带有toast.前缀的附加参数,它能被用来控制该表的二级TOAST表(如果存在)的行为。 如果一个表的参数值被设置但是相应的toast.参数没有被设置,那么 TOAST 表将使用该表的参数值。 不支持为分区表指定这些参数,但可以为单个叶子分区指定它们。

  • fillfactor (integer)

    一个表的填充因子是一个 10 到 100 之间的百分数。100(完全填满)是默认值。当一个较小的填充因子被指定时,INSERT操作会把表页面只填满到指定的百分比,每个页面上剩余的空间被保留给该页上行的更新。这就让UPDATE有机会把一行的已更新版本放在与其原始版本相同的页面上,这比把它放在一个不同的页面上效率更高。对于一个项从来不会被更新的表来说,完全填满是最好的选择,但是在更新繁重的表上则较小的填充因子更合适。这个参数不能对 TOAST 表设置。

  • toast_tuple_target (integer)

    在我们尝试压缩和/或将长列值移动到TOAST表中之前,toast_tuple_target指定需要的最小元组长度, 也是在toasting开始时尝试减少长度的目标长度。这会影响标记为 External(用于移动)、 Main(用于压缩)或 Extended(用于两者)的列,并且仅适用于新元组。 对现有行没有影响。 这仅影响标记为”外部”或”扩展”的列,并且仅适用于新元数 - 对现有行没有影响。 默认情况下此参数设置为允许每个块至少 4 个元组,默认块大小为 2040 字节。 有效值介于 128 字节和(块大小-标头)之间,默认大小为 8160 字节。 更改此值对于非常短或非常长的行可能没有用处。 请注意默认设置通常接近最佳状态,在某些情况下设置此参数可能会产生负面影响。 不能对TOAST表设置此参数。

  • parallel_workers (integer)

    这个参数设置用于辅助并行扫描这个表的工作者数量。 如果没有设置这个参数,系统将基于关系的尺寸来决定一个值。 规划者或使用并行扫描的实用程序选择的工作者数量可能会比较少,例如max_worker_processes的设置较小就是一种可能的原因。

  • autovacuum_enabled, toast.autovacuum_enabled (boolean)

    为一个特定的表启用或者禁用自动清理守护进程。如果为真,自动清理守护进程这个表上执行自动的VACUUM或者ANALYZE操作。如果为假,这个表不会被自动清理,不过为了阻止事务 ID 回卷时还是会对它进行自动的清理。如果autovacuum参数为假,自动清理守护进程根本就不会运行(除非为了阻止事务 ID 回卷),设置独立的表存储参数也不会覆盖这个设置。因此显式地将这个存储参数设置为true很少有大的意义,只有设置为false才更有用。

  • vacuum_index_cleanup, toast.vacuum_index_cleanup (boolean)

    当VACUUM在此表上运行时强制或禁用索引清理。 默认值为AUTO。 用OFF,索引清理被禁用,用ON则被启用,而采用AUTO ,决定被动态做出,每次VACUUM运行时。 动态行为允许VACUUM不需要的扫描索引以移除很少的死元组。 强制禁用全部索引清理可以显著加快VACUUM,但如果表修改很频繁,也可能导致索引严重膨胀。 VACUUM的INDEX_CLEANUP参数,如果指定,将覆盖此选项的值。

  • vacuum_truncate, toast.vacuum_truncate (boolean)

    启用或禁用vacuum以尝试截断此表末尾的任何空页。默认值为true。 如果true,VACUUM和autovacuum将执行截断,截断页的磁盘空间将返回到操作系统。 请注意,截断需要 ACCESS EXCLUSIVE在表上锁定。 VACUUM的TRUNCATE参数,如果指定,覆盖此选项的值。

  • autovacuum_vacuum_threshold, toast.autovacuum_vacuum_threshold (integer)

    autovacuum_vacuum_threshold参数对于每个表的值。

  • autovacuum_vacuum_scale_factor, toast.autovacuum_vacuum_scale_factor (floating point)

    autovacuum_vacuum_scale_factor参数对于每个表的值。

  • autovacuum_vacuum_insert_threshold, toast.autovacuum_vacuum_insert_threshold (integer)

    autovacuum_vacuum_insert_threshold参数对于每个表的值。特殊值-1可用于禁用表上的插入为空。

  • autovacuum_vacuum_insert_scale_factor, toast.autovacuum_vacuum_insert_scale_factor (floating point)

    autovacuum_vacuum_insert_scale_factor参数对于每个表的值。

  • autovacuum_analyze_threshold (integer)

    autovacuum_analyze_threshold参数对于每个表的值。

  • autovacuum_analyze_scale_factor (floating point)

    autovacuum_analyze_scale_factor参数对于每个表的值。

  • autovacuum_vacuum_cost_delay, toast.autovacuum_vacuum_cost_delay (floating point)

    autovacuum_vacuum_cost_delay参数对于每个表的值。

  • autovacuum_vacuum_cost_limit, toast.autovacuum_vacuum_cost_limit (integer)

    autovacuum_vacuum_cost_limit参数对于每个表的值。

  • autovacuum_freeze_min_age, toast.autovacuum_freeze_min_age (integer)

    vacuum_freeze_min_age参数对于每个表的值。注意自动清理将忽略超过系统范围autovacuum_freeze_max_age参数一半的针对每个表的autovacuum_freeze_min_age参数。

  • autovacuum_freeze_max_age, toast.autovacuum_freeze_max_age (integer)

    autovacuum_freeze_max_age参数对于每个表的值。注意自动清理将忽略超过系统范围参数(只能被设置得较小)一半的针对每个表的autovacuum_freeze_max_age参数。

  • autovacuum_freeze_table_age, toast.autovacuum_freeze_table_age (integer)

    vacuum_freeze_table_age参数对于每个表的值。

  • autovacuum_multixact_freeze_min_age, toast.autovacuum_multixact_freeze_min_age (integer)

    vacuum_multixact_freeze_min_age参数对于每个表的值。注意自动清理将忽略超过系统范围autovacuum_multixact_freeze_max_age参数一半的针对每个表的autovacuum_multixact_freeze_min_age参数。

  • autovacuum_multixact_freeze_max_age, toast.autovacuum_multixact_freeze_max_age (integer)

    autovacuum_multixact_freeze_max_age参数对于每个表的值。注意自动清理将忽略超过系统范围参数(只能被设置得较小)一半的针对每个表的autovacuum_multixact_freeze_max_age参数。

  • autovacuum_multixact_freeze_table_age, toast.autovacuum_multixact_freeze_table_age (integer)

    vacuum_multixact_freeze_table_age参数对于每个表的值。

  • log_autovacuum_min_duration, toast.log_autovacuum_min_duration (integer)

    log_autovacuum_min_duration参数对于每个表的值。

  • user_catalog_table (boolean)

    声明该表是一个用于逻辑复制目的的额外的目录表。不能对 TOAST 表设置这个参数。

示例:

创建表films和表distributors:

CREATE TABLE films (
        code        char(5) CONSTRAINT firstkey PRIMARY KEY,
        title       varchar(40) NOT NULL,
        did         integer NOT NULL,
        date_prod   date,
        kind        varchar(10),
        len         interval hour to minute
);

CREATE TABLE distributors (
        did    integer PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY,
        name   varchar(40) NOT NULL CHECK (name <> '')
);

创建有一个二维数组的表:

CREATE TABLE array_int (
        vector  int[][]
);

为表films定义一个唯一表约束。唯一表约束能够被定义在表的一列或多列上:

CREATE TABLE films (
        code        char(5),
        title       varchar(40),
        did         integer,
        date_prod   date,
        kind        varchar(10),
        len         interval hour to minute,
        CONSTRAINT production UNIQUE(date_prod)
);

定义一个列检查约束:

CREATE TABLE distributors (
        did     integer CHECK (did > 100),
        name    varchar(40)
);

定义部分列的注释及表注释:

CREATE TABLE films (
        code        char(5) COMMENT 'code of films',
        title       varchar(40),
        did         integer CHECK (did > 100) COMMENT 'comment for did',
        date_prod   date,
        kind        varchar(10),
        len         interval hour to minute COMMENT 'length of the films',
        CONSTRAINT production UNIQUE(date_prod)
) COMMENT = 'films table';

定义一个表检查约束:

CREATE TABLE distributors (
        did     integer,
        name    varchar(40),
        CONSTRAINT con1 CHECK (did > 100 AND name <> '')
);

为表films定义一个主键表约束:

CREATE TABLE films (
        code        char(5),
        title       varchar(40),
        did         integer,
        date_prod   date,
        kind        varchar(10),
        len         interval hour to minute,
        CONSTRAINT code_title PRIMARY KEY(code,title)
);

为表distributors定义一个主键约束。下面的两个例子是等价的,第一个使用表约束语法,第二个使用列约束语法:

CREATE TABLE distributors (
        did     integer,
        name    varchar(40),
        PRIMARY KEY(did)
);

CREATE TABLE distributors (
        did     integer PRIMARY KEY,
        name    varchar(40)
);

为列name赋予一个文字常量默认值,安排列did的默认值是从一个序列对象中选择下一个值产生,并且让modtime的默认值是该行被插入的时间:

CREATE TABLE distributors (
        name      varchar(40) DEFAULT 'Luso Films',
        did       integer DEFAULT nextval('distributors_serial'),
        modtime   timestamp DEFAULT current_timestamp
);

在表distributors上定义两个NOT NULL列约束,其中之一被显式给定了一个名称:

CREATE TABLE distributors (
        did     integer CONSTRAINT no_null NOT NULL,
        name    varchar(40) NOT NULL
);

在表 distributors 上定义一个 ON UPDATE CURRENT_TIMESTAMP 列,其中一个列被显式地命名:

CREATE TABLE distributors (
        did     int,
        modtime timestamp ON UPDATE CURRENT_TIMESTAMP
);

创建表 distributors,并定义 WITH UPDATE CURRENT_TIMESTAMP。

CREATE TABLE distributors (
        did     int,
) WITH UPDATE CURRENT_TIMESTAMP;

在表 distributors 上定义 AUTO_INCREMENT 列约束,其中一个列被显式地命名:

CREATE TABLE distributors (
        did     int AUTO_INCREMENT,
        name    varchar(40) NOT NULL
);

为name列定义一个唯一约束:

CREATE TABLE distributors (
        did     integer,
        name    varchar(40) UNIQUE
);

同样的唯一约束用表约束指定:

CREATE TABLE distributors (
        did     integer,
        name    varchar(40),
        UNIQUE(name)
);

创建相同的表,指定表和它的唯一索引指定 70% 的填充因子:

CREATE TABLE distributors (
        did     integer,
        name    varchar(40),
        UNIQUE(name) WITH (fillfactor=70)
)
WITH (fillfactor=70);

创建表circles,带有一个排除约束阻止任意两个圆重叠:

CREATE TABLE circles (
        c circle,
        EXCLUDE USING gist (c WITH &&)
);

在表空间diskvol1中创建表cinemas:

CREATE TABLE cinemas (
                id serial,
                name text,
                location text
) TABLESPACE diskvol1;

创建一个组合类型以及一个类型化的表:

CREATE TYPE employee_type AS (name text, salary numeric);

CREATE TABLE employees OF employee_type (
        PRIMARY KEY (name),
        salary WITH OPTIONS DEFAULT 1000
);

创建一个范围分区表:

CREATE TABLE measurement (
        logdate         date not null,
        peaktemp        int,
        unitsales       int
) PARTITION BY RANGE (logdate);

创建在分区键中具有多个列的范围分区表:

CREATE TABLE measurement_year_month (
        logdate         date not null,
        peaktemp        int,
        unitsales       int
) PARTITION BY RANGE (EXTRACT(YEAR FROM logdate), EXTRACT(MONTH FROM logdate));

创建列表分区表:

CREATE TABLE cities (
        city_id      bigserial not null,
        name         text not null,
        population   bigint
) PARTITION BY LIST (left(lower(name), 1));

建立哈希分区表:

CREATE TABLE orders (
        order_id     bigint not null,
        cust_id      bigint not null,
        status       text
) PARTITION BY HASH (order_id);

创建范围分区表的分区:

CREATE TABLE measurement_y2016m07
        PARTITION OF measurement (
        unitsales DEFAULT 0
) FOR VALUES FROM ('2016-07-01') TO ('2016-08-01');

使用分区键中的多个列创建范围分区表的几个分区:

CREATE TABLE measurement_ym_older
        PARTITION OF measurement_year_month
        FOR VALUES FROM (MINVALUE, MINVALUE) TO (2016, 11);

CREATE TABLE measurement_ym_y2016m11
        PARTITION OF measurement_year_month
        FOR VALUES FROM (2016, 11) TO (2016, 12);

CREATE TABLE measurement_ym_y2016m12
        PARTITION OF measurement_year_month
        FOR VALUES FROM (2016, 12) TO (2017, 01);

CREATE TABLE measurement_ym_y2017m01
        PARTITION OF measurement_year_month
        FOR VALUES FROM (2017, 01) TO (2017, 02);

创建列表分区表的分区:

CREATE TABLE cities_ab
        PARTITION OF cities (
        CONSTRAINT city_id_nonzero CHECK (city_id != 0)
) FOR VALUES IN ('a', 'b');

创建本身是分区的列表分区表的分区,然后向其添加分区:

CREATE TABLE cities_ab
        PARTITION OF cities (
        CONSTRAINT city_id_nonzero CHECK (city_id != 0)
) FOR VALUES IN ('a', 'b') PARTITION BY RANGE (population);

CREATE TABLE cities_ab_10000_to_100000
        PARTITION OF cities_ab FOR VALUES FROM (10000) TO (100000);

建立哈希分区表的分区:

CREATE TABLE orders_p1 PARTITION OF orders
        FOR VALUES WITH (MODULUS 4, REMAINDER 0);
CREATE TABLE orders_p2 PARTITION OF orders
        FOR VALUES WITH (MODULUS 4, REMAINDER 1);
CREATE TABLE orders_p3 PARTITION OF orders
        FOR VALUES WITH (MODULUS 4, REMAINDER 2);
CREATE TABLE orders_p4 PARTITION OF orders
        FOR VALUES WITH (MODULUS 4, REMAINDER 3);

建立默认分区:

CREATE TABLE cities_partdef
        PARTITION OF cities DEFAULT;

创建范围分区表:

CREATE TABLE sales (
        id int,
        date date
) PARTITION BY RANGE (date)
(
START (date '2020-01-01') INCLUSIVE
END (date '2021-01-01') EXCLUSIVE
EVERY (INTERVAL '1 day')
);

创建范围分区表(Oracle 兼容语法): 需要将配置更改为 Oracle 兼容模式。

CREATE TABLE oracle_partition_range
(
        a int,
        b float,
        c date,
        d timestamp
)PARTITION BY RANGE (c)
(
        PARTITION p1 VALUES LESS THAN(to_date('2022-01-01', 'yyyy-mm-dd')),
        PARTITION p2 VALUES LESS THAN(to_date('2022-02-01', 'yyyy-mm-dd')),
        PARTITION p3 VALUES LESS THAN(to_date('2022-03-01', 'yyyy-mm-dd'))
);

创建列表分区表:

CREATE TABLE rank (
        id int,
        gender char(1)
) PARTITION BY LIST (gender)
(
PARTITION girls VALUES ('F'),
PARTITION boys VALUES ('M'),
DEFAULT PARTITION other
);

创建包含列表默认分区的基于列表分区的分区表(Oracle 兼容语法): 需要将配置更改为 Oracle 兼容模式。

CREATE TABLE l(a int) partition by list(a) (
partition l_1 values(1),
partition l_def values(default)
);

创建哈希分区表:

CREATE TABLE thash (
        a int,
        b int,
        c text
) PARTITION BY HASH(a,b)
(
        PARTITION p1 VALUES WITH (MODULUS 3, REMAINDER 0),
        PARTITION p2 VALUES WITH (MODULUS 3, REMAINDER 1),
        PARTITION p3 VALUES WITH (MODULUS 3, REMAINDER 2)
);

创建哈希分区表(Oracle 兼容语法): 需要将配置更改为 Oracle 兼容模式。

CREATE TABLE oracle_hash1
(
        a int,
        b float,
        c VARCHAR(20),
        d DATE,
        e timestamp
) PARTITION BY HASH (a)
(
        PARTITION p1,
        PARTITION p2,
        PARTITION p3
);
CREATE TABLE oracle_hash2
(
        a int,
        b float,
        c VARCHAR(20),
        d DATE,
        e timestamp
) PARTITION BY HASH (a) PARTITIONS 3;

创建范围间隔分区表(Oracle 兼容语法): 需要将配置更改为 Oracle 兼容模式。

CREATE TABLE lt_oracle_interval1
(
        a int,
        b float,
        c date,
        d timestamp,
        e varchar(20)
)PARTITION BY RANGE (c) INTERVAL (numtoyminterval(3, 'month'))
(
        PARTITION p1 VALUES LESS THAN(to_date('2022-01-01', 'yyyy-mm-dd'))
);
CREATE TABLE lt_oracle_interval2
(
        a int,
        b float,
        c date,
        d timestamp,
        e varchar(20)
)PARTITION BY RANGE (c) INTERVAL (numtodsinterval(3, 'day'))
(
        PARTITION p1 VALUES LESS THAN(to_date('2022-01-01', 'yyyy-mm-dd'))
);

创建子分区:

CREATE TABLE sub_partition_list (a text) PARTITION BY LIST(a)
(PARTITION p1 VALUES ('1','2','3'));
CREATE TABLE sub_partition_range (a int) PARTITION BY RANGE(a)
(PARTITION p1 FROM (0) TO (10));
CREATE TABLE sub_partition_range2 (a int) PARTITION BY RANGE(a)
(PARTITION p1 START (0) END (10));
CREATE TABLE sub_partition_hash (a int) PARTITION BY HASH(a)
(
        PARTITION p1 VALUES WITH (MODULUS 3, REMAINDER 0),
        PARTITION p2 VALUES WITH (MODULUS 3, REMAINDER 1),
        PARTITION p3 VALUES WITH (MODULUS 3, REMAINDER 2)
);
CREATE TABLE sub_partition_sp (
        a int, b int, c text
) PARTITION BY RANGE(a)
SUBPARTITION BY LIST (c)
SUBPARTITION TEMPLATE (
        VALUES ('0000', '0001', '0002'),
        VALUES ('0003')
)
(
        PARTITION p1 FROM (0) TO (12),
        PARTITION p2 FROM (12) TO (20)
);

创建子分区(Oracle 兼容语法):

CREATE TABLE lt_oracle_partition_rh
(
        transaction_id number,
        item_id number(8) not null,
        item_description VARCHAR(300),
        transaction_date DATE
)
PARTITION BY RANGE(transaction_date)
SUBPARTITION BY HASH(transaction_id)
SUBPARTITIONS 10
(
        PARTITION P1 VALUES LESS THAN(to_date('2020-01-01','yyyy-mm-dd')),
        PARTITION P2 VALUES LESS THAN(to_date('2021-01-01','yyyy-mm-dd')),
        PARTITION P3 VALUES LESS THAN(to_date('2022-01-01','yyyy-mm-dd'))
);

创建基于范围-列表复合分区,且包含列表默认分区的分区表(Oracle 兼容语法): 需要将配置更改为 Oracle 兼容模式。

CREATE TABLE RL(a int, b int) PARTITION BY RANGE(a)
        SUBPARTITION BY LIST(b)
        SUBPARTITION TEMPLATE
        (
                SUBPARTITION l0 VALUES(0,1,2,3,4,5,6,7,8,9),
                SUBPARTITION l1 VALUES(10,11,12,13,14,15,16,17,18,19),
                SUBPARTITION l_default VALUES(DEFAULT) tablespace pg_default
        )
(
        PARTITION r_lt10 VALUES less than(10)
);

创建基于列表-哈希复合分区,不指定子分区数目的分区表(Oracle 兼容语法): 需要将配置更改为 Oracle 兼容模式。

create table LH(a int, b int)
partition by list(a)
subpartition by hash(b)
(
        partition l_1 values(1),
        partition l_2 values(2)
);

创建基于列表-哈希复合分区,指定子分区数目的分区表(Oracle 兼容语法): 需要将配置更改为 Oracle 兼容模式。

create table LH(a int, b int)
partition by list(a)
subpartition by hash(b) subpartitions 4
(
        partition l_1 values(1),
        partition l_2 values(2)
);

创建基于列表-哈希复合分区,指定子分区模板的分区表(Oracle 兼容语法): 需要将配置更改为 Oracle 兼容模式。

create table LH(a int, b int)
partition by list(a)
subpartition by hash(b)
subpartition template
        (
                subpartition h_0,
                subpartition h_1
        )
(
        partition l_1 values(1),
        partition l_2 values(2)
);

创建引用表:

CREATE TABLE dist_reference_table(a int, b text) DISTRIBUTED REPLICATED;

创建分布式哈希表:

CREATE TABLE dist_table(a int, b text) DISTRIBUTED BY(a);
CREATE TABLE dist_hash_table(a int, b text) DISTRIBUTED BY HASH(a);

创建分布式追加表:

CREATE TABLE dist_append_table(a int, b text) DISTRIBUTED BY APPEND(a);

创建分布式表,并指定分片数量为 4:

CREATE TABLE dist_shard_table(a int, b text) DISTRIBUTED BY(a) shard_count(4);

创建分布式表,并指定与 dist_table 共存:

CREATE TABLE dist_colocate_table(a int, b text) DISTRIBUTED BY (a) colocate_with('dist_table');

创建一个会话级别的全局临时表。

CREATE GLOBAL TEMPORARY TABLE gtt_session(id number,ename varchar(15)) ON COMMIT PRESERVE ROWS;

创建一个事务级别的全局临时表。

CREATE GLOBAL TEMPORARY TABLE gtt_transaction(id number,ename varchar(15)) ON COMMIT DELETE ROWS;

使用COMPRESS/NOCOMPRESS/LOGGING/NOLOGGING选项来创建表。

CREATE TABLE comp_log1(id int) COMPRESS;
CREATE TABLE comp_log2(id int) NOCOMPRESS;
CREATE TABLE comp_log3(id int) LOGGING;
CREATE TABLE comp_log4(id int) NOLOGGING;
CREATE TABLE comp_log5(id int) COMPRESS LOGGING;
CREATE TABLE comp_log6(id int) COMPRESS NOLOGGING;
CREATE TABLE comp_log7(id int) NOCOMPRESS LOGGING;
CREATE TABLE comp_log8(id int) NOCOMPRESS NOLOGGING;
CREATE TABLE comp_log9(id int) LOGGING COMPRESS;
CREATE TABLE comp_log10(id int) LOGGING NOCOMPRESS;
CREATE TABLE comp_log11(id int) NOLOGGING COMPRESS;
CREATE TABLE comp_log12(id int) NOLOGGING NOCOMPRESS;

使用STORAGE选项来创建表。

create table comp_log1(id int) storage(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 PCTINCREASE 0 FREELISTS 1
FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT);
create table comp_log2(id int) storage(464 131 fw f31 fe31);
create table comp_log3(id int) storage(dfa fdsa fdasf fdsa fdsa fads dfsa 1234 454);
create table comp_log4(id int) storage(abcd);
create table comp_log5(id int) storage(654123);

创建一张带嵌套表类型的表。

create type nt_type is table of int;
create table nt_table (col nt_type);

创建分区时支持 nocompress/compress 关键字

CREATE TABLE lt_oracle_partition_list1
(
        a int,
        b float,
        c date,
        d timestamp,
        e varchar2(20)
) PARTITION BY LIST(e)
(
        PARTITION p1 VALUES ('0001', '0002', '0003', '0004', '0005') compress,
        PARTITION p2 VALUES ('0006', '0007', '0008', '0009') nocompress,
        PARTITION p3 VALUES ('0010', '0011')
);
\d+ lt_oracle_partition_list1

Partitioned table "public.lt_oracle_partition_list1"
Column |            Type             | Collation | Nullable | Default | Storage  | Stats target | Description
--------+-----------------------------+-----------+----------+---------+----------+--------------+-------------
a      | integer                     |           |          |         | plain    |              |
b      | double precision            |           |          |         | plain    |              |
c      | oracle.date                 |           |          |         | plain    |              |
d      | timestamp without time zone |           |          |         | plain    |              |
e      | varchar2(20)                |           |          |         | extended |              |
Partition key: LIST (e)
Partitions: "lt_oracle_partition_list1$p$p1" FOR VALUES IN ('0001', '0002', '0003', '0004', '0005'),
"lt_oracle_partition_list1$p$p2" FOR VALUES IN ('0006', '0007', '0008', '0009'),
"lt_oracle_partition_list1$p$p3" FOR VALUES IN ('0010', '0011')

创建分区时支持 list+hash 复合分区

create table lt_lh_partition(a int, b int)
partition by list(a)
subpartition by hash(b)
(
        partition l_1 values(1),
        partition l_2 values(2)
);

\d+ lt_lh_partition

Partitioned table "public.lt_lh_partition"
Column |  Type   | Collation | Nullable | Default | Storage | Stats target | Description
--------+---------+-----------+----------+---------+---------+--------------+-------------
a      | integer |           |          |         | plain   |              |
b      | integer |           |          |         | plain   |              |
Partition key: LIST (a)
Partitions: "lt_lh_partition$p$l_1" FOR VALUES IN (1), PARTITIONED,
"lt_lh_partition$p$l_2" FOR VALUES IN (2), PARTITIONED

\d+ lt_lh_partition$p$l_1

Partitioned table "public.lt_lh_partition$p$l_1"
Column |  Type   | Collation | Nullable | Default | Storage | Stats target | Description
--------+---------+-----------+----------+---------+---------+--------------+-------------
a      | integer |           |          |         | plain   |              |
b      | integer |           |          |         | plain   |              |
Partition of: lt_lh_partition FOR VALUES IN (1)
Partition constraint: ((a IS NOT NULL) AND (a = 1))
Partition key: HASH (b)
Partitions: "lt_lh_partition$p$l_1_p0" FOR VALUES WITH (modulus 1, remainder 0)

5.1.9. CREATE TABLESPACE

定义一个新的表空间

语法:

CREATE TABLESPACE tablespace_name
        [ OWNER { new_owner | CURRENT_USER | SESSION_USER } ]
        LOCATION 'directory'
        [ WITH ( tablespace_option = value [, ... ] ) ]

描述:

  • CREATE TABLESPACE注册一个新的集簇范围 的表空间。表空间的名称必须与数据库集簇中现有的任何表空间不同。

  • 表空间允许超级用户在文件系统上定义另一个位置,可以把包含数据库对象 (例如表和索引)的数据文件放在那里。

  • 一个具有适当特权的用户可以把 tablespace_name传递给 CREATE DATABASE、CREATE TABLE、 CREATE INDEX或者ADD CONSTRAINT 来让这些对象的数据文件存储在指定的表空间中。

参数:

  • tablespace_name

    The name of a tablespace to be created. The name cannot begin with pg_, as such names are reserved for system tablespaces.

  • user_name

    将拥有该表空间的用户名。如果省略,默认为执行该命令的用户。只有 超级用户能创建表空间,但是它们能把表空间的拥有权赋予给非超级 用户。

  • directory

    要被用于表空间的目录。该目录必需存在(CREATE TABLESPACE 将不创建它),应该为空,并且必须由 LightDB系统用户拥有。该目录必须用一个绝对 路径指定。

  • tablespace_option

    要设置或者重置的表空间参数。当前,唯一可用的参数是 seq_page_cost、random_page_cost、 effective_io_concurrency以及maintenance_io_concurrency。 为一个特定表空间设定这些值将覆盖规划器对该表空间中表页读取的 常规代价估计,和执行程序的预取行为,由同名的配置参数确定(见 seq_page_cost、random_page_cost、 effective_io_concurrency、maintenance_io_concurrency)。 如果一个表空间位于一个比其他 I/O 子系统更慢或者更快的磁盘上,这些参数就能发挥作用。

示例:

要在文件系统位置/data/dbs创建表空间dbspace,请首先使用操作系统工具创建目录并设置正确的所有权:

mkdir /data/dbs
chown lightdb:lightdb /data/dbs

然后在内部发出表空间创建命令 LightDB:

CREATE TABLESPACE dbspace LOCATION '/data/dbs';

要创建由不同数据库用户拥有的表空间,可用类似这样的命令:

CREATE TABLESPACE indexspace OWNER genevieve LOCATION '/data/indexes';

5.1.10. CREATE TRIGGER

定义一个新触发器

语法:

CREATE [ CONSTRAINT ] TRIGGER name { BEFORE | AFTER | INSTEAD OF } { event [ OR ... ] }
        ON table_name
        [ FROM referenced_table_name ]
        [ NOT DEFERRABLE | [ DEFERRABLE ] [ INITIALLY IMMEDIATE | INITIALLY DEFERRED ] ]
        [ REFERENCING { { OLD | NEW } TABLE [ AS ] transition_relation_name } [ ... ] ]
        [ FOR [ EACH ] { ROW | STATEMENT } ]
        [ WHEN ( condition ) ]
        EXECUTE { FUNCTION | PROCEDURE } function_name ( arguments )

这里的event可以是下列之一:

        INSERT
        UPDATE [ OF column_name [, ... ] ]
        DELETE
        TRUNCATE

描述:

  • CREATE TRIGGER创建一个新触发器。 CREATE OR REPLACE TRIGGER 将创建一个新触发器,或者替换一个已有的触发器。 该触发器将被关联到指定的表、视图或者外部表并且在表上发生特定操作时将执行指定的函数function_name。

  • 该触发器可以被指定为在一行上尝试该操作之前触发(在约束被检查并且INSERT、UPDATE或者DELETE被尝试之前);也可以在该操作完成之后触发(在约束被检查并且INSERT、UPDATE或者DELETE完成之后);或者取代该操作(在对一个视图插入、更新或删除的情况中)。如果该触发器在事件之前触发或者取代事件,该触发器可以跳过对当前行的操作或者改变正在被插入的行(只对INSERT以及UPDATE操作)。如果该触发器在事件之后触发,所有更改(包括其他触发器的效果)对该触发器“可见”。

  • 一个被标记为FOR EACH ROW的触发器会对该操作修改的每一行都调用一次。例如,一个影响 10 行的DELETE将导致在目标关系上的任何ON DELETE触发器被独立调用 10 次,也就是为每一个被删除的行调用一次。与此相反,一个被标记为FOR EACH STATEMENT的触发器只会为任何给定的操作执行一次,不管该操作修改多少行(特别地,一个修改零行的操作将仍会导致任何可用的FOR EACH STATEMENT触发器被执行)。

  • 被指定为要触发INSTEAD OF触发器事件的触发器必须被标记为FOR EACH ROW,并且只能被定义在视图上。一个视图上的BEFORE和AFTER触发器必须被标记为FOR EACH STATEMENT。

  • 此外,触发器可以被定义成为TRUNCATE触发,但只能是FOR EACH STATEMENT。

  • 如果有多个同种触发器被定义为相同事件触发,它们将按照名称的字母表顺序被触发。

  • 当CONSTRAINT选项被指定,这个命令会创建一个约束触发器。 这和一个常规触发器相同,不过触发该触发器的时机可以使用SET CONSTRAINTS.调整。 约束触发器必须是表上的AFTER ROW触发器。 它们可以在导致触发器事件的语句末尾被引发或者在包含该语句的事务末尾被引发。 在后一种情况中,它们被称作是被延迟。 一个待处理的延迟触发器的引发也可以使用SET CONSTRAINTS立即强制发生。 当约束触发器实现的约束被违背时,约束触发器应该抛出一个异常。

  • REFERENCING选项启用对传递关系的收集,传递关系是包括被当前SQL语句插入、删除或者修改的行的行集合。这个特性让触发器能看到该语句做的事情的全局视图,而不是一次只看到一行。仅对非约束触发器的AFTER触发器允许这个选项。此外,如果触发器是一个UPDATE触发器,则它不能指定column_name列表。OLD TABLE仅可以被指定一次,并且只能为在UPDATE或DELETE事件上引发的触发器指定,它创建的传递关系包含有该语句更新或删除的所有行的前映像。类似地,NEW TABLE仅可以被指定一次,并且只能为在UPDATE或INSERT事件上引发的触发器指定,它创建的传递关系包含有该语句更新或插入的所有行的后映像。

  • SELECT不修改任何行,因此你无法创建SELECT触发器。规则和视图可以为需要SELECT触发器的问题提供可行的解决方案。

参数:

  • name

    给新触发器的名称。这必须与同一个表上的任何其他触发器相区别。名称不能是模式限定的 ? 该触发器会继承它所在表的模式。对于一个约束触发器,这也是使用SET CONSTRAINTS修改触发器行为时要用到的名字。

  • BEFORE

  • AFTER

  • INSTEAD OF

    决定该函数是要在事件之前、之后被调用还是会取代该事件。一个约束触发器也能被指定为AFTER。

  • event

    INSERT、UPDATE、DELETE或者TRUNCATE之一,这指定了将要引发该触发器的事件。多个事件可以用OR指定,要求传递关系的时候除外。

    对于UPDATE事件,可以使用下面的语法指定一个列的列表:

  • UPDATE OF column_name1 [, column_name2 … ]

    只有当至少一个被列出的列出现在UPDATE命令的更新目标中时,或者如果列出的列之一是生成的列,而且依赖的列是UPDATE的目标,该触发器才会触发。

    INSTEAD OF UPDATE事件不允许列的列表。在请求传递关系时,也不能指定列的列表。

  • table_name

    要使用该触发器的表、视图或外部表的名称(可能是模式限定的)。

  • referenced_table_name

    约束引用的另一个表的名称(可能是模式限定的)。这个选项被用于外键约束并且不推荐用于一般的目的。这只能为约束触发器指定。

  • DEFERRABLE

  • NOT DEFERRABLE

  • INITIALLY IMMEDIATE

  • INITIALLY DEFERRED

    该触发器的默认时机。这些约束选项的细节可参考CREATE TABLE文档。这只能为约束触发器指定。

  • REFERENCING

    这个关键词紧接在一个或者两个关系名的声明之前,这些关系提供对触发语句的传递关系的访问。

  • OLD TABLE

  • NEW TABLE

    这个子句指示接下来的关系名是用于前映像传递关系还是后映像传递关系。

  • transition_relation_name

    在该触发器中这个传递关系要使用的(未限定)名称。

  • FOR EACH ROW

  • FOR EACH STATEMENT

    这指定该触发器函数是应该为该触发器事件影响的每一行被引发一次,还是只为每个 SQL 语句被引发一次。如果都没有被指定,FOR EACH STATEMENT会是默认值。约束触发器只能被指定为FOR EACH ROW。

  • condition

    一个决定该触发器函数是否将被实际执行的布尔表达式。如果指定了WHEN,只有condition返回true时才会调用该函数。在FOR EACH ROW触发器中,WHEN条件可以分别写OLD.column_name或者NEW.column_name来引用列的新旧行值。当然,INSERT触发器不能引用OLD并且DELETE触发器不能引用NEW。

    INSTEAD OF触发器不支持WHEN条件。

    当前,WHEN表达式不能包含子查询。

    注意对于约束触发器,对于WHEN条件的计算不会被延迟,而是直接在行更新操作被执行之后立刻发生。如果该条件计算得不到真,那么该触发器就不会被放在延迟执行的队列中。

  • function_name

    一个用户提供的函数,它被声明为不用参数并且返回类型trigger,当触发器引发时会执行该函数。

    在CREATE TRIGGER的语法中,关键词FUNCTION和PROCEDURE是等效的,但是任何情况下被引用的函数必须是一个函数而不是过程。这里,关键词PROCEDURE的使用是有历史原因的并且已经被废弃。

  • arguments

    一个可选的逗号分隔的参数列表,它在该触发器被执行时会被提供给该函数。参数是字符串常量。简单的名称和数字常量也可以被写在这里,但是它们将全部被转换成字符串。请检查该触发器函数的实现语言的描述来找出在函数内部如何访问这些参数,这可能与普通函数参数不同。

示例:

只要表accounts的一行即将要被更新时会执行函数check_account_update:

CREATE TRIGGER check_update
        BEFORE UPDATE ON accounts
        FOR EACH ROW
        EXECUTE FUNCTION check_account_update();

修改该触发器定义,使其仅在UPDATE命令中将balance列指定为目标时执行函数:

CREATE TRIGGER check_update
        BEFORE UPDATE OF balance ON accounts
        FOR EACH ROW
        EXECUTE FUNCTION check_account_update();

这种形式只有列balance具有真正被改变的值时才执行该函数:

CREATE TRIGGER check_update
        BEFORE UPDATE ON accounts
        FOR EACH ROW
        WHEN (OLD.balance IS DISTINCT FROM NEW.balance)
        EXECUTE FUNCTION check_account_update();

调用一个函数来记录accounts的更新,但是只在有东西被改变时才调用:

CREATE TRIGGER log_update
        AFTER UPDATE ON accounts
        FOR EACH ROW
        WHEN (OLD.* IS DISTINCT FROM NEW.*)
        EXECUTE FUNCTION log_account_update();

为每一个要插入到视图底层表中的行执行函数view_insert_row:

CREATE TRIGGER view_insert
        INSTEAD OF INSERT ON my_view
        FOR EACH ROW
        EXECUTE FUNCTION view_insert_row();

为每个语句执行函数check_transfer_balances_to_zero以确认transfer的行不会有净值增加:

CREATE TRIGGER transfer_insert
        AFTER INSERT ON transfer
        REFERENCING NEW TABLE AS inserted
        FOR EACH STATEMENT
        EXECUTE FUNCTION check_transfer_balances_to_zero();

为每一行执行函数check_matching_pairs以确认(同一个语句)同时对匹配对做了更改 :

CREATE TRIGGER paired_items_update
        AFTER UPDATE ON paired_items
        REFERENCING NEW TABLE AS newtab OLD TABLE AS oldtab
        FOR EACH ROW
        EXECUTE FUNCTION check_matching_pairs();

5.1.11. CREATE TYPE

定义一种新的数据类型

语法:

CREATE TYPE name AS
        ( [ attribute_name data_type [ COLLATE collation ] [, ... ] ] )

CREATE TYPE name AS ENUM
        ( [ 'label' [, ... ] ] )

CREATE TYPE name AS RANGE (
        SUBTYPE = subtype
        [ , SUBTYPE_OPCLASS = subtype_operator_class ]
        [ , COLLATION = collation ]
        [ , CANONICAL = canonical_function ]
        [ , SUBTYPE_DIFF = subtype_diff_function ]
)

CREATE TYPE name (
        INPUT = input_function,
        OUTPUT = output_function
        [ , RECEIVE = receive_function ]
        [ , SEND = send_function ]
        [ , TYPMOD_IN = type_modifier_input_function ]
        [ , TYPMOD_OUT = type_modifier_output_function ]
        [ , ANALYZE = analyze_function ]
        [ , INTERNALLENGTH = { internallength | VARIABLE } ]
        [ , PASSEDBYVALUE ]
        [ , ALIGNMENT = alignment ]
        [ , STORAGE = storage ]
        [ , LIKE = like_type ]
        [ , CATEGORY = category ]
        [ , PREFERRED = preferred ]
        [ , DEFAULT = default ]
        [ , ELEMENT = element ]
        [ , DELIMITER = delimiter ]
        [ , COLLATABLE = collatable ]
)

CREATE TYPE name

CREATE TYPE name AS TABLE OF data_type


CREATE TYPE name as_is OBJECT ( [ object_type_element_list ] )

where as_is is:

AS | IS

and object_type_element_list is:

TableFuncElementList [ object_type_func_list ]

and TableFuncElementList is:

attribute_name data_type [ COLLATE collation ] [, ... ]

and object_type_func_list is:

{ type_function_spec | type_procedure_spec } [, ... ]

and type_function_spec is:

MEMBER FUNCTION func_name ( [ [ argmode ] [ argname ] argtype [ { DEFAULT | = } default_expr ] [, ...] ] ) RETURN rettype

and type_procedure_spec is:

MEMBER FUNCTION func_name ( [ [ argmode ] [ argname ] argtype [ { DEFAULT | = } default_expr ] [, ...] ] )


CREATE TYPE BODY name as_is subprog_decl_in_type_list END

where subprog_decl_in_type_list is:
{ func_decl_in_type | proc_decl_in_type }  [ ... ]

and func_decl_in_type is:
MEMBER FUNCTION func_name ( [ [ argmode ] [ argname ] argtype [ { DEFAULT | = } default_expr ] [, ...] ] ) RETURN rettype as_is pl_block ;

and proc_decl_in_type is:
MEMBER PROCEDURE func_name ( [ [ argmode ] [ argname ] argtype [ { DEFAULT | = } default_expr ] [, ...] ] ) as_is pl_block ;

and as_is  is:
AS | IS

and pl_block  is:
[ DECLARE decl_stmts ] BEGIN statement [ , ... ] END

描述:

CREATE TYPE在当前数据库中注册一种新的 数据类型。定义数据类型的用户将成为它的拥有者。

如果给定一个模式名,那么该类型将被创建在指定的模式中。否则它会被 创建在当前模式中。类型名称必须与同一个模式中任何现有的类型或者域 相区别(因为表具有相关的数据类型,类型名称也必须与同一个模式中任 何现有表的名字不同)。

如上面的语法所示,有五种形式的CREATE TYPE。 它们分别创建组合类型、枚举类型、 范围类型、基础类型或者 shell 类型。下文将依次讨论前四种形式。shell 类型仅仅 是一种用于后面要定义的类型的占位符,通过发出一个不带除类型名之外其 他参数的CREATE TYPE命令可以创建这种类型。 在创建范围类型和基础类型时,需要 shell 类型作为一种向前引用。

组合类型

第一种形式的CREATE TYPE创建组合类型。 组合类型由一个属性名和数据类型的列表指定。如果属性的数据类型是可 排序的,也可以指定该属性的排序规则。组合类型本质上和表的行类型相 同,但是如果只想定义一种类型,使用 CREATE TYPE避免了创建一个实际的表。单 独的组合类型也是很有用的,例如可以作为函数的参数或者返回类型。

为了能够创建组合类型,必须拥有在其所有属性类型上的 USAGE特权。

枚举类型

第二种形式的CREATE TYPE创建枚举类型。 枚举类型需要一个带引号的标签构成的列表,每一个标签长度必须不超过NAMEDATALEN字节(在标准的LightDB编译中是 64 字节)。 可以创建具有零个标签的枚举类型,但是在使用ALTER TYPE添加至少一个标签之前,不能使用这种类型来保存值。

范围类型

范围类型的subtype可以 是任何带有一个相关的 B 树操作符类(用来决定该范围类型值的顺序)的类型。 通常,子类型的默认 B 树操作符类被用来决定顺序。要使用一种非默认操作符 类,可以用 subtype_opclass指定它 的名字。如果子类型是可排序的并且希望在该范围的顺序中使用一种非默认的 排序规则,可以用collation选项来指定。

可选的canonical函数 必须接受一个所定义的范围类型的参数,并且返回同样类型的一个值。在适 用时,它被用来把范围值转换成一种规范的形式。创建一个 canonical函数有点棘 手,因为必须在声明范围类型之前定义它。要这样做,必须首先创建一种 shell 类型,它是一种没有属性只有名称和拥有者的占位符类型。这可以通过 发出不带额外参数的命令CREATE TYPE name来完成。然后可以使用该 shell 类型作为 参数和结果来声明该函数,并且最终用同样的名称来声明范围类型。这会自动 用一种合法的范围类型替换 shell 类型项。

可选的subtype_diff函数 必须接受两个subtype类型 的值作为参数,并且返回一个double precision值表示两个给定 值之间的差别。虽然这是可选的,但是提供这个函数会让该范围类型列上 GiST 索 引效率更高。

基础类型

第四种形式的CREATE TYPE创建一种新的 基本类型(标量类型)。为了创建一种新的基本类型,你必须是一个超级 用户(做这种限制的原因是一种错误的类型定义可能让服务器混淆甚至 崩溃)。

参数可以以任意顺序出现(而不仅是按照上面所示的顺序),并且大部分 是可选的。在定义类型前,必须注册两个或者更多函数(使用 CREATE FUNCTION)。支持函数 input_function以及 output_function 是必需的,而函数 receive_function、 send_function、 type_modifier_input_function、 type_modifier_output_function 和 analyze_function 是可选的。通常来说这些函数必须是用 C 或者另外一种低层语言编写的。

input_function将 类型的外部文本表达转换成为该类型定义的操作符和函数所使用的内部 表达。 output_function 执行反向的转换。输入函数可以被声明为有一个cstring 类型的参数,或者有三个类型分别为cstring、 oid、integer的参数。第一个参数是 以 C 字符串存在的输入文本,第二个参数是该类型自身的 OID(对于 数组类型则是其元素类型的 OID),第三个参数是目标列的 typmod(如果知道,不知道则将传递 -1)。输入函数必须 返回一个该数据类型本身的值。通常,一个输入函数应该被声明为 STRICT。 如果不是这样,在读到一个 NULL 输入值时,调用它时第一个参数会是 NULL。在这种情况下,该函数必须仍然返回 NULL,除非它发生了错误( 这种情况主要是想支持域输入函数,它们可能需要拒绝 NULL 输入)。 输出函数必须被声明为有一个新数据类型的参数。输出函数必须返回类型 cstring。对于 NULL 值不会调用输出函数。

T可选的receive_function 会把类型的外部二进制表达转换成内部表达。如果没有提供这个函数, 该类型不能参与到二进制输入中。二进制表达转换成内部形式代价更低, 然而却更容易移植(例如,标准的整数数据类型使用网络字节序作为外 部二进制表达,而内部表达是机器本地的字节序)。接收函数应该执行 足够的检查以确保该值是有效的。接收函数可以被声明为有一个 internal类型的参数,或者有三个类型分别为 internal、oid、integer 的参数。第一个参数是一个指向StringInfo缓冲区的 指针,其中保存着接收到的字节串。其余可选的参数和文本输入函数的 相同。接收函数必须返回一个该数据类型本身的值。通常,一个接收函 数应该被声明为 STRICT。如果不是这样,在读到一个 NULL 输入值时, 调用它时第一个参数会是 NULL。在这种情况下,该函数必须仍然返回 NULL,除非它发生了错误(这种情况主要是想支持域接收函数,它们 可能需要拒绝 NULL 输入)。类似地,可选的 send_function将 内部表达转换成外部二进制表达。如果没有提供这个函数,该类型将不 能参与到二进制输出中。发送函数必须被声明为有一个新数据类型的参 数。发送函数必须返回类型bytea。对于 NULL 值不 会调用发送函数。

到这里你应该在疑惑输入和输出函数是如何能被声明为具有新类型的 结果或参数的?因为必须在创建新类型之前创建这两个函数。这个问题 的答案是,新类型应该首先被定义为一种shell type, 它是一种占位符类型,除了名称和拥有者之外它没有其他属性。这可以 通过不带额外参数的命令CREATE TYPE name做到。然后用 C 写的 I/O 函数可以 被定义为引用这种 shell type。最后,用带有完整定义的 CREATE TYPE把该 shell type 替换为一个完全的、合 法的类型定义,之后新类型就可以正常使用了。

如果该类型支持修饰符(附加在类型声明上的可选约束,例如 char(5)或者numeric(30,2)),则需要可选的 type_modifier_input_function 以及type_modifier_output_function。 LightDB允许用户定义的类型有一个或者 多个简单常量或者标识符作为修饰符。不过,为了存储在系统目录中,该信息必须 能被打包到一个非负整数值中。所声明的修饰符会被以cstring数组的形式 传递给 type_modifier_input_function。 它必须检查该值的合法性(如果值错误就抛出一个错误),如果值正确,要返回 一个非负integer值,它将被存储在“typmod”列中。如果 类型没有 type_modifier_input_function 则类型修饰符将被拒绝。 type_modifier_output_function 把内部的整数 typmod 值转换回正确的形式用于用户显示。它必须返回一个 cstring值,该值就是追加到类型名称后的字符串。例如 numeric的函数可能会返回(30,2)。如果默认的显示格式 就是只把存储的 typmod 整数值放在圆括号内,则允许省略 type_modifier_output_function。

可选的analyze_function 为该数据类型的列执行与类型相关的统计信息收集。默认情况下,如果 该类型有一个默认的 B-树操作符类,ANALYZE将尝试用 类型的“equals”和“less-than”操作符来收集统计信息。 这种行为对于非标量类型并不合适,因此可以通过指定一个自定义分析函数来 覆盖这种行为。分析函数必须被声明为有一个类型为internal的参 数,并且返回一个boolean结果。分析函数的详细 API 请见 src/include/commands/vacuum.h。

虽然只有 I/O 函数和其他为该类型创建的函数才知道新类型的内部表达的细节, 但是内部表达的一些属性必须被向 LightDB声明。其中最重要的是 internallength。基本数据 类型可以是定长的(这种情况下 internallength是一个正 整数)或者是变长的(把 internallength设置为 VARIABLE,在内部通过把typlen设置为 -1 表示)。 所有变长类型的内部表达都必须以一个 4 字节整数开始,它给出了这个值的总 长度。

可选的标志PASSEDBYVALUE表示这种数据类型的值需要 被传值而不是传引用。传值的类型必须是定长的,并且它们的内部表达不能超 过Datum类型(某些机器上是 4 字节,其他机器上是 8 字节)的 尺寸。

alignment参数指定数据 类型的存储对齐要求。允许的值等同于以 1、2、4 或 8 字节边界对齐。注意 变长类型的 alignment 参数必须至少为 4,因为它们需要包含一个 int4作为它们的第一个组成部分。

storage参数允许 为变长数据类型选择存储策略(对定长类型只允许 plain)。plain指定该类型的数 据将总是被存储在线内并且不会被压缩。extended 指定系统将首先尝试压缩一个长的数据值,并且将在数据仍然太长的情 况下把值移出主表行。external允许值被移出主表, 但是系统将不会尝试对它进行压缩。main允许压缩, 但是不鼓励把值移出主表(如果没有其他办法让行的大小变得合适,具有 这种存储策略的数据项仍将被移出主表,但比起 extended以及external项来, 这种存储策略的数据项会被优先考虑保留在主表中)。

除plain之外所有的 storage值都暗示 该数据类型的函数能处理被TOAST 过的值。指定的值 仅仅是决定一种可 TOAST 数据类型的列的默认 TOAST 存储策略,用户 可以使用ALTER TABLE SET STORAGE为列选取其他策略。

like_type参数提供 了另一种方法来指定一种数据类型的基本表达属性:从某种现有的类型中 拷贝。internallength、 passedbyvalue、 alignment和 storage的值会从指 定的类型中复制而来(也可以通过在LIKE子句中指定这些属 性的值来覆盖复制过来的值,不过通常并不这么做)。当新类型的低层 实现是以一种现有的类型为“载体”时,用这种方式指定表达特别有用。

category和 preferred参数可以被用来 帮助控制在混淆的情况下应用哪一种隐式造型。每一种数据类型都属于一个用 单个 ASCII 字符命名的分类,并且每一种类型可以是其所属分类中的 “首选”。当有助于解决重载函数或操作符时,解析器将优先 造型到首选类型(但是只能从同类的其他类型造型)。更多细节请见 Chapter 10。对于没有隐式造型到任意其他类型或者 从任意其他类型造型的类型,让这些设置保持默认即可。不过,对于一组 具有隐式造型的相关类型,把它们都标记为属于同一个类别并且选择一种 或两种“最常用”的类型作为该类别的首选通常是很有用的。在 把一种用户定义的类型增加到一个现有的内建类别(例如数字或者字符串 类型)中时, category参数特别 有用。不过,也可以创建新的全部是用户定义类型的类别。对这样的类别, 可选择除大写字母之外的任何 ASCII 字符。

如果用户希望该数据类型的列被默认为某种非空值,可以指定一个默认值。 默认值可以用DEFAULT关键词指定(这样一个默认值 可以被附加到一个特定列的显式DEFAULT子句覆盖)。

若要指示一个类型是一个数组,请使用 ELEMENT 关键字指定数组元素的类型。 例如,要定义一个 4 字节整数 (int4) 数组,指定 ELEMENT = int4。 有关数组类型的更多详细信息,请参见下面的内容。

要指定在这种类型数组的外部表达中分隔值的定界符,可以把delimiter设置为一个特定字符。默认 的定界符是逗号(,)。注意定界符是与数组元素类型相 关的,而不是数组类型本身相关。

如果可选的布尔参数 collatable为真,这种 类型的列定义和表达式可能通过使用COLLATE子句携带 有排序规则信息。在该类型上操作的函数的实现负责真正利用这些信息,仅 把类型标记为可排序的并不会让它们自动地去使用这类信息。

数组类型

只要一种用户定义的类型被创建,LightDB会自动地创建一种相关的数组类型,其名称由元素类型的名称前面加上一个下划线组成,并且如果长度超过NAMEDATALEN字节会自动地被截断。 (如果这样生成的名称与一种现有类型的名称冲突,该过程将会重复直到找到一个不冲突的名字)。 这种隐式创建的数组类型是变长的并且使用内建的输入和输出函数(array_in以及array_out)。 此外, 这种类型是系统用于构建诸如用户定义类型之上的ARRAY[]。 该数组类型会追随其元素类型的拥有者或所在模式的任何更改,并且在元素类型被删除时也被删除。

如果系统会自动地创建正确的数组类型,你可能会很合情合理地问为什么会有一个ELEMENT选项。 使用ELEMENT主要有用的情况是:当你在创建一种定长类型,它正好在内部是一个多个相同东西的数组,并且除了计划给该类型提供的整体操作之外,你想要允许用下标来直接访问这些东西。 例如,类型point被表示为两个浮点数,可以使用point[0]以及point[1]来访问它们。 注意,这种功能只适用于内部形式正好是一个相同定长域序列的定长类型。 由于历史原因(即很明显是错的,但现在改已经太晚了),定长数组类型的下标是从零开始的,而不是像变长数组那样。

嵌套表类型

类似于数组,但没有长度限制,主要用于存储过程中。

对象类型

类似于组合类型,但是可以携带函数。

参数:

  • name

    要创建的类型的名称(可以被模式限定)。

  • attribute_name

    组合类型的一个属性(列)的名称。

  • data_type

    要成为组合类型的一个列的现有数据类型的名称。

  • collation

    要关联到组合类型的一列或者范围类型的现有排序规则的名称。

  • label

    一个字符串,它表达与枚举类型的一个值相关的文本标签。

  • subtype

    范围类型的元素类型的名称,范围类型表示的范围属于该类型。

  • subtype_operator_class

    用于 subtype 的 B 树操作符类的名称。

  • canonical_function

    范围类型的规范化函数的名称。

  • subtype_diff_function

    用于 subtype 的差函数的名称。

  • input_function

    将数据从类型的外部文本形式转换为内部形式的函数名。

  • output_function

    将数据从类型的内部形式转换为外部文本形式的函数名。

  • receive_function

    将数据从类型的外部二进制形式转换成内部形式的函数名。

  • send_function

    将数据从类型的内部形式转换为外部二进制形式的函数名。

  • type_modifier_input_function

    将类型的修饰符数组转换为内部形式的函数名。

  • type_modifier_output_function

    将类型的修饰符的内部形式转换为外部文本形式的函数名。

  • analyze_function

    为该数据类型执行统计分析的函数名。

  • internallength

    一个数字常量,它指定新类型的内部表达的字节长度。默认的假设是 它是变长的。

  • alignment

    该数据类型的存储对齐需求。如果被指定,它必须是 char、int2、 int4或者double。默认是 int4。

  • storage

    该数据类型的存储策略。如果被指定,必须是 plain、external、 extended或者main。 默认是plain。

  • like_type

    与新类型具有相同表达的现有数据类型的名称。会从这个类型中复制 internallength、 passedbyvalue、 alignment以及 storage的值( 除非在这个CREATE TYPE命令的其他地方用显式说 明覆盖)。

  • category

    这种类型的分类码(一个 ASCII 字符)。 默认是 “用户定义类型”的’U’。其他的标准分类码可见 Table 48.71。为了创建自定义分类, 你也可以选择其他 ASCII 字符。

  • preferred

    如果这种类型是其类型分类中的优先类型则为真,否则为假。默认 为假。在一个现有类型分类中创建一种新的优先类型要非常小心, 因为这可能会导致行为上令人惊奇的改变。

  • default

    数据类型的默认值。如果被省略,默认值是空。

  • element

    被创建的类型是一个数组,这指定了数组元素的类型。

  • delimiter

    在由这种类型组成的数组中值之间的定界符。

  • collatable

    如果这个类型的操作可以使用排序规则信息,则为真。默认为假。

  • func_name

    要创建的函数的名称。

  • argmode

    一个参数的模式:IN、OUT、INOUT或者VARIADIC。如果省略,默认为IN。只有OUT参数能跟在一个VARIADIC参数后面。还有,OUT和INOUT参数不能和RETURNS TABLE符号一起使用。

  • argname

    一个参数的名称。一些语言(包括 SQL 和 PL/pgSQL)让你在函数体中使用该名称。对于其他语言,一个输入参数的名字只是额外的文字(就该函数本身所关心的来说)。但是你可以在调用一个函数时使用输入参数名来提高可读性。在任何情况下,输出参数的名称是有意义的,因为它定义了结果行类型中的列名(如果忽略一个输出参数的名称,系统将选择一个默认的列名)。

  • argtype

    该函数参数(如果有)的数据类型(可以是模式限定的)。参数类型可以是基本类型、组合类型或者域类型,或者可以引用一个表列的类型。

    根据实现语言,也可以允许指定cstring之类的“伪类型”。伪类型表示实际参数类型没有被完整指定或者不属于普通 SQL 数据类型集合。

    可以写table_name.column_name%TYPE来引用一列的类型。使用这种特性有时可以帮助创建一个不受表定义更改影响的函数。

  • default_expr

    如果参数没有被指定值时要用作默认值的表达式。该表达式必须能被强制为该参数的参数类型。只有输入(包括INOUT)参数可以具有默认值。所有跟随在一个具有默认值的参数之后的输入参数也必须有默认值。

  • rettype

    返回数据类型(可能被模式限定)。返回类型可以是一种基本类型、组合类型或者域类型,也可以引用一个表列的类型。根据实现语言,也可以允许指定cstring之类的“伪类型”。如果该函数不会返回一个值,可以指定返回类型为void。

    当有OUT或者INOUT参数时,可以省略RETURNS子句。如果存在,该子句必须和输出参数所表示的结果类型一致:如果有多个输出参数,则为RECORD,否则与单个输出参数的类型相同。

    SETOF修饰符表示该函数将返回一个项的集合而不是一个单一项。

    可以写table_name.column_name%TYPE来引用一列的类型。

  • decl_stmts

    PL/oraSQL 声明语句块。

  • statement

    PL/oraSQL 执行语句块。

示例:

这个例子创建了一种组合类型并且将其用在了一个函数定义中:

CREATE TYPE compfoo AS (f1 int, f2 text);

CREATE FUNCTION getfoo() RETURNS SETOF compfoo AS $$
        SELECT fooid, fooname FROM foo
$$ LANGUAGE SQL;

这个例子创建了一个枚举类型并且将其用在一个表定义中:

CREATE TYPE bug_status AS ENUM ('new', 'open', 'closed');

CREATE TABLE bug (
        id serial,
        description text,
        status bug_status
);

这个例子创建了一个范围类型:

CREATE TYPE float8_range AS RANGE (subtype = float8, subtype_diff = float8mi);

这个例子创建了基本数据类型box然后将它用在一个表定义中:

CREATE TYPE box;

CREATE FUNCTION my_box_in_function(cstring) RETURNS box AS ... ;
CREATE FUNCTION my_box_out_function(box) RETURNS cstring AS ... ;

CREATE TYPE box (
        INTERNALLENGTH = 16,
        INPUT = my_box_in_function,
        OUTPUT = my_box_out_function
);

CREATE TABLE myboxes (
        id integer,
        description box
);

如果box的内部结构是四个 float4元素的一个数组,我们可能会使用:

CREATE TYPE box (
        INTERNALLENGTH = 16,
        INPUT = my_box_in_function,
        OUTPUT = my_box_out_function,
        ELEMENT = float4
);

这将允许用下标来访问一个 box 值的组件编号。否则该类型的行为和 前面的一样。

这个例子创建了一个大对象类型并且将它用在了一个表定义中:

CREATE TYPE bigobj (
        INPUT = lo_filein, OUTPUT = lo_fileout,
        INTERNALLENGTH = VARIABLE
);
CREATE TABLE big_objs (
        id integer,
        obj bigobj
);

这个例子创建了一个嵌套表类型,并在匿名块中使用它:

CREATE TYPE names2 IS TABLE OF VARCHAR(15);

DECLARE
        nt names2 ;
BEGIN
        nt(1) = 'D Caruso';
        nt(2) = 'J Hamil';
        nt(3) = 'R Singh';
        DBMS_OUTPUT.PUT_LINE(nt(2));
END;
/

创建对象类型:

CREATE TYPE tp AS OBJECT (
x INT,
y INT,
member FUNCTION d(prompt VARCHAR) RETURN VARCHAR,
member PROCEDURE p(prompt VARCHAR)
);

创建对象类型体:

CREATE TYPE BODY tp AS
MEMBER FUNCTION d(prompt VARCHAR) RETURN VARCHAR IS
DECLARE
        v VARCHAR;
BEGIN
        v := '(' || self.x || ',' || self.y || ')';
        raise notice '%', v;
        return v;
END;

MEMBER PROCEDURE p(prompt VARCHAR) IS
BEGIN
        raise notice '%', '(' || self.x || ',' || self.y || ')';
END;
END;
/

支持创建对象类型

select dbms_output.serveroutput(true);
CREATE TYPE stock AS OBJECT (
        stock_no int,
        price    numeric(16,2),
        member procedure dis(prompt varchar)
);

CREATE TYPE BODY stock AS
member procedure dis(prompt varchar) is
        begin
                dbms_output.put_line(prompt || ':' || self.stock_no || '-' || self.price);
        end;
END;
/

DECLARE
        s stock := stock(600570, 180.00);
BEGIN
        s.dis('current');
END;
/

current:600570-180.00
DO

5.1.12. CREATE USER

创建和配置数据库用户

语法:

CREATE USER name [ [ WITH ] option [ ... ] | IDENTIFIED BY password option_for_oracle ]

这里 option 可以是:

        SUPERUSER | NOSUPERUSER
        | CREATEDB | NOCREATEDB
        | CREATEROLE | NOCREATEROLE
        | INHERIT | NOINHERIT
        | LOGIN | NOLOGIN
        | REPLICATION | NOREPLICATION
        | BYPASSRLS | NOBYPASSRLS
        | CONNECTION LIMIT connlimit
        | [ ENCRYPTED ] PASSWORD 'password' | PASSWORD NULL
        | VALID UNTIL 'timestamp'
        | IN ROLE role_name [, ...]
        | IN GROUP role_name [, ...]
        | ROLE role_name [, ...]
        | ADMIN role_name [, ...]
        | USER role_name [, ...]
        | SYSID uid

where option_for_oracle can be:
        DEFAULT TABLESPACE tablespace
        | TEMPORARY TABLESPACE tablespace

参数:

  • IDENTIFIED BY

    用于与 Oracle 兼容的 CREATE USER 语句。 仅提供语法支持,不提供功能支持的 option_for_oracle。 为了与 Oracle 授权功能兼容,在 Oracle 模式下不允许使用名称为“connect”和“resource”的用户进行 CREATE USER。

描述:

CREATE USER现在是 CREATE ROLE的一个别名。唯一的区别是 CREATE USER中LOGIN 被作为默认值,而NOLOGIN是 CREATE ROLE的默认值。

示例:

CREATE USER user_name IDENTIFIED BY passwd DEFAULT TABLESPACE dt_space TEMPORARY TABLESPACE tt_space;

5.1.13. CREATE VIEW

定义一个新视图

语法:

CREATE [ OR REPLACE ] [ TEMP | TEMPORARY ] [ RECURSIVE ] VIEW name [ ( column_name [, ...] ) ]
        [ WITH ( view_option_name [= view_option_value] [, ... ] ) ]
        AS query
        [ WITH [ CASCADED | LOCAL ] CHECK OPTION ]

描述:

  • CREATE VIEW定义一个查询的视图。该视图不会被 物理上物质化。相反,在每一次有查询引用该视图时,视图的查询都会被运行。

  • CREATE OR REPLACE VIEW与之相似,但是如果 已经存在一个同名视图,该视图会被替换。新查询必须产生和现有试图查询相同 的列(也就是相同的列序、相同的列名、相同的数据类型),但是它可以在列表 的末尾加上额外的列。产生输出列的计算可以完全不同。

  • 如果给定了一个模式名(例如CREATE VIEW myschema.myview …),那么该视图会被创建在指定的模式中。否则,它会 被创建在当前模式中。临时视图存在于一个特殊模式中,因此创建临时视图时不能 给定一个模式名。视图的名称不能与同一模式中任何其他视图、表、序列、索引或 外部表同名。

参数:

  • TEMPORARY或者TEMP

    如果被指定,视图被创建为一个临时视图。在当前会话结束时会自动 删掉临时视图。当临时视图存在时,具有相同名称的已有永久视图对 当前会话不可见,除非用模式限定的名称引用它们。

    如果视图引用的任何表是临时的,视图将被创建为临时视图(不管有 没有指定TEMPORARY)。

  • RECURSIVE

    创建一个递归视图。语法

    CREATE RECURSIVE VIEW [ schema . ] view_name (column_names) AS SELECT ...;
    

    等效于

    CREATE VIEW [ schema . ] view_name AS WITH RECURSIVE view_name (column_names) AS (SELECT ...) SELECT column_names FROM view_name;
    

    对于一个递归视图必须指定一个视图列名列表。

  • name

    要创建的视图的名字(可以是模式限定的)。

  • column_name

    要用于视图列的名称列表,可选。如果没有给出,列名会根据查询 推导。

  • WITH ( view_option_name [= view_option_value] [, … ] )

    这个子句为视图指定一些可选的参数,支持下列参数:

    • check_option (enum)

      这个参数可以是local或者cascaded,并且它 等效于指定 WITH [ CASCADED | LOCAL ] CHECK OPTION(见下文)。 可以使用ALTER VIEW在一个现有视图上修改这个选项。

    • security_barrier (boolean)

      如果希望视图提供行级安全性,应该使用这个参数。

  • query

    提供视图的行和列的一个SELECT 或者 VALUES命令。

  • WITH [ CASCADED | LOCAL ] CHECK OPTION

    这个选项控制自动可更新视图的行为。这个选项被指定时,将检查该视图上的 INSERT和UPDATE命令以确保新行满足 视图的定义条件(也就是,将检查新行来确保通过视图能看到它们)。如果新行 不满足条件,更新将被拒绝。如果没有指定CHECK OPTION, 会允许该视图上的INSERT和UPDATE命令 创建通过该视图不可见的行。支持下列检查选项:

    • LOCAL

      只根据直接定义在该视图本身的条件检查新行。任何定义在底层基视图上的 条件都不会被检查(除非它们也指定了CHECK OPTION)。

    • CASCADED

      会根据该视图和所有底层基视图上的条件检查新行。如果 CHECK OPTION被指定,并且没有指定 LOCAL和CASCADED,则会假定为 CASCADED。

  • CHECK OPTION不应该和RECURSIVE视图一起使用。

注意,只有在自动可更新的、没有INSTEAD OF触发器或者 INSTEAD规则的视图上才支持CHECK OPTION。 如果一个自动可更新的视图被定义在一个具有INSTEAD OF 触发器的基视图之上,那么LOCAL CHECK OPTION可以被 用来检查该自动可更新的视图之上的条件,但具有INSTEAD OF 触发器的基视图上的条件不会被检查(一个级联检查选项将不会级联到一个 触发器可更新的视图,并且任何直接定义在一个触发器可更新视图上的检查 选项将被忽略)。如果该视图或者任何基础关系具有导致 INSERT或UPDATE命令被重写的 INSTEAD规则,那么在被重写的查询中将忽略所有检查选项, 包括任何来自于定义在带有INSTEAD规则的关系之上的自动 可更新视图的检查。

示例:

创建一个由所有喜剧电影组成的视图:

CREATE VIEW comedies AS
        SELECT *
        FROM films
        WHERE kind = 'Comedy';

创建的视图包含创建时film表中的列。尽管* 被用来创建该视图,后来被加入到该表中的列不会成为该视图的组成部分。

创建带有LOCAL CHECK OPTION的视图:

CREATE VIEW universal_comedies AS
        SELECT *
        FROM comedies
        WHERE classification = 'U'
        WITH LOCAL CHECK OPTION;

这将创建一个基于comedies视图的视图,只显示 kind = ‘Comedy’和classification = ‘U’的电影。 如果新行没有classification = ‘U’,在该视图中的任何 INSERT或UPDATE尝试将被拒绝, 但是电影的kind将不会被检查。

用CASCADED CHECK OPTION创建一个视图:

CREATE VIEW pg_comedies AS
        SELECT *
        FROM comedies
        WHERE classification = 'PG'
        WITH CASCADED CHECK OPTION;

这将创建一个检查新行的kind和classification 的视图。

创建一个由可更新列和不可更新列混合而成的视图:

CREATE VIEW comedies AS
        SELECT f.*,
                country_code_to_name(f.country_code) AS country,
                (SELECT avg(r.rating)
                        FROM user_ratings r
                        WHERE r.film_id = f.id) AS avg_rating
        FROM films f
        WHERE f.kind = 'Comedy';

这个视图将支持INSERT、UPDATE 以及DELETE。所有来自于films表的列都 将是可更新的,而计算列country和avg_rating 将是只读的。

创建一个由数字 1 到 100 组成的递归视图:

CREATE RECURSIVE VIEW public.nums_1_100 (n) AS
        VALUES (1)
UNION ALL
        SELECT n+1 FROM nums_1_100 WHERE n < 100;

注意在这个CREATE中尽管递归的视图名称是方案限定的,但它内部的自引用不是方案限定的。这是因为隐式创建的CTE的名称不能是方案限定的。

5.1.14. ALTER DATABASE

更改一个数据库

语法:

ALTER DATABASE name [ [ WITH ] option [ ... ] ]

这里 option 可以是:

        ALLOW_CONNECTIONS allowconn
        CONNECTION LIMIT connlimit
        IS_TEMPLATE istemplate

ALTER DATABASE name RENAME TO new_name

ALTER DATABASE name OWNER TO { new_owner | CURRENT_USER | SESSION_USER }

ALTER DATABASE name SET TABLESPACE new_tablespace

ALTER DATABASE name SET configuration_parameter { TO | = } { value | DEFAULT }
ALTER DATABASE name SET configuration_parameter FROM CURRENT
ALTER DATABASE name RESET configuration_parameter
ALTER DATABASE name RESET ALL

描述:

ALTER DATABASE更改一个数据库的属性。

第一种形式更改某些针对每个数据库的设置(详见下文)。只有数据库拥有者或者超级用户可以更改这些设置。

第二种形式更改数据库的名称。只有数据库拥有者或者超级用户可以重命名一个数据库,非超级用户拥有者还必须拥有CREATEDB特权。当前数据库不能被重命名(如果你需要这样做请连接到一个不同的数据库)。

第三种形式更改数据库的拥有者。要修改拥有者,你必须拥有该数据库并且也是新拥有角色的一个直接或间接成员,并且你必须具有CREATEDB特权(注意超级用户自动拥有所有这些特权)。

第四种形式更改数据库的默认表空间。只有数据库拥有者或超级用户能够这样做,你还必须对新表空间具有创建特权。这个命令会在物理上移动位于该数据库旧的默认表空间中的任何表或索引到新的表空间中。新的默认表空间对于这个数据库必须是空的,并且不能有人可以连接到该数据库。在非默认表空间中的表和索引不受影响。

剩下的形式更改用于一个LightDB数据库的运行时配置变量的会话默认值。接下来只要一个新的会话在该数据库中开始,指定的值就会成为该会话的默认值。数据库相关的默认值会覆盖出现在lightdb.conf中或者从lightdb命令行接收到的设置。只有数据库拥有者或超级用户可以更改一个数据库的会话默认值。一些变量不能用这种方式设置或者只能由超级用户更改。

参数:

  • name

    要被修改属性的数据库名称。

  • allowconn

    如果为假,则没有人能连接到这个数据库。

  • connlimit

    与这个数据库可以建立多少个并发连接。-1 表示没有限制。

  • istemplate

    如果为真,则任何具有CREATEDB特权的用户都可以从这个数据库进行克隆。如果为假,则只有超级用户或者这个数据库的拥有者可以克隆它。

  • new_name

    数据库的新名称。

  • new_owner

    数据库的新拥有者。

  • new_tablespace

    数据库的新默认表空间。

    这种形式的命令不能在事务块内执行。

  • configuration_parameter

  • value

    将这个数据库的指定配置参数的会话默认值设置为给定值。如果value是DEFAULT,或者等效地使用了RESET,数据库相关的设置会被移除,因此系统范围的默认设置将会在新会话中继承。使用RESET ALL可清除所有数据库相关的设置。SET FROM CURRENT会保存该会话的当前参数值作为数据库相关的值。

示例:

要在数据库test中默认禁用索引扫描:

ALTER DATABASE test SET enable_indexscan TO off;

5.1.15. ALTER INDEX

更改一个索引的定义

语法:

ALTER INDEX [ IF EXISTS ] name RENAME TO [schema_name.]new_name
ALTER INDEX [ IF EXISTS ] name SET TABLESPACE tablespace_name
ALTER INDEX name ATTACH PARTITION index_name
ALTER INDEX name [ NO ] DEPENDS ON EXTENSION extension_name
ALTER INDEX [ IF EXISTS ] name SET ( storage_parameter [= value] [, ... ] )
ALTER INDEX [ IF EXISTS ] name RESET ( storage_parameter [, ... ] )
ALTER INDEX [ IF EXISTS ] name ALTER [ COLUMN ] column_number
        SET STATISTICS integer
ALTER INDEX ALL IN TABLESPACE name [ OWNED BY role_name [, ... ] ]
        SET TABLESPACE new_tablespace [ NOWAIT ]
ALTER INDEX [ IF EXISTS ] index_name REBUILD

描述:

ALTER INDEX更改一个现有索引的定义。下面描述了几种子窗体。 注意每个子窗体所需的锁级别可能不同。除非显式说明,ACCESS EXCLUSIVE锁被持有。 列出多个子命令时,锁的持有将是任何子命令所需的最严格的子命令。 ALTER INDEX index_name REBUILD 类似于 REINDEX index name,此语法特性自LightDB 23.2起包含,以实现与Oracle的兼容性。

  • RENAME

    RENAME形式更改该索引的名称。如果索引与一个表约束(UNIQUE、PRIMARY KEY或者EXCLUDE)关联,该约束也会被重命名。这对已存储的数据没有影响。

    重命名索引取得一个 SHARE UPDATE EXCLUSIVE锁。

  • SET TABLESPACE

    这种形式更改该索引的表空间为指定的表空间,并且把与该索引相关联的数据文件 移动到新的表空间中。要更改一个索引的表空间,你必须拥有该索引并且具有新表 空间上的CREATE特权。可以使用 ALL IN TABLESPACE形式把当前数据库中在一个表空间内的 所有索引全部移动到另一个表空间中,这将会锁定所有要被移动的索引然后挨个移 动它们。这种形式也支持OWNED BY,即只移动属于指定角色 的索引。如果指定了NOWAIT选项,那么当该命令无法立刻获 得所有锁时将会失败。注意这个命令不会移动系统目录,如果想要移动系统目录, 应使用ALTER DATABASE或者显式的 ALTER INDEX调用。另见 CREATE TABLESPACE。

  • ATTACH PARTITION

    导致提到的索引变成附着于被修改的索引。提及的索引必须在包含被修改索引的表的一个分区上,并且具有一种等效的定义。一个附着索引不能被单独删除,它会在其父索引被删除时自动连带删除。

  • DEPENDS ON EXTENSION extension_name

  • NO DEPENDS ON EXTENSION extension_name

    ]这种形式将索引标记为依赖于扩展,或者如果指定了 NO ,则不再依赖于该扩展名。标记为依赖于扩展名的索引会在删除扩展名时自动删除。

  • SET ( storage_parameter [= value] [, … ] )

    这种形式为该索引更改一个或者多个索引方法相关的存储参数。可用的参数详见 CREATE INDEX。注意这个命令不会立刻修改索引内容, 根据参数你可能需要用REINDEX重建索引来得到想要的 效果。

  • RESET ( storage_parameter [, … ] )

    这种形式把一个或者多个索引方法相关的存储参数重置为其默认值。正如 SET一样,可能需要一次REINDEX来完全更新 该索引。

  • ALTER [ COLUMN ] column_number SET STATISTICS integer

    这种形式为后续的ANALYZE操作设置针对每个列的统计信息收集目标,不过只能用在被定义为表达式的索引列上。由于表达式缺少唯一的名称,我们通过该索引列的顺序号来引用它们。收集目标可以被设置为范围0到10000之间的值。另外,把它设置为-1会恢复到使用系统的默认统计信息目标(default_statistics_target)。更多有关LightDB查询规划器使用统计信息的内容。

  • REBUILD

    REBUILD 使用索引表中存储的数据重建索引。

参数:

  • IF EXISTS

    如果该索引不存在不要抛出错误。这种情况下将发出一个提示。

  • column_number

    引用该索引列的顺序(从左往右)位置的顺序号。

  • name

    要更改的一个现有索引的名称(可能被模式限定)。

  • new_name

    该索引的新名称。

  • schema_name

    为了兼容Oracle数据库语法,ALTER INDEX RENAME TO语句支持为新的索引名称指定schema_name。这个功能仅是语法糖。

  • tablespace_name

    该索引将被移动到的表空间。

  • extension_name

    该索引所依赖的扩展的名称。

  • storage_parameter

    一个索引方法相关的存储参数的名称。

  • value

    一个索引方法相关的存储参数的新值。根据该参数,这可能是一个数字或者一个 词。

  • index_name

    重建索引的名字。

示例:

要重命名一个现有索引:

ALTER INDEX distributors RENAME TO suppliers;

把一个索引移动到一个不同的表空间:

ALTER INDEX distributors SET TABLESPACE fasttablespace;

更改一个索引的填充因子(假设该索引方法支持填充因子):

ALTER INDEX distributors SET (fillfactor = 75);
REINDEX INDEX distributors;

为一个表达式索引设置统计信息收集目标:

CREATE INDEX coord_idx ON measured (x, y, (z + t));
ALTER INDEX coord_idx ALTER COLUMN 3 SET STATISTICS 1000;

在重命名索引时使用schema_name前缀。

create table t1(id int);
create index hahaha.index_t1_id on t1(id);
alter index index_t1_id rename to xxww.index_t1_id_1;

重建索引:

create table t1(id int);
create index idx_t1_id on t1(id);
ALTER INDEX idx_t1_id REBUILD;

支持 ALTER INDEX idx_name REBUILD 语法,用于重建指定索引

CREATE TABLE tt(a int);
CREATE INDEX idx_tt_a on tt(a);
ALTER INDEX idx_tt_a REBUILD;

5.1.16. ALTER MATERIALIZED VIEW

更改一个物化视图的定义

语法:

ALTER MATERIALIZED VIEW [ IF EXISTS ] name
        action [, ... ]
ALTER MATERIALIZED VIEW name
        [ NO ] DEPENDS ON EXTENSION extension_name
ALTER MATERIALIZED VIEW [ IF EXISTS ] name
        RENAME [ COLUMN ] column_name TO new_column_name
ALTER MATERIALIZED VIEW [ IF EXISTS ] name
        RENAME TO new_name
ALTER MATERIALIZED VIEW [ IF EXISTS ] name
        SET SCHEMA new_schema
ALTER MATERIALIZED VIEW ALL IN TABLESPACE name [ OWNED BY role_name [, ... ] ]
        SET TABLESPACE new_tablespace [ NOWAIT ]

其中 action是下列之一:

        ALTER [ COLUMN ] column_name SET STATISTICS integer
        ALTER [ COLUMN ] column_name SET ( attribute_option = value [, ... ] )
        ALTER [ COLUMN ] column_name RESET ( attribute_option [, ... ] )
        ALTER [ COLUMN ] column_name SET STORAGE { PLAIN | EXTERNAL | EXTENDED | MAIN }
        ALTER [ COLUMN ] column_name SET COMPRESSION compression_method
        CLUSTER ON index_name
        SET WITHOUT CLUSTER
        SET ( storage_parameter [= value] [, ... ] )
        RESET ( storage_parameter [, ... ] )
        OWNER TO { new_owner | CURRENT_USER | SESSION_USER }

描述:

ALTER MATERIALIZED VIEW更改一个现有物化视图的 多个辅助属性。

要使用ALTER MATERIALIZED VIEW,你必须拥有该物化视图。要 更改一个物化视图的模式,你还必须拥有新模式上的CREATE特权。要更 改拥有者,你还必须是新拥有角色的一个直接或者间接成员,并且该角色必须拥有该 物化视图所在模式上的CREATE特权(这些限制强制修改拥有者不 能做一些通过删除和重建该物化视图做不到的事情。不过,一个超级用户怎么都能更改 任何视图的所有权。)。

可用于ALTER MATERIALIZED VIEW的语句形式和动作是 ALTER TABLE的一个子集,并且在用于物化视图时具有相 同的含义。详见ALTER TABLE的描述。

参数:

  • name

    一个现有物化视图的名称(可以是模式限定的)。

  • column_name

    一个新的或者现有的列的名称。

  • extension_name

    该物化视图所依赖的扩展的名称(如果指定了 NO ,则不再依赖)。 删除扩展时,会自动删除标记为依赖于扩展的实例化视图。

  • new_column_name

    一个现有列的新名称。

  • new_owner

    该物化视图的新拥有者的用户名。

  • new_name

    该物化视图的新名称。

  • new_schema

    该物化视图的新模式。

示例:

把物化视图foo重命名为 bar:

ALTER MATERIALIZED VIEW foo RENAME TO bar;

5.1.17. ALTER OPERATOR

更改一个操作符的定义

语法:

ALTER OPERATOR name ( { left_type | NONE } , { right_type | NONE } )
        OWNER TO { new_owner | CURRENT_USER | SESSION_USER }

ALTER OPERATOR name ( { left_type | NONE } , { right_type | NONE } )
        SET SCHEMA new_schema

ALTER OPERATOR name ( { left_type | NONE } , { right_type | NONE } )
        SET ( {  RESTRICT = { res_proc | NONE }
                | JOIN = { join_proc | NONE }
                } [, ... ] )

描述:

ALTER OPERATOR更改一个操作符的定义。

要使用ALTER OPERATOR,你必须拥有该操作符。要更改拥有者, 你还必须是新拥有角色的一个直接或者间接成员,并且该角色必须具有该操作符所在 模式上的CREATE特权(这些限制强制修改拥有者不能做一些通过 删除和重建操作符做不到的事情。不过,一个超级用户怎么都能更改任何操作符的所 有权。)。

参数:

  • name

    一个现有操作符的名称(可以是模式限定的)。

  • left_type

    该操作符左操作数的数据类型,如果该操作符没有左操作数可以写成 NONE。

  • right_type

    该操作符右操作数的数据类型。

  • new_owner

    该操作符的新拥有者。

  • new_schema

    该操作符的新模式。

  • res_proc

    这个操作符的约束选择度估算器函数,写成 NONE 可以移除现有的选择度估算器。

  • join_proc

    这个操作符的连接选择度估算器函数,写成 NONE 可以移除现有的选择度估算器。

示例:

更改类型text的一个自定义操作符a @@ b 的拥有者:

ALTER OPERATOR @@ (text, text) OWNER TO joe;

更改类型int[]的自定义操作符a && b的 约束和连接选择度估算器函数:

ALTER OPERATOR && (_int4, _int4) SET (RESTRICT = _int_contsel, JOIN = _int_contjoinsel);

5.1.18. ALTER PROCEDURE

更改一个过程的定义

语法:

ALTER PROCEDURE name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ]
        action [ ... ] [ RESTRICT ]
ALTER PROCEDURE name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ]
        RENAME TO new_name
ALTER PROCEDURE name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ]
        OWNER TO { new_owner | CURRENT_USER | SESSION_USER }
ALTER PROCEDURE name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ]
        SET SCHEMA new_schema
ALTER PROCEDURE name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ]
        [ NO ] DEPENDS ON EXTENSION extension_name

其中action是下列之一:

        [ EXTERNAL ] SECURITY INVOKER | [ EXTERNAL ] SECURITY DEFINER
        SET configuration_parameter { TO | = } { value | DEFAULT }
        SET configuration_parameter FROM CURRENT
        RESET configuration_parameter
        RESET ALL

描述:

ALTER PROCEDURE更改一个过程的定义。

要使用ALTER PROCEDURE,你必须拥有该过程。要更改一个过程的方案,你还必须有新方案上的CREATE特权。要更改拥有者,你还必须是新拥有角色的直接或间接成员,并且那个角色在该过程的方案上拥有CREATE特权(这些限制强制更新拥有者无法做到通过删除和重建该过程无法做到的事情。不过,超级用户总是能够更改任何过程的拥有关系)。

参数:

  • name

    一个现有的过程的名字(可以被方案限定)。如果没有指定参数列表,这个名字必须在其方案中唯一。

  • argmode

    参数的模式:IN, OUT, INOUT, 或VARIADIC。如果被省略,默认是IN。

  • argname

    参数的名字。注意ALTER PROCEDURE实际上并不关心参数名,因为仅有参数的数据类型被用来确定过程的身份。

  • argtype

    如果该过程有参数,这是参数的数据类型(可以被方案限定)。 有关如何使用参数数据类型来查找过程的详细信息,参见DROP PROCEDURE。

  • new_name

    该过程的新名字。

  • new_owner

    该过程的新拥有者。注意,如果这个过程被标记为SECURITY DEFINER,接下来它将被作为新拥有者执行。

  • new_schema

    该过程的新方案。

  • extension_name

    该过程所依赖的扩展的名称。

  • [ EXTERNAL ] SECURITY INVOKER

  • [ EXTERNAL ] SECURITY DEFINER

    更改该过程是否为一个安全性定义器。关键词EXTERNAL由于SQL符合性的原因被忽略。更多有关这个能力的信息请见CREATE PROCEDURE。

  • configuration_parameter

  • value

    增加或者更改在调用该过程时,要对一个配置参数做的赋值。如果value是DEFAULT或者等效的值,则会使用RESET,过程本地的设置会被移除,这样该过程的执行就会使用其所处环境中的值。使用RESET ALL可以清除所有的过程本地设置。SET FROM CURRENT会把ALTER PROCEDURE执行时该参数的当前值保存为进入该过程时要被应用的值。

    关于允许的参数名和参数值的更多信息请见SET和Chapter 17。

  • RESTRICT

    为了符合SQL标准会被忽略。

示例:

要重命名具有两个integer类型参数的过程insert_data为insert_record:

ALTER PROCEDURE insert_data(integer, integer) RENAME TO insert_record;

要把具有两个integer类型参数的过程insert_data的拥有者改为joe:

ALTER PROCEDURE insert_data(integer, integer) OWNER TO joe;

要重把具有两个integer类型参数的过程insert_data的方案改为accounting:

ALTER PROCEDURE insert_data(integer, integer) SET SCHEMA accounting;

把过程insert_data(integer, integer)标记为依赖于扩展myext:

ALTER PROCEDURE insert_data(integer, integer) DEPENDS ON EXTENSION myext;

要调整一个过程自动设置的搜索路径:

ALTER PROCEDURE check_password(text) SET search_path = admin, pg_temp;

要为一个过程禁用search_path的自动设置:

ALTER PROCEDURE check_password(text) RESET search_path;

现在这个过程将用其调用者所使用的任何搜索路径执行。

5.1.19. ALTER ROLE

更改一个数据库角色

语法:

ALTER ROLE role_specification [ WITH ] option [ ... ]

其中option可以是:

        SUPERUSER | NOSUPERUSER
        | CREATEDB | NOCREATEDB
        | CREATEROLE | NOCREATEROLE
        | INHERIT | NOINHERIT
        | LOGIN | NOLOGIN
        | REPLICATION | NOREPLICATION
        | BYPASSRLS | NOBYPASSRLS
        | CONNECTION LIMIT connlimit
        | [ ENCRYPTED ] PASSWORD 'password' | PASSWORD NULL
        | VALID UNTIL 'timestamp'

ALTER ROLE name RENAME TO new_name

ALTER ROLE { role_specification | ALL } [ IN DATABASE database_name ] SET configuration_parameter { TO | = } { value | DEFAULT }
ALTER ROLE { role_specification | ALL } [ IN DATABASE database_name ] SET configuration_parameter FROM CURRENT
ALTER ROLE { role_specification | ALL } [ IN DATABASE database_name ] RESET configuration_parameter
ALTER ROLE { role_specification | ALL } [ IN DATABASE database_name ] RESET ALL

其中role_specification可以是:

        role_name
| CURRENT_USER
| SESSION_USER

描述:

ALTER ROLE更改一个 LightDB角色的属性。

前面列出的这个命令的第一种变体能够更改CREATE ROLE中 指定的很多角色属性(覆盖了所有可能的属性,不过没有增加和移除成员关系的选项, 如果要增加和移除成员关系可使用GRANT和 REVOKE)。该命令中没有提到的属性保持它们之前的设置。 数据库超级用户能够更改任何角色的任何这些设置。具有CREATEROLE 特权的角色能够更改除SUPERUSER,REPLICATION和 BYPASSRLS外的任何这些设置,但是只能为非超级用户和非复制角色修改。普通 角色只能更改它们自己的口令。

第二种变体更改该角色的名称。数据库超级用户能重命名任何角色。具有 CREATEROLE特权的角色能够重命名任何非超级用户角色。当前的会话 用户不能被重命名(如果需要这样做,请以一个不同的用户连接)。由于 MD5加密的口令使用角色名作为 salt,因此如果一个角色的口令是 MD5加密的,重命名该角色会清空其口令。

其余的变体用于更改一个角色的配置变量的会话默认值,可以为所有数据库设置,或者 只为IN DATABASE中指定的数据库设置。如果指定的是 ALL而不是一个角色名,将会为所有角色更改该设置。把 ALL和IN DATABASE一起使用实际上和使用命 令ALTER DATABASE … SET …相同。

只要改角色后续开始一个新会话,指定的值将会成为该会话的默认值,并且会覆盖 lightdb.conf中存在的值或者从 lightdb命令行收到的值。这只在登录时发生,执行 SET ROLE或者 SET SESSION AUTHORIZATION不会导致新的配置值被设置。 对于所有数据库设置的值会被附加到一个角色的数据库相关的设置所覆盖。特定数 据库或角色的设置会覆盖为所有角色所作的设置。

超级用户能够更改任何人的会话默认值。具有CREATEROLE特权的角色 能够更改非超级用户的默认值。普通角色只能为它们自己设置默认值。某些配置变量 不能以这种方式设置,或者只能由一个超级用户发出的命令设置。只有超级用户能够 更改所有角色在所有数据库中的设置。

参数:

  • name

    要对其属性进行修改的角色的名称。

  • CURRENT_USER

    修改当前用户而不是一个显式标识的角色。

  • SESSION_USER

    修改当前会话用户而不是一个显式标识的角色。

  • SUPERUSER

  • NOSUPERUSER

  • CREATEDB

  • NOCREATEDB

  • CREATEROLE

  • NOCREATEROLE

  • INHERIT

  • NOINHERIT

  • LOGIN

  • NOLOGIN

  • REPLICATION

  • NOREPLICATION

  • BYPASSRLS

  • NOBYPASSRLS

  • CONNECTION LIMIT connlimit

  • [ ENCRYPTED ] PASSWORD ‘password’

  • PASSWORD NULL

  • VALID UNTIL ‘timestamp’

    这些子句修改原来有CREATE ROLE 设置的属性。更多信息请见 CREATE ROLE参考页。

  • new_name

    该角色的新名称。

  • database_name

    要在其中设置该配置变量的数据库名称。

  • configuration_parameter

  • value

    把这个角色的指定配置参数的会话默认值设置为给定值。如果 value为DEFAULT 或者等效地使用了RESET,角色相关的变量 设置会被移除,这样该角色将会在新会话中继承系统范围的默认 设置。使用RESET ALL可清除所有角色相关的 设置。SET FROM CURRENT可以把会话中该参数的 当前值保存为角色相关的值。如果指定了 IN DATABASE,只会为给定的角色和数据库 设置或者移除该配置参数。

示例:

更改一个角色的口令:

ALTER ROLE davide WITH PASSWORD 'hu8jmn3';

移除一个角色的口令:

ALTER ROLE davide WITH PASSWORD NULL;

更改一个口令的失效日期,指定该口令应该在 2015 年 5 月 4 日中午 (在一个比UTC快 1 小时的时区)过期:

ALTER ROLE chris VALID UNTIL 'May 4 12:00:00 2015 +1';

让一个口令永远有效:

ALTER ROLE fred VALID UNTIL 'infinity';

让一个角色能够创建其他角色和新的数据库:

ALTER ROLE miriam CREATEROLE CREATEDB;

为一个角色指定 maintenance_work_mem参数的非默认设置:

ALTER ROLE worker_bee SET maintenance_work_mem = 100000;

为一个角色指定 client_min_messages参数的数据库相关的非 默认设置:

ALTER ROLE fred IN DATABASE devel SET client_min_messages = DEBUG;

5.1.20. ALTER SEQUENCE

更改一个序列发生器的定义

语法:

ALTER SEQUENCE [ IF EXISTS ] name
        [ AS data_type ]
        [ INCREMENT [ BY ] increment ]
        [ MINVALUE minvalue | NO MINVALUE ] [ MAXVALUE maxvalue | NO MAXVALUE ]
        [ START [ WITH ] start ]
        [ RESTART [ [ WITH ] restart ] ]
        [ CACHE cache ] [ [ NO ] CYCLE ]
        [ OWNED BY { table_name.column_name | NONE } ]
        [ NOORDER ]
        [ ORDER ]
        [ NOCACHE ]
        [ NOCYCLE ]
        [ NOMAXVALUE ]
ALTER SEQUENCE [ IF EXISTS ] name OWNER TO { new_owner | CURRENT_USER | SESSION_USER }
ALTER SEQUENCE [ IF EXISTS ] name RENAME TO new_name
ALTER SEQUENCE [ IF EXISTS ] name SET SCHEMA new_schema

描述:

ALTER SEQUENCE更改一个现有序列发生器的参数。 任何没有在ALTER SEQUENCE命令中明确设置的参数 保持它们之前的设置。

要使用ALTER SEQUENCE,你必须拥有该序列。要更改一个序列 的模式,你还必须拥有新模式上的CREATE特权。要更改拥有者,你还必须 是新拥有角色的一个直接或者间接成员,并且该角色必须具有该域的模式上的 CREATE特权(这些限制强制修改拥有者不能做一些通过删除和重 建该序列做不到的事情。不过,一个超级用户怎么都能更改任何序列的所有权。)。

参数:

  • name

    要修改的序列的名称(可以是模式限定的)。

  • IF EXISTS

    在序列不存在时不要抛出一个错误。这种情况下会发出一个提示。

  • data_type

    可选子句AS data_type 改变序列的数据类型。有效类型是smallint、integer 和bigint。

    当且仅当先前的最小值和最大值是旧数据类型的最小值或最大值时(换句话说, 如果序列是使用NO MINVALUE或NO MAXVALUE, 隐式或显式创建的),则更改数据类型会自动更改序列的最小值和最大值。 否则,将保留最小值和最大值,除非将新值作为同一命令的一部分给出。 如果最小值和最大值不符合新的数据类型,则会生成错误。

  • increment

    子句INCREMENT BY increment是可选的。 一个正值将产生一个上升序列,一个负值会产生一个下降序列。如果 没有指定,旧的增量值将被保持。

  • minvalue

  • NO MINVALUE

    可选的子句MINVALUE minvalue决定一个序列 能产生的最小值。如果指定了NO MINVALUE,上升序列和下降序列的默认值分别是 1 和 数据类型的最小值。如果这些选项都没有被指定,将保持当前的 最小值。

  • maxvalue

  • NO MAXVALUE

    可选的子句MAXVALUE maxvalue决定一个序列 能产生的最大值。如果指定了NO MAXVALUE,上升序列和下降序列的默认值分别是 数据类型的最大值和 -1。如果这些选项都没有被指定,将保持当前的 最大值。

    如果maxvalue的值大于INT64_MAX(9223372036854775807),则设置maxvalue为sequence类型所对应的最大值。

  • start

    可选的子句START WITH start更改该序列被记录的开始值。 这对于当前序列值没有影响,它会简单地设置 未来ALTER SEQUENCE RESTART命令将会使用的值。

  • restart

    可选的子句RESTART [ WITH restart ]更改该序列的 当前值。这类似于用is_called = false 调用setval函数:被指定的值将会被 下一次nextval调用返回。写上没有 restart值的 RESTART等效于提供被 CREATE SEQUENCE记录的或者上一次被 ALTER SEQUENCE START WITH设置的开始值。

    与setval调用相比,序列上的RESTART 操作是事务性的并阻止并发事务从同一序列中获取数字。 如果这不是所需的操作模式,则应使用setval。

  • cache

    子句CACHE cache使得序列数字被预先 分配并且保存在内存中以便更快的访问。最小值是 1(每次只产生一个值,即 无缓存)。如果没有指定,旧的缓冲值将被保持。

  • CYCLE

    可选的CYCLE关键词可以被用来允许该序列在达到 maxvalue(上升序列)或 minvalue(下降序列)时 回卷。如果到达该限制,下一个被产生的数字将分别是 minvalue或者 maxvalue。

  • NO CYCLE

    如果指定了可选的NO CYCLE关键词,任何在该 序列到达其最大值后的nextval调用将会返回 一个错误。如果既没有指定CYCLE也没有指定 NO CYCLE,旧的循环行为将被保持。

  • OWNED BY table_name.column_name

  • OWNED BY NONE

    OWNED BY选项导致该序列与一个特定的表列相关联, 这样如果该列(或者整个表)被删除,该序列也会被自动删除。如果指定, 这种关联会替代之前为该序列指定的任何关联。被指定的表必须具有相同的 拥有者并且与该序列在同一个模式中。指定 OWNED BY NONE可以移除任何现有的关联,让该序列 “自立”。

  • NOORDER

  • ORDER

  • NOCACHE

  • NOCYCLE

    为了兼容Oracle数据库语法,ALTER SEQUENCE语句支持 NOORDER/ORDER/NOCACHE/NOCYCLE 关键字。这些关键字仅是语法糖。

  • new_owner

    该序列的新拥有者的用户名。

  • new_name

    该序列的新名称。

  • new_schema

    该序列的新模式。

  • NOMAXVALUE

    为了兼容Oracle数据库语法,ALTER SEQUENCE语句支持 NOMAXVALUE 关键字。内部逻辑和NO MAXVALUE相同。

示例:

使用ORDER/NOORDER/NOCACHE/NOCYCLE选项来修改sequence。

alter sequence lt_seq_test1 nocache nocycle noorder;
alter sequence lt_seq_test1 order nocycle nocache;

5.1.21. ALTER SYSTEM

更改一个服务器配置参数

语法:

ALTER SYSTEM SET configuration_parameter { TO | = } { value | 'value' | DEFAULT }

ALTER SYSTEM RESET configuration_parameter
ALTER SYSTEM RESET ALL

描述:

ALTER SYSTEM被用来在整个数据库集簇范围内更改 服务器配置参数。它比传统的手动编辑lightdb.conf 文件的方法更方便。ALTER SYSTEM会把给出的参数 设置写入到lightdb.auto.conf文件中,该文件会随着 lightdb.conf一起被读入。把一个参数设置为 DEFAULT或者使用RESET变体可以 把该配置项从lightdb.auto.conf文件中移除。使用 RESET ALL可以移除所有这类配置项。

用ALTER SYSTEM设置的值将在下一次重载服务器 配置后生效,那些只能在服务器启动时更改的参数则会在下一次服务器重启后生效。 重载服务器配置可以通过以下做法实现:调用 SQL 函数pg_reload_conf(), 运行lt_ctl reload或者向主服务器进程发送一个SIGHUP信号。

只有超级用户能够使用ALTER SYSTEM。还有,由于 这个命令直接作用于文件系统并且不能被回滚,不允许在一个事务块或者函数中使用它。

参数:

  • configuration_parameter

    一个可设置配置参数的名称。可用的参数可见Chapter 17。

  • value

    该参数的新值。值可以被指定为字符串常量、标识符、数字或者以上这些构成的 逗号分隔的列表,值的具体形式取决于特定的参数。写上 DEFAULT可以用来把该参数及其值从 lightdb.auto.conf中移除。

示例:

设置wal_level:

ALTER SYSTEM SET wal_level = replica;

撤销以上的设置,恢复lightdb.conf中有效的设置:

ALTER SYSTEM RESET wal_level;

5.1.22. ALTER TABLE

更改一个表的定义

语法:

ALTER TABLE [ IF EXISTS ] [ ONLY ] name [ * ]
        action [, ... ]
ALTER TABLE [ IF EXISTS ] [ ONLY ] name [ * ]
        RENAME [ COLUMN ] column_name TO new_column_name
ALTER TABLE [ IF EXISTS ] [ ONLY ] name [ * ]
        RENAME CONSTRAINT constraint_name TO new_constraint_name
ALTER TABLE [ IF EXISTS ] name
        RENAME TO new_name
ALTER TABLE name WITH UPDATE CURRENT_TIMESTAMP
ALTER TABLE name WITH PRIMARY KEY [ smallserial | serial | bigserial ]
ALTER TABLE [ IF EXISTS ] name
        SET SCHEMA new_schema
ALTER TABLE ALL IN TABLESPACE name [ OWNED BY role_name [, ... ] ]
        SET TABLESPACE new_tablespace [ NOWAIT ]
ALTER TABLE [ IF EXISTS ] name
        ATTACH PARTITION partition_name { FOR VALUES partition_bound_spec | DEFAULT }
ALTER TABLE [ IF EXISTS ] name
        DETACH PARTITION partition_name
ALTER TABLE [ IF EXISTS ] name
        ADD PARTITION partition_name { VALUES partition_bound_spec }
ALTER TABLE [ IF EXISTS ] name
        DROP PARTITION partition_name [ UPDATE GLOBAL INDEXES ]
ALTER TABLE [ IF EXISTS ] name
        TRUNCATE PARTITION partition_name [ UPDATE INDEXES ]
ALTER TABLE [ IF EXISTS ] name
        MODIFY PARTITION BY RANGE (column) { partition_spec | ONLINE | index_spec }
ALTER TABLE [ IF EXISTS ] name
        MODIFY ( [ column modify_column_type modify_column_properites ] [, ... ] )

其中action 是以下之一:

        ADD [ COLUMN ] [ IF NOT EXISTS ] column_definition
        ADD ( column_definition [, ...] )
        DROP [ COLUMN ] [ IF EXISTS ] column_name [ RESTRICT | CASCADE ]
        ALTER [ COLUMN ] column_name [ SET DATA ] TYPE data_type [ COLLATE collation ] [ USING expression ]
        ALTER [ COLUMN ] column_name SET DEFAULT expression
        ALTER [ COLUMN ] column_name DROP DEFAULT
        ALTER [ COLUMN ] column_name { SET | DROP } NOT NULL
        ALTER [ COLUMN ] column_name DROP EXPRESSION [ IF EXISTS ]
        ALTER [ COLUMN ] column_name ADD GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY [ ( sequence_options ) ]
        ALTER [ COLUMN ] column_name { SET GENERATED { ALWAYS | BY DEFAULT } | SET sequence_option | RESTART [ [ WITH ] restart ] } [...]
        ALTER [ COLUMN ] column_name DROP IDENTITY [ IF EXISTS ]
        ADD AUTO_INCREMENT(column_name) [ =N ]
        ALTER [ COLUMN ] column_name DROP AUTO_INCREMENT
        ALTER [ COLUMN ] column_name SET STATISTICS integer
        ALTER [ COLUMN ] column_name SET ( attribute_option = value [, ... ] )
        ALTER [ COLUMN ] column_name RESET ( attribute_option [, ... ] )
        ALTER [ COLUMN ] column_name SET STORAGE { PLAIN | EXTERNAL | EXTENDED | MAIN }
        ADD table_constraint [ NOT VALID ]
        ADD table_constraint_using_index
        ALTER CONSTRAINT constraint_name [ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]
        VALIDATE CONSTRAINT constraint_name
        DROP CONSTRAINT [ IF EXISTS ]  constraint_name [ RESTRICT | CASCADE ] [ DROP INDEX ]
        DISABLE TRIGGER [ trigger_name | ALL | USER ]
        ENABLE TRIGGER [ trigger_name | ALL | USER ]
        ENABLE REPLICA TRIGGER trigger_name
        ENABLE ALWAYS TRIGGER trigger_name
        DISABLE RULE rewrite_rule_name
        ENABLE RULE rewrite_rule_name
        ENABLE REPLICA RULE rewrite_rule_name
        ENABLE ALWAYS RULE rewrite_rule_name
        DISABLE ROW LEVEL SECURITY
        ENABLE ROW LEVEL SECURITY
        FORCE ROW LEVEL SECURITY
        NO FORCE ROW LEVEL SECURITY
        CLUSTER ON index_name
        SET WITHOUT CLUSTER
        SET WITHOUT OIDS
        SET TABLESPACE new_tablespace
        SET { LOGGED | UNLOGGED }
        SET ( storage_parameter [= value] [, ... ] )
        RESET ( storage_parameter [, ... ] )
        INHERIT parent_table
        NO INHERIT parent_table
        OF type_name
        NOT OF
        OWNER TO { new_owner | CURRENT_USER | SESSION_USER }
        REPLICA IDENTITY { DEFAULT | USING INDEX index_name | FULL | NOTHING }

        MODIFY column_name data_type [ USING expression ]
        MODIFY column_name DEFAULT expression
        MODIFY column_name { NOT NULL | NULL } [ENABLE]
        MODIFY column_name GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY [ ( sequence_options ) ]
        MODIFY column_name DROP IDENTITY
        MODIFY column_name CONSTRAINT constraint_name { NOT NULL | NULL } [ENABLE]
        MODIFY column_name CONSTRAINT constraint_name UNIQUE [ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]
        MODIFY column_name CONSTRAINT constraint_name PRIMARY KEY [ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]
        MODIFY column_name CONSTRAINT constraint_name REFERENCES reftable [ ( refcolumn ) ]
        [ MATCH FULL | MATCH PARTIAL | MATCH SIMPLE ] [ ON DELETE referential_action ] [ ON UPDATE referential_action ] [ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]
        MODIFY column_name CONSTRAINT constraint_name CHECK '(' a_expr ')' [ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]
        DROP PRIMARY KEY [ RESTRICT | CASCADE ] [ DROP INDEX ]

并且 column_definition 是:

column_name data_type [ COLLATE collation ] [ column_constraint [ ... ] ]

并且 partition_bound_spec 是:

IN ( partition_bound_expr [, ...] ) |
FROM ( { partition_bound_expr | MINVALUE | MAXVALUE } [, ...] )
TO ( { partition_bound_expr | MINVALUE | MAXVALUE } [, ...] ) |
WITH ( MODULUS numeric_literal, REMAINDER numeric_literal ) |
LESS THAN ( { partition_bound_expr | MAXVALUE } ) |
( partition_bound_expr [, ...] )

并且 column_constraint 是:

[ CONSTRAINT constraint_name ]
{ NOT NULL |
NULL |
CHECK ( expression ) [ NO INHERIT ] |
DEFAULT default_expr |
ON UPDATE CURRENT_TIMESTAMP |
GENERATED ALWAYS AS ( generation_expr ) STORED |
GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY [ ( sequence_options ) ] |
UNIQUE index_parameters |
PRIMARY KEY index_parameters |
REFERENCES reftable [ ( refcolumn ) ] [ MATCH FULL | MATCH PARTIAL | MATCH SIMPLE ]
        [ ON DELETE referential_action ] [ ON UPDATE referential_action ] }
[ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]

而table_constraint是:

[ CONSTRAINT constraint_name ]
{ CHECK ( expression ) [ NO INHERIT ] |
UNIQUE ( column_name [, ... ] ) index_parameters |
PRIMARY KEY ( column_name [, ... ] ) index_parameters |
EXCLUDE [ USING index_method ] ( exclude_element WITH operator [, ... ] ) index_parameters [ WHERE ( predicate ) ] |
FOREIGN KEY ( column_name [, ... ] ) REFERENCES reftable [ ( refcolumn [, ... ] ) ]
        [ MATCH FULL | MATCH PARTIAL | MATCH SIMPLE ] [ ON DELETE referential_action ] [ ON UPDATE referential_action ] }
[ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]

并且 table_constraint_using_index 是:

        [ CONSTRAINT constraint_name ]
        { UNIQUE | PRIMARY KEY } USING INDEX index_name
        [ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]

UNIQUE、PRIMARY KEY以及EXCLUDE约束中的index_parameters是:

[ INCLUDE ( column_name [, ... ] ) ]
[ WITH ( storage_parameter [= value] [, ... ] ) ]
[ USING INDEX | USING INDEX TABLESPACE tablespace_name ]

EXCLUDE约束中的exclude_element是:

{ column_name | ( expression ) } [ opclass ] [ ASC | DESC ] [ NULLS { FIRST | LAST } ]

partition_spec 是:
partition_element [, ...]
并且 partition_element 是:
        [PARTITION name] VALUES LESS THAN ( { partition_value | MAXVALUE } )

index_spec 是:
index_element [, ...]
并且 index_element 是:
        [index name] [ GLOBAL | LOCAL ]

modify_column_type 是:
Typename alter_using
并且 alter_using 是:
        USING a_expr

modify_column_properites 是:
( [ { NULL | NOT NULL [ ENABLE_P ] | DEFAULT a_expr } ] [ ... ] )

描述:

ALTER TABLE更改一个现有表的定义。下文描述了 几种形式。注意每一种形式所要求的锁级别可能不同。如果没有明确说明,将会 获得一个ACCESS EXCLUSIVE锁。当给出多个子命令时,获得 的锁将是子命令所要求的最严格的那一个。

  • ADD COLUMN [ IF NOT EXISTS ]

    这种形式向该表增加一个新列,使用与 CREATE TABLE相同的语法。如果指定了 IF NOT EXISTS并且使用这个名字的列已经存在,则 不会抛出错误。

  • ADD (column_definition [,…])

    这种形式可以向该表一次增加多个新列。

  • DROP COLUMN [ IF EXISTS ]

    这种形式从表删除一列。涉及到该列的索引和表约束也将会被自动 删除。如果该列的移除会导致引用它的多元统计信息仅包含单一列的数据,则该多元统计信息也将被移除。如果在该表之外有任何东西(例如外键引用或者视图)依赖 于该列,你将需要用到CASCADE。如果指定了 IF EXISTS但该列不存在,则不会抛出错误。 这种情况中会发出一个提示。

  • SET DATA TYPE

    这种形式更改表中一列的类型。涉及到该列的索引和简单表约束将通过 重新解析最初提供的表达式被自动转换为使用新的列类型。可选的 COLLATE子句为新列指定一种排序规则,如果被省略, 排序规则会是新列类型的默认排序规则。可选的USING 子句指定如何从旧的列值计算新列值,如果被省略,默认的转换和从旧类型 到新类型的赋值造型一样。如果没有从旧类型到新类型的隐式或者赋值造型, 则必须提供一个USING子句。

  • SET/DROP DEFAULT

    这些表单设置或删除列的默认值(其中删除等同于将默认值设置为NULL)。 新的默认值仅适用于后续的INSERT或 UPDATE命令; 它不会导致表中已有的行发生更改。

  • SET/DROP NOT NULL

    这些形式更改一列是否被标记为允许空值或者拒绝空值。

    SET NOT NULL 只能应用于列,前提是表中没有任何记录包含该列的NULL值。 通常,这一点在ALTER TABLE全表扫描时来检查;但是,如果找到有效的CHECK约束证明不存在NULL,则跳过表扫描。

    如果这个表是一个分区,对于在父表中被标记为NOT NULL的列,不能在其上执行DROP NOT NULL。要从所有的分区中删除NOT NULL约束,可以在父表上执行DROP NOT NULL。即使在父表上没有NOT NULL约束,这样的约束还是能被增加到分区上。也就是说,即便父表允许空值,子表也可以不允许空值,但反过来不行。

  • DROP EXPRESSION [ IF EXISTS ]

    此表单将存储的生成的列转换为普通的基本列。列中的现有数据将会保留, 但未来的更改将不会应用于生成的表达式。

    如果指定了DROP EXPRESSION IF EXISTS,并且该列不是存储的已生成列,不会抛出任何错误。 在这种情况下,将发出通知。

  • ADD GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY

  • SET GENERATED { ALWAYS | BY DEFAULT }

  • DROP IDENTITY [ IF EXISTS ]

    这些形式更改一列是否是一个标识列,或者是更改一个已有的标识列的产生属性。详情请参考CREATE TABLE。 像SET DEFAULT一样,这些形式仅影响随后的INSERT和UPDATE命令的行为。 它们不会导致表中已有的行发生更改。

    如果DROP IDENTITY IF EXISTS被指定并且该列不是一个标识列,则不会有错误被抛出。在这种情况下会发出一个提示。

  • ADD AUTO_INCREMENT(column_name) [ =N ]

    此表单将column_name列更改为自动递增列,默认从1开始,如果set=N,则从N开始。

  • DROP AUTO_INCREMENT

    此表单删除列的自动递增属性。删除后,该列无法在上自动递增。

  • ON UPDATE CURRENT_TIMESTAMP

    此表单允许在行更新时自动更新时间戳列。

  • SET sequence_option

  • RESTART

    这些形式修改位于一个现有标识列之下的序列。sequence_option是一个ALTER SEQUENCE所支持的选项,例如INCREMENT BY。

  • SET STATISTICS

    这种形式为后续的ANALYZE操作设置针对每列 的统计收集目标。目标可以被设置在范围 0 到 10000 之间,还可以 把它设置为 -1 来恢复到使用系统默认的统计目标( default_statistics_target)。更多有关 LightDB查询规划器使用统计 信息的内容可见。

    SET STATISTICS要求一个SHARE UPDATE EXCLUSIVE锁。

  • SET ( attribute_option = value [, … ] )

  • RESET ( attribute_option [, … ] )

    这种形式设置或者重置每个属性的选项。当前,已定义的针对每个属性的 选项只有n_distinct和n_distinct_inherited, 它们会覆盖后续ANALYZE操作所得到的可区分值数量 估计。n_distinct影响该表本身的统计信息,而 n_distinct_inherited影响为该表外加其继承子女收集的统计信息。 当被设置为一个正值时,ANALYZE将假定该列刚好包含指定 数量的可区分非空值。当被设置为一个负值(必须大于等于 -1)时, ANALYZE将假定可区分非空值的数量与表的尺寸成线性比例, 确切的计数由估计的表尺寸乘以给定数字的绝对值计算得到。例如,值 -1 表示 该列中所有的值都是可区分的,而值 -0.5 则表示每一个值平均出现两次。当表 的尺寸随时间变化时,这会有所帮助,因为这种计算只有在查询规划时才会被 执行。指定值为 0 将回到正常的估计可区分值数量的做法。更多有关 LightDB查询规划器使用统计 信息的内容可见。

    更改针对每个属性的选项要求一个 SHARE UPDATE EXCLUSIVE锁。

  • SET STORAGE

    这种形式为一列设置存储模式。这会控制这列是会被保持在线内还是放在一个 二级TOAST表中,以及数据是否应被压缩。对于 integer之类的定长、线内、未压缩值必须使用 PLAIN。MAIN用于线内、可压缩的 数据。EXTERNAL用于外部的、未压缩数据。而 EXTENDED用于外部的、压缩数据。对于大部分支持 非-PLAIN存储的数据类型,EXTENDED 是默认值。使用EXTERNAL将会让很大的 text和bytea之上的子串操作运行得更快, 但是代价是存储空间会增加。注意SET STORAGE本身并不改变 表中的任何东西,它只是设置在未来的表更新时要追求的策略。

  • ADD table_constraint [ NOT VALID ]

    这种形式使用和CREATE TABLE相同的约束语法外加 NOT VALID选项为一个表增加一个新的约束,该选项 当前只被允许用于外键和 CHECK 约束。

    通常,此窗体将导致对表进行扫描,以验证表中的所有现有行是否满足新约束。 但是如果使用了 NOT VALID选项 ,则跳过此可能很漫长的扫描。 该约束仍将被强制到后续的插入和删除上(也就是说,在外键的情况下如果在被引用表中没有一个匹配的行,操作会失败;或者如果新行不匹配指定的检查条件,操作也会失败)。 但是数据库不会假定约束对该表中的所有行都成立,直到通过使用VALIDATE CONSTRAINT选项对它进行验证。 参见下述 Notes 以了解关于使用NOT VALID选项的更多信息。

    尽管大多数形式的ADDtable_constraint 都需要ACCESS EXCLUSIVE锁,但ADD FOREIGN KEY仅需要SHARE ROW EXCLUSIVE 锁。 请注意,除了声明约束的表上的锁之外,ADD FOREIGN KEY还获得了对引用表的SHARE ROW EXCLUSIVE锁。

    当唯一或者主键约束被添加到分区表时,会有额外的限制,请参考CREATE TABLE。 此外,当前分区表上的外键约束不能被声明为NOT VALID。

  • ADD table_constraint_using_index

    这种形式基于一个已有的唯一索引为一个表增加新的 PRIMARY KEY或UNIQUE约束。该索引中的 所有列将被包括在约束中。

    该索引不能有表达式列或者是一个部分索引。还有,它必须是一个带有 默认排序顺序的 B-树索引。这些限制确保该索引等效于使用常规 ADD PRIMARY KEY或者ADD UNIQUE命令 时创建的索引。

    如果PRIMARY KEY被指定,并且该索引的列没有被标记 NOT NULL,那么这个命令将尝试对每一个这样的列做 ALTER COLUMN SET NOT NULL。这需要一次全表扫描 来验证这些列不包含空值。在所有其他情况中,这都是一种很快的操作。

    如果提供了一个约束名,那么该索引将被重命名以匹配该约束名。否则 该约束将被命名成索引的名称。

    这个命令被执行后,该索引被增加的约束“拥有”,这和用常规 ADD PRIMARY KEY或ADD UNIQUE命令 创建的索引一样。特别地,删掉该约束将会导致该索引也消失。

    当前在分区表上不支持这种形式。

    Note

    如果需要增加一个新的约束但是不希望长时间阻塞表更新,那么使用现有 索引增加约束会有所帮助。要这样做,用 CREATE INDEX CONCURRENTLY创建该索引,并且 接着使用这种语法把它安装为一个正式的约束。例子见下文。

  • ALTER CONSTRAINT

    这种形式修改之前创建的一个约束的属性。当前只能修改外键约束。

  • VALIDATE CONSTRAINT

    这种形式验证之前创建为NOT VALID的外键或检查约束, 它会扫描表来确保对于该约束没有行不满足约束。如果约束已经被标记为合法,则什么也不会发生。 (参见下述 Notes 以了解此命令用途的说明。)

    此命令需要一个SHARE UPDATE EXCLUSIVE锁。

  • DROP CONSTRAINT [ IF EXISTS ]

    这种形式在一个表上删除指定的约束,还有位于该约束之下的任何索引。如果IF EXISTS 被指定并且该约束不存在,不会抛出错误。在这种情况下会发出一个提示。

  • DISABLE/ENABLE [ REPLICA | ALWAYS ] TRIGGER

    这些形式配置属于该表的触发器的触发设置。系统仍然知道被禁用触发器 的存在,但是即使它的触发事件发生也不会执行它。对于一个延迟触发器, 会在事件发生时而不是触发器函数真正被执行时检查其启用状态。可以禁 用或者启用用名称指定的单个触发器、表上的所有触发器、用户拥有的触 发器(这个选项会排除内部生成的约束触发器,例如用来实现外键约束或 可延迟唯一和排除约束)。禁用或者启用内部生成的约束触发器要求超级 用户特权,这样做要小心因为如果这类触发器不被执行,约束的完整性当 然无法保证。

    触发器引发机制也受到配置变量 session_replication_role的影响。当复制角色是 “origin”(默认)或者“local”时,被简单启用的 触发器将被触发。被配置为ENABLE REPLICA的触发 器只有在会话处于“replica”模式时才将被触发。被配置为 ENABLE ALWAYS的触发器的触发不会考虑当前复制 角色。

    这种机制的效果就是,在默认配置中,触发器不会在复制体上引发。这种效果很有用,因为如果一个触发器在源头上被用来在表之间传播数据,那么复制系统也将复制被传播的数据,并且触发器不应该在复制体上引发第二次,因为那会导致重复。不过,如果一个触发器被用于另一种目的(例如创建外部告警),那么将它设置为ENABLE ALWAYS可能更加合适,这样它在复制体上也会被引发。

    这个命令要求一个SHARE ROW EXCLUSIVE锁。

  • DISABLE/ENABLE [ REPLICA | ALWAYS ] RULE

    这些形式配置属于表的重写规则的触发设置。系统仍然知道一个被禁用规则的 存在,但在查询重写时不会应用它。其语义与禁用的/启用的触发器的一样。 对于ON SELECT规则会忽略这个配置,即使当前会话处于 一种非默认的复制角色,这类规则总是会被应用以保持视图工作正常。

    规则引发机制也受到配置变量session_replication_role的影响,这和上述的触发器类似。

  • DISABLE/ENABLE ROW LEVEL SECURITY

    这些形式控制属于该表的行安全性策略的应用。如果被启用并且该表上 不存在策略,则将应用一个默认否定的策略。注意即使行级安全性被禁 用,在表上还是可以存在策略。在这种情况下,这些策略将不会被应用 并且会被忽略。另见CREATE POLICY。

  • NO FORCE/FORCE ROW LEVEL SECURITY

    这些形式控制当用户是表拥有者时表上的行安全性策略的应用。如果被启用, 当用户是表拥有者时,行级安全性策略将被应用。如果被禁用(默认),则 当用户是表拥有者时,行级安全性将不会被应用。另见 CREATE POLICY。

  • CLUSTER ON

    这种形式为未来的CLUSTER操作选择默认的索引。 它不会真正地对表进行聚簇。

    改变聚簇选项要求一个SHARE UPDATE EXCLUSIVE锁。

  • SET WITHOUT CLUSTER

    这种形式从表中移除最近使用的 CLUSTER索引说明。这会影响未来的不指定索引 的聚簇操作。

    改变聚簇选项要求一个SHARE UPDATE EXCLUSIVE锁。

  • SET WITHOUT OIDS

    向后兼容的语法,用于删除oid系统列。由于oid系统列无法再添加,所以不会有实际效果。

  • SET TABLESPACE

    这种形式把该表的表空间更改为指定的表空间并且把该表相关联的数据文件 移动到新的表空间中。表上的索引(如果有)不会被移动,但是它们可以用 额外的SET TABLESPACE命令单独移动。 当应用于分区表时,不会移动任何内容,但之后用CREATE TABLE PARTITION OF创建的 任何分区将使用该表空间,除非被TABLESPACE子句覆盖。

    当前数据库在一个表空间中的所有表可以用ALL IN TABLESPACE形式 移动,这将会首先锁住所有将被移动的表然后逐个移动。这种形式也支持 OWNED BY,它将只移动指定角色所拥有的表。如果指 定了NOWAIT选项,则命令将在无法立刻获得所有所需 要的锁时失败。注意这个命令不移动系统目录;如果想要移动系统目录,应 该用ALTER DATABASE或者显式的 ALTER TABLE调用。对于这种形式来说, information_schema关系不被认为是系统目录的一部分, 因此它们将会被移动。另见CREATE TABLESPACE。

  • SET { LOGGED | UNLOGGED }

    This form changes the table from unlogged to logged or vice-versa (see UNLOGGED). It cannot be applied to a temporary table.

  • SET ( storage_parameter [= value] [, … ] )

    这种形式为该表更改一个或者更多存储参数。可用的参数请见 Storage Parameters的 CREATE TABLE。注意这个 命令将不会立刻修改表内容,这取决于重写表以得到想要的结果可能需要的 参数。可以用VACUUM FULL、CLUSTER或者 ALTER TABLE的一种形式来强制一次表重写。对于规划器相关的参数,更改将从该表下一次被锁定开始生效,因此当前执行的查询不会受到影响。

    对fillfactor、toast以及autovacuum存储参数,将会拿取SHARE UPDATE EXCLUSIVE锁,就像计划器参数 parallel_workers。

  • RESET ( storage_parameter [, … ] )

    这种形式把一个或者更多存储参数重置到它们的默认值。和 SET一样,可能需要一次表重写来更新整个表。

  • INHERIT parent_table

    这种形式把目标表增加为指定父表的一个新子女。随后,针对父亲的查询将 包括目标表中的记录。要被增加为一个子女,目标表必须已经包含和父表完 全相同的列(也可以有额外的列)。这些列必须具有匹配的数据类型,并且 如果它们在父表中具有NOT NULL约束,它们在子表中 也必须有NOT NULL约束。

    也必须把子表约束与所有父表的CHECK约束进行匹配, 不过父表中那些被标记为非可继承(也就是用ALTER TABLE … ADD CONSTRAINT … NO INHERIT 创建的)除外,它们会被忽略。所有匹配得上的子表约束不能被标记为不可 继承。当前,UNIQUE、PRIMARY KEY 以及FOREIGN KEY约束没有被考虑,但是这种情况可能 会在未来发生变化。

  • NO INHERIT parent_table

    这种形式把目标表从指定父表的子女列表中移除。针对父表的查询将不再包括 来自目标表的记录。

  • OF type_name

    这种形式把该表链接到一种组合类型,就好像CREATE TABLE OF所做的那样。该表的列名和类型列表必须精确地匹配该组合类型。 该表必须不从任何其他表继承。这些限制确保CREATE TABLE OF能允许一个等价的表定义。

  • NOT OF

    这种形式解除一个有类型的表和其类型之间的关联。

  • OWNER TO

    这种形式把表、序列、视图、物化视图或外部表的拥有者改为指定用户。

  • REPLICA IDENTITY

    此表单更改写入预写日志的信息,以标识更新或删除的行。 在大多数情况下,只有当每列的旧值与新值不同时,才会记录该值; 但是,如果旧值存储在外部,则无论它是否发生了更改,它都会被记录下来。 除非正在使用逻辑复制,否则此选项无效。

  • DEFAULT

    (非系统表的默认值)记录主键列(如果有)的旧值。

  • USING INDEX index_name

    记录被所提到的索引所覆盖的列的旧值,该索引必须是唯一索引、不是部分索引、不是可延迟索引并且只包括被标记成NOT NULL的列。 如果删除此索引,则行为与NOTHING相同。

  • FULL

    记录行中所有列的旧值。

  • NOTHING

    Records no information about the old row. This is the default for system tables. 不记录有关旧行的任何信息(这是系统表的默认值)。

  • RENAME

    RENAME形式更改一个表(或者一个索引、序列、视图、物化视图 或者外部表)的名称、表中一个列的名称或者表的一个约束的名称。在重命名一个具有底层索引的约束时,该索引也会被重命名。它对已存储的数据 没有影响。

  • WITH UPDATE CURRENT_TIMESTAMP

    WITH UPDATE CURRENT_TIMESTAMP表单添加表的隐藏列”ltaut”。 “ltaut”列等于”ltaut TIMESTAMP ON UPDATE CURRENT_TIMESTAMP”。

  • WITH PRIMARY KEY [ smallserial | serial | bigserial ]

    WITH PRIMARY KEY表单添加表的隐藏列”ltapk”。 “ltapk”列会自动递增,并指定为主键约束。 如果表已经有主键,则不允许使用WITH PRIMARY KEY。 你可以像往常一样删除它并修改它的类型,但只能使用integer、smallint和bigint。

  • SET SCHEMA

    这种形式把该表移动到另一个模式中。相关的该表列拥有的索引、约束和序列也会被 移动。

  • ATTACH PARTITION partition_name { FOR VALUES partition_bound_spec | DEFAULT }

    这种形式把一个已有表(自身也可能被分区)作为一个分区挂接到目标表。该表可以为特定的值使用FOR VALUES挂接为分区,或者用DEFAULT挂接为一个默认分区。 对于目标表中的每一个索引,在被挂接的表上都将创建一个响应的索引,如果已经存在等效的索引,该索引将被挂接到目标表的索引,就像执行了ALTER INDEX ATTACH PARTITION一样。 请注意,如果现有表是外表,如果目标表上有UNIQUE索引, 则当前不允许将表作为目标表的分区附加。(参见 CREATE FOREIGN TABLE.) 对于目标表中存在的每个用户定义的行级触发器,将在附加表中创建一个对应的触发器。

    一个使用FOR VALUES的分区使用与CREATE TABLE中partition_bound_spec相同的语法。分区边界说明必须对应于目标表的分区策略以及分区键。要被挂接的表必须具有和目标表完全相同的所有列,并且不能有多出来的列,而且列的类型也必须匹配。此外,它必须有目标表上所有的NOT NULL以及CHECK约束。当前不考虑FOREIGN KEY约束。来自于父表的UNIQUE和PRIMARY KEY约束将被创建在分区上(如果它们还不存在)。如果被挂接的表上的任何CHECK约束被标记为NO INHERIT,则命令将失败,这类约束必须被重建且重建时不能有NO INHERIT子句。

    如果新分区是一个常规表,会执行一次全表扫描来检查表中现有行没有违背分区约束。 可以通过对表增加一个有效的CHECK约束来避免这种扫描,该约束可以在运行这个命令之前仅允许满足所需分区约束的行。 CHECK约束可以解决让表无需被扫描就能验证分区约束。但是,如果任一分区键是一个表达式并且该分区不接受NULL值,这种方式就无效了。 如果挂接一个不接受NULL值的列表分区,还应该为分区键列增加NOT NULL约束,除非它是一个表达式。

    如果新分区是一个外部表,则不需要验证该外部表中的所有行遵守分区约束(有关外部表上的约束请参考CREATE FOREIGN TABLE中的讨论)。

    当一个表有默认分区时,定义新分区会更改默认分区的分区约束。默认分区不能包含任何需要被移动到新分区中的行,并且将被扫描以验证不存在那样的行。如果一个合适的CHECK约束存在,这种扫描(和新分区的扫描一样)可以被避免。还是和新分区的扫描一样,当默认分区是外部表时这种扫描总是会被跳过。

    在父表上附加一个分区获得一个SHARE UPDATE EXCLUSIVE锁,除了附加的表和默认分区上的ACCESS EXCLUSIVE 锁(如果有)。

    如果所附加的表本身是分区表,则还必须在所有子分区上保持进一步的锁。同样,如果默认分区本身是分区表。可以通过添加CHECK约束来避免子分区的锁定.

  • DETACH PARTITION partition_name

    这种形式会分离目标表的指定分区。被分离的分区继续作为独立的表存在,但是与它之前挂接的表不再有任何联系。任何被挂接到目标表索引的索引也会被分离。 任何作为目标表中那些表的副本创建的表也会被删除。 SHARE锁在外键约束中引用此分区表的任何表上都可用获得。

  • ADD PARTITION partition_name { VALUES partition_bound_spec }

    此语法用于为与Oracle兼容的现有分区表创建新分区。支持添加范围分区和列表分区,不支持添加哈希分区。需要将配置更改为Oracle兼容模式。

    自LightDB23.3起,Oracle兼容模式下,支持列表默认分区。已经存在默认分区的情况下,添加分区将会失败。

    创建分区的时候,子分区不会自动创建。

  • DROP PARTITION partition_name

    此语法用于从与Oracle兼容的现有分区表中删除分区。支持丢弃范围分区和列表分区,不支持丢弃哈希分区。需要将配置更改为Oracle兼容模式。参数UPDATE GLOBAL INDEXES仅语法兼容,但函数不兼容。

  • TRUNCATE PARTITION partition_name [ UPDATE INDEXES ]

    此语法用于清除一个分区表中的数据,使用时,需要将配置更改为Oracle兼容模式,自23.2开始支持。

  • MODIFY PARTITION BY RANGE(column)

    此语法用于将普通表转换为分区表。仅支持转换范围分区(不支持自动分区)。不支持转换分布式表。有必要将配置更改为Oracle兼容模式。

    除了RENAME、SET SCHEMA、ATTACH PARTITION和DETACH PARTITION之外,所有形式的ALTER TABLE都作用在单个表上,前面这些形式可以被组合成一个多修改的列表被一起应用。例如,可以在一个命令中增加多个列并且/或者修改多个列的类型。对于大型表来说这会特别有用,因为只需要对表做一趟操作。

    要使用ALTER TABLE,你必须拥有该表。要更改一个表的 模式或者表空间,你还必须拥有新模式或表空间上的 CREATE特权。要把一个表作为一个父表的新子表加入, 你必须也拥有该父表。此外,要把一个表挂接为另一个表的新分区,你必须拥有被挂接的表。要更改拥有者,你还必须 是新拥有角色的一个直接或者间接成员,并且该角色必须具有该表的模式上的 CREATE特权(这些限制强制修改拥有者不能做一些通过删除和重 建表做不到的事情。不过,一个超级用户怎么都能更改任何表的所有权。)。 要增加一个列、修改一列的类型或者使用OF子句,你还必 须具有该数据类型上的USAGE特权。

参数:

  • IF EXISTS

    如果表不存在则不要抛出一个错误。这种情况下会发出一个提示。

  • name

    要修改的一个现有表的名称(可以是模式限定的)。如果在表名前指定了 ONLY,则只会修改该表。如果没有指定ONLY, 该表及其所有后代表(如果有)都会被修改。可选地,在表名后面可以指定 *用来显式地指示包括后代表。

  • column_name

    一个新列或者现有列的名称。

  • new_column_name

    一个现有列的新名称。

  • new_name

    该表的新名称。

  • data_type

    一个新列的数据类型或者一个现有列的新数据类型。

  • table_constraint

    该表的新的表约束。

  • constraint_name

    一个新约束或者现有约束的名称。

  • CASCADE

    自动删除依赖于被删除列或约束的对象(例如引用该列的视图), 并且接着删除依赖于那些对象的 所有对象。

  • RESTRICT

    如果有任何依赖对象时拒绝删除列或者约束。这是默认行为。

  • trigger_name

    一个要禁用或启用的触发器的名称。

  • ALL

    禁用或者启用属于该表的所有触发器(如果有任何触发器是内部产生的约 束触发器则需要超级用户特权,例如那些被用来实现外键约束或者可延迟 一致性和排他约束的触发器)。

  • USER

    禁用或者启用属于该表的所有触发器,内部产生的约束触发器(例如那些 被用来实现外键约束或者可延迟一致性和排他约束的触发器)除外。

  • index_name

    一个现有索引的名称。

  • storage_parameter

    一个表存储参数的名称。

  • value

    一个表存储参数的新值。根据该参数,该值可能是一个数字或者一个词。

  • parent_table

    要与这个表关联或者解除关联的父表。

  • new_owner

    该表的新拥有者的用户名。

  • new_tablespace

    要把该表移入其中的表空间的名称。

  • new_schema

    要把该表移入其中的模式的名称。

  • partition_name

    要被作为新分区附着到这个表或者从这个表上分离的表的名称。 ORACLE兼容模式下,通过ORACLE语法CREATE/ADD/DROP/TRUNCATE/MODIFY创建的分区名,与传入的名称相同。分区名与分区表名长度限制为30字符,可通过DBA_TAB_PARTITIONS视图查询分区名。 可能过d+命令查询表所代表的分区。

  • partition_bound_spec

    新分区的分区边界说明。更多细节请参考CREATE TABLE中相同的语法。

  • DROP INDEX

    为了兼容Oracle数据库的DROP CONSTRAINT DROP INDEX和DROP PRIMARY KEY DROP INDEX语句, 增加了DROP INDEX后缀的语法糖.

示例:

要向一个表增加一个类型为varchar的列:

ALTER TABLE distributors ADD COLUMN address varchar(30);

这将导致表中所有现有行都用新列的空值填充。

要添加默认值为非空的列:

ALTER TABLE measurements
ADD COLUMN mtime timestamp with time zone DEFAULT now();

现有行将以当前时间填充为新列的值,然后新行直将使用其插入时间。

要添加一列并用不同于默认值的值填充它:

ALTER TABLE transactions
ADD COLUMN status varchar(30) DEFAULT 'old',
ALTER COLUMN status SET default 'current';

现有行将用old填充,但是随后的命令的默认值将是current。 其效果与在单独的ALTER TABLE命令中发出两个子命令的效果相同。

要从表中删除一列:

ALTER TABLE distributors DROP COLUMN address RESTRICT;

要在一个操作中更改两个现有列的类型:

ALTER TABLE distributors
        ALTER COLUMN address TYPE varchar(80),
        ALTER COLUMN name TYPE varchar(100);

通过一个USING子句更改一个包含 Unix 时间戳的整数列为 timestamp with time zone:

ALTER TABLE foo
        ALTER COLUMN foo_timestamp SET DATA TYPE timestamp with time zone
        USING
                timestamp with time zone 'epoch' + foo_timestamp * interval '1 second';

同样的,当该列具有一个不能自动造型成新数据类型的默认值表达式时:

ALTER TABLE foo
        ALTER COLUMN foo_timestamp DROP DEFAULT,
        ALTER COLUMN foo_timestamp TYPE timestamp with time zone
        USING
                timestamp with time zone 'epoch' + foo_timestamp * interval '1 second',
        ALTER COLUMN foo_timestamp SET DEFAULT now();

添加隐藏列”ltaut”:

ALTER TABLE distributors WITH UPDATE CURRENT_TIMESTAMP;

添加隐藏列”ltapk”:

ALTER TABLE distributors WITH PRIMARY KEY serial;

重命名一个现有列:

ALTER TABLE distributors RENAME COLUMN address TO city;

重命名一个现有的表:

ALTER TABLE distributors RENAME TO suppliers;

重命名一个现有的约束:

ALTER TABLE distributors RENAME CONSTRAINT zipchk TO zip_check;

为一列增加一个非空约束:

ALTER TABLE distributors ALTER COLUMN street SET NOT NULL;

从一列移除一个非空约束:

ALTER TABLE distributors ALTER COLUMN street DROP NOT NULL;

向一个表及其所有子女增加一个检查约束:

ALTER TABLE distributors ADD CONSTRAINT zipchk CHECK (char_length(zipcode) = 5);

只向一个表增加一个检查约束(不为其子女增加):

ALTER TABLE distributors ADD CONSTRAINT zipchk CHECK (char_length(zipcode) = 5) NO INHERIT;

(该检查约束也不会被未来的子女继承)。

从一个表及其子女移除一个检查约束:

ALTER TABLE distributors DROP CONSTRAINT zipchk;

只从一个表移除一个检查约束:

ALTER TABLE ONLY distributors DROP CONSTRAINT zipchk; (该检查约束仍为子女表保留在某个地方)。

为一个表增加一个外键约束:

ALTER TABLE distributors ADD CONSTRAINT distfk FOREIGN KEY (address) REFERENCES addresses (address);

为一个表增加一个外键约束,并且尽量不要影响其他工作:

ALTER TABLE distributors ADD CONSTRAINT distfk FOREIGN KEY (address) REFERENCES addresses (address) NOT VALID;
ALTER TABLE distributors VALIDATE CONSTRAINT distfk;

为一个表增加一个(多列)唯一约束:

ALTER TABLE distributors ADD CONSTRAINT dist_id_zipcode_key UNIQUE (dist_id, zipcode);

为一个表增加一个自动命名的主键约束,注意一个表只能拥有一个主键:

ALTER TABLE distributors ADD PRIMARY KEY (dist_id);

把一个表移动到一个不同的表空间:

ALTER TABLE distributors SET TABLESPACE fasttablespace;

把一个表移动到一个不同的模式:

ALTER TABLE myschema.distributors SET SCHEMA yourschema;

重建一个主键约束,并且在重建索引期间不阻塞更新:

CREATE UNIQUE INDEX CONCURRENTLY dist_id_temp_idx ON distributors (dist_id);
ALTER TABLE distributors DROP CONSTRAINT distributors_pkey,
        ADD CONSTRAINT distributors_pkey PRIMARY KEY USING INDEX dist_id_temp_idx;

要把一个分区挂接到一个范围分区表上:

ALTER TABLE measurement
        ATTACH PARTITION measurement_y2016m07 FOR VALUES FROM ('2016-07-01') TO ('2016-08-01');

要把一个分区挂接到一个列表分区表上:

ALTER TABLE cities
        ATTACH PARTITION cities_ab FOR VALUES IN ('a', 'b');

要把一个分区挂接到一个哈希分区表上:

ALTER TABLE orders
        ATTACH PARTITION orders_p4 FOR VALUES WITH (MODULUS 4, REMAINDER 3);

要把一个默认分区挂接到一个分区表上:

ALTER TABLE cities
        ATTACH PARTITION cities_partdef DEFAULT;

从一个分区表分离一个分区:

ALTER TABLE measurement
        DETACH PARTITION measurement_y2015m12;

要将范围分区添加到分区表,请执行以下操作:

ALTER TABLE oracle_partition_range ADD PARTITION oracle_partition_range_p4 VALUES LESS THAN (to_date('2022-04-01', 'yyyy-mm-dd'));

要将范围分区添加到分区表,请执行以下操作:

ALTER TABLE oracle_partition_list ADD PARTITION oracle_partition_list_p4 VALUES ('0012');

要将列表默认分区添加到分区表,请执行以下操作: (Oracle 兼容模式)

ALTER TABLE oracle_partition_list ADD PARTITION oracle_partition_list_pdef VALUES (DEFAULT);

要从分区表中删除分区,请执行以下操作:

ALTER TABLE oracle_partition_range DROP PARTITION oracle_partition_range_p4;

要从具有更新全局索引的分区表中删除分区,请执行以下操作:

ALTER TABLE oracle_partition_range DROP PARTITION oracle_partition_range_p4 UPDATE GLOBAL INDEXES;

清除一个分区表中分区的数据:

ALTER TABLE oracle_partition_range TRUNCATE PARTITION oracle_partition_range_p4;

要将普通表转换为分区表,请执行以下操作:

ALTER TABLE ordinary_table MODIFY PARTITION BY RANGE(a)
(
        PARTITION p1 VALUES LESS THAN(10),
        PARTITION p2 VALUES LESS THAN(30),
        PARTITION p3 VALUES LESS THAN(20)
)ONLINE UPDATE INDEXES
(
        a_i global,
        b_i local,
        c_i local,
        d_i global
);

DROP INDEX后缀语法糖的使用演示。

create table t1(id number, name varchar2(30));

alter table t1 add constraint pk_t1 primary key (id);

alter table t1 drop constraint pk_t1 drop index;

alter table t1 drop primary key drop index;

删除同一列的索引和约束

ALTER TABLE my_table
DROP CONSTRAINT my_constraint,
DROP INDEX my_index

使用 USING INDEX 子句来指定使用索引来支持约束,在创建约束的时候同时为约束指定一个索引

ALTER TABLE employees
ADD CONSTRAINT emp_id_pk
PRIMARY KEY (id)
USING INDEX;

5.1.23. ALTER TABLESPACE

更改一个表空间的定义

语法:

ALTER TABLESPACE name RENAME TO new_name
ALTER TABLESPACE name OWNER TO { new_owner | CURRENT_USER | SESSION_USER }
ALTER TABLESPACE name SET ( tablespace_option = value [, ... ] )
ALTER TABLESPACE name RESET ( tablespace_option [, ... ] )

描述:

ALTER TABLESPACE可以被用于更改一个 表空间的定义。

要更改一个表空间的定义,你必须拥有它。要修改拥有者,你还必须是 新拥有角色的一个直接或间接成员(注意超级用户自动拥有这些特权)。

参数:

  • name

    一个现有表空间的名称。

  • new_name

    该表空间的新名称。新名称不能以pg_开始,因为这类名称被 保留用于系统表空间。

  • new_owner

    该表空间的新拥有者。

  • tablespace_option

    要设置或者重置的一个表空间参数。当前,唯一可用的参数是 seq_page_cost、random_page_cost、 effective_io_concurrency和maintenance_io_concurrency。 为一个特定表空间设定这两个参数值将覆盖规划器对从该表空间中的表读取 页面代价的估计值,以及执行者的预取行为,这些估计值由具有相同名称配置参数建立(见 seq_page_cost、random_page_cost、 effective_io_concurrency、maintenance_io_concurrency)。 如果一个表空间位于一个比其余 I/O 子系统更快或者更慢的磁盘上时,这些参数就能派上用场。

示例:

将表空间index_space重命名为fast_raid:

ALTER TABLESPACE index_space RENAME TO fast_raid;

更改表空间index_space的拥有者:

ALTER TABLESPACE index_space OWNER TO mary;

5.1.24. ALTER TRIGGER

更改一个触发器的定义

语法:

ALTER TRIGGER name ON table_name RENAME TO new_name
ALTER TRIGGER name ON table_name [ NO ] DEPENDS ON EXTENSION extension_name

描述:

ALTER TRIGGER更改一个现有触发器的属性。 RENAME子句更改给定触发器的名称而不更改其定义。 DEPENDS ON EXTENSION子句把该触发器标记为依赖于 一个扩展,这样如果扩展被删除,该触发器也会被自动删除。

要更改一个触发器的属性,你必须拥有该触发器所作用的表。

参数:

  • name

    要修改的一个现有触发器的名称。

  • table_name

    这个触发器所作用的表的名称。

  • new_name

    该触发器的新名称。

  • extension_name

    触发器依赖于某名称的扩展(如果指定了NO,则不再依赖)。 删除扩展时,会自动删除标记为依赖于扩展的触发器。

示例:

要重命名一个现有的触发器:

ALTER TRIGGER emp_stamp ON emp RENAME TO emp_track_chgs;

要把一个触发器标记为依赖于一个扩展:

ALTER TRIGGER emp_stamp ON emp DEPENDS ON EXTENSION emplib;

ALTER TABLE 命令支持一次添加多列时可以把列定义放在要括号里

CREATE TABLE foo(a int);
ALTER TABLE foo ADD COLUMN a1 int;
ALTER TABLE foo ADD COLUMN a2 int default 3;
ALTER TABLE foo ADD COLUMN b1 int, ADD COLUMN b2 int;
ALTER TABLE foo ADD (c1 int);
ALTER TABLE foo ADD (c2 int default 3);
ALTER TABLE foo ADD (e1 int), ADD e2 int, ADD COLUMN e3 int, ADD (e4 int, e5 int);
begin
        execute immediate 'alter table foo add(d int)';
end;
/

ALTER TABLE 命令支持 TRUNCATE PARTITION partition_name 时指定 update indexes

create table part_update_indexes_range(id int primary key)
PARTITION by range(id)(
        partition p1 VALUES LESS THAN (202000) nocompress,
        partition p2 VALUES LESS THAN (202001) compress,
        partition p3 VALUES LESS THAN (202002)
);

ALTER  TABLE  part_update_indexes_range  TRUNCATE  PARTITION  p1 update indexes;

5.1.25. ALTER TYPE

更改一个类型的定义

语法:

ALTER TYPE name OWNER TO { new_owner | CURRENT_USER | SESSION_USER }
ALTER TYPE name RENAME TO new_name
ALTER TYPE name SET SCHEMA new_schema
ALTER TYPE name RENAME ATTRIBUTE attribute_name TO new_attribute_name [ CASCADE | RESTRICT ]
ALTER TYPE name action [, ... ]
ALTER TYPE name ADD VALUE [ IF NOT EXISTS ] new_enum_value [ { BEFORE | AFTER } neighbor_enum_value ]
ALTER TYPE name RENAME VALUE existing_enum_value TO new_enum_value
ALTER TYPE name SET ( property = value [, ... ] )

这里action 是以下之一:

        ADD ATTRIBUTE attribute_name data_type [ COLLATE collation ] [ CASCADE | RESTRICT ]
        DROP ATTRIBUTE [ IF EXISTS ] attribute_name [ CASCADE | RESTRICT ]
        ALTER ATTRIBUTE attribute_name [ SET DATA ] TYPE data_type [ COLLATE collation ] [ CASCADE | RESTRICT ]

描述:

ALTER TYPE更改一种现有类型的定义。 它有几种形式:

  • OWNER

    此表单更改类型的所有者。

  • RENAME

    此表单更改类型的名称。

  • SET SCHEMA

    这种形式将类型移动到另一个模式。

  • RENAME ATTRIBUTE

    该形式仅可用于复合类型。它更改类型的单个属性的名称。

  • ADD ATTRIBUTE

    这种形式为一种组合类型增加一个新属性,使用的语法和 CREATE TYPE相同。

  • DROP ATTRIBUTE [ IF EXISTS ]

    这种形式从一种组合类型删除一个属性。如果指定了 IF EXISTS并且该属性不存在,则不会抛出错误。 这种情况下会发出一个提示。

  • ALTER ATTRIBUTE … SET DATA TYPE

    这种形式更改一种组合类型的一个属性类型。

  • ADD VALUE [ IF NOT EXISTS ] [ BEFORE | AFTER ]

    这种形式为一种枚举类型增加一个新值。可以用BEFORE或者 AFTER一个现有值来指定新值在枚举顺序中的位置。 否则,新项会被增加在值列表的最后。

    如果指定了IF NOT EXISTS,该类型已经包含新值时不会发生 错误:会发出一个提示但是不采取其他行动。否则,如果新值已经存在会发生错误。

  • RENAME VALUE

    该形式重命名枚举类型的值。该值在枚举排序中的位置不受影响。 如果指定的值不存在或新名称已存在,则会发生错误。

  • SET ( property = value [, … ] )

    该表格仅适用于基本类型。 它允许调整可以在CREATE TYPE中设置的基本类型属性的子集。 具体来说,可以更改以下属性:

    可以将RECEIVE设置为二进制输入函数的名称, 或者设置为NONE删除类型的二进制输入函数。 使用此选项需要超级用户特权。

    可以将SEND设置为二进制输出函数的名称, 或者设置为NONE删除类型的二进制输入函数。 使用此选项需要超级用户特权。

    可以将TYPMOD_IN设置为类型修饰符输入函数的名称, 或者设置为NONE删除类型的类型修饰符输入函数。 使用此选项需要超级用户特权。

    可以将TYPMOD_OUT设置为类型修饰符输出函数的名称, 或者设置为NONE删除类型的类型修饰符输出函数的名称。 使用此选项需要超级用户特权。

    可以将ANALYZE设置为特定于类型的统计信息收集功能的名称, 或者设置为NONE删除该类型的统计信息收集功能。 使用此选项需要超级用户特权。

    SUBSCRIPT可以设置为特定于类型的下标处理程序函数的名称,也可以设置为NONE以删除类型的下注处理程序函数。使用此选项需要超级用户权限。

    可以将STORAGE设置为plain, extended, external, 或 main。 但是,从plain更改为另一个设置需要超级用户特权(因为它要求该类型的C函数全部是TOAST-ready), 而从另一个设置更改为 plain 则不是完全允许(因为类型可能已经在数据库中包含TOASTed值)。 请注意,更改此选项本身并不会更改任何存储的数据,它只是设置默认的TOAST策略以用于将来创建的表列。 请参见ALTER TABLE更改现有表列的TOAST策略。

    有关这些类型属性的更多详细信息,请参见CREATE TYPE。 请注意,在适当的情况下,基本类型的这些属性中的更改将自动传播到基于该类型的域。

ADD ATTRIBUTE、DROP ATTRIBUTE和ALTER ATTRIBUTE动作 可以被整合到一个多个修改组成的列表中,以便被平行应用。例如, 可以在一个命令中增加多个属性并且/或者修改多个属性的类型。

要使用ALTER TYPE,你必须拥有该类型。要更改 一个类型的模式,你还必须拥有新模式上的 CREATE特权。要更改拥有者,你还必须 是新拥有角色的一个直接或者间接成员,并且该角色必须具有该类型的模式上的 CREATE特权(这些限制强制修改拥有者不能做一些通过删除和重 建该类型做不到的事情。不过,一个超级用户怎么都能更改任何类型的所有权。)。 要增加一个属性或者修改一个属性类型,你还必须具有该属性数据类型上的 USAGE特权。

5.1.26. ALTER USER

更改一个数据库角色

语法:

ALTER USER role_specification [ WITH ] option [ ... ]

其中 option 可以是:

        SUPERUSER | NOSUPERUSER
        | CREATEDB | NOCREATEDB
        | CREATEROLE | NOCREATEROLE
        | INHERIT | NOINHERIT
        | LOGIN | NOLOGIN
        | REPLICATION | NOREPLICATION
        | BYPASSRLS | NOBYPASSRLS
        | CONNECTION LIMIT connlimit
        | [ ENCRYPTED ] PASSWORD 'password' | PASSWORD NULL
        | VALID UNTIL 'timestamp'

ALTER USER name RENAME TO new_name

ALTER USER { role_specification | ALL } [ IN DATABASE database_name ] SET configuration_parameter { TO | = } { value | DEFAULT }
ALTER USER { role_specification | ALL } [ IN DATABASE database_name ] SET configuration_parameter FROM CURRENT
ALTER USER { role_specification | ALL } [ IN DATABASE database_name ] RESET configuration_parameter
ALTER USER { role_specification | ALL } [ IN DATABASE database_name ] RESET ALL

其中 role_specification 可以是:

        role_name
| CURRENT_USER
| SESSION_USER

描述:

ALTER USER现在是 ALTER ROLE的一种别名。

5.1.27. ALTER VIEW

更改一个视图的定义

语法:

ALTER VIEW [ IF EXISTS ] name ALTER [ COLUMN ] column_name SET DEFAULT expression
ALTER VIEW [ IF EXISTS ] name ALTER [ COLUMN ] column_name DROP DEFAULT
ALTER VIEW [ IF EXISTS ] name OWNER TO { new_owner | CURRENT_USER | SESSION_USER }
ALTER VIEW [ IF EXISTS ] name RENAME [ COLUMN ] column_name TO new_column_name
ALTER VIEW [ IF EXISTS ] name RENAME TO new_name
ALTER VIEW [ IF EXISTS ] name SET SCHEMA new_schema
ALTER VIEW [ IF EXISTS ] name SET ( view_option_name [= view_option_value] [, ... ] )
ALTER VIEW [ IF EXISTS ] name RESET ( view_option_name [, ... ] )

描述:

ALTER VIEW更改一个视图的多种辅助属性(如果想要 修改视图的查询定义,应使用CREATE OR REPLACE VIEW)。

要使用ALTER VIEW,你必须拥有该视图。要更改一个视图的模式, 你还必须具有新模式上的CREATE特权。要更改拥有者,你还必须 是新拥有角色的一个直接或者间接成员,并且该角色必须具有该视图的模式上的 CREATE特权(这些限制强制修改拥有者不能做一些通过删除和重 建视图做不到的事情。不过,一个超级用户怎么都能更改任何视图的所有权。)。

参数:

  • name

    一个现有视图的名称(可以是模式限定的)。

  • column_name

    现有列的名称。

  • new_column_name

    现有列的新名称。

  • IF EXISTS

    该视图不存在时不要抛出一个错误。这种情况下会发出一个提示。

  • SET/DROP DEFAULT

    这些形式为一个列设置或者移除默认值。对于任何在该视图上的 INSERT或者UPDATE命令,一个视图列的默认值 会在引用该视图的任何规则或触发器之前被替换进来。因此,该视图的默认值将会 优先于来自底层关系的任何默认值。

  • new_owner

    该视图的新拥有者的用户名。

  • new_name

    该视图的新名称。

  • new_schema

    该视图的新模式。

  • SET ( view_option_name [= view_option_value] [, … ] )

  • RESET ( view_option_name [, … ] )

    设置或者重置一个视图选项。当前支持的选项有:

    • check_option (enum)

      更改该视图的检查选项。值必须是local 或者cascaded。

    • security_barrier (boolean)

      更改该视图的安全屏障属性。值必须是一个布尔值,如 true或者false。

示例:

把视图foo重命名为 bar:

ALTER VIEW foo RENAME TO bar;

要为一个可更新视图附加一个默认列值:

CREATE TABLE base_table (id int, ts timestamptz);
CREATE VIEW a_view AS SELECT * FROM base_table;
ALTER VIEW a_view ALTER COLUMN ts SET DEFAULT now();
INSERT INTO base_table(id) VALUES(1);  -- ts will receive a NULL
INSERT INTO a_view(id) VALUES(2);  -- ts will receive the current time

5.1.28. DROP DATABASE

移除一个数据库

语法:

DROP DATABASE [ IF EXISTS ] name [ [ WITH ] ( option [, ...] ) ]

其中选项 可以是:

        FORCE

描述:

DROP DATABASE移除一个数据库。它会 移除该数据库的系统目录项并且删除包含数据的文件目录。它只能由数据库 拥有者执行。当你已经连接到目标数据库时,它不能被执行(连接 到postgres或者任何其他数据库来发出这个命令)。 另外,如果其他任何人已经连接到目标数据库,这个命令将会失败,除非您 使用以下所述的FORCE选项。

DROP DATABASE不能被撤销。请小心使用!

参数:

  • IF EXISTS

    如果该数据库不存在则不要抛出一个错误,而是发出一个提示。

  • name

    要移除的数据库的名称。

  • FORCE

    尝试终止与目标数据库的所有现有连接。 如果目标数据库中存在准备好的事务、活跃的逻辑复制槽或订阅,则不会终止。

    如果当前用户没有终止其他连接的权限,则此操作将失败。所需权限与 pg_terminate_backend相同。如果我们不能 终止连接,则此操作也将会失败。

5.1.29. DROP FUNCTION

移除一个函数

语法:

DROP FUNCTION [ IF EXISTS ] name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ] [, ...]
        [ CASCADE | RESTRICT ]

描述:

DROP FUNCTION移除一个已有函数 的定义。要执行这个命令用户必须是该函数的拥有者。该函数的参数 类型必须被指定,因为多个不同的函数可能会具有相同的函数名和不 同的参数列表。

参数:

  • IF EXISTS

    如果该函数不存在则不要抛出一个错误,而是发出一个提示。

  • name

    一个现有函数的名称(可以是模式限定的)。 如果未指定参数列表,则该名称在其模式中必须是唯一的。

  • argmode

    一个参数的模式:IN、OUT、 INOUT或者VARIADIC。如果被忽略, 则默认为IN。注意 DROP FUNCTION并不真正关心 OUT参数,因为决定函数的身份时只需要输入参数。 因此列出IN、INOUT和 VARIADIC参数足以。

  • argname

    一个参数的名称。注意 DROP FUNCTION并不真正关心 参数名称,因为决定函数的身份时只需要参数的数据类型。

  • argtype

    如果函数有参数,这是函数参数的数据类型(可以是模式限定的)。

  • CASCADE

    自动删除依赖于该函数的对象(例如操作符和触发器),然后删除所有 依赖于那些对象的对象。

  • RESTRICT

    如果有任何对象依赖于该函数,则拒绝删除它。这是默认值。

示例:

这个命令移除平方根函数:

DROP FUNCTION sqrt(integer);

在一个命令中删除多个函数:

DROP FUNCTION sqrt(integer), sqrt(bigint);

如果函数名称在其模式中是唯一的,则可以在不带参数列表的情况下引用它:

DROP FUNCTION update_employee_salaries;

请注意,这与

DROP FUNCTION update_employee_salaries();

5.1.30. DROP INDEX

移除一个索引

语法

DROP INDEX [ CONCURRENTLY ] [ IF EXISTS ] name [, ...] [ ON  tbname ] [ CASCADE | RESTRICT ]

描述:

DROP INDEX从数据库系统中 移除一个已有的索引。要执行这个命令你必须是该索引的拥 有者。

参数:

  • CONCURRENTLY

    删除索引并且不阻塞在索引基表上的并发选择、插入、更新和删除操作。一个 普通的DROP INDEX会要求该表上的排他锁,这样会阻塞 其他访问直至索引删除完成。通过这个选项,该命令会等待直至冲突事务完成。

    在使用这个选项时有一些需要注意的事情。只能指定一个索引名称,并且不支 持CASCADE选项(因此,一个支持UNIQUE或者 PRIMARY KEY约束的索引不能以这种方式删除)。还有,常规 的DROP INDEX命令可以在一个事务块内执行,而 DROP INDEX CONCURRENTLY不能。 最后,不能使用此选项删除分区表上的索引。

    对于临时表,DROP INDEX始终是非并发的,因为没有其他会话可以访问它们,而且非并发的索引移除代价更小。

  • IF EXISTS

    如果该索引不存在则不要抛出一个错误,而是发出一个提示。

  • name

    要移除的索引名称(可以是模式限定的)。

  • tbname

    要删除的索引的表名(可选的表名)。但这是一种语法糖,相当于不使用` ON tbname `

  • CASCADE

    自动删除依赖于该索引的对象,然后删除所有 依赖于那些对象的对象。

  • RESTRICT

    如果有任何对象依赖于该索引,则拒绝删除它。这是默认值。

示例:

这个命令将移除索引title_idx:

DROP INDEX title_idx;

5.1.31. DROP MATERIALIZED VIEW

移除一个物化视图

语法:

DROP MATERIALIZED VIEW [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ]

描述:

DROP MATERIALIZED VIEW删除一个 现有的物化视图。要执行这个命令你必须是该物化视图的拥有者。

参数:

  • IF EXISTS

    如果该物化视图不存在则不要抛出一个错误,而是发出一个提示。

  • name

    要移除的物化视图的名称(可以是模式限定的)。

  • CASCADE

    自动删除依赖于该物化视图的对象(例如其他物化视图或常规视图),然后删除所有 依赖于那些对象的对象。

  • RESTRICT

    如果有任何对象依赖于该物化视图,则拒绝删除它。这是默认值。

示例:

这个命令将移除名为order_summary的物化视图:

DROP MATERIALIZED VIEW order_summary;

5.1.32. DROP OPERATOR

移除一个操作符

语法:

DROP OPERATOR [ IF EXISTS ] name ( { left_type | NONE } , { right_type | NONE } ) [, ...] [ CASCADE | RESTRICT ]

描述:

DROP OPERATOR从数据库系统中 删除一个现有的操作符。要执行这个命令,你必须是该操作符的拥有者。

参数:

  • IF EXISTS

    如果该操作符不存在则不会抛出一个错误,而是发出一个提示。

  • name

    一个现有的操作符的名称(可以是模式限定的)。

  • left_type

    该操作符左操作数的数据类型,如果没有左操作数就写NONE。

  • right_type

    该操作符右操作数的数据类型,如果没有右操作数就写NONE。

  • CASCADE

    自动删除依赖于该操作符的对象(例如使用它的视图),然后删除所有 依赖于那些对象的对象。

  • RESTRICT

    如果有任何对象依赖于该操作符,则拒绝删除它。这是默认值。

示例:

为类型integer移除幂操作符a^b:

DROP OPERATOR ^ (integer, integer);

为类型bit移除左一元按位补操作符~b:

DROP OPERATOR ~ (none, bit);

为类型bigint移除右一元阶乘操作符x!:

DROP OPERATOR ! (bigint, none);

在一条命令中删除多个操作符:

DROP OPERATOR ~ (none, bit), ! (bigint, none);

5.1.33. DROP PROCEDURE

移除一个过程

语法:

DROP PROCEDURE [ IF EXISTS ] name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ] [, ...]
        [ CASCADE | RESTRICT ]

描述:

DROP PROCEDURE移除一个现有过程的定义。为了执行这个命令,用户必须是该过程的拥有者。该过程的参数类型必须被指定,因为可能存在多个不同的过程具有相同名称和不同参数列表。

参数:

  • IF EXISTS

    如果该过程不存在也不抛出一个错误。这种情况下会发出一个提示。

  • name

    现有过程的名称(可以被模式限定的)。如果没有指定参数列表,则该名称在其所属的模式中必须是唯一的。

  • argmode

    参数的模式:IN或者VARIADIC。如果省略,默认为IN。

  • argname

    参数的名称。注意,其实DROP PROCEDURE并不真正在意参数名称,因为只需要参数的数据类型来确定过程的身份。

  • argtype

    该过程如果有参数,这里是参数的数据类型(可以是模式限定的)。

  • CASCADE

    自动删除依赖于该过程的对象,然后接着删除依赖于那些对象的对象。

  • RESTRICT

    如果有任何对象依赖于该过程,则拒绝删除它。这是默认选项。

示例:

DROP PROCEDURE do_db_maintenance();

5.1.34. DROP ROLE

移除一个数据库角色

语法:

DROP ROLE [ IF EXISTS ] name [, ...]

描述:

DROP ROLE移除指定的角色。要删除一个超级用户角色,你必须自己就是一个超级用户。要删除一个非超级用户角色,你必须具有CREATEROLE特权。

如果一个角色仍然在集簇中任何数据库中被引用,它就不能被移除,如果尝试移除将会抛出一个错误。在删除该角色前,你必须删除(或者重新授予所有权)它所拥有的所有对象并且收回该已经授予给该角色的在其他对象上的特权。REASSIGN OWNED和DROP OWNED命令可以用于这个目的。

不过,没有必要移除涉及该角色的角色成员关系。DROP ROLE会自动收回目标角色在其他角色中的成员关系以及其他角色在目标角色中的成员关系。其他角色不会被删除也不会被影响。

参数:

  • IF EXISTS

    如果该角色不存在则不要抛出一个错误,而是发出一个提示。

  • name

    要移除的角色的名称。

示例:

要删除一个角色:

DROP ROLE jonathan;

5.1.35. DROP SEQUENCE

移除一个序列

语法:

DROP SEQUENCE [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ]

描述:

DROP SEQUENCE移除序数生成器。 一个序列只能被其拥有者或超级用户删除。

参数:

  • IF EXISTS

    如果该序列不存在则不要抛出一个错误,而是发出一个提示。

  • name

    一个序列的名称(可以是模式限定的)。

  • CASCADE

    自动删除依赖于该序列的对象,然后删除所有 依赖于那些对象的对象。

  • RESTRICT

    如果有任何对象依赖于该序列,则拒绝删除它。这是默认值。

示例:

要移除序列serial:

DROP SEQUENCE serial;

5.1.36. DROP TABLE

移除一个表

语法:

DROP TABLE [ IF EXISTS ] name [, ...] [ CASCADE [CONSTRAINTS] | RESTRICT ]

描述:

DROP TABLE从数据库移除表。只有表拥有者、模式拥有者和超级用户能删除一个表。要清空一个表中的行但是不销毁该表,可以使用DELETE或者TRUNCATE。

DROP TABLE总是移除目标表的任何索引、规则、触发器和约束。不过,要删除一个被视图或者另一个表的外键约束所引用的表,必须指定CASCADE(CASCADE将会把依赖的视图也完全移除,但是对于外键它将只移除外键约束,而不是完全移除其他表)。

参数:

  • IF EXISTS

    如果该表不存在则不要抛出一个错误,这种情况下会发出一个提示。

  • name

    要删除的表的名称(可以是模式限定的)。

  • CASCADE

    自动删除依赖于该表的对象(例如视图),然后删除所有依赖于那些对象的对象。

  • CASCADE CONSTRAINTS

    自动删除依赖于该表的对象(例如视图),然后删除所有依赖于那些对象的对象。此为兼容Oracle语法,实际功能与CASCADE相同。

  • RESTRICT

    如果有任何对象依赖于该表,则拒绝删除它。这是默认值。

示例:

要销毁两个表films和distributors:

DROP TABLE films, distributors;

删除表films,并自动删除依赖于该表的对象:

DROP TABLE films CASCADE;

DROP TABLE films CASCADE CONSTRAINTS;

通过 cascade constraints 级联删除该表所有的约束

CREATE TABLE student(id int, name varchar2(100));

ALTER TABLE student ADD CONSTRAINT uk_student unique(id);

\d student
Table "public.student"
Column |     Type      | Collation | Nullable | Default
--------+---------------+-----------+----------+---------
id     | integer       |           |          |
name   | varchar2(100) |           |          |
Indexes:
"uk_student" UNIQUE CONSTRAINT, btree (id)

DROP TABLE student cascade constraints;

5.1.37. DROP TABLESPACE

移除一个表空间

语法:

DROP TABLESPACE [ IF EXISTS ] name

描述:

DROP TABLESPACE从系统中移除一个表空间。

一个表空间只能被其拥有者或超级用户删除。在一个表空间能被删除前,其中 必须没有任何数据库对象。即使当前数据库中没有对象正在使用该表空间,也 可能有其他数据库的对象存在于其中。还有,如果该表空间被列在任何活动会 话的temp_tablespaces设置中, DROP也可能会失败,因为可能有临时文件存在其中。

参数:

  • IF EXISTS

    如果该表空间不存在则不要抛出一个错误,而是发出一个提示。

  • name

    一个表空间的名称。

示例:

要从系统移除表空间mystuff:

DROP TABLESPACE mystuff;

5.1.38. DROP TRIGGER

移除一个触发器

语法:

DROP TRIGGER [ IF EXISTS ] name ON table_name [ CASCADE | RESTRICT ]

描述:

DROP TRIGGER移除一个现有的触发器定义。 要执行这个命令,当前用户必须是触发器基表的拥有者。

参数:

  • IF EXISTS

    如果该触发器不存在则不要抛出一个错误,而是发出一个提示。

  • name

    要移除的触发器的名称。

  • table_name

    定义了该触发器的表的名称(可以是模式限定的)。

  • CASCADE

    自动删除依赖于该触发器的对象,然后删除所有 依赖于那些对象的对象。

  • RESTRICT

    如果有任何对象依赖于该触发器,则拒绝删除它。这是默认值。

示例:

销毁表films上的触发器 if_dist_exists:

  • DROP TRIGGER if_dist_exists ON films;

5.1.39. DROP TYPE

移除一个数据类型

语法:

DROP TYPE [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ]

DROP TYPE BODY name [, ...] [ CASCADE | RESTRICT ]

描述:

DROP TYPE移除一种用户定义的数据类型。 只有一个类型的拥有者才能移除它。

DROP TYPE BODY 移除用户定义对象类型的函数定义。 只有一个类型的拥有者才能移除它。

参数:

  • IF EXISTS

    如果该类型不存在则不要抛出一个错误,而是发出一个提示。

  • name

    要移除的数据类型的名称(可以是模式限定的)。

  • CASCADE

    自动删除依赖于该类型的对象(例如表列、函数、操作符),然后删除所有 依赖于那些对象的对象。

  • RESTRICT

    如果有任何对象依赖于该类型,则拒绝删除它。这是默认值。

示例:

要移除数据类型box:

DROP TYPE box;

要移除数据类型体tp:

DROP TYPE BODY tp;

5.1.40. DROP USER

移除一个数据库角色

语法:

DROP USER [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ]

描述:

DROP USER现在是DROP ROLE另一种写法。

参数:

  • CASCADE

    用于与 Oracle 兼容的 DROP USER 语句。 自动删除包含在用户中的对象(表、函数等),以及依赖于这些对象的所有对象。 必须在 Oracle 数据库中使用。

  • RESTRICT

    用于与 Oracle 兼容的 DROP USER 语句。如果用户包含任何对象,则拒绝删除该用户。这是默认行为。必须在 Oracle 数据库中使用。

5.1.41. DROP VIEW

移除一个视图

语法:

DROP VIEW [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ]

描述:

DROP VIEW删除一个现有的视图。要执行 这个命令你必须是该视图的拥有者。

参数:

  • IF EXISTS

    如果该视图不存在则不要抛出一个错误,而是发出一个提示。

  • name

    要移除的视图的名称(可以是模式限定的)。

  • CASCADE

    自动删除依赖于该视图的对象(例如其他视图),然后删除所有 依赖于那些对象的对象。

  • RESTRICT

    如果有任何对象依赖于该视图,则拒绝删除它。这是默认值。

示例:

这个命令将移除名为kinds的视图:

DROP VIEW kinds;

5.1.42. GRANT

定义访问特权

语法:

GRANT { { SELECT | INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES | TRIGGER }
        [, ...] | ALL [ PRIVILEGES ] }
        ON { [ TABLE ] table_name [, ...]
                | ALL TABLES IN SCHEMA schema_name [, ...] }
        TO role_specification [, ...] [ WITH GRANT OPTION ]

GRANT { { SELECT | INSERT | UPDATE | REFERENCES } ( column_name [, ...] )
        [, ...] | ALL [ PRIVILEGES ] ( column_name [, ...] ) }
        ON [ TABLE ] table_name [, ...]
        TO role_specification [, ...] [ WITH GRANT OPTION ]

GRANT { { USAGE | SELECT | UPDATE }
        [, ...] | ALL [ PRIVILEGES ] }
        ON { SEQUENCE sequence_name [, ...]
                | ALL SEQUENCES IN SCHEMA schema_name [, ...] }
        TO role_specification [, ...] [ WITH GRANT OPTION ]

GRANT { { CREATE | CONNECT | TEMPORARY | TEMP } [, ...] | ALL [ PRIVILEGES ] }
        ON DATABASE database_name [, ...]
        TO role_specification [, ...] [ WITH GRANT OPTION ]

GRANT { USAGE | ALL [ PRIVILEGES ] }
        ON DOMAIN domain_name [, ...]
        TO role_specification [, ...] [ WITH GRANT OPTION ]

GRANT { USAGE | ALL [ PRIVILEGES ] }
        ON FOREIGN DATA WRAPPER fdw_name [, ...]
        TO role_specification [, ...] [ WITH GRANT OPTION ]

GRANT { USAGE | ALL [ PRIVILEGES ] }
        ON FOREIGN SERVER server_name [, ...]
        TO role_specification [, ...] [ WITH GRANT OPTION ]

GRANT { EXECUTE | ALL [ PRIVILEGES ] }
        ON { { FUNCTION | PROCEDURE | ROUTINE } routine_name [ ( [ [ argmode ] [ arg_name ] arg_type [, ...] ] ) ] [, ...]
                | ALL { FUNCTIONS | PROCEDURES | ROUTINES } IN SCHEMA schema_name [, ...] }
        TO role_specification [, ...] [ WITH GRANT OPTION ]

GRANT { USAGE | ALL [ PRIVILEGES ] }
        ON LANGUAGE lang_name [, ...]
        TO role_specification [, ...] [ WITH GRANT OPTION ]

GRANT { { SELECT | UPDATE } [, ...] | ALL [ PRIVILEGES ] }
        ON LARGE OBJECT loid [, ...]
        TO role_specification [, ...] [ WITH GRANT OPTION ]

GRANT { { CREATE | USAGE } [, ...] | ALL [ PRIVILEGES ] }
        ON SCHEMA schema_name [, ...]
        TO role_specification [, ...] [ WITH GRANT OPTION ]

GRANT { CREATE | ALL [ PRIVILEGES ] }
        ON TABLESPACE tablespace_name [, ...]
        TO role_specification [, ...] [ WITH GRANT OPTION ]

GRANT { USAGE | ALL [ PRIVILEGES ] }
        ON TYPE type_name [, ...]
        TO role_specification [, ...] [ WITH GRANT OPTION ]

GRANT role_name [, ...] TO role_specification [, ...]
        [ WITH ADMIN OPTION ]
        [ GRANTED BY role_specification ]

GRANT option_for_oracle TO role_specification [, ...]
        [ WITH ADMIN OPTION ]

where role_specification can be:

        [ GROUP ] role_name
| PUBLIC
| CURRENT_USER
| SESSION_USER

其中 option_for_oracle 可以是:
        CONNECT
| RESOURCE
| UNLIMITED TABLESPACE

描述:

GRANT命令由两种基本的变体:一种授予在一个数据库对象(表、列、视图、外部表、序列、数据库、外部数据包装器、外部服务器、函数、过程、过程语言、模式或表空间)上的特权,另一个授予一个角色中的成员关系。这些变体在很多方面都相似,但是也有很多不同,所以还是得分别描述它们。

在数据库对象上 GRANT

这种GRANT命令的变体将一个数据库对象上的指定特权交给一个或多个角色。如果有一些已经被授予,这些特权会被加入到它们之中。

关键词PUBLIC指示特权要被授予给所有角色,包括那些可能稍后会被创建的角色。PUBLIC可以被认为是一个被隐式定义的总是包含所有角色的组。任何特定角色都将具有直接授予给它的特权、授予给它作为成员所在的任何角色的特权以及被授予给PUBLIC的特权。

如果指定了WITH GRANT OPTION,特权的接收者可以接着把它授予给其他人。如果没有授权选项,接收者就不能这样做。授权选项不能被授予给PUBLIC。

没有必要把权限授予给一个对象的拥有者(通常就是创建该对象的用户), 因为拥有者默认具有所有的特权(不过拥有者可能为了安全选择撤回一些 它们自己的特权)。

删除一个对象或者以任何方式修改其定义的权力是不被当作一个可授予特权的,它被固化在拥有者中,并且不能被授予和撤回(不过,相似地效果可以通过授予或者撤回在拥有该对象的角色中的成员关系来实现,见下文)。拥有者也隐式地拥有该对象的所有授权选项。

The possible privileges are:

SELECT INSERT UPDATE DELETE TRUNCATE REFERENCES TRIGGER CREATE CONNECT TEMPORARY EXECUTE USAGE 特定类型的权限。

TEMP TEMPORARY的替代拼写。

ALL PRIVILEGES 授予对象的类型可用的所有权限。PRIVILEGES关键词在LightDB中是可选的,尽管它是严格的 SQL 所需要的。

FUNCTION语法适用于简单函数、聚合函数和窗口函数,但不适用于过程;对过程使用PROCEDURE。 或者,使用ROUTINE来引用函数、聚合函数、窗口函数或过程而不管其精确类型。

还有一个选项,可以在一个或多个模式中对所有相同类型的对象授予特权。此功能当前仅支持表、序列、函数和过程。 ALL TABLES也会影响视图和外表,就像特定对象 GRANT命令。 ALL FUNCTIONS也会影响聚合和窗口函数,但不影响过程,就像特定对象GRANT命令一样。 使用 ALL ROUTINES 来包括过程。

角色上的 GRANT

GRANT命令的这种变体把一个角色中的成员关系授予一个或者多个其他角色。一个角色中的成员关系是有意义的,因为它会把授予给一个角色的特权带给该角色的每一个成员。

如果指定了WITH ADMIN OPTION,成员接着可以把该角色中的成员关系授予给其他用户,也可以撤回该角色中的成员关系。如果没有管理选项,普通用户就不能做这些工作。一个角色不被认为持有自身的WITH ADMIN OPTION,但是它可以从一个会话用户匹配该角色的数据库会话中授予或撤回自身中的成员关系。数据库超级用户能够授予或撤回任何角色中任何人的成员关系。具有CREATEROLE特权的角色能够授予或者撤回任何非超级用户角色中的成员关系。

如果指定了GRANTED BY,则该授予被记录为已由指定角色完成。 只有数据库超级用户可以使用此选项,除非它为执行命令指定了相同的角色。

和特权的情况不同,一个角色中的成员关系不能被授予PUBLIC。还要注意 这种形式的命令不允许role_specification 中的噪声词GROUP。

示例:

把表films上的插入特权授予给所有用户:

GRANT INSERT ON films TO PUBLIC;

把视图kinds上的所有可用特权授予给用户manuel:

GRANT ALL PRIVILEGES ON kinds TO manuel;

注意虽然上述语句被一个超级用户或者kinds的拥有者执行时确实会授予所有特权,但是当由其他人执行时将只会授予那些执行者拥有授权选项的权限。

把角色admins中的成员关系授予给用户joe:

GRANT admins TO joe;

Oracle 兼容的授权语句:

GRANT CONNECT TO HS_SES;
GRANT RESOURCE TO HS_SES;
GRANT UNLIMITED TABLESPACE TO HS_SES;

5.1.43. REVOKE

移除访问特权

语法:

REVOKE [ GRANT OPTION FOR ]
        { { SELECT | INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES | TRIGGER }
        [, ...] | ALL [ PRIVILEGES ] }
        ON { [ TABLE ] table_name [, ...]
                | ALL TABLES IN SCHEMA schema_name [, ...] }
        FROM role_specification [, ...]
        [ CASCADE | RESTRICT ]

REVOKE [ GRANT OPTION FOR ]
        { { SELECT | INSERT | UPDATE | REFERENCES } ( column_name [, ...] )
        [, ...] | ALL [ PRIVILEGES ] ( column_name [, ...] ) }
        ON [ TABLE ] table_name [, ...]
        FROM role_specification [, ...]
        [ CASCADE | RESTRICT ]

REVOKE [ GRANT OPTION FOR ]
        { { USAGE | SELECT | UPDATE }
        [, ...] | ALL [ PRIVILEGES ] }
        ON { SEQUENCE sequence_name [, ...]
                | ALL SEQUENCES IN SCHEMA schema_name [, ...] }
        FROM role_specification [, ...]
        [ CASCADE | RESTRICT ]

REVOKE [ GRANT OPTION FOR ]
        { { CREATE | CONNECT | TEMPORARY | TEMP } [, ...] | ALL [ PRIVILEGES ] }
        ON DATABASE database_name [, ...]
        FROM role_specification [, ...]
        [ CASCADE | RESTRICT ]

REVOKE [ GRANT OPTION FOR ]
        { USAGE | ALL [ PRIVILEGES ] }
        ON DOMAIN domain_name [, ...]
        FROM role_specification [, ...]
        [ CASCADE | RESTRICT ]

REVOKE [ GRANT OPTION FOR ]
        { USAGE | ALL [ PRIVILEGES ] }
        ON FOREIGN DATA WRAPPER fdw_name [, ...]
        FROM role_specification [, ...]
        [ CASCADE | RESTRICT ]

REVOKE [ GRANT OPTION FOR ]
        { USAGE | ALL [ PRIVILEGES ] }
        ON FOREIGN SERVER server_name [, ...]
        FROM role_specification [, ...]
        [ CASCADE | RESTRICT ]

REVOKE [ GRANT OPTION FOR ]
        { EXECUTE | ALL [ PRIVILEGES ] }
        ON { { FUNCTION | PROCEDURE | ROUTINE } function_name [ ( [ [ argmode ] [ arg_name ] arg_type [, ...] ] ) ] [, ...]
                | ALL { FUNCTIONS | PROCEDURES | ROUTINES } IN SCHEMA schema_name [, ...] }
        FROM role_specification [, ...]
        [ CASCADE | RESTRICT ]

REVOKE [ GRANT OPTION FOR ]
        { USAGE | ALL [ PRIVILEGES ] }
        ON LANGUAGE lang_name [, ...]
        FROM role_specification [, ...]
        [ CASCADE | RESTRICT ]

REVOKE [ GRANT OPTION FOR ]
        { { SELECT | UPDATE } [, ...] | ALL [ PRIVILEGES ] }
        ON LARGE OBJECT loid [, ...]
        FROM role_specification [, ...]
        [ CASCADE | RESTRICT ]

REVOKE [ GRANT OPTION FOR ]
        { { CREATE | USAGE } [, ...] | ALL [ PRIVILEGES ] }
        ON SCHEMA schema_name [, ...]
        FROM role_specification [, ...]
        [ CASCADE | RESTRICT ]

REVOKE [ GRANT OPTION FOR ]
        { CREATE | ALL [ PRIVILEGES ] }
        ON TABLESPACE tablespace_name [, ...]
        FROM role_specification [, ...]
        [ CASCADE | RESTRICT ]

REVOKE [ GRANT OPTION FOR ]
        { USAGE | ALL [ PRIVILEGES ] }
        ON TYPE type_name [, ...]
        FROM role_specification [, ...]
        [ CASCADE | RESTRICT ]

REVOKE [ ADMIN OPTION FOR ]
        role_name [, ...] FROM role_specification [, ...]
        [ GRANTED BY role_specification ]
        [ CASCADE | RESTRICT ]

where role_specification can be:

        [ GROUP ] role_name
| PUBLIC
| CURRENT_USER
| SESSION_USER

描述:

REVOKE命令收回之前从一个或者更多角色 授予的特权。关键词PUBLIC隐式定义的全部角色的组。

特权类型的含义见GRANT命令的描述。

注意任何特定角色拥有的特权包括直接授予给它的特权、从它作为其成员的 角色中得到的特权以及授予给PUBLIC的特权。因此, 从PUBLIC收回SELECT特权并不一定会意味 着所有角色都会失去在该对象上的SELECT特权:那些直接被授 予的或者通过另一个角色被授予的角色仍然会拥有它。类似地,从一个用户 收回SELECT后,如果PUBLIC或者另一个 成员关系角色仍有SELECT权利,该用户还是可以使用 SELECT。

如果指定了GRANT OPTION FOR,只会回收该特权 的授予选项,特权本身不被回收。否则,特权及其授予选项都会被回收。

如果一个用户持有一个带有授予选项的特权并且把它授予给了其他用户, 那么被那些其他用户持有的该特权被称为依赖特权。如果第一个用户持有 的该特权或者授予选项正在被收回且存在依赖特权,指定 CASCADE可以连带回收那些依赖特权,不指定则会 导致回收动作失败。这种递归回收只影响通过可追溯到该 REVOKE命令的主体的用户链授予的特权。因此, 如果该特权经由其他用户授予给受影响用户,受影响用户可能实际上还 保留有该特权。

在回收一个表上的特权时,也会在该表的每一个列上自动回收对应的列 特权(如果有)。在另一方面,如果一个角色已经被授予一个表上的 特权,那么从个别的列上回收同一个特权将不会生效。

在回收一个角色中的成员关系时,GRANT OPTION被改 称为ADMIN OPTION,但行为是类似的。这种形式的命 令也允许使用 GRANTED BY 选项,但该选项当前被忽 略(除了检查指定角色的存在)。也要注意这种形式的命令不允许在 role_specification 中使用噪声词GROUP。

示例:

从 public 收回表films上的插入特权:

REVOKE INSERT ON films FROM PUBLIC;

从用户manuel收回视图 kinds上的所有特权:

REVOKE ALL PRIVILEGES ON kinds FROM manuel;

注意着实际意味着“收回所有我授出的特权”。

从用户joe收回角色admins中的成员关系:

REVOKE admins FROM joe;

5.1.44. TRUNCATE

清空一个表或者一组表

语法:

TRUNCATE [ TABLE ] [ ONLY ] name [ * ] [, ... ]
        [ RESTART IDENTITY | CONTINUE IDENTITY ] [ CASCADE | RESTRICT ]

描述:

TRUNCATE可以从一组表中快速地移除所有行。 它具有和在每个表上执行无条件DELETE相同的 效果,不过它会更快,因为它没有实际扫描表。此外,它会立刻回收磁盘空间, 而不是要求一个后续的VACUUM操作。在大表上 它最有用。

参数:

  • name

    要截断的表的名字(可以是模式限定的)。如果在表名前指定了 ONLY,则只会截断该表。如果没有指定ONLY, 该表及其所有后代表(如果有)都会被截断。可选地,可以在表名后指定 *来显式地包括后代表。

  • RESTART IDENTITY

    自动重新开始被截断表的列所拥有的序列。

  • CONTINUE IDENTITY

    不更改序列值。这是默认值。

  • CASCADE

    自动截断所有对任一所提及表有外键引用的表以及任何由于 CASCADE被加入到组中的表。

  • RESTRICT

    如果任一表上具有来自命令中没有列出的表的外键引用,则拒绝截断。这是默认值。

示例:

截断表bigtable和 fattable:

TRUNCATE bigtable, fattable;

做同样的事情,并且还重置任何相关联的序列发生器:

TRUNCATE bigtable, fattable RESTART IDENTITY;

截断表othertable,并且级联地截断任何通过 外键约束引用othertable的表:

TRUNCATE othertable CASCADE;

5.2. DML语句

DML语句

类型

概要

详细说明链接

是否支持

DML

创建一个分析视图

CALL

支持

DML

删除一个表的行

DELETE

支持

DML

创建一个分析视图

EXPLAIN

支持

DML

从一个表或视图检索行

SELECT

支持

DML

更新一个表的行

UPDATE

支持

5.2.1. CALL

调用一个过程

语法:

CALL name ( [ argument ] [, ...] )

描述:

CALL执行一个过程。

如果过程有任何输出参数,则会返回一个结果行,返回这些参数的值。

参数:

  • name

    过程的名称(可以被方案限定)。

  • argument

    参数可以包括参数名称,使用语法为 name => value。 这与普通函数调用的工作方式相同。

示例:

CALL do_db_maintenance();

5.2.2. DELETE

删除一个表的行

语法:

[ WITH [ RECURSIVE ] with_query [, ...] ]
DELETE FROM [ ONLY ] table_name [ * ] [ [ AS ] alias ]
        [ USING from_item [, ...] ]
        [ WHERE condition | WHERE CURRENT OF cursor_name ]
        [ ORDER BY expression [ ASC | DESC | USING operator ] [ NULLS { FIRST | LAST } ] [, ...] ]
        [ LIMIT { count | ALL } ]
        [ OFFSET start [ ROW | ROWS ] ]
        [ RETURNING * | output_expression [ [ AS ] output_name ] [, ...] ]

描述:

DELETE从指定表中删除满足 WHERE子句的行。如果WHERE 子句没有出现,效果将会是删除表中的所有行。结果是一个合法的空表。

Tip

TRUNCATE提供移除表中所有行的快速机制。

有两种方式可以使用数据库中其他表中包含的信息来删除一个表的行: 使用子选择或者在USING子句中指定额外的表。 哪种技术更合适取决于特定的环境。

可选的RETURNING子句导致DELETE 基于实际被删除的每一行计算并且返回值。任何使用被删除表列或者 USING中提到的其他表的列的表达式都可以被计算。 RETURNING列表的语法和SELECT的 输出列表语法相同。

要从表中删除行,你必须具有其上的DELETE特权, 以及USING子句中任何表以及其值在condition中被读取的表上的 SELECT特权。

如果指定了 ORDER BY 子句,可以按指定的顺序删除行。 它的语义类似于 SELECT 中的 ORDER BY 子句。 请注意,不支持带有 ORDER BY 子句的继承表删除,也不支持 Canopy。

如果指定了 LIMIT 或 OFFSET 子句,则可以删除行的子集。 它的语义类似于 SELECT 中的 LIMIT 子句。 请注意,不支持带有 LIMIT 或 OFFSET 子句的继承表更新,也不支持 Canopy。

参数:

  • with_query

    WITH子句允许你指定一个或者多个子查询,在 DELETE查询中可以用子查询的名字来引用它们。

  • table_name

    要从其中删除行的表名(可以是模式限定的)。如果在表名前指定 ONLY,只会从提到的表中删除匹配的行。如果没有指定 ONLY,还会删除该表的任何继承表中的匹配行。可选地, 可以在表名后面指定*来显式指定要包括继承表。

  • alias

    目标表的一个别名。提供别名时,它会完全隐藏该表的真实名称。例如, 对于DELETE FROM foo AS f, DELETE语句的剩余部分都会用 f而不是 foo来引用该表。

  • from_item

    一个表的表达式允许在WHERE条件中出现 来自其他表的列。这使用与SELECT语法的 FROM子句相同的语法; 例如,可以指定表名的别名。除非您希望建立自联接(在这种情况下,它必须与 from_item中的别名一起出现),否则不要 将目标表重复为from_item。

  • condition

    一个返回boolean类型值的表达式。只有让这个 表达式返回true的行才将被删除。

  • cursor_name

    要在WHERE CURRENT OF情况中使用的游标 的名称。最近一次从这个游标中取出的行将被删除。该游标 必须是DELETE的目标表上的非分组查询。 注意不能在使用WHERE CURRENT OF的同时 指定一个布尔条件。有关将游标用于 WHERE CURRENT OF的更多信息请见 DECLARE。

  • output_expression

    在每一行被删除后,会被DELETE计算并且返回的表达式。 该表达式可以使用table_name 以及USING中的表的任何列。写成*可以返回所有列。

  • output_name

    被返回列的名称。

示例:

删除所有电影,但音乐剧除外:

DELETE FROM films WHERE kind <> 'Musical';

清空表films:

DELETE FROM films;

删除已完成的任务,返回被删除行的明细:

DELETE FROM tasks WHERE status = 'DONE' RETURNING *;

删除tasks中游标c_tasks 当前位于其上的行:

DELETE FROM tasks WHERE CURRENT OF c_tasks;

删除 citys 表中按 id 排序的前 5 行。

DELETE FROM citys order by id LIMIT 5;

5.2.3. EXPLAIN

显示一个语句的执行计划

语法:

EXPLAIN [ ( option [, ...] ) ] statement
EXPLAIN [ ANALYZE ] [ VERBOSE ] statement

这里 option可以是:

        ANALYZE [ boolean ]
        VERBOSE [ boolean ]
        COSTS [ boolean ]
        SETTINGS [ boolean ]
        BUFFERS [ boolean ]
        WAL [ boolean ]
        TIMING [ boolean ]
        SUMMARY [ boolean ]
        FORMAT { TEXT | XML | JSON | YAML }

描述:

这个命令显示LightDB计划器为提供的语句所生成的执行计划。该执行计划会显示将怎样扫描语句中引用的表 ? 普通的顺序扫描、索引扫描等等 ? 以及在引用多个表时使用何种连接算法来把来自每个输入表的行连接在一起。

显示中最重要的部分是估计出的语句执行代价,它是计划器对于该语句要运行多久的猜测(以任意的代价单位度量,但是习惯上表示取磁盘页面的次数)。事实上会显示两个数字:在第一行能被返回前的启动代价,以及返回所有行的总代价。对于大部分查询来说总代价是最重要的,但是在一些情景中(如EXISTS中的子查询),计划器将选择更小的启动代价来代替最小的总代价(因为执行器将在得到一行后停止)。此外,如果你用一个LIMIT子句限制返回行的数量,计划器会在终端代价之间做出适当的插值来估计到底哪个计划是真正代价最低的。

ANALYZE选项导致该语句被实际执行,而不仅仅是被计划。那么实际的运行时间统计会被显示出来,包括在每个计划结点上花费的总时间(以毫秒计)以及它实际返回的行数。这对观察计划器的估计是否与实际相近很有用。

Important

记住当使用了ANALYZE选项时语句会被实际执行。尽管EXPLAIN将丢弃SELECT所返回的任何输出,照例该语句的其他副作用还是会发生。如果你希望在INSERT、UPDATE、DELETE、CREATE TABLE AS或者EXECUTE上使用EXPLAIN ANALYZE而不希望它们影响你的数据,可以使用下面的方法:

BEGIN;
EXPLAIN ANALYZE ...;
ROLLBACK;

只有ANALYZE和VERBOSE选项能被指定,并且必须按照上述的顺序,不要把选项列表放在圆括号内。在LightDB 9.0 之前,只支持没有圆括号的语法。我们期望所有新的选项将只在圆括号语法中支持。

参数:

  • ANALYZE

    执行命令并且显示实际的运行时间和其他统计信息。这个参数默认被设置为FALSE。

  • VERBOSE

    显示关于计划的额外信息。 特别是:计划树中每个结点的输出列列表、模式限定的表和函数名、总是把表达式中的变量标上它们的范围表别名,以及总是打印统计信息被显示的每个触发器的名称。 如果已经被计算,查询标识符也会被显示,详请参见compute_query_id。 这个参数默认被设置为FALSE。

  • COSTS

    包括每一个计划结点的估计启动和总代价,以及估计的行数和每行的宽度。这个参数默认被设置为TRUE。

  • SETTINGS

    包括有关配置参数的信息。具体来说,包括影响查询计划的选项,其值与内置默认值不同。此参数默认为FALSE。

  • BUFFERS

    包括缓冲区使用的信息。特别是:共享块命中、读取、标记为脏和写入的次数、本地块命中、 读取、标记为脏和写入的次数、临时块读取和写入的次数 以及track_io_timing启用时读取和写入数据文件块所用的 时间(毫秒)。 一次命中表示避免了一次读取,因为需要的块已经在缓存中找 到了。 共享块包含着来自于常规表和索引的数据; 本地块包含着来自于临时表和索引的数据; 而临时块包含着在排序、哈希、物化计划结点和类似情况中使用的短期工作数据。 脏块的数量表示被这个查询改变的之前未被修改块的数量, 而写入块的数量表示这个后台在查询处理期间从缓存中替换出去 的脏块的数量。 为一个较高层结点显示的块数包括它的所有子结点所用到的块数。在文本格 式中,只会打印非零值。它默认为FALSE。

  • WAL

    包括有关WAL记录生成的信息。 具体来说,包括记录数、整页图像数(fpi)和生成的WAL字节数量。 在文本格式中,仅打印非零值。 此参数只能在同时启用ANALYZE时使用。 它默认为FALSE。

  • TIMING

    在输出中包括实际启动时间以及在每个结点中花掉的时间。反复读取系统时钟的负荷在某些系统上会显著地拖慢查询,因此在只需要实际的行计数而不是实际时间时,把这个参数设置为FALSE可能会有用。即便用这个选项关闭结点层的计时,整个语句的运行时间也总是会被度量。只有当ANALYZE也被启用时,这个参数才能使用。它的默认被设置为TRUE。

  • SUMMARY

    在查询计划之后包含摘要信息(例如,总计的时间信息)。当使用ANALYZE 时默认包含摘要信息,但默认情况下不包含摘要信息,但可以使用此选项启用摘要信息。 使用EXPLAIN EXECUTE中的计划时间包括从缓存中获取计划所需的时间 以及重新计划所需的时间(如有必要)。

  • FORMAT

    指定输出格式,可以是 TEXT、XML、JSON 或者 YAML。非文本输出包含和文本输出格式相同的信息,但是更容易被程序解析。这个参数默认被设置为TEXT。

  • boolean

    指定被选中的选项是否应该被打开或关闭。可以写TRUE、ON或1来启用选项,写FALSE、OFF或0禁用它。boolean值也能被忽略,在这种情况下会假定值为TRUE。

  • statement

    你想查看其执行计划的任何SELECT、INSERT、UPDATE、DELETE、VALUES、EXECUTE、DECLARE、CREATE TABLE AS或者CREATE MATERIALIZED VIEW AS语句。

示例:

有一个具有单个integer列和 10000 行的表,要显示在其上的一个简单查询的计划:

EXPLAIN SELECT * FROM foo;

                                        QUERY PLAN
---------------------------------------------------------
Seq Scan on foo  (cost=0.00..155.00 rows=10000 width=4)
(1 row)

这里有同样一个查询的 JSON 输出格式:

EXPLAIN (FORMAT JSON) SELECT * FROM foo;
                QUERY PLAN
--------------------------------
[                             +
{                           +
        "Plan": {                 +
        "Node Type": "Seq Scan",+
        "Relation Name": "foo", +
        "Alias": "foo",         +
        "Startup Cost": 0.00,   +
        "Total Cost": 155.00,   +
        "Plan Rows": 10000,     +
        "Plan Width": 4         +
        }                         +
}                           +
]
(1 row)

如果有一个索引,并且我们使用了一个带有可索引WHERE条件的查询,EXPLAIN可能会显示一个不同的计划:

EXPLAIN SELECT * FROM foo WHERE i = 4;

                                                QUERY PLAN
--------------------------------------------------------------
Index Scan using fi on foo  (cost=0.00..5.98 rows=1 width=4)
Index Cond: (i = 4)
(2 rows)

这里是同一查询的 YAML 格式:

EXPLAIN (FORMAT YAML) SELECT * FROM foo WHERE i='4';
                QUERY PLAN
-------------------------------
- Plan:                      +
        Node Type: "Index Scan"  +
        Scan Direction: "Forward"+
        Index Name: "fi"         +
        Relation Name: "foo"     +
        Alias: "foo"             +
        Startup Cost: 0.00       +
        Total Cost: 5.98         +
        Plan Rows: 1             +
        Plan Width: 4            +
        Index Cond: "(i = 4)"
(1 row)

XML 格式我们留给读者做练习。

这里是去掉了代价估计的同样一个计划:

EXPLAIN (COSTS FALSE) SELECT * FROM foo WHERE i = 4;

                QUERY PLAN
----------------------------
Index Scan using fi on foo
Index Cond: (i = 4)
(2 rows)

这里是一个使用聚集函数的查询的查询计划例子:

EXPLAIN SELECT sum(i) FROM foo WHERE i < 10;

                                                        QUERY PLAN
-------------------------------------------------------------------?--
Aggregate  (cost=23.93..23.93 rows=1 width=4)
->  Index Scan using fi on foo  (cost=0.00..23.92 rows=6 width=4)
                Index Cond: (i < 10)
(3 rows)

这里是一个使用EXPLAIN EXECUTE显示预备查询的执行计划的例子:

PREPARE query(int, int) AS SELECT sum(bar) FROM test
        WHERE id > $1 AND id < $2
        GROUP BY foo;

EXPLAIN ANALYZE EXECUTE query(100, 200);

                                                                                                        QUERY PLAN
-------------------------------------------------------------------?-----------------------------------------------------
HashAggregate  (cost=9.54..9.54 rows=1 width=8) (actual time=0.156..0.161 rows=11 loops=1)
Group Key: foo
->  Index Scan using test_pkey on test  (cost=0.29..9.29 rows=50 width=8) (actual time=0.039..0.091 rows=99 loops=1)
                Index Cond: ((id > $1) AND (id < $2))
Planning time: 0.197 ms
Execution time: 0.225 ms
(6 rows)

当然,这里显示的有关数字取决于表涉及到的实际内容。还要注意这些数字甚至选中的查询策略,可能在LightDB的不同版本之间变化,因为计划器可能被改进。此外,ANALYZE命令使用随机采样来估计数据统计。因此,在一次新的ANALYZE运行之后,代价估计可能会改变,即便是表中数据的实际分布没有改变也是如此。

5.2.4. INSERT

在一个表中创建新行

语法:

[ WITH [ RECURSIVE ] with_query [, ...] ]
INSERT [IGNORE] INTO table_name [ AS alias ] [ ( column_name [, ...] ) ]
        [ OVERRIDING { SYSTEM | USER } VALUE ]
        { DEFAULT VALUES | VALUES ( { expression | DEFAULT } [, ...] ) [, ...] | query }
        [ ON CONFLICT [ conflict_target ] conflict_action | ON DUPLICATE KEY UPDATE { column_name = { expression | DEFAULT } } [, ...] ]
        [ RETURNING * | output_expression [ [ AS ] output_name ] [, ...] ]

其中 conflict_target 可以是以下之一:

        ( { index_column_name | ( index_expression ) } [ COLLATE collation ] [ opclass ] [, ...] ) [ WHERE index_predicate ]
        ON CONSTRAINT constraint_name

并且 conflict_action 是以下之一:

        DO NOTHING
        DO UPDATE SET { column_name = { expression | DEFAULT } |
                                        ( column_name [, ...] ) = [ ROW ] ( { expression | DEFAULT } [, ...] ) |
                                        ( column_name [, ...] ) = ( sub-SELECT )
                                } [, ...]
                        [ WHERE condition ]

INSERT ALL insert_into_clause [values_clause]  query
| INSERT ALL conditional_insert_clause query

where insert_into_clause can be list of:
        INTO table_name [ ( column_name [, ...] ) ]

and values_clause is:
VALUES(, ...)

and conditional_insert_clause is one of:
WHEN condition THEN insert_into_clause [values_clause]
ELSE insert_into_clause [values_clause]

描述:

INSERT将新行插入到一个表中。我们可以 插入一个或者更多由值表达式指定的行,或者插入来自一个查询的零行 或者更多行。

目标列的名称可以以任意顺序列出。如果没有给出列名列表,则有两种确定 目标列的可能性。第一种是以被声明的顺序列出该表的所有列。另一种可能 性是,如果VALUES 子句或者query只提 供N个列,则以被声明的顺序列出该表的前 N列。VALUES 子句或者 query提供的值会被从左至右关联到这些显式或者隐式 给出的目标列。

每一个没有出现在显式或者隐式列列表中的列都将被默认填充,如果为该列 声明过默认值则用默认值填充,否则用空值填充。

如果任意列的表达式不是正确的数据类型,将会尝试自动类型转换。

如果表缺少唯一索引,则并发操作不会阻塞对表的 INSERT 操作。 对于具有唯一索引的表,如果并发会话执行锁定或修改与插入的唯一索引值匹配的行的操作,则可能会被阻塞; 可以使用 ON CONFLICT 指定替代操作以避免唯一约束或排除约束违规错误。 (请参见下文的 ON CONFLICT Clause。)

可选的RETURNING子句让INSERT根据 实际被插入(如果使用了ON CONFLICT DO UPDATE子句, 可能是被更新)的每一行来计算和返回值。这主要用来获取由默认值提供 的值,例如一个序列号。不过,允许在其中包括使用该表列的任何表达式。 RETURNING列表的语法与SELECT的输出 列表的相同。只有被成功地插入或者更新的行才将被返回。例如,如果一 行被锁定但由于不满足ON CONFLICT DO UPDATE … WHERE clause condition没有被更新,该行将 不被返回。

为了向表中插入,你必须具有其上的INSERT特权。 如果存在ON CONFLICT DO UPDATE子句,还要求该表上 的UPDATE特权。

如果一个列列表被指定,你只需要其中的列上的INSERT 特权。类似地,在指定了ON CONFLICT DO UPDATE时,你只 需要被列出要更新的列上的UPDATE特权。不过, ON CONFLICT DO UPDATE还要求其值被 ON CONFLICT DO UPDATE表达式或者 condition使用的列上的SELECT特权。

使用RETURNING子句需要RETURNING中提到的所有列的 SELECT权限。 如果使用query子句从查询中插入行, 则当然需要对查询中使用的任何表或列具有SELECT权限。

要对多表进行插入, 你可以使用 INSERT ALL 语句。 在一个多表插入中,将把根据子查询返回的行派生出的计算行插入到一个或多个表中。

参数:

插入

这个小节介绍了在只插入新行时可以使用的参数。 专门用于ON CONFLICT子句的 参数会单独介绍。

  • with_query

    WITH子句允许指定一个或者更多子查询,在 INSERT查询中可以用名称引用这些子查询。

    query (SELECT语句)也可以包含一个 WITH子句。在这种情况下 query中可以引用 两组with_query,但是第二个优先级更 高(因为它被嵌套更近)。

  • ignore

    关键字 ignore 为兼容 MySQL 语法添加 。使用 ignore 时,在当前的实现中,违反唯一性约束的插入行将产生一个警告,而不是错误。 若要使用关键字 ignore,必须设置为MySQL兼容模式。

  • table_name

    一个已有表的名称(可以被模式限定)。

  • alias

    table_name 的替补名称。当提供了一个别名时,它会完全隐藏掉表的实际名称。 当ON CONFLICT DO UPDATE的目标是一个被排除的表时这特别有用,因为那将被当作表示要被插入行的特殊表的名称。

  • column_name

    名为table_name的表中的一个列 的名称。如有必要,列名可以用一个子域名或者数组下标限定(指向 一个组合列的某些列中插入会让其他域为空)。当用 ON CONFLICT DO UPDATE引用一列时,不要在一个 目标列的说明中国包括表名。例如, INSERT INTO table_name … ON CONFLICT DO UPDATE SET table_name.col = 1是非法的(这遵循UPDATE 的一般行为)。

  • OVERRIDING SYSTEM VALUE

    如果指定了此子句,那么为标识列提供的任何值都将覆盖默认的序列生成的值。

    对于定义为GENERATED ALWAYS的标识列,插入显式值(DEFAULT及部分情况下NULL除外)而不指定 OVERRIDING SYSTEM VALUE或OVERRIDING USER VALUE是错误的。(对于定义 为GENERATED BY DEFAULT的标识列,OVERRIDING SYSTEM VALUE是正常行为, 并指定其不执行任何操作,但是LightDB允许它作为扩展名。)

  • OVERRIDING USER VALUE

    如果指定了此子句,则将忽略为标识列提供的任何值,并应用默认的序列生成的值。

    例如,当在表之间拷贝值时,这个子句有能派上用场。INSERT INTO tbl2 OVERRIDING USER VALUE SELECT * FROM tbl1将从tbl1中拷贝所有在tbl2中不是标识列的列,而tbl2中标识列的值将由与tbl2关联的序列产生。

  • DEFAULT VALUES

    所有列都将被其默认值填充,就像为每个列显式指定了DEFAULT。 (例如这种形式下不允许OVERRIDING子句)。

  • expression

    要赋予给相应列的表达式或者值。

  • DEFAULT

    相应的列将填充其默认值。标识列将由关联序列生成的新值填充。对于生成的列,允许指定该值,但仅指定根据其生成表达式计算该列的正常行为。

  • NULL

    相应的列将填充空值。但是如果该列包含自增序列,它将插入由该序列所生成的默认值并遵循前述DEFAULT的规则。

  • query

    提供要被插入行的查询(SELECT语句)。 其语法描述请参考SELECT语句。

  • output_expression

    在每一行被插入或更新后由INSERT命令计算并且返回的 表达式。该表达式可以使用table_name 指定的表中的任何列。写成*可返回被插入或更新行的所有列。

  • output_name

    要用于被返回列的名称。

  • conditional_insert_clause

    通过指定 conditional_insert_clause 来进行带条件的多表插入。 LightDB 通过相应的 WHEN 条件对每个 insert_into_clause 进行过滤, 该条件决定是否执行对应的 insert_into_clause。

ON CONFLICT 子句

可选的ON CONFLICT子句为出现唯一性违背或排除 约束违背错误时提供另一种可供选择的动作。对于每一个要插入的行, 不管是插入进行下去还是由conflict_target 指定的一个仲裁者约束或者索引被违背,都会 采取可供选择的conflict_action。 ON CONFLICT DO NOTHING简单地把避免插入行。 ON CONFLICT DO UPDATE则会 更新与要插入的行冲突的已有行。

conflict_target可以执行 唯一索引推断。在执行推断时,它由一个或者多个 index_column_name 列或者 index_expression 表达式以及一个可选的 index_predicate构成。所有刚好包含 conflict_target指定的列/表达式的table_name唯一索引(不管顺序)都 会被推断为(选择为)仲裁者索引。如果指定了 index_predicate,它 必须满足仲裁者索引(也是推断过程的一个进一步的要求)。注意这意味着如果 有一个满足其他条件的非部分唯一索引(没有谓词的唯一索引)可用,它将被 推断为仲裁者(并且会被ON CONFLICT使用)。如果推断 尝试不成功,则会发生一个错误。

ON CONFLICT DO UPDATE保证一个原子的 INSERT或者 UPDATE结果。在没有无关错误的前提下,这两种 结果之一可以得到保证,即使在很高的并发度也能保证。这也可以被称作 UPSERT ? “UPDATE 或 INSERT”。

  • conflict_target

    通过选择仲裁者索引来指定哪些行与 ON CONFLICT在其上采取可替代动作的行相冲突。 要么执行唯一索引推断,要么显式命名一个 约束。对于ON CONFLICT DO NOTHING来说, 它对于指定一个conflict_target是可选的。 在被省略时,与所有有效约束(以及唯一索引)的冲突都会被处理。对于 ON CONFLICT DO UPDATE,必须 提供一个conflict_target。

  • conflict_action

    conflict_action指定一个可替换的 ON CONFLICT动作。它可以是 DO NOTHING,也可以是一个指定在冲突情况下 要被执行的UPDATE动作细节的DO UPDATE子句。ON CONFLICT DO UPDATE中的SET和 WHERE子句能够使用该表的名称(或者别名) 访问现有的行,并且可以用特殊的被排除 表访问要插入的行。这个动作要求被排除 列所在目标表的任何列上的SELECT特权。

    注意所有行级BEFORE INSERT触发器的效果都会 反映在被排除值中,因为那些效果可能会 让该行避免被插入。

  • index_column_name

    一个table_name列 的名称。它被用来推断仲裁者索引。它遵循CREATE INDEX格式。这要求 index_column_name 上的SELECT特权。

  • index_expression

    和index_column_name类似,但是 被用来推断出现在索引定义中的table_name列(非简单列)上的 表达式。遵循CREATE INDEX格式。这要求 任何出现在index_expression中的列上的 SELECT特权。

  • collation

    指定时,强制相应的index_column_name或 index_expression 使用一种特定的排序规则以便在推断期间能被匹配上。通常 会被省略,因为排序规则通常不会影响约束违背的发生。遵循 CREATE INDEX格式。

  • opclass

    指定时,强制相应的index_column_name或 index_expression 使用特定的操作符类以便在推断期间能被匹配上。通常会被省略, 因为相等语义在一种类型的操作符类 之间都是等价的,或者因为足以信任已定义的唯一索引具有适当的 相等定义。遵循CREATE INDEX格式。

  • index_predicate

    用于允许推断部分唯一索引。任何满足该谓词(不一定需要真的是 部分索引)的索引都能被推断。遵循CREATE INDEX格式。这要求任何出现在index_predicate中的列上 的SELECT特权。

  • constraint_name

    用名称显式地指定一个仲裁者约束, 而不是推断一个约束或者索引。

  • condition

    一个能返回boolean值的表达式。只有让这个表达式返回 true的行才将被更新,不过在采用 ON CONFLICT DO UPDATE动作时所有的行都会被锁定。 注意condition会被最后计算,即一个冲突 被标识为要更新的候选对象之后。

    注意不支持把排除约束作为ON CONFLICT DO UPDATE的 仲裁者。在所有的情况中,只支持NOT DEFERRABLE约束和 唯一索引作为仲裁者。

    带有ON CONFLICT DO UPDATE子句的 INSERT是一种“确定性的” 语句。这表明不允许该命令影响任何单个现有行超过一次,如果发生则会 发生一个基数违背错误。要插入的行不应该在仲裁者索引或约束所限制的 属性上相重复。

    注意,当前不支持用分区表上的INSERT的ON CONFLICT DO UPDATE子句更新冲突行的分区键,因为那样会让行移动到新的分区中。

    Tip

    使用唯一索引推断通常比使用ON CONFLICT ON CONSTRAINT constraint_name直接提名一个约束更好。当底层索引被以重叠方式替换成另一个或多或少等效的索引时,推断将能继续正确地工作,例如在删除要被替换的索引之前使用CREATE UNIQUE INDEX … CONCURRENTLY。

ON DUPLICATE KEY UPDATE 子句

如果您指定了一个 ON DUPLICATE KEY UPDATE 子句,并且要插入的行会导致主键中出现重复值, 则会更新旧的行。例如,如果列 a 被声明为 PRIMARY KEY 并包含值 1,则以下两个语句具有类似的效果:

INSERT INTO t1 (a,b,c) VALUES (1,2,3) ON DUPLICATE KEY UPDATE c=t1.c+1;

UPDATE t1 SET c=c+1 WHERE a=1;

在 ON DUPLICATE KEY UPDATE 子句中的赋值值表达式中, 您可以使用 VALUES(col_name) 函数来引用 INSERT … ON DUPLICATE KEY UPDATE 语句的 INSERT 部分中的列值, 而不是使用 excluded 表。 换句话说,在 ON DUPLICATE KEY UPDATE 子句中,VALUES(col_name) 指的是如果没有重复键冲突将要插入的 col_name 的值。 此函数在多行插入中特别有用。 VALUES() 函数仅受支持在 ON DUPLICATE KEY UPDATE 子句或 INSERT 语句中。

示例:

向films中插入一行:

INSERT INTO films VALUES
        ('UA502', 'Bananas', 105, '1971-07-13', 'Comedy', '82 minutes');

在这个例子中,len列被省略并且因此会具有默认值:

INSERT INTO films (code, title, did, date_prod, kind)
        VALUES ('T_601', 'Yojimbo', 106, '1961-06-16', 'Drama');

这个例子为日期列使用DEFAULT子句而不是指定一个值:

INSERT INTO films VALUES
        ('UA502', 'Bananas', 105, DEFAULT, 'Comedy', '82 minutes');
INSERT INTO films (code, title, did, date_prod, kind)
        VALUES ('T_601', 'Yojimbo', 106, DEFAULT, 'Drama');

插入一个完全由默认值构成的行:

INSERT INTO films DEFAULT VALUES;

用多行VALUES语法插入多个行:

INSERT INTO films (code, title, did, date_prod, kind) VALUES
        ('B6717', 'Tampopo', 110, '1985-02-10', 'Comedy'),
        ('HG120', 'The Dinner Game', 140, DEFAULT, 'Comedy');

这个例子从表tmp_films中获得一些行插入到表 films中,两个表具有相同的列布局:

INSERT INTO films SELECT * FROM tmp_films WHERE date_prod < '2004-05-07';

这个例子插入数组列:

– 为 noughts-and-crosses 游戏创建一个空的 3x3 棋盘

INSERT INTO tictactoe (game, board[1:3][1:3])
        VALUES (1, '{{" "," "," "},{" "," "," "},{" "," "," "}}');

– 实际上可以不用上面例子中的下标

INSERT INTO tictactoe (game, board)
        VALUES (2, '{{X," "," "},{" ",O," "},{" ",X," "}}');

向表distributors中插入一行,返回由 DEFAULT子句生成的序号:

INSERT INTO distributors (did, dname) VALUES (DEFAULT, 'XYZ Widgets')
RETURNING did;

增加为 Acme Corporation 管理账户的销售人员的销量,并且把整个被 更新的行以及当前时间记录到一个日志表中:

WITH upd AS (
UPDATE employees SET sales_count = sales_count + 1 WHERE id =
        (SELECT sales_person FROM accounts WHERE name = 'Acme Corporation')
        RETURNING *
)
INSERT INTO employees_log SELECT *, current_timestamp FROM upd;

酌情插入或者更新新的 distributor。假设已经定义了一个唯一索引来约束 出现在did列中的值。注意,特殊的 excluded表被用来引用原来要插入的值:

INSERT INTO distributors (did, dname)
        VALUES (5, 'Gizmo Transglobal'), (6, 'Associated Computing, Inc')
        ON CONFLICT (did) DO UPDATE SET dname = EXCLUDED.dname;

插入一个 distributor,或者在一个被排除的行(具有一个匹配约束的列或者 会让行级前(或者后)插入触发器引发的列的行)存在时不处理要插入的行。 例子假设已经定义了一个唯一触发器来约束出现在did列 中的值:

INSERT INTO distributors (did, dname) VALUES (7, 'Redline GmbH')
        ON CONFLICT (did) DO NOTHING;

酌情插入或者更新新的 distributor。例子假设已经定义了一个唯一触发器来 约束出现在did列中的值。WHERE子句被用 来限制实际被更新的行(不过,任何没有被更新的已有行仍将被锁定):

– 根据一个特定的 ZIP 编码更新 distributors

INSERT INTO distributors AS d (did, dname) VALUES (8, 'Anvil Distribution')
        ON CONFLICT (did) DO UPDATE
        SET dname = EXCLUDED.dname || ' (formerly ' || d.dname || ')'
        WHERE d.zipcode <> '21201';

– 直接在语句中命名一个约束(使用相关的索引来判断是否做 – DO NOTHING 动作)

INSERT INTO distributors (did, dname) VALUES (9, 'Antwerp Design')
        ON CONFLICT ON CONSTRAINT distributors_pkey DO NOTHING;

如果可能就插入新的 distributor,否则DO NOTHING。 例子假设已经定义了一个唯一索引,它约束让is_active 布尔列为true的行子集上did列中的值:

– 这个语句可能推断出一个在 “did” 上带有谓词 “WHERE is_active” – 的部分唯一索引,但是它可能也只是使用了 “did” 上的一个常规唯一约束

INSERT INTO distributors (did, dname) VALUES (10, 'Conrad International')
        ON CONFLICT (did) WHERE is_active DO NOTHING;

考虑以下 CREATE TABLE 语句创建的表,然后运行 ltsql 客户端中显示的语句,结果如下所示:

CREATE TABLE test (
id INT NOT NULL,
name CHAR(16),
age INT DEFAULT 0,
PRIMARY KEY(id)
);

lightdb@testdb=# INSERT INTO test VALUES (1, 'Old name', '18');
INSERT 0 1

lightdb@testdb=# INSERT INTO test VALUES (2, 'Old name', '19') ON DUPLICATE KEY UPDATE name = 'New name';
INSERT 0 1

lightdb@testdb=# SELECT * FROM test;
id |       name       | age
----+------------------+-----
1 | Old name         |  18
2 | Old name         |  19
(2 rows)

lightdb@testdb=# INSERT INTO test VALUES (2, 'Old name', '20') ON DUPLICATE KEY UPDATE name = 'New name', age = test.age + 5;
INSERT 0 1

lightdb@testdb=# SELECT * FROM test;
id |       name       | age
----+------------------+-----
1 | Old name         |  18
2 | New name         |  24
(2 rows)

lightdb@testdb=# INSERT INTO test VALUES (2, 'Old name', '20') ON DUPLICATE KEY UPDATE name = 'New name', age = excluded.age;
INSERT 0 1

lightdb@testdb=# SELECT * FROM test;
id |       name       | age
----+------------------+-----
1 | Old name         |  18
2 | New name         |  20
(2 rows)

lightdb@testdb=# INSERT INTO test VALUES (2, 'Old name', '20') ON DUPLICATE KEY UPDATE name = VALUES(name), age = VALUES(age);
INSERT 0 1

lightdb@testdb=# SELECT * FROM test;
id |       name       | age
----+------------------+-----
1 | Old name         |  18
2 | Old name         |  20
(2 rows)

lightdb@testdb=# INSERT INTO test VALUES (2, 'New name', '29') ON DUPLICATE KEY UPDATE name = name, age = VALUES(age);
INSERT 0 1

lightdb@testdb=# SELECT * FROM test;
id |       name       | age
----+------------------+-----
1 | Old name         |  18
2 | Old name         |  29
(2 rows)

可以通过使用 insert all 语句去对多个表进行插入, 同时也支持通过条件来进行插入,案例如下:

CREATE TABLE T1(a int , b text);
CREATE TABLE T1_1(a int , b text);
CREATE TABLE T1_2(a int , b text);

-- 多表插入
INSERT ALL INTO T1_1 VALUES(1,1) INTO T1_2 VALUES(2,2) SELECT * FROM DUAL;
INSERT ALL INTO T1_1 VALUES(a,b) INTO T1_2 VALUES(a%100, b) SELECT * FROM T1;
-- 带条件的多表插入
INSERT ALL WHEN a > 2 THEN INTO T1_1 ELSE INTO T1_2 SELECT * FROM T1;

一次性插入多条记录到一个或多个表中

INSERT ALL
        INTO table_name (column1, column2, column3) VALUES (value1, value2, value3)
        INTO table_name (column1, column2, column3) VALUES (value1, value2, value3)
SELECT 1 FROM DUAL;

使用别名来指定要插入数据的表

INSERT INTO employees e (employee_id, first_name, last_name)
VALUES (1001, 'John', 'Doe');

5.2.5. SELECT

从一个表或视图检索行

语法:

[ WITH [ RECURSIVE ] with_query [, ...] ]
SELECT [ ALL | DISTINCT [ ON ( expression [, ...] ) ] ]
        [ * | expression [ [ AS ] output_name ] [, ...] ]
        [ FROM from_item [, ...] ]
        [ { USE | IGNORE | FORCE } { INDEX | KEY } [ FOR { JOIN | ORDER BY | GROUP BY } ] (index_list) ]
        [ WHERE condition ]
        [ START WITH start_expression ]
        [ CONNECT BY { PRIOR parent_expr = child_expr | child_expr = PRIOR parent_expr} ]
        [ GROUP BY grouping_element [, ...] ]
        [ HAVING condition ]
        [ WINDOW window_name AS ( window_definition ) [, ...] ]
        [ { UNION | INTERSECT | EXCEPT | MINUS } [ ALL | DISTINCT ] select ]
        [ ORDER BY expression [ ASC | DESC | USING operator ] [ NULLS { FIRST | LAST } ] [, ...] ]
        [ LIMIT { count | ALL } ]
        [ OFFSET start [ ROW | ROWS ] ]
        [ FETCH { FIRST | NEXT } [ count ] { ROW | ROWS } { ONLY | WITH TIES } ]
        [ FOR { UPDATE | NO KEY UPDATE | SHARE | KEY SHARE } [ OF table_name [, ...] ] [ NOWAIT | SKIP LOCKED ] [...] ]

其中 from_item 可以是以下之一:

        [ ONLY ] table_name [ * ] [ [ AS ] alias [ ( column_alias [, ...] ) ] ]
                                [ TABLESAMPLE sampling_method ( argument [, ...] ) [ REPEATABLE ( seed ) ] ]
        [ LATERAL ] ( select ) [ AS ] alias [ ( column_alias [, ...] ) ]
        with_query_name [ [ AS ] alias [ ( column_alias [, ...] ) ] ]
        [ LATERAL ] function_name ( [ argument [, ...] ] )
                                [ WITH ORDINALITY ] [ [ AS ] alias [ ( column_alias [, ...] ) ] ]
        [ LATERAL ] function_name ( [ argument [, ...] ] ) [ AS ] alias ( column_definition [, ...] )
        [ LATERAL ] function_name ( [ argument [, ...] ] ) AS ( column_definition [, ...] )
        [ LATERAL ] ROWS FROM( function_name ( [ argument [, ...] ] ) [ AS ( column_definition [, ...] ) ] [, ...] )
                                [ WITH ORDINALITY ] [ [ AS ] alias [ ( column_alias [, ...] ) ] ]
        from_item [ NATURAL ] join_type from_item [ ON join_condition | USING ( join_column [, ...] ) ]

并且 grouping_element 可以是以下之一:

        ( )
        expression
        ( expression [, ...] )
        ROLLUP ( { expression | ( expression [, ...] ) } [, ...] )
        CUBE ( { expression | ( expression [, ...] ) } [, ...] )
        GROUPING SETS ( grouping_element [, ...] )

并且 with_query 是:

        with_query_name [ ( column_name [, ...] ) ] AS [ [ NOT ] MATERIALIZED ] ( select | values | insert | update | delete )

TABLE [ ONLY ] table_name [ * ]

描述:

SELECT从零或更多表中检索行。 SELECT的通常处理如下:

  • WITH列表中的所有查询都会被计算。这些查询实际 充当了在FROM列表中可以引用的临时表。在 FROM中被引用多次的WITH查 询只会被计算一次,除非另有说明,否则NOT MATERIALIZED。 (见下文的WITH Clause)。

  • FROM列表中的所有元素都会被计算( FROM中的每一个元素都是一个真实表或者虚拟表)。 如果在FROM列表中指定了多于一个元素,它们会被 交叉连接在一起(见下文的 FROM Clause)。

  • 如果指定了WHERE子句,所有不满足该条件的行都会 被从输出中消除(见下文的WHERE Clause)。

  • 如果指定了 WHERE 子句,则不满足条件的所有行都将从输出中删除。(请参见下面的 WHERE Clause。)

  • 通过在条件中使用 ‘(+)’, 你可以像 Oracle 一样指定外连接. (See oracle plus below.)

  • 如果指定了CONNECT BY子句,则可以按层次顺序选择行。(请参见下面的CONNECT BY Clause。) 对于由分层查询返回的每一行,LEVEL伪列对于根行返回1,对于根的子项返回2,依此类推。 SYS_CONNECT_BY_PATH仅在分层查询中有效。对于由CONNECT BY条件返回的每一行,SYS_CONNECT_BY_PATH(column, char)使用char分隔的column值。CONNECT_BY_ ROOT是一种仅在分层查询中有效的一元运算符。当使用此运算符对列进行限定时,它会返回使用根行数据的列值。CONNECT BY LEVEL < n 显示 n 级以下的所有递归结果。 CONNECT_BY_ISLEAF 是一个伪列,通常与递归查询(使用 CONNECT BY 子句)一起使用。它的作用是标识在递归查询的上下文中,当前行是否为叶子节点(没有子节点)。CONNECT_BY_ISLEAF 列返回一个布尔值,如果当前行没有子节点,则返回 1(表示是叶子节点),否则返回 0(表示不是叶子节点)。

  • 如果指定了GROUP BY子句或者如果有聚集函数,输出 会被组合成由在一个或者多个值上匹配的行构成的分组,并且在其上计算聚 集函数的结果。如果出现了HAVING子句,它会消除不 满足给定条件的分组(见下文的 GROUP BY Clause以及 HAVING Clause)。

  • 对于每一个被选中的行或者行组,会使用SELECT 输出表达式计算实际的输出行(见下文的 SELECT List)。

  • SELECT DISTINCT从结果中消除重复的行。 SELECT DISTINCT ON消除在所有指定表达式上匹 配的行。SELECT ALL(默认)将返回所有候选行, 包括重复的行(见下文的DISTINCT Clause)。

  • 通过使用操作符UNION、 INTERSECT和EXCEPT,多于 一个SELECT语句的输出可以被整合形成 一个结果集。UNION操作符返回位于一个或者两 个结果集中的全部行。INTERSECT操作符返回同时 位于两个结果集中的所有行。EXCEPT操作符返回 位于第一个结果集但不在第二个结果集中的行。在所有三种情况下, 重复行都会被消除(除非指定ALL)。可以增加噪 声词DISTINCT来显式地消除重复行。注意虽然 ALL是SELECT自身的默认行为, 但这里DISTINCT是默认行为(见下文的 UNION Clause、INTERSECT Clause以及 EXCEPT Clause)。

  • 如果指定了ORDER BY子句,被返回的行会以指定的 顺序排序。如果没有给定ORDER BY,系统会以能最 快产生行的顺序返回它们(见下文的 ORDER BY Clause)。

  • 如果指定了LIMIT(或FETCH FIRST) 或者OFFSET子句,SELECT 语句只返回结果行的一个子集(见下文的LIMIT Clause)。

  • 如果指定了FOR UPDATE、 FOR NO KEY UPDATE、 FOR SHARE 或者FOR KEY SHARE, SELECT语句会把被选中的行锁定而不让并发 更新访问它们(见下文的The Locking Clause)。

你必须拥有在一个SELECT命令中使用的每一列上的 SELECT特权。FOR NO KEY UPDATE、 FOR UPDATE、 FOR SHARE或者FOR KEY SHARE 还要求(对这样选中的每一个表至少一列的)UPDATE 特权。

参数:

WITH 子句

WITH子句允许你指定一个或者多个在主查询中可以 其名称引用的子查询。在主查询期间子查询实际扮演了临时表或者视图 的角色。每一个子查询都可以是一个SELECT、 TABLE、VALUES、 INSERT、 UPDATE或者 DELETE语句。在WITH中书写 一个数据修改语句(INSERT、 UPDATE或者 DELETE)时,通常要包括一个 RETURNING子句。构成被主查询读取的临时表的是 RETURNING的输出,而不是该语句修改的 底层表。如果省略RETURNING,该语句仍会被执行,但是它 不会产生输出,因此它不能作为一个表从主查询引用。

对于每一个WITH查询,都必须指定一个名称(无需模 式限定)。可选地,可以指定一个列名列表。如果省略该列表,会从该子查 询中推导列名。

如果指定了RECURSIVE,则允许一个 SELECT子查询使用名称引用自身。 这样一个子查询的形式必须是

non_recursive_term UNION [ ALL | DISTINCT ] recursive_term

其中递归自引用必须出现在UNION的右手边。每个 查询中只允许一个递归自引用。不支持递归数据修改语句,但是 可以在一个数据查询语句中使用一个递归 SELECT查询的结果。

RECURSIVE的另一个效果是 WITH查询不需要被排序:一个查询可以引用另一个 在列表中比它靠后的查询(不过,循环引用或者互递归没有实现)。 如果没有RECURSIVE,WITH 查询只能引用在WITH列表中位置更前面的兄弟 WITH查询。

当WITH子句中有多个查询时,RECURSIVE应只编写一次,紧跟在WITH之后。 它适用于WITH子句中的所有查询,尽管它对不使用递归或前向引用的查询没有影响。

主查询和 WITH 查询都(概念上)同时执行。 这意味着 WITH 中的修改数据语句的影响不能从查询的其他部分看到, 除非读取其 RETURNING 输出。 如果两个这样的修改数据语句尝试修改同一行,则结果是未指定的。

WITH 查询的一个关键特性是,它们通常只在主查询的每次执行中被评估一次,即使主查询多次引用它们。 特别是,修改数据语句保证只执行一次,无论主查询是否读取它们的所有或任何输出。

但是,WITH查询可以标记为NOT MATERIALIZED以移除此保证。 在这种情况下,WITH查询可以折叠到主查询中,就好像它是主查询的FROM子句中的简单的sub-SELECT。 如果主查询多次引用WITH查询,则会导致重复计算;但是,如果每次此类使用只需要WITH查询的总输出中的几行,NOT MATERIALIZED可以通过允许查询联合优化来节省开销。 NOT MATERIALIZED被忽略,如果它被附加到一个递归的WITH查询,或者不是边际效应无关的(也就是说,不是包含非易失性函数的普通的SELECT)。

默认情况下,如果查询在主查询的FROM子句中仅一次使用,则边际效应无关的WITH查询将折叠到主查询中。 这允许在语义不可见的情况下两个查询级别的联合优化。 但是,通过将WITH查询标记为MATERIALIZED,可以防止此类折叠。 这可能很有用,例如,如果WITH查询被用作优化围栏,以防止规划者选择错误计划。 LightDBv12版本之前没有做过这样的折叠,所以为旧版本编写的查询可能依赖于WITH作为优化围栏。

FROM 子句

FROM子句为SELECT 指定一个或者更多源表。如果指定了多个源表,结果将是所有源表的 笛卡尔积(交叉连接)。但是通常会增加限定条件(通过 WHERE)来把返回的行限制为该笛卡尔积的一个小子集。

FROM子句可以包含下列元素:

  • table_name

    一个现有表或视图的名称(可以是模式限定的)。如果在表名前指定了 ONLY,则只会扫描该表。如果没有指定 ONLY,该表及其所有后代表(如果有)都会被扫描。可 选地,可以在表名后指定*来显式地指示包括后代表。

  • alias

一个包含别名的FROM项的替代名称。别名被用于 让书写简洁或者消除自连接中的混淆(其中同一个表会被扫描多 次)。当提供一个别名时,表或者函数的实际名称会被隐藏。例 如,给定FROM foo AS f, SELECT的剩余部分就必须以 f而不是foo来引用这个 FROM项。如果写了一个别名,还可以写一个列别 名列表来为该表的一个或者多个列提供替代名称。

  • TABLESAMPLE sampling_method ( argument [, …] ) [ REPEATABLE ( seed ) ]

    table_name之后的 TABLESAMPLE子句表示应该用指定的 sampling_method 来检索表中行的子集。这种采样优先于任何其他过滤器(例如 WHERE子句)。标准 LightDB发布包括两种采样 方法:BERNOULLI和SYSTEM, 其他采样方法可以通过扩展安装在数据库中。

    BERNOULLI以及SYSTEM采样方法都接受 一个参数,它表示要采样的表 的分数,表示为一个 0 到 100 之间的百分数。这个参数可以是任意的 实数值表达式(其他的采样方法可能接受更多或者不同的 参数)。这两种方法都返回一个随机选取的该表采样,其中包含了指定 百分数的表行。BERNOULLI方法扫描整个表并且 用指定的几率选择或者忽略行。SYSTEM方法会做 块层的采样,每个块都有指定的机会能被选中,被选中块中的所有行都 会被返回。在指定较小的采样百分数时,SYSTEM 方法要比BERNOULLI方法快很多,但是前者可能 由于聚簇效应返回随机性较差的表采样。

    可选的REPEATABLE子句指定一个用于产生采样方法中随机数的种子数或表达式。种子值可以是任何非空浮点值。如果查询时表没有被更改,指定相同种子和argument值的两个查询将会选择该表相同的采样。但是不同的种子值通常将会产生不同的采样。如果没有给出REPEATABLE,则会基于一个系统产生的种子为每一个查询选择一个新的随机采样。注意有些扩展采样方法不接受REPEATABLE,并且将总是为每一次使用产生新的采样。

  • select

    一个子-SELECT可以出现在FROM子句中。 这就好像把它的输出创建为一个存在于该SELECT命令期间的临时表。 注意子-SELECT必须用圆括号包围,并且必须为它提供一个别名。 也可以在这里使用一个VALUES command命令。

  • with_query_name

    可以通过写一个WITH查询的名称来引用它,就好像 该查询的名称是一个表名(实际上,该WITH查询会 为主查询隐藏任何具有相同名称的真实表。如果必要,你可以使用 带模式限定的方式以相同的名称来引用真实表)。可以像表一样, 以同样的方式提供一个别名。

  • function_name

    函数调用可以出现在FROM子句中(对于返回结果集合的函数特别有用,但是可以使用任何函数)。 这就好像把该函数的输出创建为一个存在于该SELECT命令期间的临时表。 如果函数的结果类型是合成的(包括函数有多个OUT参数的情况),在隐式表中每个属性成为单独的列。

    当为该函数调用增加可选的WITH ORDINALITY子句时,会在该函数的结果列之后附加一个 bigint类型的列。 这个列的编号函数的结果集的行,从1开始。 默认的,这个列被命名为ordinality。

    可以用和表一样的方式提供一个别名。 如果写了一个别名,还可以写一个列别名列表来为该函数的组合返回类型的一个或者多个属性提供替代名称,如果有的话包括ordinality列。

    通过把多个函数调用包围在ROWS FROM( … )中可以把它们 整合在单个FROM-子句项中。这样一个项的输出是把每一个 函数的第一行串接起来,然后是每个函数的第二行,以此类推。如果有些 函数产生的行比其他函数少,则在缺失数据的地方放上空值,这样被返回 的总行数总是和产生最多行的函数一样。

    如果函数被定义为返回record数据类型,那么必须出现一个 别名或者关键词AS,后面跟上形为 ( column_name data_type [, … ])的列定义列表。列定义列表必须匹配该函数返回的列的实际 数量和类型。

    在使用ROWS FROM( … )语法时,如果函数之一要求一个列 定义列表,最好把该列定义列表放在ROWS FROM( … )中该 函数的调用之后。当且仅当正好只有一个函数并且没有 WITH ORDINALITY子句时,才能把列定义列表放在 ROWS FROM( … )结构后面。

    要把ORDINALITY和列定义列表一起使用,你必须使用 ROWS FROM( … )语法,并且把列定义列表放在 ROWS FROM( … )里面。

  • join_type

    • One of

      • [ INNER ] JOIN

      • LEFT [ OUTER ] JOIN

      • RIGHT [ OUTER ] JOIN

      • FULL [ OUTER ] JOIN

      • CROSS JOIN

    对于INNER和OUTER连接类型,必须指定 一个连接条件,即 NATURAL、ON join_condition或者 USING (join_column [, …]) 之一(只能有一种)。其含义见下文。对于 CROSS JOIN,上述子句不能出现。

    一个JOIN子句联合两个FROM项( 为了方便我们称之为“表”,尽管实际上它们可以是任何类型 的FROM项)。如有必要可以使用圆括号确定嵌套的顺序。 在没有圆括号时,JOIN会从左至右嵌套。在任何情 况下,JOIN的联合比分隔FROM-列表 项的逗号更强。

    CROSS JOIN和INNER JOIN 会产生简单的笛卡尔积,也就是与在FROM的顶层列出两个 表得到的结果相同,但是要用连接条件(如果有)约束该结果。 CROSS JOIN与INNER JOIN ON (TRUE)等效,也就是说条件不会移除任何行。这些连接类型只是一种 记号上的方便,因为没有什么是你用纯粹的FROM和 WHERE能做而它们不能做的。

    LEFT OUTER JOIN返回被限制过的笛卡尔积 中的所有行(即所有通过了其连接条件的组合行),外加左手表中 没有相应的通过了连接条件的右手行的每一行的拷贝。通过在右手 列中插入空值,这种左手行会被扩展为连接表的完整行。注意在决 定哪些行匹配时,只考虑JOIN子句自身的条件。之后 才应用外条件。

    相反,RIGHT OUTER JOIN返回所有连接行,外加每 一个没有匹配上的右手行(在左端用空值扩展)。这只是为了记号 上的方便,因为你可以通过交换左右表把它转换成一个LEFT OUTER JOIN。

    FULL OUTER JOIN返回所有连接行,外加每 一个没有匹配上的左手行(在右端用空值扩展),再外加每一个没有 匹配上的右手行(在左端用空值扩展)。

  • ON join_condition

    join_condition 是一个会得到boolean类型值的表达式(类似于一个 WHERE子句),它说明一次连接中哪些行被认为 相匹配。

  • USING ( join_column [, …] )

    形式USING ( a, b, … )的子句是 ON left_table.a = right_table.a AND left_table.b = right_table.b …的简写。还有, USING表示每一对相等列中只有一个会被 包括在连接输出中。

  • NATURAL

    NATURAL是一个USING列表的速记,该列表中提到两个表中具有匹配名称的所有的列。如果没有公共列名,则NATURAL等效于ON TRUE。

  • LATERAL

    LATERAL关键词可以放在一个 子-SELECT FROM项前面。这允许该 子-SELECT引用FROM列表中在它之 前的FROM项的列(如果没有LATERAL,每一 个子-SELECT会被独立计算并且因此不能交叉引用 任何其他的FROM项)。

    LATERAL也可以放在一个函数调用 FROM项前面,但是在这种情况下它只是一个噪声 词,因为在任何情况下函数表达式都可以引用在它之前的 FROM项。

    LATERAL项可以出现在FROM列表 顶层,或者一个JOIN中。在后一种情况中,它也可以引 用其作为右手端的JOIN左手端上的任何项。

    当一个FROM项包含LATERAL交叉引用 时,计算会如此进行:对提供被交叉引用列的FROM项的每 一行或者提供那些列的多个FROM项的每一个行集,使用该 行或者行集的那些列值计算LATERAL项。结果行会与 计算得到它们的行进行通常的连接。对来自哪些列的源表的每一行或者行 集都会重复这样的步骤。

    列的源表必须以INNER或者LEFT的方式连接到 LATERAL项,否则就没有用于为 LATERAL项计算每一个行集的良定行集。尽管 X RIGHT JOIN LATERAL Y这样的结构在语法上是合法的, 但实际上不允许用于在Y中引用 X。

WHERE 子句

可选的WHERE子句的形式

WHERE condition

其中condition 是任一计算得到布尔类型结果的表达式。任何不满足 这个条件的行都会从输出中被消除。如果用一行的实际值替换其中的 变量引用后,该表达式返回真,则该行符合条件。

CONNECT BY 子句

可选的CONNECT BY子句的形式

CONNECT BY { PRIOR parent_expr = child_expr |
child_expr = PRIOR parent_expr}.

CONNECT BY 指定分层结构中父行和子行之间的关系。 在分层查询中,条件中的一个表达式必须使用 PRIOR 运算符限定,以引用父行。

START 子句

可选的START WITH子句的形式

[ START WITH start_expression ]
.

START WITH 指定分层结构的根行。

GROUP BY 子句

可选的GROUP BY子句的形式

GROUP BY grouping_element [, ...]

GROUP BY将会把所有被选择的行中共享相同分组表达式 值的那些行压缩成一个行。一个被用在 grouping_element中的 expression可以是输入列名、输出列 (SELECT列表项)的名称或序号或者由输入列 值构成的任意表达式。在出现歧义时,GROUP BY名称 将被解释为输入列名而不是输出列名。

如果任何GROUPING SETS、ROLLUP或者CUBE作为分组元素存在,则GROUP BY子句整体上定义了数个独立的分组集。 其效果等效于在子查询间构建一个UNION ALL,子查询带有分组集作为它们的GROUP BY子句。 在处理前可选的DISTINCT子句移除副本集合;它不做UNION ALL到UNION DISTINCT的转换 处理分组集的进一步细节请见。

聚集函数(如果使用)会在组成每一个分组的所有行上进行计算,从而为每 一个分组产生一个单独的值(如果有聚集函数但是没有 GROUP BY子句,则查询会被当成是由所有选中行构成 的一个单一分组)。传递给每一个聚集函数的行集合可以通过在聚集函数调 用附加一个FILTER子句来进一步过滤,详见。当存在一个 FILTER子句时,只有那些匹配它的行才会被包括在该聚 集函数的输入中。

当存在GROUP BY子句或者任何聚集函数时, SELECT列表表达式不能引用非分组列(除非它 出现在聚集函数中或者它函数依赖于分组列),因为这样做会导致返回 非分组列的值时会有多种可能的值。如果分组列是包含非分组列的表的主键( 或者主键的子集),则存在函数依赖。

记住所有的聚集函数都是在HAVING子句或者 SELECT列表中的任何“标量”表达式之前被计算。 这意味着一个CASE表达式不能被用来跳过一个聚集表达式的计算。

当前,FOR NO KEY UPDATE、FOR UPDATE、 FOR SHARE和FOR KEY SHARE不能和 GROUP BY一起指定。

HAVING 子句

可选的HAVING子句的形式

HAVING condition

其中condition与 WHERE子句中指定的条件相同。

HAVING消除不满足该条件的分组行。 HAVING与WHERE不同: WHERE会在应用GROUP BY之前过滤个体行,而HAVING过滤由 GROUP BY创建的分组行。 condition中引用 的每一个列必须无歧义地引用一个分组列(除非该引用出现在一个聚集 函数中或者该非分组列函数依赖于分组列。

即使没有GROUP BY子句,HAVING 的存在也会把一个查询转变成一个分组查询。这和查询中包含聚集函数但没有 GROUP BY子句时的情况相同。所有被选择的行都被认为是一个 单一分组,并且SELECT列表和 HAVING子句只能引用聚集函数中的表列。如果该 HAVING条件为真,这样一个查询将会发出一个单一行; 否则不返回行。

当前,FOR NO KEY UPDATE、FOR UPDATE、 FOR SHARE和FOR KEY SHARE不能与 HAVING一起指定。

WINDOW 子句

可选的WINDOW子句的形式

WINDOW window_name AS ( window_definition ) [, ...]

其中window_name 是一个可以从OVER子句或者后续窗口定义中引用的名称。 window_definition是

[ existing_window_name ]
[ PARTITION BY expression [, ...] ]
[ ORDER BY expression [ ASC | DESC | USING operator ] [ NULLS { FIRST | LAST } ] [, ...] ]
[ frame_clause ]

如果指定了一个existing_window_name, 它必须引用WINDOW列表中一个更早出现的项。新窗口将从 该项中复制它的划分子句以及排序子句(如果有)。在这种情况下,新窗口 不能指定它自己的PARTITION BY子句,并且它只能在被复制 窗口没有ORDER BY的情况下指定该子句。新窗口总是使用它 自己的帧子句,被复制的窗口不必指定一个帧子句。

PARTITION BY列表元素的解释以 GROUP BY子句元素的方式 进行,不过它们总是简单表达式并且绝不能是输出列的名称或编号。另一个区 别是这些表达式可以包含聚集函数调用,而这在常规GROUP BY 子句中是不被允许的。它们被允许的原因是窗口是出现在分组和聚集之后的。

类似地,ORDER BY列表元素的解释也以语句级 ORDER BY子句元素的方式进行, 不过该表达式总是被当做简单表达式并且绝不会是输出列的名称或编号。

可选的frame_clause为依赖帧的窗口函数 定义窗口帧(并非所有窗口函数都依赖于帧)。窗口帧是查询中 每一样(称为当前行)的相关行的集合。 frame_clause可以是

{ RANGE | ROWS | GROUPS } frame_start [ frame_exclusion ]
{ RANGE | ROWS | GROUPS } BETWEEN frame_start AND frame_end [ frame_exclusion ]

之一,其中frame_start和frame_end可以是

UNBOUNDED PRECEDING
offset PRECEDING
CURRENT ROW
offset FOLLOWING
UNBOUNDED FOLLOWING

之一,并且frame_exclusion可以是

EXCLUDE CURRENT ROW
EXCLUDE GROUP
EXCLUDE TIES
EXCLUDE NO OTHERS

之一。如果省略frame_end,它会被默认为CURRENT ROW。限制是: frame_start不能是UNBOUNDED FOLLOWING, frame_end不能是UNBOUNDED PRECEDING, 并且frame_end的选择在上面of frame_start以及frame_end 选项的列表中不能早于 frame_start的选择 ? 例如 RANGE BETWEEN CURRENT ROW AND offset PRECEDING是不被允许的。

默认的帧选项是RANGE UNBOUNDED PRECEDING,它和 RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW相同。它把帧设置为从分区开始直到当前行的最后一个平级行(被该窗口的ORDER BY子句认为等价于当前行的行,如果没有ORDER BY则所有的行都是平级的)。通常, UNBOUNDED PRECEDING表示从分区第一行开始的帧,类似地 UNBOUNDED FOLLOWING表示以分区最后一行结束的帧,不论是处于RANGE、ROWS或者GROUPS模式中。在ROWS模式中, CURRENT ROW表示以当前行开始或者结束的帧。而在 RANGE或者GROUPS模式中它表示当前行在ORDER BY排序中的第一个 或者最后一个平级行开始或者结束的帧。 offset PRECEDING和offset FOLLOWING选项的含义会随着帧模式而变化。在ROWS模式中,offset是一个整数,表示帧开始或者结束于当前行之前或者之后的那么多行处。在GROUPS模式中,offset是一个整数,表示真开始或者结束于当前行的平级组之前或者之后那么多个平级组处,其中平级组是一组根据窗口的ORDER BY子句等效的行。在RANGE模式中,offset选项的使用要求在窗口定义中正好有一个ORDER BY列。那么该帧包含的行的排序列值不超过offset且小于(对于PRECEDING)或者大于(对于FOLLOWING)当前行的排序列值。在这些情况中,offset表达式的数据类型取决于排序列的数据类型。对于数字排序列,它通常与排序列是相同类型,但对于datetime类型的排序列它是interval。在所有这些情况中,offset的值必须是非空和非负。此外,虽然offset并非必须是简单常量,但它不能包含变量、聚集函数或者窗口函数。

frame_exclusion选项允许从帧中排除当前行周围的行,即便根据帧的起始选项来说它们应该被包含在帧中。EXCLUDE CURRENT ROW把当前行从帧中排除。EXCLUDE GROUP把当前行和它在排序上的平级行从帧中排除。EXCLUDE TIES从帧中排除当前行的任何平级行,但是不排除当前行本身。EXCLUDE NO OTHERS只是明确地指定不排除当前行或其平级行的默认行为。

注意,如果ORDER BY排序无法把行唯一地排序,则ROWS模式可能产生不可预测的结果。RANGE以及GROUPS模式的目的是确保在ORDER BY顺序中平等的行被同样对待:一个给定平级组中的所有行将在一个帧中或者被从帧中排除。

WINDOW子句的目的是指定出现在查询的 SELECT list或 ORDER BY子句中的 窗口函数的行为。这些函数可以在它们的 OVER子句中用名称引用WINDOW 子句项。不过,WINDOW子句项不是必须被引用。 如果在查询中没有用到它,它会被简单地忽略。可以使用根本没有任何 WINDOW子句的窗口函数,因为窗口函数调用可 以直接在其OVER子句中指定它的窗口定义。不过,当多 个窗口函数都需要相同的窗口定义时, WINDOW子句能够减少输入。

当前,FOR NO KEY UPDATE、FOR UPDATE、 FOR SHARE和FOR KEY SHARE不能和 WINDOW一起被指定。

SELECT 列表

SELECT列表(位于关键词 SELECT和FROM之间)指定构成 SELECT语句输出行的表达式。这些表达式 可以(并且通常确实会)引用FROM子句中计算得到的列。

正如在表中一样,SELECT的每一个输出列都有一个名称。 在一个简单的SELECT中,这个名称只是被用来标记要显 示的列,但是当SELECT是一个大型查询的一个子查询时,大型查询 会把该名称看做子查询产生的虚表的列名。要指定用于输出列的名称,在该列的表达式 后面写上 AS output_name( 你可以省略AS,但只能在期望的输出名称不匹配任何 LightDB关键词(见Appendix C)时省略。为了避免和未来增加的关键词冲突, 推荐总是写上AS或者用双引号引用输出名称)。如果你不指定列名, LightDB会自动选择一个名称。如果列的表达式 是一个简单的列引用,那么被选择的名称就和该列的名称相同。在使用函数或者类型名称 的更复杂的情况中,系统可能会生成诸如 ?column?之类的名称。

然而,显示的列名将被转换成小写,即便特地使用 AS 来指定其别名,除非 使用双引号或反引号引用它们。但是如果在mysql模式下,即创建数据库时指定 lightdb_syntax_compatible_type mysql 同时设置lightdb_sql_mode包含 ‘uppercase_identifier’参数,那么可保证大小写不变。特别地,’uppercase_identifier’选项建议 在lightdb.conf中设置而不是在会话中设置,因为这个参数最好设置后就不做改动。缺少上述条件中的任 意一项都会使这项特性失效。为实现这个特性,达成与mysql一致的效果,查询时列名与存储文件内列名进行 匹配时将忽略大小写,比如查询时列名’fOo’将认为与磁盘中存储的’FoO’相等。

与mysql模式类似但略有不同的是,oracle模式下guc参数’lightdb_oracle_sql_mode’可以在会话中配置, 取值为’true’或’false’。如果设置为’true’,则执行一个select语句返回的结果列名默认显示大写。用户 只有通过使用双引号包含列名才能使得大小写不变。设置’lightdb_oracle_sql_mode’为false,那么该功能 会被禁用并恢复默认模式。

一个输出列的名称可以被用来在ORDER BY以及 GROUP BY子句中引用该列的值,但是不能用于 WHERE和HAVING子句(在其中 必须写出表达式)。

可以在输出列表中写*来取代表达式,它是被选中 行的所有列的一种简写方式。还可以写 table_name.*,它 是只来自那个表的所有列的简写形式。在这些情况中无法用 AS指定新的名称,输出行的名称将和表列的名称相同。

根据 SQL 标准,输出列表中的表达式应该在应用DISTINCT、ORDER BY或者LIMIT之前计算。在使用DISTINCT时显然必须这样做,否则就无法搞清到底在区分什么值。不过,在很多情况下如果先计算ORDER BY和LIMIT再计算输出表达式会很方便,特别是如果输出列表中包含任何 volatile 函数或者代价昂贵的函数时尤其如此。通过这种行为,函数计算的顺序更加直观并且对于从未出现在输出中的行将不会进行计算。只要输出表达式没有被DISTINCT、ORDER BY或者GROUP BY引用,LightDB实际将在排序和限制行数之后计算输出表达式(作为一个反例,SELECT f(x) FROM tab ORDER BY 1显然必须在排序之前计算f(x))。包含有集合返回函数的输出表达式实际是在排序之后和限制行数之前被计算,这样LIMIT才能切断来自集合返回函数的输出。

DISTINCT 子句

如果指定了SELECT DISTINCT,所有重复的行会被从结果 集中移除(为每一组重复的行保留一行)。SELECT ALL则 指定相反的行为:所有行都会被保留,这也是默认情况。

SELECT DISTINCT ON ( expression [, …] ) 只保留在给定表达式上计算相等的行集合中的第一行。 DISTINCT ON表达式使用和 ORDER BY相同的规则(见上文)解释。注意,除非用 ORDER BY来确保所期望的行出现在第一位,每一个集 合的“第一行”是不可预测的。例如:

SELECT DISTINCT ON (location) location, time, report
        FROM weather_reports
        ORDER BY location, time DESC;

为每个地点检索最近的天气报告。但是如果我们不使用 ORDER BY来强制对每个地点的时间值进行降序排序, 我们为每个地点得到的报告的时间可能是无法预测的。

DISTINCT ON表达式必须匹配最左边的 ORDER BY表达式。ORDER BY子句通常 将包含额外的表达式,这些额外的表达式用于决定在每一个 DISTINCT ON分组内行的优先级。

DISTINCT支持与CONNECT BY一同使用。例如:

select distinct test_area1.id, test_area1.name, test_area1.pid
        from test_area1 join test_area2
        on test_area1.id = test_area2.id
        connect by level < 3 order by test_area1.id;

当前,FOR NO KEY UPDATE、FOR UPDATE、 FOR SHARE和FOR KEY SHARE不能和 DISTINCT一起使用。

UNION 子句

UNION子句具有下面的形式:

select_statement UNION [ ALL | DISTINCT ] select_statement

select_statement 是任何没有ORDER BY、LIMIT、 FOR NO KEY UPDATE、FOR UPDATE、 FOR SHARE和FOR KEY SHARE子句的 SELECT语句(如果子表达式被包围在圆括号内, ORDER BY和LIMIT可以被附着到其上。如果没有 圆括号,这些子句将被应用到UNION的结果而不是右手边 的表达式上)。

UNION操作符计算所涉及的 SELECT语句所返回的行的并集。如果一行 至少出现在两个结果集中的一个内,它就会在并集中。作为 UNION两个操作数的 SELECT语句必须产生相同数量的列并且 对应位置上的列必须具有兼容的数据类型。

UNION的结果不会包含重复行,除非指定了 ALL选项。ALL会阻止消除重复(因此, UNION ALL通常显著地快于UNION, 尽量使用ALL)。可以写DISTINCT来 显式地指定消除重复行的行为。

除非用圆括号指定计算顺序, 同一个SELECT语句中的多个 UNION操作符会从左至右计算。

当前,FOR NO KEY UPDATE、FOR UPDATE、 FOR SHARE和 FOR KEY SHARE不能用于UNION结果或者 UNION的任何输入。

INTERSECT 子句

INTERSECT子句具有下面的形式:

select_statement INTERSECT [ ALL | DISTINCT ] select_statement

select_statement 是任何没有ORDER BY, LIMIT、FOR NO KEY UPDATE、FOR UPDATE、 FOR SHARE以及FOR KEY SHARE子句的 SELECT语句。

INTERSECT操作符计算所涉及的 SELECT语句返回的行的交集。如果 一行同时出现在两个结果集中,它就在交集中。

INTERSECT的结果不会包含重复行,除非指定了 ALL选项。如果有ALL,一个在左表中有 m次重复并且在右表中有n 次重复的行将会在结果中出现 min(m,n) 次。 DISTINCT可以写DISTINCT来 显式地指定消除重复行的行为。

除非用圆括号指定计算顺序, 同一个SELECT语句中的多个 INTERSECT操作符会从左至右计算。 INTERSECT的优先级比 UNION更高。也就是说, A UNION B INTERSECT C将被读成A UNION (B INTERSECT C)。

当前,FOR NO KEY UPDATE、FOR UPDATE、 FOR SHARE和 FOR KEY SHARE不能用于INTERSECT结果或者 INTERSECT的任何输入。

EXCEPT 子句

EXCEPT子句具有下面的形式:

select_statement EXCEPT [ ALL | DISTINCT ] select_statement

select_statement 是任何没有ORDER BY、LIMIT、FOR NO KEY UPDATE、FOR UPDATE、 FOR SHARE以及FOR KEY SHARE子句的 SELECT语句。

EXCEPT操作符计算位于左 SELECT语句的结果中但不在右 SELECT语句结果中的行集合。

EXCEPT的结果不会包含重复行,除非指定了 ALL选项。如果有ALL,一个在左表中有 m次重复并且在右表中有 n次重复的行将会在结果集中出现 max(m-n,0) 次。 DISTINCT可以写DISTINCT来 显式地指定消除重复行的行为。

除非用圆括号指定计算顺序, 同一个SELECT语句中的多个 EXCEPT操作符会从左至右计算。 EXCEPT的优先级与 UNION相同。

当前,FOR NO KEY UPDATE、FOR UPDATE、 FOR SHARE和 FOR KEY SHARE不能用于EXCEPT结果或者 EXCEPT的任何输入。

ORDER BY 子句

可选的ORDER BY子句的形式如下:

ORDER BY expression [ ASC | DESC | USING operator ] [ NULLS { FIRST | LAST } ] [, ...]

ORDER BY子句导致结果行被按照指定的表达式排序。 如果两行按照最左边的表达式是相等的,则会根据下一个表达式比较它们, 依次类推。如果按照所有指定的表达式它们都是相等的,则它们被返回的 顺序取决于实现。

每一个expression 可以是输出列(SELECT列表项)的名称或 者序号,它也可以是由输入列值构成的任意表达式。

序号指的是输出列的顺序(从左至右)位置。这种特性可以为不具有唯一 名称的列定义一个顺序。这不是绝对必要的,因为总是可以使用 AS子句为输出列赋予一个名称。

也可以在ORDER BY子句中使用任意表达式,包括没 有出现在SELECT输出列表中的列。因此, 下面的语句是合法的:

SELECT name FROM distributors ORDER BY code;

这种特性的一个限制是一个应用在UNION、 INTERSECT或EXCEPT子句结果上的 ORDER BY只能指定输出列名称或序号,但不能指定表达式。

如果一个ORDER BY表达式是一个既匹配输出列名称又匹配 输入列名称的简单名称,ORDER BY将把它解读成输出列名 称。这与在同样情况下GROUP BY会做出的选择相反。这种 不一致是为了与 SQL 标准兼容。

可以为ORDER BY子句中的任何表达式之后增加关键词 ASC(上升)DESC(下降)。如果没有指定, ASC被假定为默认值。或者,可以在USING 子句中指定一个特定的排序操作符名称。一个排序操作符必须是某个 B-树操作符族的小于或者大于成员。ASC通常等价于 USING <而DESC通常等价于 USING >(但是一种用户定义数据类型的创建者可以 准确地定义默认排序顺序是什么,并且它可能会对应于其他名称的操作符)。

如果指定NULLS LAST,空值会排在非空值之后;如果指定 NULLS FIRST,空值会排在非空值之前。如果都没有指定, 在指定或者隐含ASC时的默认行为是NULLS LAST, 而指定或者隐含DESC时的默认行为是 NULLS FIRST(因此,默认行为是空值大于非空值)。 当指定USING时,默认的空值顺序取决于该操作符是否为 小于或者大于操作符。

注意顺序选项只应用到它们所跟随的表达式上。例如 ORDER BY x, y DESC和 ORDER BY x DESC, y DESC是不同的。

字符串数据会被根据引用到被排序列上的排序规则排序。根据需要可以通过在 expression中包括一个 COLLATE子句来覆盖,例如 ORDER BY mycolumn COLLATE “en_US”。

LIMIT 子句

LIMIT子句由两个独立的子句构成:

LIMIT { count | ALL }
OFFSET start

参数count指定要返回 的最大行数,而start 指定在返回行之前要跳过的行数。在两者都被指定时,在开始计算要返回的 count行之前会跳过 start行。

如果count表达式计算 为 NULL,它会被当成LIMIT ALL,即没有限制。如果 start计算为 NULL,它会被当作OFFSET 0。

SQL:2008 引入了一种不同的语法来达到相同的结果, LightDB也支持它:

OFFSET start { ROW | ROWS }
FETCH { FIRST | NEXT } [ count ] { ROW | ROWS } { ONLY | WITH TIES }

在这种语法中,标准要求start或count是一个文本常量、一个参数或者一个变量名。 而作为一种LightDB的扩展,还允许其他的表达式,但通常需要被封闭在圆括号中以避免歧义。 如果在一个FETCH子句中省略count,它的默认值为 1。 WITH TIES选项用于根据ORDER BY子句返回与结果集中最后一个位置相关的任何附加行;ORDER BY在这种情况下是强制性的,并且SKIP LOCKED是不被允许的。 ROW和ROWS以及FIRST和NEXT是噪声,它们不影响这些子句的效果。 根据标准,如果都存在,OFFSET子句必须出现在FETCH子句之前。 但是LightDB更宽松,它允许两种顺序。

在使用LIMIT时,用一个ORDER BY子句把 结果行约束到一个唯一顺序是个好办法。否则你讲得到该查询结果行的 一个不可预测的子集 ? 你可能要求从第 10 到第 20 行,但是在 什么顺序下的第 10 到第 20 呢?除非指定ORDER BY,你 是不知道顺序的。

查询规划器在生成一个查询计划时会考虑LIMIT,因此 根据你使用的LIMIT和OFFSET,你很可能 得到不同的计划(得到不同的行序)。所以,使用不同的 LIMIT/OFFSET值来选择一个查询结果的 不同子集将会给出不一致的结果,除非你 用ORDER BY强制一种可预测的结果顺序。这不是一个 缺陷,它是 SQL 不承诺以任何特定顺序(除非使用 ORDER BY来约束顺序)给出一个查询结果这一事实造 成的必然后果。

如果没有一个ORDER BY来强制选择一个确定的子集, 重复执行同样的LIMIT查询甚至可能会返回一个表中行 的不同子集。同样,这也不是一种缺陷,再这样一种情况下也无法 保证结果的确定性。

锁定子句

FOR UPDATE、FOR NO KEY UPDATE、 FOR SHARE和FOR KEY SHARE 是锁定子句,它们影响SELECT 把行从表中取得时如何对它们加锁。

锁定子句的一般形式:

FOR lock_strength [ OF table_name [, ...] ] [ NOWAIT | SKIP LOCKED ]

其中lock_strength可以是

UPDATE
NO KEY UPDATE
SHARE
KEY SHARE

为了防止该操作等待其他事务提交,可使用NOWAIT或者SKIP LOCKED选项。 使用NOWAIT时,如果选中的行不能被立即锁定,该语句会报告错误而不是等待。 使用 SKIP LOCKED时,无法被立即锁定的任何选中行都会被跳过。 跳过已锁定行会提供数据的一个不一致的视图,因此这不适合于一般目的的工作,但是可以被用来避免多个用户访问一个类似队列的表时出现锁竞争。 注意NOWAIT和SKIP LOCKED只适合行级锁 ? 所要求的ROW SHARE表级锁仍然会以常规的方式(见Chapter 13)取得。 如果想要不等待的表级锁,你可以先使用带NOWAIT的LOCK。

如果在一个锁定子句中提到了特定的表,则只有来自于那些表的 行会被锁定,任何SELECT中用到的 其他表还是被简单地照常读取。一个没有表列表的锁定子句会影响 该语句中用到的所有表。如果一个锁定子句被应用到一个视图或者 子查询,它会影响在该视图或子查询中用到的所有表。不过,这些 子句不适用于主查询引用的WITH查询。如果你希望 在一个WITH查询中发生行锁定,应该在该 WITH查询内指定一个锁定子句。

如果有必要对不同的表指定不同的锁定行为,可以写多个锁定子句。 如果同一个表在多于一个锁定子句中被提到(或者被隐式的影响到), 那么会按照所指定的最强的锁定行为来处理它。类似地,如果在任何 影响一个表的子句中指定了NOWAIT,就会按照 NOWAIT的行为来处理该表。否则如果 SKIP LOCKED在任何影响该表的子句中被指定, 该表就会被按照SKIP LOCKED来处理。

如果被返回的行无法清晰地与表中的行保持一致,则不能使用锁定子句。 例如锁定子句不能与聚集一起使用。

当一个锁定子句出现在一个SELECT查询的顶层时, 被锁定的行正好就是该查询返回的行。在连接查询的情况下,被锁定 的行是那些对返回的连接行有贡献的行。此外,自该查询的快照起满足 查询条件的行将被锁定,如果它们在该快照后被更新并且不再满足 查询条件,它们将不会被返回。如果使用了LIMIT,只要 已经返回的行数满足了限制,锁定就会停止(但注意被 OFFSET跳过的行将被锁定)。类似地,如果在一个游标 的查询中使用锁定子句,只有被该游标实际取出或者跳过的行才将被 锁定。

当一个锁定子句出现在一个子-SELECT中时,被锁定 行是那些该子查询返回给外层查询的行。这些被锁定的行的数量可能比 从子查询自身的角度看到的要少,因为来自外层查询的条件可能会被用 来优化子查询的执行。例如:

SELECT * FROM (SELECT * FROM mytable FOR UPDATE) ss WHERE col1 = 5;

将只锁定具有col1 = 5的行(虽然在子查询中并没有写上 该条件)。

注意

一个运行在READ COMMITTED事务隔离级别并且使用ORDER BY和锁定子句的SELECT命令有可能返回无序的行。 这是因为ORDER BY会被首先应用。该命令对结果排序,但是可能 接着在尝试获得一个或者多个行上的锁时阻塞。一旦SELECT解除 阻塞,某些排序列值可能已经被修改,从而导致那些行变成无序的(尽管它们根 据原始列值是有序的)。根据需要,可以通过在子查询中放置 FOR UPDATE/SHARE来解决之一问题,例如

SELECT * FROM (SELECT * FROM mytable FOR UPDATE) ss ORDER BY column1; 注意这将导致锁定mytable的所有行,而顶层的 FOR UPDATE只会锁定实际被返回的行。这可能会导致显著的 性能差异,特别是把ORDER BY与LIMIT或者其他 限制组合使用时。因此只有在并发更新排序列并且要求严格的排序结果时才推 荐使用这种技术。

在REPEATABLE READ或者SERIALIZABLE 事务隔离级别上这可能导致一个序列化失败(SQLSTATE 是’40001’),因此在这些隔离级别下不可能收到无序行。

5.2.5.1. 简单查询

查询表ligthdb_test的所有数据

lightdb@postgres=# select * from lightdb_table1;
id |    name
----+------------
1 | lightdb11
2 | lightdb112
(2 rows)

根据条件id查询ligthdb_test表数据

lightdb@postgres=# select * from lightdb_table1 where id = 1;
id |   name
----+-----------
1 | lightdb11
(1 row)

5.2.5.2. 关联查询

把表films与表 distributors连接:

SELECT f.title, f.did, d.name, f.date_prod, f.kind
        FROM distributors d, films f
        WHERE f.did = d.did

        title       | did |     name     | date_prod  |   kind
----------------+-----+--------------+------------+----------
The Third Man     | 101 | British Lion | 1949-12-23 | Drama
The African Queen | 101 | British Lion | 1951-08-11 | Romantic
...

5.2.5.3. 分组查询

要对所有电影的len列求和并且用 kind对结果分组:

SELECT kind, sum(len) AS total FROM films GROUP BY kind;

kind   | total
----------+-------
Action   | 07:34
Comedy   | 02:58
Drama    | 14:28
Musical  | 06:42
Romantic | 04:38

5.2.5.4. join查询

表ligthdb_test与表ligthdb_test1做join查询

lightdb@postgres=# select * from lightdb_table1 a join lightdb_table2 b on a.id=b.id;
id |   name    | id |   name
----+-----------+----+-----------
1 | lightdb11 |  1 | lightdb21
1 | lightdb11 |  1 | lightdb22
(2 rows)

表ligthdb_test与表ligthdb_test1左连接查询

lightdb@postgres=# select * from lightdb_table1 a left join lightdb_table1 b on a.id=b.id where a.id = 1;
id |   name    | id |   name
----+-----------+----+-----------
1 | lightdb11 |  1 | lightdb11
(1 row)

外连接 + 号表示 LEFT JOIN 和 RIGHT JOIN

SELECT *
FROM table1, table2
WHERE table1.id = table2.id (+);

5.2.5.5. 子查询

in子查询示例

lightdb@postgres=# select * from lightdb_table1 a where a.id in (select id from lightdb_table2 where id = 1);
id |   name
----+-----------
1 | lightdb11
(1 row)

exist 子查询示例

lightdb@postgres=# select a, count(1) from lightdb_table1 a where exists (select * from lightdb_table2 b where a.id=b.id) group by a;
        a          | count
---------------+-------
(1,lightdb11)  |     1
(1 row)

复合函数和exists子查询

lightdb@postgres=# select count(distinct a) from lightdb_table1 a  where exists (select * from lightdb_table2 b where a.id=b.id);
count
-------
        1
(1 row)

5.2.6. MERGE

基于源数据插入、更新表中的行

语法:

MERGE INTO target_table_name [ [ AS ] target_alias ]
                        USING data_source
                        ON join_condition
                        when_clause [...]

                        其中 data_source                         { source_table_name |
                        ( source_query )
                        }
                        [ [ AS ] source_alias ]

                         when_clause                         { WHEN MATCHED THEN { merge_update } |
                        WHEN NOT MATCHED THEN { merge_insert }
                        }

                         merge_insert                         INSERT [( column_name [, ...] )]
                        { VALUES ( { expression | DEFAULT } [, ...] ) | DEFAULT VALUES
                        }
                        [ WHERE condition ]

                         merge_update                         UPDATE SET { column_name = {
                                expression | DEFAULT } |
                        ( column_name [, ...] ) = ( {
                                expression | DEFAULT } [, ...] )
                        } [, ...]
                        [ WHERE condition ]

描述:

MERGE 命令通过使用 data_source,对 target_table_name 中的行进行修改。MERGE 提供了一个单一的 SQL 语句,可以有条件地 INSERT 或 UPDATE 行,这是一个通常需要多个过程式语言语句才能完成的任务。

首先,MERGE 命令从 data_source 到 target_table_name 执行联接,产生零个或多个候选更改行。 对于每个候选更改行,MATCHED 或 NOT MATCHED 的状态仅设置一次, 然后按指定顺序评估 WHEN 子句。如果其中一个被激活,则执行指定的操作。 对于任何候选更改行,最多只能激活一个 WHEN 子句。

MERGE 命令的操作与同名的常规 UPDATE、INSERT 命令具有相同的效果。这些命令的语法不同,特别是没有指定表名。所有操作都参考 target_table_name。

没有 MERGE 权限。如果指定了更新操作,则必须在 SET 子句中引用 target_table_name 的列的 UPDATE 权限, 如果指定了插入操作,则必须在 target_table_name 上拥有 INSERT 权限。权限在语句开始时进行测试,无论是否激活特定的 WHEN 子句,在随后的执行过程中都会进行检查。在引用 condition 中的 data_source 和 target_table_name 的任何列时,都需要具有 SELECT 权限。

如果 target_table_name 上定义了 RULES,则不支持 MERGE。

参数:

  • target_table_name

    要合并到的目标表的名称(可选带模式限定符)。

  • target_alias

    目标表的替代名称。提供别名时,它完全隐藏了表的实际名称。例如,给定 MERGE foo AS f,MERGE 语句的其余部分必须将该表称为 f 而不是 foo。

  • source_table_name

    源表、视图或转换表的名称(可选带模式限定符)。

  • source_query

一个查询(SELECT 语句或 VALUES 语句),提供要合并到 target_table_name 中的行。请参考 SELECT 语句或 VALUES 语句,了解其语法的说明。

  • source_alias

    数据源的替代名称。提供别名时,它完全隐藏了指定了表还是查询。

  • join_condition

    join_condition 是一个表达式,其结果为 boolean 类型的值(类似于 WHERE 子句),指定哪些 data_source 中的行与 target_table_name 中的行匹配。

    Warning

    只有尝试匹配 data_source 行的 target_table_name 列应出现在 join_condition 中。仅引用 target_table_name 列的 join_condition 子表达式只能影响采取哪些操作, 通常是以令人惊讶的方式。

  • when_clause

    至少需要一个 WHEN 子句。

    如果 WHEN 子句指定了 WHEN MATCHED,并且候选更改行与 target_table_name 中的一行匹配, 如果 condition 不存在或存在且评估为 true,则会激活 WHEN 子句。 如果 WHEN 子句指定了 WHEN NOT MATCHED,并且候选更改行与 target_table_name 中的一行不匹配, 如果 condition 不存在或存在且评估为 true,则会激活 WHEN 子句。

  • merge_insert

    指定一个 INSERT 操作,将一行插入目标表中。 目标列名可以以任何顺序列出。如果根本没有给出列名列表,则默认为表中所有列按其声明的顺序。

    未在显式或隐式列列表中出现的每个列将填充其声明的默认值或 null(如果没有默认值)。

    如果任何列的表达式不是正确的数据类型,则会尝试进行自动类型转换。

    如果 target_table_name 是分区表,则每行将路由到适当的分区并插入其中。 如果 target_table_name 是分区,则如果其中一个输入行违反分区约束,则会出现错误。

    列名不能指定多次。 INSERT 操作不能包含子查询。

    只能指定一个 VALUES 子句。 VALUES 子句只能引用来自源关系的列,因为根据定义,没有匹配的目标行。

  • merge_update

    指定一个 UPDATE 操作,更新 target_table_name 的当前行。列名不能指定多次。

    不要包含表名,因为这与 UPDATE 命令通常不同。 例如,UPDATE tab SET col = 1 是无效的。

  • column_name

    target_table_name 中的列名。 如果需要,可以使用子字段名或数组下标限定列名。(仅插入复合列的某些字段将使其他字段为空。) 在引用列时,不要在目标列的规范中包含表名。

  • expression

    赋给该列的表达式。该表达式可以使用该表中此列和其他列的旧值。

  • condition

    返回类型为 boolean 的表达式。如果此表达式返回 true,则将激活 WHEN 子句, 并对该行执行相应的操作。该表达式可能不包含可能对数据库执行写操作的函数。

    对于 WHEN MATCHED 子句的条件可以引用源关系和目标关系中的列。 对于 WHEN NOT MATCHED 子句的条件只能引用来自源关系的列, 因为根据定义,没有匹配的目标行。

示例:

基于新事务对 CustomerAccounts 进行维护。

MERGE INTO CustomerAccount CA
USING RecentTransactions T
ON T.CustomerId = CA.CustomerId
WHEN MATCHED THEN
UPDATE SET Balance = Balance + TransactionValue
WHEN NOT MATCHED THEN
INSERT (CustomerId, Balance)
VALUES (T.CustomerId, T.TransactionValue);

注意,由于执行过程中 MATCHED 结果不会改变,因此这与以下语句完全等效:

MERGE INTO CustomerAccount CA
USING (Select CustomerId, TransactionValue From RecentTransactions) AS T
ON CA.CustomerId = T.CustomerId
WHEN NOT MATCHED THEN
INSERT (CustomerId, Balance)
VALUES (T.CustomerId, T.TransactionValue)
WHEN MATCHED THEN
UPDATE SET Balance = Balance + TransactionValue;

尝试插入一个新的库存项以及库存数量。如果该项已经存在,则更新现有项的库存计数。不允许具有零库存的条目。

MERGE INTO wines w
USING wine_stock_changes s
ON s.winename = w.winename
WHEN NOT MATCHED THEN
INSERT VALUES(s.winename, s.stock_delta) WHERE s.stock_delta > 0
WHEN MATCHED THEN
UPDATE SET stock = w.stock + s.stock_delta WHERE w.stock + s.stock_delta > 0;

merge into 支持分布式

MERGE INTO target t
USING source s
ON t.tid = s.sid
WHEN MATCHED THEN
        update set balance = t.balance + s.delta
WHEN NOT MATCHED THEN
        INSERT VALUES(s.sid, s.delta);

5.2.7. UPDATE

更新一个表的行

语法:

[ WITH [ RECURSIVE ] with_query [, ...] ]
UPDATE [ ONLY ] table_name [ * ] [ [ AS ] alias ]
        SET { column_name = { expression | DEFAULT } |
                ( column_name [, ...] ) = [ ROW ] ( { expression | DEFAULT } [, ...] ) |
                ( column_name [, ...] ) = ( sub-SELECT )
                } [, ...]
        [ FROM from_item [, ...] ]
        [ WHERE condition | WHERE CURRENT OF cursor_name ]
        [ ORDER BY expression [ ASC | DESC | USING operator ] [ NULLS { FIRST | LAST } ] [, ...] ]
        [ LIMIT { count | ALL } ]
        [ OFFSET start [ ROW | ROWS ] ]
        [ RETURNING * | output_expression [ [ AS ] output_name ] [, ...] ]

描述:

UPDATE更改满足条件的所有行中指定列 的值。只有要被修改的列需要在SET子句中提及, 没有被显式修改的列保持它们之前的值。

有两种方法使用包含在数据库其他表中的信息来修改一个表:使用子选择 或者在FROM子句中指定额外的表。这种技术只适合 特定的环境。

可选的RETURNING子句导致UPDATE 基于实际被更新的每一行计算并且返回值。任何使用该表的列以及 FROM中提到的其他表的列的表达式都能被计算。 计算时会使用该表的列的新(更新后)值。RETURNING 列表的语法和SELECT的输出列表相同。

你必须拥有该表上的UPDATE特权,或者至少拥有 要被更新的列上的该特权。如果任何一列的值需要被 expressions或者 condition读取, 你还必须拥有该列上的SELECT特权。

如果指定了 ORDER BY 子句,则可以按指定的顺序更新行。 它的语义类似于 SELECT 的 ORDER BY 子句。请注意,不支持在具有 ORDER BY 子句的继承表中进行更新,也不支持 Canopy。

如果指定了 LIMIT 或 OFFSET 子句,则可以更新行的子集。 它的语义类似于 SELECT 的 LIMIT 子句。 请注意,不支持在具有 LIMIT 或 OFFSET 子句的继承表中进行更新,也不支持 Canopy。

参数:

  • with_query

    WITH子句允许你指定一个或者更多个在 UPDATE中可用其名称引用的子查询。

  • table_name

    要更新的表的名称(可以是模式限定的)。如果在表名前指定了 ONLY,只会更新所提及表中的匹配行。如果没有指定 ONLY,任何从所提及表继承得到的表中的匹配行也会 被更新。可选地,在表名之后指定*可以显式地指示要 把后代表也包括在内。

  • alias

    目标表的一个替代名称。在提供了一个别名时,它会完全隐藏表的真实 名称。例如,给定UPDATE foo AS f, UPDATE语句的剩余部分必须用 f而不是foo来引用该表。

  • column_name

    指定表 table_name 中的列名。 如果需要,列名可以带有子字段名或数组下标。也可以使用别名来限定名称, 例如 UPDATE table_name AS t SET t.col = 1。 请勿在目标列的指定中包含表的名称, 例如 UPDATE table_name SET table_name.col = 1 是无效的。

  • expression

    要被赋值给该列的一个表达式。该表达式可以使用该表中这一列或者 其他列的旧值。

  • DEFAULT

    将该列设置为它的默认值(如果没有为它指定默认值表达式,默认值 将会为 NULL)。标识列将设置为关联序列生成的新值。 对于生成的列,允许指定此项,但仅指定从其生成表达式计算列的正常行为。

  • sub-SELECT

    一个SELECT子查询,它产生和在它之前的圆括号中列列表中 一样多的输出列。被执行时,该子查询必须得到不超过一行。如果它得到 一行,其列值会被赋予给目标列。如果它得不到行,NULL 值将被赋予给 目标列。该子查询可以引用被更新表中当前行的旧值。

  • from_item

    表表达式允许来自其他表的列出现在WHERE条件和更新表达式中。这使用与 SELECT语句的FROM 子句相同的语法;例如,可以指定表名的别名。不要将目标表作为from_list 重复,除非你想做自连接(这种情况下它必须以别名出现在from_list中)。

  • condition

    一个返回boolean类型值的表达式。让这个 表达式返回true的行将会被更新。

  • cursor_name

    要在WHERE CURRENT OF条件中使用的游标名。 要被更新的是从这个游标中最近取出的行。该游标必须是一个 在UPDATE目标表上的非分组查询。注意 WHERE CURRENT OF不能和一个布尔条件一起 指定。有关对游标使用WHERE CURRENT OF的 更多信息请见DECLARE。

  • output_expression

    在每一行被更新后,要被UPDATE命令计算并且返回 的表达式。该表达式可以使用 table_name指定 的表或者FROM列出的表中的任何列名。写* 可以返回所有列。

  • output_name

    用于一个被返回列的名称。

示例:

把表films的列kind 中的单词Drama改成Dramatic:

UPDATE films SET kind = 'Dramatic' WHERE kind = 'Drama';

在表weather的一行中调整温度项并且 把沉淀物重置为它的默认值:

UPDATE weather SET temp_lo = temp_lo+1, temp_hi = temp_lo+15, prcp = DEFAULT
WHERE city = 'San Francisco' AND date = '2003-07-03';

执行相同的操作并且返回更新后的项:

UPDATE weather SET temp_lo = temp_lo+1, temp_hi = temp_lo+15, prcp = DEFAULT
WHERE city = 'San Francisco' AND date = '2003-07-03'
RETURNING temp_lo, temp_hi, prcp;

使用另一种列列表语法来做同样的更新:

UPDATE weather SET (temp_lo, temp_hi, prcp) = (temp_lo+1, temp_lo+15, DEFAULT)
WHERE city = 'San Francisco' AND date = '2003-07-03';

为管理Acme Corporation账户的销售人员增加销售量,使用 FROM子句语法:

UPDATE employees SET sales_count = sales_count + 1 FROM accounts
WHERE accounts.name = 'Acme Corporation'
AND employees.id = accounts.sales_person;

执行相同的操作,在 WHERE子句中使用子选择:

UPDATE employees SET sales_count = sales_count + 1 WHERE id =
(SELECT sales_person FROM accounts WHERE name = 'Acme Corporation');

更新 accounts 表中的联系人姓名以匹配当前被分配的销售员:

UPDATE accounts SET (contact_first_name, contact_last_name) =
        (SELECT first_name, last_name FROM salesmen
        WHERE salesmen.id = accounts.sales_id);

可以用连接完成类似的结果:

UPDATE accounts SET contact_first_name = first_name,
                                        contact_last_name = last_name
FROM salesmen WHERE salesmen.id = accounts.sales_id;

不过,如果salesmen.id不是一个唯一键, 第二个查询可能会给出令人意外的结果,然而如果有多个id匹配, 第一个查询保证会发生错误。还有,如果对于一个特定的 accounts.sales_id项没有匹配,第一个查询将 把相应的姓名域设置为 NULL,而第二个查询完全不会更新该行。

更新一个统计表中的统计数据以匹配当前数据:

UPDATE summary s SET (sum_x, sum_y, avg_x, avg_y) =
        (SELECT sum(x), sum(y), avg(x), avg(y) FROM data d
        WHERE d.group_id = s.group_id);

尝试插入一个新库存项及其库存量。如果该项已经存在,则转而更新 已有项的库存量。要这样做并且不让整个事务失败,可以使用保存点:

BEGIN;
-- 其他操作
SAVEPOINT sp1;
INSERT INTO wines VALUES('Chateau Lafite 2003', '24');
-- 假定上述语句由于未被唯一键失败,
-- 那么现在我们发出这些命令:
ROLLBACK TO sp1;
UPDATE wines SET stock = stock + 24 WHERE winename = 'Chateau Lafite 2003';
-- 继续其他操作,并且最终
COMMIT;

更改表films中由游标c_films 定位的行的kind列:

UPDATE films SET kind = 'Dramatic' WHERE CURRENT OF c_films;

更新表 citys 中按 id 排序的前 5 条记录的 name 列。

UPDATE citys SET name = 'null' order by id LIMIT 5;

5.3. 事务控制语句

TCL语句

类型

概要

详细说明链接

是否支持

TCL

提交当前事务

COMMIT

支持

TCL

中止当前事务

ROLLBACK

支持

TCL

在当前事务中定义一个新的保存点

SAVEPOINT

支持

TCL

设置当前事务的特性

SET TRANSACTION

支持

TCL

为当前事务设置约束检查时机

SET CONSTRAINT

支持

5.3.1. COMMIT

提交当前事务

语法:

COMMIT [ WORK | TRANSACTION ] [ AND [ NO ] CHAIN ]

描述:

COMMIT提交当前事务。所有由该 事务所作的更改会变得对他人可见并且被保证在崩溃发生时仍能 持久。

参数:

  • WORK

  • TRANSACTION

    可选的关键词。它们没有效果。

  • AND CHAIN

    如果指定了AND CHAIN,则立即启动与刚刚完成的事务具有相同事务特征(参见SET TRANSACTION)的新事务。 否则,没有新事务被启动。

5.3.2. ROLLBACK

中止当前事务

语法:

ROLLBACK [ WORK | TRANSACTION ] [ AND [ NO ] CHAIN ]

描述:

ROLLBACK回滚当前事务并且导致 该事务所作的所有更新都被抛弃。

参数:

  • WORK

  • TRANSACTION

    可选关键词,没有效果。

  • AND CHAIN

    如果指定了AND CHAIN,则立即启动与刚刚完成事务具有相同事务特征(参见 SET TRANSACTION)的新事务。 否则,不会启动任何新事务。

5.3.3. SAVEPOINT

在当前事务中定义一个新的保存点

语法:

SAVEPOINT savepoint_name

描述:

SAVEPOINT在当前事务中建立一个新保存点。

保存点是事务内的一种特殊标记,它允许所有在它被建立之后执行的命令被 回滚,把该事务的状态恢复到它处于保存点时的样子。

参数:

  • savepoint_name

    给新保存点的名字。

示例:

要建立一个保存点并且后来撤销在它建立之后执行的所有命令的效果:

BEGIN;
        INSERT INTO table1 VALUES (1);
        SAVEPOINT my_savepoint;
        INSERT INTO table1 VALUES (2);
        ROLLBACK TO SAVEPOINT my_savepoint;
        INSERT INTO table1 VALUES (3);
COMMIT;

上面的事务将插入值 1 和 3,但不会插入 2。

要建立并且稍后销毁一个保存点:

BEGIN;
        INSERT INTO table1 VALUES (3);
        SAVEPOINT my_savepoint;
        INSERT INTO table1 VALUES (4);
        RELEASE SAVEPOINT my_savepoint;
COMMIT;

上面的事务将插入 3 和 4。

要使用单个保存点名称:

BEGIN;
        INSERT INTO table1 VALUES (1);
        SAVEPOINT my_savepoint;
        INSERT INTO table1 VALUES (2);
        SAVEPOINT my_savepoint;
        INSERT INTO table1 VALUES (3);

        -- rollback to the second savepoint
        ROLLBACK TO SAVEPOINT my_savepoint;
        SELECT * FROM table1;               -- shows rows 1 and 2

        -- release the second savepoint
        RELEASE SAVEPOINT my_savepoint;

        -- rollback to the first savepoint
        ROLLBACK TO SAVEPOINT my_savepoint;
        SELECT * FROM table1;               -- shows only row 1
COMMIT;

上述事务显示先回滚第三行,然后回滚第二行。

5.3.4. SET TRANSACTION

设置当前事务的特性

语法:

SET TRANSACTION transaction_mode [, ...]
SET TRANSACTION SNAPSHOT snapshot_id
SET SESSION CHARACTERISTICS AS TRANSACTION transaction_mode [, ...]

其中 transaction_mode 是下列之一:

        ISOLATION LEVEL { SERIALIZABLE | REPEATABLE READ | READ COMMITTED | READ UNCOMMITTED }
        READ WRITE | READ ONLY
        [ NOT ] DEFERRABLE

描述:

SET TRANSACTION命令设置当前 会话的特性。SET SESSION CHARACTERISTICS设置一个会话后续事务的默认 事务特性。在个体事务中可以用 SET TRANSACTION覆盖这些默认值。

可用的事务特性是事务隔离级别、事务访问模式(读/写或只读)以及 可延迟模式。此外,可以选择一个快照,不过只能用于当前事务而不能 作为会话默认值。

一个事务的隔离级别决定当其他事务并行运行时该事务能看见什么数据:

  • READ COMMITTED

    一个语句只能看到在它开始前提交的行。这是默认值。

  • REPEATABLE READ

    当前事务的所有语句只能看到这个事务中执行的第一个查询或者 数据修改语句之前提交的行。

  • SERIALIZABLE

    当前事务的所有语句只能看到这个事务中执行的第一个查询或者 数据修改语句之前提交的行。如果并发的可序列化事务间的读写 模式可能导致一种那些事务串行(一次一个)执行时不可能出现 的情况,其中之一将会被回滚并且得到一个 serialization_failure错误。

SQL 标准定义了一种额外的级别:READ UNCOMMITTED。在 LightDB中READ UNCOMMITTED被视作 READ COMMITTED。

一个事务执行了第一个查询或者数据修改语句( SELECT、 INSERT、DELETE、 UPDATE、FETCH或 COPY)之后就无法更改事务隔离级别。 更多有关事务隔离级别和并发控制的信息可见Chapter 13。

事务的访问模式决定该事务是否为读/写或者只读。读/写是默认值。 当一个事务为只读时,如果 SQL 命令 INSERT、UPDATE、 DELETE和COPY FROM 要写的表不是一个临时表,则它们不被允许。不允许 CREATE、ALTER以及 DROP命令。不允许COMMENT、 GRANT、REVOKE、 TRUNCATE。如果EXPLAIN ANALYZE 和EXECUTE要执行的命令是上述命令之一, 则它们也不被允许。这是一种高层的只读概念,它不能阻止所有对 磁盘的写入。

只有事务也是SERIALIZABLE以及 READ ONLY时,DEFERRABLE 事务属性才会有效。当一个事务的所有这三个属性都被选择时,该事务在 第一次获取其快照时可能会阻塞,在那之后它运行时就不会有 SERIALIZABLE事务的开销并且不会有任何牺牲或者 被一次序列化失败取消的风险。这种模式很适合于长时间运行的报表或者 备份。

SET TRANSACTION SNAPSHOT命令允许新的事务 使用与一个现有事务相同的快照运行。已经存在的事务 必须已经把它的快照用pg_export_snapshot函数导出。 该函数会返回一个快照标识符,SET TRANSACTION SNAPSHOT需要被给定一个快照标识符来指定要导入的快照。 在这个命令中该标识符必须被写成一个字符串,例如 ‘000003A1-1’。 SET TRANSACTION SNAPSHOT只能在一个事务的 开始执行,并且要在该事务的第一个查询或者数据修改语句( SELECT、 INSERT、DELETE、 UPDATE、FETCH或 COPY)之前执行。此外,该事务必须已经被设置 为SERIALIZABLE或者 REPEATABLE READ隔离级别(否则,该快照将被立刻抛弃, 因为READ COMMITTED模式会为每一个命令取一个新快照)。 如果导入事务使用了SERIALIZABLE隔离级别,那么导入快照 的事务必须也使用该隔离级别。还有,一个非只读可序列化事务不能导入来自只读 事务的快照。

示例:

要用一个已经存在的事务的同一快照开始一个新事务,首先要从该现有 事务导出快照。这将会返回快照标识符,例如:

BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ;
SELECT pg_export_snapshot();
pg_export_snapshot
---------------------
00000003-0000001B-1
(1 row)

然后在一个新开始的事务的开头把该快照标识符用在一个 SET TRANSACTION SNAPSHOT命令中:

BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ;
SET TRANSACTION SNAPSHOT '00000003-0000001B-1';

5.3.5. SET CONSTRAINTS

为当前事务设置约束检查时机

语法:

SET CONSTRAINTS { ALL | name [, ...] } { DEFERRED | IMMEDIATE }

描述:

SET CONSTRAINTS设置当前事务内约束检查 的行为。IMMEDIATE约束在每个语句结束时被检查。 DEFERRED约束直到事务提交时才被检查。每个约束都有 自己的IMMEDIATE或DEFERRED模式。

在创建时,一个约束会被给定三种特性之一: DEFERRABLE INITIALLY DEFERRED、 DEFERRABLE INITIALLY IMMEDIATE或者 NOT DEFERRABLE。第三类总是 IMMEDIATE并且不会受到 SET CONSTRAINTS命令的影响。前两类在每个 事务开始时都处于指定的模式,但是它们的行为可以在一个事务内用 SET CONSTRAINTS更改。

带有一个约束名称列表的SET CONSTRAINTS 只更改那些约束(都必须是可延迟的)的模式。每一个约束名称都可以是 模式限定的。如果没有指定模式名称,则当前的模式搜索路径将被用来寻找 第一个匹配的名称。SET CONSTRAINTS ALL 更改所有可延迟约束的模式。

当SET CONSTRAINTS把一个约束的模式从 DEFERRED改成IMMEDIATE时, 新模式会有追溯效果:任何还没有解决的数据修改(本来会在事务结束时 被检查)会转而在SET CONSTRAINTS命令 的执行期间被检查。如果任何这种约束被违背, SET CONSTRAINTS将会失败(并且不会改 变该约束模式)。这样,SET CONSTRAINTS可以被用来在一个事务中的特定点强制进 行约束检查。

当前,只有UNIQUE、PRIMARY KEY、 REFERENCES(外键)以及EXCLUDE 约束受到这个设置的影响。 NOT NULL以及CHECK约束总是在一行 被插入或修改时立即检查(不是在语句结束时)。 没有被声明为DEFERRABLE的唯一和排除约束也会被 立刻检查。

被声明为“约束触发器”的触发器的引发也受到这个设置 的控制 ? 它们会在相关约束被检查的同时被引发。

5.4. 会话控制语句

CSC语句

类型

概要

详细说明链接

是否支持

CSC

设置当前会话的当前用户标识符

SET ROLE

支持

CSC

创建一个分析视图

ALTER SESSION

暂不支持

5.4.1. SET ROLE

设置当前会话的当前用户标识符

语法:

SET [ SESSION | LOCAL ] ROLE role_name
SET [ SESSION | LOCAL ] ROLE NONE
RESET ROLE

描述:

这个命令把当前 SQL 会话的当前用户标识符设置为 role_name。 角色名可以写成一个标识符或者一个字符串。在 SET ROLE之后,对 SQL 命令的权限检查时就 好像该角色就是原先登录的角色一样。

当前会话用户必须是指定的 角色role_name 的一个成员(如果会话用户是一个超级用户,则可以选择任何角色)。

SESSION和LOCAL修饰符发挥的作用和常规的SET命令一样。

SET ROLE NONE设置当前用户标识符为当前会话用户标识符,由session_user返回。 RESET ROLE设置当前用户标识符为由command-line options、ALTER ROLE, 或ALTER DATABASE指定的连接时间设定,如果存在这样的设置的话。 否则,RESET ROLE设置当前用户标识符到当前会话用户标识符。 这些形式可以由任何用户执行。

示例:

SELECT SESSION_USER, CURRENT_USER;

session_user | current_user
--------------+--------------
peter        | peter

SET ROLE 'paul';

SELECT SESSION_USER, CURRENT_USER;

session_user | current_user
--------------+--------------
peter        | paul