VastbaseG100

基于openGauss内核开发的企业级关系型数据库。

Menu

SELECT

功能描述

SELECT用于从表或视图中查询数据。

SELECT语句就像叠加在数据库表上的过滤器,利用SQL关键字从数据表中过滤出用户需要的数据。

注意事项

  • 需要对每个在SELECT命令中使用的字段具有SELECT权限。
  • 使用FOR UPDATE,FOR NO KEY UPDATE,FOR SHARE或FOR KEY SHARE还要求UPDATE权限。

语法格式

  • 查询数据

    [ WITH [ RECURSIVE ] with_query [, ...] ]
    SELECT [/*+ plan_hint */] [ ALL | DISTINCT | UNIQUE [ ON ( expression [, ...] ) ] ]
        { * | {expression [ [ AS ] output_name ]} [, ...] }
        [ FROM from_item [, ...] ]
        [START WITH condition CONNECT BY PRIOR condition]
        [ WHERE condition ]
        [ [ START WITH condition ] CONNECT BY condition [ ORDER SIBLINGS BY expression ] ]
        [ 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 ] | nlssort_expression_clause ] [ NULLS {
    FIRST | LAST } ]} [, ...] ]
        [ LIMIT { [offset,] count | ALL } ]
        [ OFFSET start [ ROW | ROWS ] ]
        [ FETCH { FIRST | NEXT } [ count ] { ROW | ROWS } ONLY ]
        [ { FOR { UPDATE | NO KEY UPDATE | SHARE | KEY SHARE } [ OF table_name [, ...] ] [ NOWAIT | WAIT N | SKIP LOCKED]} [...] ]
    TABLE { ONLY { (table_name) | table_name } | table_name [ * ]};
    

    condition和expression中可以使用targetlist中表达式的别名。

    • 只能同一层引用。
    • 只能引用targetlist中的别名。
    • 只能是后面的表达式引用前面的表达式。
    • 不能包含volatile函数。
    • 不能包含Window function函数。
    • 不支持在join on条件中引用别名。
    • targetlist中有多个要应用的别名则报错。
  • 其中子查询with_query为:

    with_query_name [ ( column_name [, ...] ) ] AS [ [ NOT ] MATERIALIZED ] ( {select | values | insert | update | delete} )
    
  • 其中指定查询源from_item为:

    {[ ONLY ] table_name [ * ] [ partition_clause ] [ [ AS ]alias [ ( column_alias [, ...] ) ] ]
    [ TABLESAMPLE sampling_method ( argument [, ...] ) [ REPEATABLE (seed ) ] ]
    |( select ) [ AS ] alias [ ( column_alias [, ...] ) ]
    |with_query_name [ [ AS ] alias [ ( column_alias [, ...] ) ]]
    |function_name ( [ argument [, ...] ] ) [ AS ] alias [ (column_alias [, ...] | column_definition [, ...] ) ]
    |function_name ( [ argument [, ...] ] ) AS ( column_definition[, ...] )
    |from_item [ NATURAL ] join_type from_item [ ON join_condition |USING ( join_column [, ...] ) ]}
    
  • 其中group子句为:

    expression
    | ( expression [, ...] )
    | ROLLUP ( { expression | ( expression [, ...] ) } [, ...] )
    | CUBE ( { expression | ( expression [, ...] ) } [, ...] )
    | GROUPING SETS ( grouping_element [, ...] )
    
  • 其中指定分区partition_clause为:

    PARTITION { ( partition_name ) |
    FOR ( partition_value [, ...] ) }
    

    指定分区只适合分区表。

  • 其中设置排序方式nlssort_expression_clause为:

    NLSSORT ( column_name, ' NLS_SORT = { SCHINESE_PINYIN_M |generic_m_ci } ' )
    
  • 简化版查询语法,功能相当于select * from table_name

    TABLE { ONLY {(table_name)| table_name} | table_name [ * ]}; 	
    
  • 在MySQL兼容模式下,支持如下语法:

    • 该语法仅在数据库兼容模式为MySQL时支持(即数据库实例初始化时指定DBCOMPATIBILITY='B')。
    • 该语法仅在Vastbase G100 V2.2 Build 10(Patch No.9)及以后版本支持。
    • 有关该语法的详细内容请参考MySQL兼容性IGNORE|FORCE INDEX语法
    table_name [ { FORCE | IGNORE } { INDEX | KEY } (index_hint_list) | USE { INDEX | KEY } (opt_index_hint_list) ]
    

    index_hint_list:

    index[,index...]
    

    opt_index_hint_list:

    empty or index_hint_list
    

