SQL语言

SQL语言

这部分描述了SQL语言在PostgreSQL中的使用。我们从描述SQL的基础语法开始,然后解释如何创建结构来保存数据,如何填充数据库以及如何查询它。中间部分列出了用于SQL命令的可用数据类型和函数。剩余部分对于优化数据库以获得最佳性能非常重要。

这个部分的信息是被安排的,这样一个新手用户可以跟随它开始结束以获得对主题的充分理解,而不必过多的引用。这些章节的内容是独立的,所以高级用户可以在选择的时候单独阅读章节。这部分的信息以一种叙事的方式呈现在主题单元中。读者在寻找特定命令的完整描述时,应该看到第VI部分。

读者在这一部分应该知道如何连接到PostgreSQL数据库并发出SQL命令。不熟悉这些问题的读者会被鼓励阅读第一部分。SQL命令通常使用PostgreSQL交互式终端psql来输入,但是其他具有类似功能的程序也可以使用。

SQL语法

本章描述SQL语法。它为理解以下章节奠定了基础,接下来的章节将详细介绍如何应用SQL命令来定义和修改数据。

我们还建议已经熟悉SQL的用户仔细阅读本章,因为它包含了一些在SQL数据库中不一致地实现的规则和概念,或者是特定于PostgreSQL的。

词汇结构

SQL输入由一系列命令组成。命令由一系列标记组成,以分号(“;”)终止。输入流的末尾也终止一个命令。哪些标记是有效的,取决于特定命令的语法。

标记 可以是关键字标识符引用标识符文字(或常量)特殊字符符号。标记通常由空格(空格、制表符、换行符)分隔,但如果没有歧义(通常只有在特殊字符与其他token类型相邻的情况下),则不需要。

例如,以下是(语法上)有效的SQL输入:

1
2
3
SELECT * FROM MY_TABLE;
UPDATE MY_TABLE SET A = 5;
INSERT INTO MY_TABLE VALUES (3, 'hi there');

这是三个命令的序列,每一行代表一个命令(尽管这不是必需的;可以在一行上执行多个命令,并且可以有效地跨行分隔命令)。

此外,可以在SQL输入中进行注释 。它们不是tokens,实际上相当于空格。