参数说明

  • WITH [ RECURSIVE ] with_query [, …]

    用于声明一个或多个可以在主查询中通过名称引用的子查询,相当于只在主查询中存在的临时表,其可以将复杂的查询简化。

    其中with_query的详细格式为:

    with_query_name [ ( column_name [, ...] ) ] AS ( {select | values | insert | update | delete} )
    
    • with_query_name指定子查询生成的结果集名称,在查询中可使用该名称访问子查询的结果集。

    • column_name指定子查询结果集中显示的列名。

    • 每个子查询可以是SELECT,VALUES,INSERT,UPDATE或DELETE语句。

    如果声明了RECURSIVE,那么允许AS后的SELECT子查询通过名称引用自己,详细格式为:

    non_recursive_term UNION [ ALL | DISTINCT ] recursive_term
    
    • 即由非递归项、UNION、递归项组成
    • 只有递归项中可以引用自己
    • 每个查询中只允许一个递归自引用
  • plan_hint子句

    以/*+*/的形式在SELECT关键字后,用于对SELECT对应的语句块生成的计划进行hint调优。

  • ALL

    声明返回所有符合条件的行,是默认行为,可以省略该关键字。

  • DISTINCT [ ON ( expression [, …] ) ]

    从SELECT的结果集中删除所有重复的行,使结果集中的每行都是唯一的。

    ON ( expression [, …] )只保留那些在给出的表达式上运算出相同结果的行集合中的第一行。

    DISTINCT ON表达式是使用与ORDER BY相同的规则进行解释的。除非使用了ORDER BY来保证需要的行首先出现,否则,“第一行” 是不可预测的。

  • SELECT列表

    指定查询表中列名,可以是部分列或者是全部(使用通配符*表示)。 通过使用子句AS output_name可以为输出字段取个别名,这个别名通常用于输出字段的显示。列名可以用下面几种形式表达:

    • 手动输入列名,多个列之间用英文逗号(,)分隔。
    • 可以是FROM子句里面计算出来的字段。
  • FROM子句

    为SELECT声明一个或者多个源表。 FROM子句涉及的元素如下所示。

    • table_name:表名或视图名,名称前可加上模式名,如:schema_name.table_name。

    • alias:给表或复杂的表引用起一个临时的表别名,以便被其余的查询引用。别名用于缩写或者在自连接中消除歧义。如果提供了别名,它就会完全隐藏表的实际名。

    • TABLESAMPLE sampling_method ( argument [, …] ) [ REPEATABLE (seed ) ]:table_name之后的TABLESAMPLE子句表示应该用指定的sampling_method来检索表中行的子集。

      • sampling_method 可以被指定为以下方法:

        • bernoulli,按行采样。
        • system,按块(页)采样。
        • hybrid,混合采样,argument 可以分别指定按行采样和按块(页)采样的百分比。
      • argument 部分用来指定采样百分比,是一个非空数值表达式(如10或'10'),取值范围是[0.000001,100)。

      • 可选的 REPEATABLE 部分指定一个用于产生采样方法中随机数的种子值seed,是一个非空数值表达式(如10或'10'),种子值的取值范围是[0,4294967295]。如果查询时表没有被更改,指定相同 seed 和 argument 值的两个查询将会选择该表相同的采样。但是不同的种子值通常将会产生不同的采样。如果没有给出 REPEATABLE,则会基于一个系统产生的种子为每一个查询选择一个新的随机采样。

      • table_name 可以是普通表,分区表,普通视图,物化视图和键保留(key-preserved)的连接视图;普通视图指在单表上查询创建的视图;键保留的连接视图指对键保留表进行连接操作后创建的视图,但不支持对包含超过一个非键保留表的连接视图进行数据采样。

    • column_alias:列别名。

    • PARTITION:查询分区表的某个分区的数据。

    • partition_name:分区名。

    • partition_value:指定的分区键值。在创建分区表时,如果指定了多个分区键,可以通过PARTITION FOR子句指定的这一组分区键的值,唯一确定一个分区。

    • subquery:FROM子句中可以出现子查询,创建一个临时表保存子查询的输出。

    • with_query_name:WITH子句同样可以作为FROM子句的源,可以通过WITH查询的名称对其进行引用。

    • function_name:函数名称。函数调用也可以出现在FROM子句中。

    • USING(join_column[,…]):ON left_table.a = right_table.a AND left_table.b = right_table.b … 的简写。要求对应的列必须同名。USING 意味着,每个等号表达式里面的列,只有一列会输出,而不是全部。

    • NATURAL:NATURAL是具有相同名称的两个表的所有列的USING列表的简写,如果没有一样名称的列,则等效于 join on true。

    • from_item:用于连接的查询源对象的名称。

    • join_type:有5种类型,如下所示。

      • [ INNER ] JOIN:一个JOIN子句组合两个FROM项。可使用圆括弧以决定嵌套的顺序。如果没有圆括弧,JOIN从左向右嵌套。在任何情况下,JOIN都比逗号分隔的FROM项绑定得更紧。

      • LEFT [ OUTER ] JOIN:返回笛卡尔积中所有符合连接条件的行,再加上左表中通过连接条件没有匹配到右表行的那些行。这样,左边的行将扩展为生成表的全长,方法是在那些右表对应的字段位置填上NULL。请注意,只在计算匹配的时候,才使用JOIN子句的条件,外层的条件是在计算完毕之后 施加的。

      • RIGHT [ OUTER ] JOIN:返回所有内连接的结果行,加上每个不匹配的右边行(左边用NULL 扩展)。这只是一个符号上的方便,因为总是可以把它转换成一个LEFT OUTER JOIN,只要把左边和右边的输入互换位置即可。

      • FULL [ OUTER ] JOIN:返回所有内连接的结果行,加上每个不匹配的左边行(右边用NULL扩展),再加上每个不匹配的右边行(左边用NULL扩展)。

      • CROSS JOIN:CROSS JOIN等效于INNER JOIN ON(TRUE) ,即没有被条件删除的行。这种连接类型只是符号上的方便,因为它们与简单的FROM和WHERE的效果相同。

        必须为INNER和OUTER连接类型声明一个连接条件,即NATURAL ON,join_condition,USING (join_column [, …]) 之一。但是它们不能出现在CROSS JOIN中。其中CROSS JOIN和INNER JOIN生成一个简单的笛卡尔积,和在FROM的顶层列出两个项的结果相同。

      • ON join_condition

        连接条件,用于限定连接中的哪些行是匹配的。如:

        ON left_table.a = right_table.a
        
  • WHERE子句

    WHERE子句构成一个行选择表达式,用来缩小SELECT查询的范围。condition是返回值为布尔型的任意表达式,任何不满足该条件的行都不会被检索。

    WHERE子句中可以通过指定“(+)”操作符的方法将表的连接关系转换为外连接。但是不建议用户使用这种用法,因为这并不是SQL的标准语法,在做平台迁移的时候可能面临语法兼容性的问题。同时,使用“(+)”有很多限制:

    • “(+)”只能出现在where子句中。
    • 如果from子句中已经有指定表连接关系,那么不能再在where子句中使用“(+)”。
    • “(+)”只能作用在表或者视图的列上,不能作用在表达式上。
    • 如果表A和表B有多个连接条件,那么必须在所有的连接条件中指定“(+)”,否则“(+)”将不会生效,表连接会转化成内连接,并且不给出任何提示信息。
    • 在任何外连接的 WHERE 子句中,无论指定哪种形式,都不能将带有“(+)”的列与子查询进行比较。
    • 如果“(+)”作用的表,不在当前查询或者子查询的from子句中,则会报错。如果“(+)”作用的对端的表不存在,则不报错,同时连接关系会转化为内连接。
    • ”(+)“作用的表达式不能直接通过“OR”连接。
    • 如果“(+)”作用的列是和一个常量的比较关系, 那么这个表达式会成为join条件的一部分。
    • Oracle兼容模式已支持一对多和多对多表的特性,详见外连接(+)。其他兼容模式下:
      • 不支持同一个表对应多个外表。
      • “(+)”只能转化为左外连接或者右外连接,不能转化为全连接,即不能在一个表达式的两个表上同时指定“(+)”。
    • “(+)”只能出现“比较表达式”,“NOT表达式”,“ANY表达式”,“ALL表达式”,“IN表达式”,“NULLIF表达式”,“IS DISTINCT FROM表达式”,“IS OF”表达式。“(+)”不能出现在其他类型表达式中,并且这些表达式中不允许出现通过“AND”和“OR”连接的表达式。

    对于WHERE子句的LIKE操作符,当LIKE中要查询特殊字符“%”、“_”、“\”的时候需要使用反斜杠“\”来进行转义。

  • START WITH子句

    START WITH子句通常与CONNECT BY子句同时出现,数据进行层次递归遍历查询,START WITH代表递归的初始条件。若省略该子句,单独使用CONNECT BY子句,则表示以表中的所有行作为初始集合。

  • CONNECT BY子句

    CONNECT BY代表递归连接条件,和START WITH一起子句一起使用,实现数据遍历递归的功能。

    create table test(name varchar, id int, fatherid int);
    insert into test values('A', 1, 0), ('B', 2, 1), ('C', 3, 1), ('D', 4, 1), ('E', 5, 2);
    select * from test start with id = 1 connect by prior id = fatherid order siblings by id desc;
    name | id | fatherid
    ------+----+----------
    A    |  1 |      0
    D    |  4 |      1
    C    |  3 |      1
    B    |  2 |      1
    E    |  5 |      2
    (5 rows)
    

    CONNECT BY代表递归连接条件,CONNECT BY条件中可以对列指定PRIOR关键字代表以这列为递归键进行递归。当前约束只能对表中的列指定PRIOR,不支持对表达式、类型转换指定PRIOR关键字。若在递归连接条件前加NOCYCLE,则表示遇到循环记录时停止递归。(注:含START WITH .. CONNECT BY子句的SELECT语句不支持使用FOR KEY SHARE/SHARE/NO KEY UPDATE/UPDATE锁)。

    Start with语句的执行流程是:

    (1)由 start with 区域的条件选择初始的数据集。上述例子里,先把 ('A', 1, 0) 选择出来。然后把初始的数据集设置为工作集。

    (2)只要工作集不为空,会用工作集的数据作为输入,查询下一轮的数据,过滤条件有 conntect by 区域指定。其中,PRIOR关键字表示当前记录,比如上位例子中 prior id = fatherid 表示当前记录的 id 是下一条记录的 fatherid。

    (3)把2中筛选出来的数据集,设为工作集,返回第二步重复操作。

    同时,数据库为每一条选出来的数据添加下述的伪列,方便用户了解数据在递归或者树状结构中的位置。

    • LEVEL:节点的层级

    • CONNECT_BY_ISLEAF:是否为叶子结点

      除了伪列外,还提供下述的查询函数:

    • sys_connect_by_path(col, separtor):返回从根节点到当前行的连接路径。参数col为路径中显示的列的名称,separator为连接符。

    • connect_by_root(col):显示该节点最顶级的节点,col为输出列的名称。 当前Start with默认行为是宽度优先搜索,但可以通过和伪列配合,实现深度优先搜索。比如:

      select sys_connect_by_path(name,'-') as path,*,LEVEL from test start with id = 1 connect by fatherid=prior id order by path;
      path  | name | id | fatherid | level
      --------+------+----+----------+-------
      -A     | A    |  1 |      0 |     1
      -A-B   | B    |  2 |      1 |     2
      -A-B-E | E    |  5 |      2 |     3
      -A-C   | C    |  3 |      1 |     2
      -A-D   | D    |  4 |      1 |     2
      (5 rows)
      
  • ORDER SIBLINGS BY子句

    ORDER SIBLINGS BY通常和START WITH、CONNECT BY子句同时使用, 用法和ORDER BY子句一样, 用于在递归过程中的层级排序。当前不支持接函数调用,如果有函数调用,且函数参数中存在列,则取第一个列作为排序键排序。

  • GROUP BY子句

    将查询结果按某一列或多列的值分组,值相等的为一组。

    • GROUPING SETS ( grouping_element [, …] )

      GROUPING SETS子句是GROUP BY子句的进一步扩展,它可以使用户指定多个GROUP BY选项。这样做可以通过裁剪用户不需要的数据组来提高效率。当用户指定了所需的数据组时,数据库不需要执行完整CUBE或ROLLUP生成的聚合集合。

    • CUBE ( { expression | ( expression [, …] ) } [, …] )

      CUBE是自动对group by子句中列出的字段进行分组汇总,结果集将包含维度列中各值的所有可能组合,以及与这些维度值组合相匹配的基础行中的聚合值。它会为每个分组返回一行汇总信息, 用户可以使用CUBE来产生交叉表值。比如,在CUBE子句中给出三个表达式(n = 3),运算结果为2n = 23 = 8组。 以n个表达式的值分组的行称为常规行,其余的行称为超级聚集行。例如:CUBE (c1,c2,c3)等效于

      GROUPING SETS (
      (c1, c2, c3),
      (c1, c2),
      (c2, c3),
      (c1, c3),
      (c1),
      (c2),
      (c3),
      ()
        )
      
    • ROLLUP ( { expression | ( expression [, …] ) } [, …] )

      ROLLUP是生成多个分组集合的快捷功能。与CUBE子句的差异是,ROLLUP不生成基于特定列所有可能的分组集合,生成分组集合为其子集。ROLLUP假设输入列之间存在层次结构,从而生成有意义的所有分组集合。例如: ROLLUP(c1,c2,c3)仅生成4种分组集合,等效于:

      GROUPING SETS (
      (c1, c2, c3),
      (c1, c2),
      (c1),
      (),
      )
      

      • SELECT子句中指定字段必须要包含在group by语句后,作为分组的依据,如果没有包含则会报错。除非SELECT子句中的字段包含在聚集函数中,因为对于未分组的字段,可能会返回多个数值。
      • 如果任何GROUPING SETS、ROLLUP、CUBE作为分组字段存在,则GROUP BY子句整体上定义了数个独立的分组集。其效果等效于在子查询间构建一个UNION ALL,子查询带有分组集作为它们的GROUP BY子句。
      • 当前,FOR UPDATE、FOR SHARE、FOR NO KEY UPDATE、FOR KEY SHARE不能和GROUP BY子句一起指定。
  • HAVING子句

    与GROUP BY子句配合用来选择特殊的组。HAVING子句将组的一些属性与一个常数值比较,只有满足HAVING子句中的逻辑表达式的组才会被提取出来。

    当前,FOR UPDATE、FOR SHARE、FOR NO KEY UPDATE、FOR KEY SHARE不能和HAVING子句一起指定。

  • WINDOW子句

    一般形式为:

    WINDOW window_name AS ( window_definition ) [,...]
    

    window_name是可以被随后的窗口定义所引用的名称,window_definition可以是以下的形式:

    [ existing_window_name ]
    [ PARTITION BY expression [, ...] ]
    [ ORDER BY expression [ ASC | DESC | USING operator ] [ NULLS {FIRST | LAST } ] [, ...] ]    
    [ frame_clause]
    

    frame_clause为窗函数定义一个窗口帧window frame,窗函数(并非所有)依赖于帧,,窗函数(并非所有)依赖于框架,window frame是当前查询行的一组相关行。frame_clause可以是以下的形式:

    [ RANGE | ROWS ] frame_start
    [ RANGE | ROWS ] BETWEEN frame_start AND frame_end
    

    frame_start和frame_end可以是:

    UNBOUNDED PRECEDING   --分区第一行开始的帧
    expr PRECEDING    --当前行开始或结束的帧
    CURRENT ROW         --当前行开始或结束的帧
    expr FOLLOWING    --当前行后value行开始或结束的帧
    UNBOUNDED FOLLOWING   --分区最后一行结束的帧
    
    • frame_start缺省为UNBOUNDED PRECEDING,frame_end缺省为CURRENT ROW。

    • frame_end的取值在列出的顺序中必须晚于frame_start的取值。

    • expr可以是表达式或数字。若为数字则不可为负数或空,可以为0;若为表达式,则结果可以为其中表达式的结果可以是0、正数和时间区间。

    • 其中expr FOLLOWING和expr PRECEDING选项从Build 14版本开始在Oracle兼容模式下支持,详情可见开窗函数支持表达式

    • 对列存表的查询目前只支持row_number窗口函数,不支持frame_clause。

    WINDOW子句可指定窗口函数的行为,在处理窗口定义相同的窗口函数时,使用WINDOW子句,在OVER中引用,能使SQL语句更简单,例如:

    SELECT sum(count) OVER w, avg(count) OVER w
    FROM table_count
    WINDOW w AS (PARTITION BY name ORDER BY count DESC);
    
  • UNION子句

    UNION计算多个SELECT语句返回行集合的并集。

    UNION子句有如下约束条件:

    • 除非声明了ALL子句,否则缺省的UNION结果不包含重复的行。
    • 同一个SELECT语句中的多个UNION操作符是从左向右计算的,除非用圆括弧进行了标识
    • FOR UPDATE不能在UNION的结果或输入中声明。

    一般表达式:

    select_statement UNION [ALL] select_statement
    
    • select_statement可以是任何没有ORDER BY、LIMIT、FOR UPDATE子句的SELECT语句。

    • 如果用圆括弧包围,ORDER BY和LIMIT可以附着在子表达式里。

  • INTERSECT子句

    INTERSECT计算多个SELECT语句返回行集合的交集,不含重复的记录。

    INTERSECT子句有如下约束条件:

    • 同一个SELECT语句中的多个INTERSECT操作符是从左向右计算的,除非用圆括弧进行了标识。
    • 当对多个SELECT语句的执行结果进行UNION和INTERSECT操作的时候,会优先处理INTERSECT。

    一般形式:

    select_statement INTERSECT select_statement
    

    select_statement可以是任何没有FOR UPDATE子句的SELECT语句。

  • EXCEPT子句

    EXCEPT子句有如下的通用形式:

    select_statement EXCEPT [ ALL ] select_statement 
    

    select_statement是任何没有FOR UPDATE子句的SELECT表达式。

    • EXCEPT操作符计算存在于左边SELECT语句的输出而不存在于右边SELECT语句输出的行。

    • EXCEPT的结果不包含任何重复的行,除非声明了ALL选项。使用ALL时,一个在左边表中有m个重复而在右边表中有n个重复的行将在结果中出现max(m-n,0)次。

    • 除非用圆括弧指明顺序,否则同一个SELECT语句中的多个EXCEPT操作符是从左向右计算的。EXCEPT和UNION的绑定级别相同。

    • 不能给EXCEPT的结果或者任何EXCEPT的输入声明FOR UPDATE子句。

  • MINUS子句

    与EXCEPT子句具有相同的功能和用法。

  • ORDER BY子句

    对SELECT语句检索得到的数据进行升序或降序排序。对于ORDER BY表达式中包含多列的情况:

    • 首先根据最左边的列进行排序,如果这一列的值相同,则根据下一个表达式进行比较,依此类推。
    • 如果对于所有声明的表达式都相同,则按随机顺序返回。
    • 在与DISTINCT关键字一起使用的情况下,ORDER BY中排序的列必须包括在SELECT语句所检索的结果集的列中。例外:在B兼容模式下,允许order by指定的列不出现在select distinct的目标列中,详见My SQL兼容性手册SELECT

    如果要支持中文拼音排序和不区分大小写排序,需要在初始化数据库时指定编码格式为UTF-8或GBK。 命令如下:

    initdb --E UTF8 --D ../data --locale=zh_CN.UTF-8
    

    initdb --E GBK --D ../data -- locale=zh_CN.GBK
    

    注意:若要使用pg_zhtrgm插件,initdb时指定的 -E和–locale参数对应的编码规则必须一致。

  • LIMIT子句

    LIMIT { count | ALL }
    

    当limit后面跟一个参数的时候,该参数表示要取的行数。 当limit后面跟两个参数的时候,第一个数表示要跳过的行数,后一位表示要取的行数。

  • OFFSET子句

    OFFSET start { ROW | ROWS }
    

    start声明开始返回行之前忽略的行数。当limit和offset组合使用的时候,limit后面只能有一个参数,表示要取的行数,offset表示要跳过的行数。

  • FETCH子句

    FETCH { FIRST | NEXT } [ count ] { ROW | ROWS } ONLY
    

    如果不指定count,默认值为1,FETCH子句限定返回查询结果从第一行开始的总行数。

  • 锁定子句

    • FOR UPDATE子句将对SELECT检索出来的行进行加锁。这样避免它们在当前事务结束前被其他事务修改或者删除,即其他企图UPDATE、DELETE、 SELECT FOR UPDATE这些行的事务将被阻塞,直到当前事务结束。
    • 支持在锁定子句中使用SKIP LOCKED选项,表示跳过其它未提交的事务锁定的记录,可以避免由于多个使用者同时访问表引起的锁争用问题。PostgreSQL兼容模式下的 SKIP LOCKED 功能,请参考《PostgreSQL兼容性》:SELECT FOR 支持 SKIP LOCKED。其它兼容模式下使用此功能时,锁的行为不完全相同,请注意区分。
    • 为了避免操作等待其他事务提交,可使用NOWAIT选项,如果被选择的行不能立即被锁住,将会立即汇报一个错误,而不是等待。

      WAIT N选项:如果被选择的行不能立即被锁住,等待N秒(其中,N为int类型,取值范围:0 <= N <= 2147483),N秒内获取锁则正常执行,否则报错。

    • FOR NO KEY UPDATE行为与FOR UPDATE类似,不过获得的锁较弱:这种锁将不会阻塞尝试在相同行上获得锁的SELECT FOR KEY SHARE命令。任何不获取FOR UPDATE锁的UPDATE也会获得这种锁模式。FOR SHARE的行为类似,只是它在每个检索出来的行上要求一个共享锁,而不是一个排他锁。一个共享锁阻塞其它事务执行UPDATE、DELETE、SELECT,不阻塞SELECT FOR SHARE。

    • 如果在FOR UPDATE或FOR SHARE中明确指定了表名称,则只有这些指定的表被锁定,其他在SELECT中使用的表将不会被锁定。否则,将锁定该命令中所有使用的表。

    • 如果FOR UPDATE或FOR SHARE应用于一个视图或者子查询,它同样将锁定所有该视图或子查询中使用到的表。

    • 多个FOR UPDATE和FOR SHARE子句可以用于为不同的表指定不同的锁定模式。

    • 如果一个表中同时出现(或隐含同时出现)在FOR UPDATE和FOR SHARE子句中,则按照FOR UPDATE处理。类似的,如果影响一个表的任意子句中出现了NOWAIT,该表将按照NOWAIT处理。

    对列存表的查询不支持for update/share。

  • NLS_SORT

    指定某字段按照特殊方式排序。目前仅支持中文拼音格式排序和不区分大小写排序。

    取值范围:

    • SCHINESE_PINYIN_M,按照中文拼音排序。如果要支持此排序方式,在创建数据库时需要指定编码格式为“GBK”,否则排序无效。

    • generic_m_ci,不区分大小写排序。

  • PARTITION子句

    查询某个分区表中相应分区的数据。

示例

1、创建测试表并插入数据。

CREATE TABLE exp_menu (id int,name text,parent_id int);
INSERT INTO exp_menu VALUES (1, 'grandpa', 0),(2, 'father', 1),(3, 'son', 2);

CREATE TABLE reason_t2(r_reason_sk    integer,
r_reason_id    character(16),r_reason_desc  character(100));
INSERT INTO reason_t2 VALUES (1, 'AAAAAAAABAAAAAAA', 'reason1'),(2, 'AAAAAAAABAAAAAAA', 'reason2'), (3, 'AAAAAAAACAAAAAAA','reason3'),(4, 'AAAAAAAADAAAAAAA', 'reason4'),(5, 'AAAAAAAAEAAAAAAA','reason5');

2、使用 WITH RECURSIVE 递归查询。

WITH RECURSIVE res AS (
    SELECT id, name, parent_id
    FROM exp_menu 
    WHERE id = 3
    UNION
    SELECT m.id,
           m.name || ' > ' || r.name,
           m.parent_id
    FROM res r INNER JOIN exp_menu m ON m.id = r.parent_id
)
select * from res;

返回结果如下:

 id |          name          | parent_id
----+------------------------+-----------
  3 | son                    |         2
  2 | father > son           |         1
  1 | grandpa > father > son |         0