对于标识命令、操作数或参数SQL语法并不十分一致。最初的几个标记通常是命令名,因此在上面的示例中,我们通常会提到SELECTUPDATEINSERT命令。但是,UPDATE命令总是需要一个SET标记出现在某个位置,而INSERT的特殊变量也需要VALUES才能完成。详细语法规则 分描述了每个命令的精确语法规则。

  1. 标识符和关键字

    在上面的示例中,诸如SELECTUPDATEVALUES之类的标记是关键字 的示例,也就是说,在SQL语言中具有固定含义的单词。MY_TABLE和A是标识符 的示例。它们根据所使用的命令来标识表、列或其他数据库对象的名称。因此,它们有时被简单地称为“名字”。关键字和标识符具有相同的语法结构,这意味着人们不知道标记是标识符还是不懂语言的关键字。关键字的完整列表可以在附录C 中找到。

    SQL标识符和关键字必须以字母开头(字母a-z,但同时还要有字母和非拉丁字母)或下划线(_)。标识符或关键字中的后续字符可以是字母、下划线、数字(0-9)或美元符号($)。注意,根据SQL标准的字母,标识符不允许使用美元符号,因此它们的使用可能会使应用程序变得更不轻便。SQL标准不会定义一个包含数字或开始或以下划线开头的关键词,因此,这种表单的标识符可以避免与将来的标准扩展冲突。

    该系统仅使用标识符的NAMEDATALEN-1字节;可以在命令中编写较长的名称,但它们将被截断,默认情况下,NAMEDATALEN 是64,因此最大标识符长度为63字节。如果这个限制是有问题的,可以通过更改src/include/pg_config_manul.h中的NAMEDATALEN 常量来提高。

    关键字和未引用的标识符是大小写不敏感的。因此:

    1
    UPDATE MY_TABLE SET A = 5;

    可以等价地写成:

    1
    uPDaTE my_TabLE SeT a = 5;

    一种常用的惯例是在大写字母和小写字母中写上关键词,例如:

    1
    UPDATE my_table SET a = 5;

    还有第二种标识符:分隔标识符或引用标识符。它是通过在双引号(“)中包含任意字符序列来形成的。分隔符始终是标识符,而不是关键字。因此,“select”可以用来引用一个名为“select”的列或表,而未引用的select将被当作一个关键字,因此当使用表或列名时,会引发解析错误。这个例子可以用引号来表示:

    1
    UPDATE "my_table" SET "a" = 5;

    引用的标识符可以包含任何字符,除了代码为零的字符。(包括双引号,两个双引号)这允许构造表或列名,否则将不可能,例如包含空格或符号的字段。长度限制仍然适用。

    引用的标识符的一个变量允许包括由其代码点标识的转义Unicode字符。此变量从u&(大小写U后面跟着ampersand)开始,然后在打开双引号之前,在中间没有任何空格,例如u&“foo”。(注意,这会给操作人员带来歧义。使用周围的空间来避免这个问题。在引号内,可以通过写反斜杠来指定Unicode字符,后跟4个十六进制代码点数或反斜杠,后跟一个加号,后跟一个6位数的十六进制代码点。例如,标识符“数据”可以写成。

    1
    U&"d\0061t\+000061"

    下面这个不那么简单的例子是用古希腊字母写的俄文“slon”(大象):

    1
    U&"\0441\043B\043E\043D"

    如果需要一个不同的转义字符,那么可以在字符串后面使用UESCAPE子语句指定它,例如:

    1
    U&"d!0061t!+000061" UESCAPE '!'

    转义字符可以是任何单个字符,而不仅仅是十六进制数字、加号、单引号、双引号或空格字符。注意,转义字符是用单引号写的,而不是双引号。

    要在标识符中包含转义字符,请写两次。

    只有当服务器编码为UTF8时,Unicode转义语法才起作用。当使用其他服务器编码时,可以指定ASCII范围内的代码点(最高为\007F)。4位和6位的形式都可以用来指定UTF-16的代理对,用比U+FFFF更大的代码点组成字符,尽管6位数字形式的可用性使得这没有必要。(代理对并不是直接存储的,而是将其组合成一个代码点,然后用UTF-8编码。)

    引用一个标识符也会使它区分大小写,而未引用的名称总是被折叠到小写。例如,标识符FOO、Foo和“Foo”在PostgreSQL中被认为是相同的,但是“Foo”和“FOO”不同于这三者和彼此。(在PostgreSQL中,未引用的名称的折叠是与SQL标准不兼容的,这意味着未引用的名称应该折叠到大写。因此,foo应该等同于“FOO”而不是“foo”。如果您想编写可移植的应用程序,建议您总是引用一个特定的名称,或者永远不要引用它。

  2. 常量

    PostgreSQL中有三种隐含类型常量:字符串、位串和数字。常量还可以使用显式类型指定,这可以使系统更准确地表示和更有效地处理。下面的小节将讨论这些替代方案。

    • 字符串常量

      SQL中的字符串常量是由单引号(‘)绑定的任意字符序列,例如'This is A string'。要在一个字符串常量中包含一个单引号字符,可以写两个相邻的单引号,例如,’Dianne’’ s horse’。请注意,这与双引号字符(“)不一样。

      两个仅由空格分隔的字符串常量,其中至少有一条新行被连接并有效地处理,就像字符串被写成一个常量一样。例如:

      1
      2
      SELECT 'foo'
      'bar';

      等价于:

      1
      SELECT 'foobar';

      但是:

      1
      SELECT 'foo'      'bar';

      这是无效的语法。(这有点奇怪的行为是由SQL指定的;PostgreSQL遵循标准。)

    • 带有C风格的字符串常量

      PostgreSQL还接受“escape”字符串常量,这是对SQL标准的扩展。一个转义字符串常数是通过写字母E(大写或小写)来指定的,就在开头的单引号之前,例如,E'foo。(当在一行中继续执行一个转义字符串时,在第一个开头引用之前写E)。在一个转义字符串中,一个反斜杠字符()开始一个类似于c的反斜杠转义序列,其中反斜杠和跟随字符的组合表示一个特殊的字节值,如表2.1所示

      表2.1反斜杠转义序列



























      反斜杠转义序列 说明
      \bbackspace
      \fform feed
      \nnewline
      \rcarriage return
      \ttab
      \o,\oo,\ooo(o = 0 - 7)octal byte value
      \xh,\xhh(h = 0 - 9, A - F)hexadecimal byte value
      \uxxxx,\Uxxxxxxxx(x = 0 - 9, A - F)16 or 32bit hexadecimal Unicode character value

      在反斜杠后面的任何其他字符都是按字面意思执行的。因此,要包含反斜杠字符,可以写两个反斜杠(\\)。另外,一个单引号可以包含在一个转义字符串中,除了正常的方式外,还可以写\\

      你的职责是创建的字节序列,特别是在使用八进制或十六进制转义时,在服务器字符集编码中组成有效的字符。当服务器编码为UTF-8时,则应该使用上节中解释的Unicode转义或替代的Unicode转义语法。(另一种方法是手工编写UTF-8编码,并将字节写出来,这将非常麻烦。)

      只有当服务器编码为UTF8时,Unicode转义语法才有效。当使用其他服务器编码时,只能指定ASCII范围内的代码点(最高为\u007F)。4位和8位的形式都可以用来指定UTF-16代理对,以比U+FFFF更大的代码点组成字符,尽管8位数字形式的可用性使得这没有必要。(当服务器编码为UTF8时使用代理对时,首先将它们组合成一个单独的代码点,然后用UTF-8编码。)

      代码为0的字符不能在字符串常量中。

    • 使用Unicode转义的字符串常量

      PostgreSQL还支持另一种用于字符串的转义语法,它允许通过代码指定任意的Unicode字符。一个Unicode的转义字符串常量从u&(上或小写字母U后面跟着ampersand)开始,在引号前面没有空格,例如u&’ foo。(注意,这会给操作人员带来歧义。使用周围的空间来避免这个问题。在引号内,可以通过写反斜杠来指定Unicode字符,后跟4个十六进制代码点数或反斜杠,后跟一个加号,后跟一个6位数的十六进制代码点。例如,字符串’data’可以写成。

      1
      U&'d\0061t\+000061'

      下面这个不那么简单的例子是用古希腊写的俄文“slon”(大象):

      1
      U&'\0441\043B\043E\043D'

      如果需要一个不同的转义字符,那么可以在字符串后面使用UESCAPE子语句指定它,例如:

      1
      U&'d!0061t!+000061' UESCAPE '!'

      转义字符可以是任何单个字符,而不是十六进制数字、加号、单引号、双引号或空格字符。

      只有当服务器编码为UTF8时,Unicode转义语法才起作用。当使用其他服务器编码时,可以指定ASCII范围内的代码点(最高为\007F)。4位和6位的形式都可以用来指定UTF-16的代理对,用比U+FFFF更大的代码点组成字符,尽管6位数字形式的可用性使得这没有必要。(当服务器编码为UTF8时使用代理对时,首先将它们组合成一个单独的代码点,然后用UTF-8编码。)

      此外,只有当配置参数standard_conforming_strings打开时,字符串常量的Unicode转义语法才会起作用。这是因为否则这种语法会使解析SQL语句的客户机感到迷惑,从而导致SQL注入和类似的安全问题。如果将参数设置为off,则将使用错误消息拒绝此语法。

      要在字串中包含转义字符,请写两次。

    • Dollar-quoted字符串常量

      虽然指定字符串常量的标准语法通常很方便,但是当所需的字符串包含许多单引号或反斜杠时,就很难理解了,因为每个字符串都必须加倍。为了在这种情况下允许更可读的查询,PostgreSQL提供了另一种方法,称为“引用美元”,以编写字符串常量。一个美元引用的字符串常量由一个美元符号($)组成,一个可选的零或多个字符的“标记”,另一个美元符号,组成字符串内容的任意字符序列,一个美元符号,开始这一美元报价的相同标签,和一个美元符号。例如,这里有两种不同的方法来指定字符串“Dianne的马”,使用$引用:

      1
      2
      $$Dianne's horse$$
      $SomeTag$Dianne's horse$SomeTag$

      注意,在美元引用的字符串中,可以使用单引号而不需要转义。事实上,一个美元引用的字符串中没有任何字符被转义:字符串内容总是按字面意思写的。反斜杠并不是特别的,美元符号也不是特别的,除非它们是与开始标签匹配的序列的一部分。

      通过在每个嵌套级别上选择不同的标记,可以使用美元引用的字符串常量。这在编写函数定义时最常用。例如:

      1
      2
      3
      4
      5
      $function$
      BEGIN
      RETURN ($1 ~ $q$[\t\r\n\v\\]$q$);
      END;
      $function$

      在这里,序列$q$[\t\r\n\v\\]$q$表示一个美元引用的字符串[\t\r\n\v\\]。但是由于这个序列与外部美元的函数值不匹配,所以它只是在外部字符串的范围内的一些字符。

      标签,如果有的话,一个美元引用的字符串遵循与未引用的标识符相同的规则,只是它不能包含一个美元符号。标签是区分大小写的,所以$tag$String content$tag$是正确的,但是$tag$String content$tag$不是。

      引用一个关键字或标识符的美元引用的字符串必须与空格分开;否则,引用分隔符的美元将作为前面标识符的一部分。

      引用美元不是SQL标准的一部分,但它通常比标准兼容的单引号语法更方便地编写复杂的字符串。当在其他常量中表示字符串常量时,它特别有用,因为在过程函数定义中经常需要这样做。使用单引号语法,上面的示例中的每个反斜杠都必须写成4个反斜杠,在解析原始字符串常量时,将减少为两个反斜杠,然后在函数执行期间重新解析内字符串常量时,将其改为1。

    • 位串常量

      在打开引号之前(不插入空格),例如B'1001',位串常量看起来就像普通的字符串常量(大写或小写)。在位串常量中允许的唯一字符是0和1。

      或者,可以用十六进制表示法来指定位串常量,前面使用的X(大写或小写),例如X'1FF'。这个符号相当于一个位串常数,每个十六进制数字的四位二进制数字。

      这两种类型的位串常数都可以像普通的字符串常量一样以相同的方式继续。美元引用不能用在位串常数中。

    • 数字常量

      数值常量在这些一般形式中被接受:

      1
      2
      3
      4
      digits
      digits.[digits][e[+-]digits]
      [digits].digits[e[+-]digits]
      digitse[+-]digits

      如果数字是一个或多个十进制数字(0到9),至少一个数字必须在小数点之前或之后,如果使用了一个数字。如果出现一个数字,至少有一个数字必须跟随指数标记(e)。不能有任何空格或其他字符嵌入在常量中。注意,任何正负号都不被认为是常数的一部分;它是一个应用于常数的算子。

      这些是一些有效的数值常量的例子:
      42
      3.5
      4.
      .001
      5e2
      1.925e-3

      一个既不包含小数点也不包含指数的数值常量,如果它的值符合integer(32位),则最初假定为整数类型;否则,如果其值符合bigint类型(64位),则假定为类型bigint;否则,它被认为是numeric的。包含小数点和/或指数的常量最初被假定为类型数值。

      数字常量的初始指定数据类型只是类型解析算法的起点。在大多数情况下,根据上下文,常量会自动被强制到最合适的类型。当需要时,您可以强制将一个数字值转换为特定的数据类型。例如,您可以通过写入来强制将数值处理为类型real (float4):

      1
      2
      REAL '1.23'  -- string style
      1.23::REAL -- PostgreSQL (historical) style

      这些实际上只是接下来讨论的一般铸造符号的特殊情况。

    • 其他类型的常量

      任意类型的arbitrary 可以使用下列任何一种符号来输入:

      1
      2
      3
      type 'string'
      'string'::type
      CAST ( 'string' AS type )

      字符串常量的文本被传递给类型为类型的输入转换例程。结果是指定类型的常数。如果对常量的类型没有歧义(例如,当它被直接分配到表列时),则可以省略显式类型转换(例如,当它被直接分配到表列时),在这种情况下它是自动强制的。

      字符串常量可以使用常规SQL符号或美元引用来编写。

      还可以使用类似函数的语法指定类型强制:

      1
      typename ( 'string' )

      但并不是所有类型的名称都可以这样使用;

      ::,CAST()和函数调用语法也可以用来指定任意表达式的运行时类型转换,为了避免语法歧义,只能使用'string'类型语法来指定简单的文字常量的类型。语法的另一个限制是,它不能用于数组类型;使用::CAST()来指定数组常量的类型。

      CAST()语法符合SQL。'string'类型语法是标准的一般化:SQL仅为少数数据类型指定此语法,但PostgreSQL允许对所有类型进行此语法。语法与::是历史的PostgreSQL用法,与函数调用语法一样。

  3. 操作符

    操作符名称是由以下列表中的NAMEDATALEN-1(默认63) 字符组成的序列:
    + - * / < > = ~ !@ # % ^ & | ?
    不过,对操作员的名字有一些限制:

    • –并且/*不能以操作符的名字出现在任何地方,因为它们将作为注释的开始。
    • 一个多字符的操作符名称不能以+或-的形式结束,除非这个名称至少包含其中一个字符:~ !@ # % & | ' ?
      例如,@是一个允许的操作符名称,但是*-不是。此限制允许PostgreSQL解析符合sql的查询,而不需要在令牌之间进行空格。

      在使用非sql标准的操作符名称时,通常需要将相邻的操作符与空格分开以避免歧义。例如,如果定义了一个名为@的左操作符,您就不能写入X@y;必须编写X@Y以确保PostgreSQL将其视为两个操作符而不是一个。

  4. 特殊字符

    一些不是字母数字的字符有一个特殊的含义,它与作为一个操作符不同。有关用法的详细信息可以在描述相应语法元素的位置找到。这一节只存在于建议存在和总结这些人物的目的。

    • 一个美元符号($)后面跟着数字,用来表示函数定义或准备语句中的位置参数。在其他情况下,美元符号可以是标识符或美元引用的字符串常量的一部分。

    • 括号(())具有对组表达式和强制优先级的通常意义。在某些情况下,括号是特定SQL命令的固定语法的一部分。

    • 方括号([])用于选择数组的元素。

    • 逗号(,)用于一些语法结构,以分隔列表的元素。

    • 分号(;)终止一个SQL命令。它不能出现在命令内的任何地方,除非在字符串常量或引用的标识符中。

    • 冒号(:)用于从数组中选择“切片”。(参见8.15节)。在某些SQL方言(如嵌入式SQL)中,冒号用于前缀变量名。

    • 在某些上下文中使用星号(*)表示表行或复合值的所有字段。当用作聚合函数的参数时,它也有特殊意义,即聚合不需要任何显式参数。

    • 期间(.)用于数值常量,并将模式、表和列名分开。

  5. 注释

    注释是一个字符序列,从双破折号开始,延伸到行尾,例如:

    1
    -- This is a standard SQL comment

    或者,可以使用c风格的块注释:

    1
    2
    3
    /* multiline comment
    * with nesting: /* nested block comment */
    */

    注释以/开头,并扩展到/的匹配发生。这些块注释嵌套在SQL标准中指定,但与C不同,因此可以注释掉可能包含现有块注释的更大的代码块。

    在进一步的语法分析之前,注释将从输入流中删除,并有效地替换为空白。

  6. 运算符优先级

    表4.2 显示了PostgreSQL中操作符的优先级和关联性。大多数操作符具有相同的优先级,并且是左关联的。操作符的优先级和结合性是硬连接到解析器的。

    在使用二进制和一元运算符的组合时,有时需要添加圆括号。例如:

    1
    SELECT 5 ! - 6;

    将解析:

    1
    SELECT 5 ! (- 6);

    因为解析器不知道——直到它太迟了!定义为后缀操作符,而不是插入操作符。要想在这种情况下获得所需的行为,您必须编写:

    1
    SELECT (5 !) - 6;

    这是为可扩展性付出的代价。

    表4.2。操作员优先级(最高到最低)















































    操作员/元素结合性描述
    .left表、列名称分隔器
    ::leftPostgreSQL-style定型
    [ ]left数组元素的选择
    + -right一元加一元减
    ^left乘方
    * / %left乘、除、模
    + -left加、减
    (any other operator)left所有其他本地和用户定义的操作符
    BETWEEN IN LIKE ILIKE SIMILAR 范围控制,设置成员,字符串匹配
    < > = <= >= <> 比较运算符
    IS ISNULL NOTNULL IS TRUE, IS FALSE, IS NULL, IS DISTINCT FROM, 等
    NOTright逻辑非
    ANDleft逻辑与
    ORleft逻辑或

    注意,操作符优先规则也适用于与上面提到的内置操作符同名的用户定义的操作符。例如,如果您为某些自定义数据类型定义了一个“+”操作符,那么它将具有与内置“+”操作符相同的优先级,无论您的操作是什么。

    在操作符语法中使用模式限定的操作符名称时,例如:

    1
    SELECT 3 OPERATOR(pg_catalog.+) 4;

    对于“任何其他操作符”,操作符构造被认为具有表4.2所示的默认优先级。无论哪个特定的操作符出现在运算符()中,这都是真的。

值表达式

值表达式在各种上下文中使用,例如在SELECT命令的目标列表中,在新的列值中使用INSERT或UPDATE,或者在一些命令中使用搜索条件。值表达式的结果有时被称为标量,以区别于表表达式的结果(这是一个表)。因此,值表达式也被称为标量表达式(或者甚至是简单的表达式)。表达式语法允许使用算术、逻辑、集合和其他操作计算原始部件的值。

一个值表达式是以下内容之一:

  • 常量或文字值

  • 列引用

  • 位置参数引用,在函数定义或准备语句的正文中

  • 一个下标表达式

  • 一个字段选择表达式

  • 操作符调用

  • 一个函数调用

  • 一个聚合表达式

  • 一个窗口函数调用

  • 一种投

  • 排序规则表达式

  • 标量子查询

  • 一个数组构造函数

  • 一行的构造函数

  • 括号中的另一个值表达式(用于组子表达式和重写优先级)

除了这个列表之外,还有一些结构可以被分类为一个表达式,但是不遵循任何一般的语法规则。

我们在上节中讨论了的常数。下面几节讨论剩下的选项。

  1. 列引用

    一列可以在表格中引用:

    1
    correlation.columnname

    相关性 是表的名称(可能符合模式名),或由FROM子句定义的表的别名。如果在当前查询中使用的所有表的列名是惟一的,则可以省略相关名称和分离点。

  2. 位置参数

    位置参数引用用于指示从外部向SQL语句提供的值。参数用于SQL函数定义和准备查询中。一些客户端库还支持从SQL命令字符串中单独指定数据值,在这种情况下,用例参数来引用脱机数据值。参数引用的形式为:

    1
    $number

    例如,考虑函数的定义,dept, as:

    1
    2
    3
    CREATE FUNCTION dept(text) RETURNS dept
    AS $$ SELECT * FROM dept WHERE name = $1 $$
    LANGUAGE SQL;

    当调用函数时,$1引用第一个函数参数的值。

  3. 下标

    如果表达式产生一个数组类型的值,那么可以通过写入来提取数组值的特定元素。

    1
    expression[subscript]

    或多个相邻元素(一个“数组片”)可以通过写入来提取

    1
    expression[lower_subscript:upper_subscript]

    (这里,括号[]是按字面意思显示的。)每个子脚本本身就是一个表达式,它必须产生一个整数值。

    一般来说,数组表达式必须是圆括号的,但是当表达式为下标的表达式只是一个列引用或位置参数时,括号可以省略。此外,当原始数组是多维的时,可以连接多个下标。例如:

    1
    2
    3
    4
    mytable.arraycolumn[4]
    mytable.two_d_column[17][34]
    $1[10:42]
    (arrayfunction(a,b))[42]

    最后一个示例中的括号是必需的。

  4. 选择字段

    如果表达式产生一个复合类型的值(row类型),那么可以通过写入来提取该行的特定字段。

    1
    expression.fieldname

    一般来说,行表达式必须是圆括号,但是当从表引用或位置参数中选择表达式时,括号可以省略。例如:

    1
    2
    3
    mytable.mycolumn
    $1.somecolumn
    (rowfunction(a,b)).col3

    (因此,一个合格的列引用实际上只是字段选择语法的一个特例)。一个重要的特殊情况是从一个组合类型的表列中提取字段:

    1
    2
    (compositecol).somefield
    (mytable.compositecol).somefield

    这里需要圆括号来显示compositecol是一个列名,而不是一个表名,或者mytable是一个表名,而不是第二个例子中的模式名。

    你可以通过写作.*来要求一个复合值的所有字段:

    1
    (compositecol).*

    这种表示法根据上下文不同而不同。

  5. 操作符调用

    对于操作员调用,有三种可能的语法:

    表达式运算符表达式(二进制infix运算符)
    运算符表达式(一元前缀运算符)
    表达式运算符(unary postfix运算符)

    操作符令牌的语法规则,或为关键字 AND,OR,and NOT,或为表单中的合格操作符名称:

    1
    OPERATOR(schema.operatorname)

    存在特定的操作符,它们是一元的还是二进制的,取决于操作符由系统或用户定义。

  6. 函数调用

    函数调用的语法是一个函数的名称(可能符合模式名),然后是它的参数列表,括在括号中:

    1
    function_name ([expression [, expression ... ]] )

    例如,下面计算2的平方根:

    1
    sqrt(2)
  7. 聚合表达式

    聚合表达式 表示在查询选择的行之间应用聚合函数。聚合函数将多个输入降低为单个输出值,例如输入的总和或平均值。聚合表达式的语法如下:

    1
    2
    3
    4
    5
    aggregate_name (expression [ , ... ] [ order_by_clause ] ) [ FILTER ( WHERE filter_clause ) ]
    aggregate_name (ALL expression [ , ... ] [ order_by_clause ] ) [ FILTER ( WHERE filter_clause ) ]
    aggregate_name (DISTINCT expression [ , ... ] [ order_by_clause ] ) [ FILTER ( WHERE filter_clause ) ]
    aggregate_name ( * ) [ FILTER ( WHERE filter_clause ) ]
    aggregate_name ( [ expression [ , ... ] ] ) WITHIN GROUP ( order_by_clause ) [ FILTER ( WHERE filter_clause ) ]

    aggregate_name 是以前定义的聚合(可能符合模式名称),表达式是任何不包含聚合表达式或窗口函数调用的值表达式。可选的order_by_clausefilter_clause 描述如下。

    聚合表达式的第一种形式为每个输入行调用一次聚合。第二个表单与第一个表单相同,因为所有的都是默认的。第三个表单将对输入行中发现的表达式的每个不同值(或不同的值集合)调用一次聚合。第四种形式为每个输入行调用一次聚合;由于没有指定特定的输入值,因此通常只对count(*)聚合函数有用。最后一种形式使用有序集聚合函数,如下所示。

    大多数聚合函数都忽略null输入,因此,在其中一个或多个表达式产生null的行被丢弃。这可以假定为真,除非另有规定,对于所有内置的集合。

    例如,count(*)会产生输入行的总数;count(f1)产生的输入行数,f1是 non-null,因为count忽略了null;并且count(distinct f1)产生了f1的不同非空值的数目。

    通常,输入行以未指定的顺序输入聚合函数。在许多情况下,这并不重要;例如,不管输入什么顺序,min都会产生相同的结果。但是,一些聚合函数(例如array_agg和string_agg)产生的结果依赖于输入行的顺序。在使用这样的聚合时,可以使用可选order_by_clause指定所需的排序。order_by_clause语法与查询级顺序相同,只是它的表达式总是表达式,不能是输出列名称或数字。例如:

    1
    SELECT array_agg(a ORDER BY b DESC) FROM table;

    在处理多参数聚合函数时,请注意,ORDER BY子句要处理所有的聚合参数。例如,写这个:

    1
    SELECT string_agg(a, ',' ORDER BY a) FROM table;

    而不是:

    1
    SELECT string_agg(a ORDER BY a, ',') FROM table;  -- incorrect

    后者在语法上是有效的,但是它代表了一个单参数聚合函数的调用,它有两个键的顺序(第二个是无用的,因为它是一个常量)。

    如果除了order_by_caluse之外,还指定了DISTINCT,那么所有ORDER BY表达式的所有顺序都必须匹配聚合的正则参数;也就是说,不能对不包含在不同列表中的表达式DISTINCT排序。

  8. 调用窗口函数

  9. 圆柱型
  10. 排序规则表达式
  11. 标量子查询
  12. 数组构造函数
  13. 行构造函数
  14. 表达式求值规则

函数调用

  1. 使用按位记数法
  2. 使用命名符号
  3. 使用复合符号

数据定义

表基础知识

默认值

约束

  1. 约束检查
  2. 非空(Not-Null)约束
  3. 唯一值约束
  4. 主键
  5. 外键
  6. 排除约束

系统列

修改表

  1. 添加列
  2. 删除列
  3. 添加约束
  4. 删除约束
  5. 更改列的默认值
  6. 更改列的数据类型
  7. 重命名列
  8. 重命名表

特权

行安全策略

模式

  1. 创建模式
  2. 公共模式
  3. 模式搜索路径
  4. 模式和特权
  5. 系统目录模式
  6. 使用模式
  7. 可移植性

继承

  1. 警告

表分区

  1. 概述
  2. 声明式分区
  3. 使用继承实现
  4. 分区和约束排斥

外部值

其他数据库对象

依赖跟踪

数据操作

插入数据

更新数据

删除数据

返回修改行数据

查询

概述

表表达式

  1. FROM子语句
  2. WHERE子语句
  3. GROUP BY和HAVING子语句
  4. GROUPING SETS,CUBE和ROLLUP
  5. 窗口处理函数

选择列表

  1. 选择列表项
  2. 列标签
  3. DISTINCT

组合查询

行排序

限制和偏移量

值列表

WITH查询(常有表表达式)

  1. 用WITH选择
  2. 用WITH修改数据状态

函数和运算符

逻辑运算符

比较函数和运算符

数学函数和运算符

字符串函数和运算符

二进制字符串函数和运算符

字节函数和运算符

模式匹配

数据类型格式函数

日期/时间函数和运算符

枚举支持函数

几何函数和运算符

网络地址函数和运算符

文本搜索函数和操作符

XML函数

JSON函数和运算符

序列操作函数

条件表达式

数组函数和运算符

范围函数和运算符

聚合函数

窗口函数

子查询表达式

行和数组比较

设置返回函数

系统信息函数

系统管理函数

触发函数

事件触发函数

类型转换

概述

运算操作

函数

值存储

UNION、CASE和相关构造

选择输出列

索引

简介

索引类型

多列索引

索引和ORDER BY

结合多个索引

唯一值索引

索引表达式

部分索引

操作类和操作家族

索引和排序

唯一索引查看

检查索引使用

全文检索

简介

  1. 文档是什么?
  2. 基本的文档匹配
  3. 配置

表和索引

  1. 查询表
  2. 创建索引

控制全文检索

  1. 解析文档
  2. 解析查询
  3. 查询结果排名
  4. 强调结果

其他特性

  1. 文档操作
  2. 查询操作
  3. 触发自动更新
  4. 收集文档统计信息

解析器

字典

  1. 停止词
  2. Simple字典
  3. Synonym字典
  4. Thesaurus字段
  5. Ispell字典
  6. Snowball字典

配置示例

测试和调试文本搜索

  1. 配置测试
  2. 解析测试
  3. 字典测试

GIN和GiST索引类型

psql支持

限制

并发控制

简介

事物隔离

  1. 读取提交隔离级别
  2. 可重复度隔离级别
  3. 可序列化隔离级别

显示锁

  1. 表级别锁
  2. 行级别锁
  3. 页面级别锁
  4. 死锁
  5. 咨询锁

在应用级别下的数据一致性检查

  1. 执行与可序列化事务的一致性
  2. 强制执行与显式阻塞锁的一致性

警告

锁定和索引

性能技巧

使用说明

  1. 使用基础
  2. 使用分析
  3. 警告

Planner使用的统计

  1. 单列数据统计
  2. 可扩展的信息统计

使用显式连接子句控制计划程序

填充一个数据库

  1. 禁止自动提交
  2. 使用COPY
  3. 删除索引
  4. 删除外键约束
  5. 增加maintenance_work_mem
  6. 增加max_wal_size
  7. 禁用WAL_Archival和流复制
  8. 运行ABALYZE
  9. 关于pg_dump笔记

非持久设置

并行查询

并行查询是如何工作的

何时可以使用并行查询?

并行计划

  1. 并行扫描
  2. 并行连接
  3. 并行聚合
  4. 并行计划建议

并行安全