(3 rows)

3、查询reason_t2表的所有r_reason_id记录,且去除重复。

SELECT DISTINCT(r_reason_id) FROM reason_t2;

返回结果如下:

   r_reason_id
------------------
 AAAAAAAABAAAAAAA
 AAAAAAAACAAAAAAA
 AAAAAAAAEAAAAAAA
 AAAAAAAADAAAAAAA
(4 rows)

4、LIMIT子句示例:获取表中一条记录。

SELECT * FROM reason_t2 LIMIT 1;

返回结果如下:

r_reason_sk |   r_reason_id    | r_reason_desc
-------- ---+------------------+--------------
          1 | AAAAAAAABAAAAAAA | reason1
(1 row)

5、查询所有记录,且按字母升序排列。

SELECT r_reason_desc FROM reason_t2 ORDER BY r_reason_desc;

返回结果如下:

r_reason_desc
-----------------
 reason1
 reason2
 reason3
 reason4
 reason5
(5 rows)

6、GROUP BY子句示例:根据查询条件过滤,并对结果进行分组。

SELECT r_reason_id, AVG(r_reason_sk) FROM reason_t2 GROUP BY r_reason_id HAVING AVG(r_reason_sk) > 2;

返回结果如下:

   r_reason_id    | avg
------------------+-----
 AAAAAAAACAAAAAAA |   3
 AAAAAAAAEAAAAAAA |   5
 AAAAAAAADAAAAAAA |   4
(3 rows)

7、GROUP BY CUBE子句示例:根据查询条件过滤,并对结果进行分组汇总。

SELECT r_reason_id,AVG(r_reason_sk) FROM reason_t2 GROUP BY CUBE(r_reason_id,r_reason_sk);

返回结果如下:

   r_reason_id    | avg
------------------+-----
 AAAAAAAABAAAAAAA |   1
 AAAAAAAABAAAAAAA |   2
 AAAAAAAABAAAAAAA | 1.5
 AAAAAAAACAAAAAAA |   3
 AAAAAAAACAAAAAAA |   3
 AAAAAAAADAAAAAAA |   4
 AAAAAAAADAAAAAAA |   4
 AAAAAAAAEAAAAAAA |   5
 AAAAAAAAEAAAAAAA |   5
                  |   3
                  |   1
                  |   2
                  |   3
                  |   4
                  |   5
(15 rows)

8、创建分区表并插入数据。

CREATE TABLE reason_p
(
  r_reason_sk integer,
  r_reason_id character(16),
  r_reason_desc character(100)
)
PARTITION BY RANGE (r_reason_sk)
(
  partition P_05_BEFORE values less than (05),
  partition P_15 values less than (15),
  partition P_25 values less than (25),
  partition P_35 values less than (35),
  partition P_45_AFTER values less than (MAXVALUE)
);

INSERT INTO reason_p values(3,'AAAAAAAABAAAAAAA','reason 1'),(10,'AAAAAAAABAAAAAAA','reason 2'),(4,'AAAAAAAABAAAAAAA','reason 3'),(10,'AAAAAAAABAAAAAAA','reason 4'),(10,'AAAAAAAABAAAAAAA','reason 5'),(20,'AAAAAAAACAAAAAAA','reason 6'),(30,'AAAAAAAACAAAAAAA','reason 7');

9、PARTITION子句示例:从reason_p的表分区P_05_BEFORE中获取数据。

SELECT * FROM reason_p PARTITION (P_05_BEFORE);

返回结果如下:

 r_reason_sk |   r_reason_id    |         r_reason_desc
-------------+--------------- --+------------------------------------------------
           3 | AAAAAAAABAAAAAAA | reason 1
           4 | AAAAAAAABAAAAAAA | reason 3
(2 rows)

10、GROUP BY子句示例:按r_reason_id分组统计reason_p表中的记录数。

SELECT COUNT(*),r_reason_id FROM reason_p GROUP BY r_reason_id;

返回结果如下:

 count |   r_reason_id
-------+------------------
     5 | AAAAAAAABAAAAAAA
     2 | AAAAAAAACAAAAAAA
(2 rows)

11、HAVING子句示例:按r_reason_id分组统计reason_p表中的记录,并只显示r_reason_id个数大于2的信息。

SELECT COUNT(*) c,r_reason_id FROM reason_p GROUP BY r_reason_id HAVING c>2;

返回结果如下:

c |   r_reason_id
---+------------------
 5 | AAAAAAAABAAAAAAA
(1 row)

12、IN子句示例:按r_reason_id分组统计reason_p表中的r_reason_id个数,并只显示r_reason_id值为 AAAAAAAABAAAAAAA或AAAAAAAADAAAAAAA的个数。

SELECT COUNT(*),r_reason_id FROM reason_p GROUP BY r_reason_id HAVING r_reason_id IN('AAAAAAAABAAAAAAA','AAAAAAAADAAAAAAA'); 

返回结果如下:

c |   r_reason_id
---+------------------
 5 | AAAAAAAABAAAAAAA
(1 row)

13、INTERSECT子句示例:查询r_reason_id等于AAAAAAAABAAAAAAA,并且r_reason_sk小于5的信息。

SELECT * FROM reason_p WHERE r_reason_id='AAAAAAAABAAAAAAA' INTERSECT SELECT * FROM reason_p WHERE r_reason_sk<5;

返回结果如下:

 r_reason_sk |   r_reason_id    |      r_reason_desc
-------------+------------------+--------------------------------------------
           4 | AAAAAAAABAAAAAAA | reason 3
           3 | AAAAAAAABAAAAAAA | reason 1
(2 rows)

14、EXCEPT子句示例:查询r_reason_id等于AAAAAAAABAAAAAAA,并且去除r_reason_sk小于4的信息。

SELECT * FROM reason_p WHERE r_reason_id='AAAAAAAABAAAAAAA' EXCEPT SELECT * FROM reason_p WHERE r_reason_sk<4;

返回结果如下:

r_reason_sk |   r_reason_id    |      r_reason_desc                  
-------------+------------------+------------------------------------
          10 | AAAAAAAABAAAAAAA | reason 2                          
          10 | AAAAAAAABAAAAAAA | reason 5                          
          10 | AAAAAAAABAAAAAAA | reason 4                          
           4 | AAAAAAAABAAAAAAA | reason 3                          
(4 rows)