#
第六十九章 SQL命令 SELECT(一) 从数据库中的一个或多个表中检索行。 # 大纲 ```sql [(] SELECT [%keyword] [DISTINCT [BY (item {,item2})] | ALL] [TOP {int | ALL}] select-item {,select-item, ...} [INTO host-variable-list] [FROM [optimize-option] table-ref [[AS] t-alias] {,table-ref [[AS] t-alias]} ] [WHERE condition-expression [{AND | OR condition-expression] ] [GROUP BY scalar-expression] [HAVING condition-expression [{AND | OR condition-expression] ] [ORDER BY item-order-list [ASC | DESC] ] [)] select-item ::= [t-alias.]* | [t-alias.]scalar-expression [[AS] c-alias] ``` ## 参数 - `%keyword` - 可选参数:`%NOFPLAN`、`%NOLOCK`、`%NORUNTIME`、`%PROFILE`、`%PROFILE_ALL`。 - `DISTINCT`,`DISTINCT BY (item)`,`ALL` - 可选—`DISTINCT`子句指定返回的每一行必须包含指定字段或字段组合的唯一值。 `DISTINCT`关键字指定选择项的值必须是唯一的。 `DISTINCT BY`关键字子句指定项值必须是唯一的。 项目(或用逗号分隔的项目列表)用括号括起来。 通常,项目是列的名称。 它可能作为选择项列出,也可能不作为选择项列出。 可选—`ALL`关键字指定返回满足`SELECT`条件的所有行。 这是SQL的默认值。 `ALL`关键字不执行任何操作; 它是为了SQL兼容性而提供的。 - `TOP int`,`TOP ALL` - 可选—`TOP`子句限制返回的行数为`int`中指定的行数。 如果查询中没有指定`ORDER BY`子句,那么将哪些记录作为`“top”`行返回是不可预测的。 如果指定了`ORDER BY`子句,顶部的行将按照指定的顺序排列。 `DISTINCT`关键字(如果指定)应用于`TOP`之前,指定要返回的唯一值的整型数。 int参数可以是一个正整数或动态SQL ? 解析为正整数的输入参数。 如果没有指定`TOP`关键字,则默认显示满足`SELECT`条件的所有行。 `TOP ALL`仅在子查询或`CREATE VIEW`语句中有意义。 它用于在这些情况下支持使用`ORDER BY`子句,满足在子查询或`CREATE VIEW`中使用的查询中`ORDER BY`子句必须与`TOP`子句配对的要求。 TOP ALL不限制返回的行数。 - `select-item` - 要检索的一个或多个列(或其他值)。 多个选择项被指定为一个逗号分隔的列表。 还可以使用`*`符号检索所有列。 - `INTO host`-`variable`-`list` - 可选-(仅嵌入式`SQL`):一个或多个主机变量,将选择项值放入其中。 多个主机变量被指定为逗号分隔的列表或单个主机变量数组。 在通过ODBC、JDBC或动态SQL处理的`SELECT`查询中指定`INTO`子句将导致`SQLCODE -422`错误。 - `FROM table-ref` - 可选的——对一个或多个表的引用,从中检索数据。 每个`FROM`子句都需要一个有效的`table-ref`,即使`SELECT`不引用该表。 不引用表数据的`SELECT`可以省略`FROM`子句。 `table-ref`可以指定为一个或多个表、视图、表值函数或子查询,以逗号分隔的列表或使用`JOIN`语法指定。 在使用带有`JOIN`语法的视图时存在一些限制。 子查询必须用括号括起来。 `table-ref`可以是限定的(`schema.tablename`),也可以是不限定的(`tablename`)。 不限定的`table-ref`要么提供默认模式名,要么提供模式搜索路径中的模式名。 多个表可以指定为逗号分隔的列表或与`ANSI`连接关键字关联。 可以指定任何表或视图的组合。 如果在这里在两个表引用之间指定逗号, IRIS将对表执行`CROSS JOIN`,并从`JOIN`操作的结果表中检索数据。 如果在两个表引用之间指定`ANSI`连接关键字, IRIS将执行指定的连接操作。 可以选择为每个`table-ref`分配别名(`t-alias`)。 AS关键字是可选的。 可以选择指定一个或多个优化选项关键字来优化查询执行。 可用选项有:`%ALLINDEX`、`%FIRSTTABLE`、`%FULL`、`%INORDER`、`%IGNOREINDEX`、`%NOFLATTEN`、`%NOMERGE`、`%NOREDUCE`、`%NOSVSO`、`%NOTOPOPT`、`%nounoropt`、`%PARALLEL`、`%STARTTABLE`。 - `WHERE condition-expression` - 可选的——为要检索的数据指定一个或多个谓词条件的限定符 - `GROUP BY scalar-expression` - 可选——用逗号分隔的一个或多个标量表达式列表,指定如何组织检索到的数据; 这些可能包括列名。 - `HAVING condition-expression` - 可选的——为要检索的数据指定一个或多个谓词条件的限定符。 - `ORDER BY item-order-list` - 可选—指定行显示顺序的选择项或以逗号分隔的项列表。 每个项目可以有一个可选的`ASC`(升序)或`DESC`(降序)。 默认为升序。 对查询结果使用`ORDER BY`子句。 子查询(例如`UNION`语句)中的`ORDER BY`子句必须与`TOP`子句配对。 如果没有指定`ORDER BY`子句,则返回记录的顺序是不可预测的。 `ORDER BY`子句可以包含窗口函数。 - `scalar-expression` - 字段标识符、包含字段标识符的表达式或通用表达式,如函数调用或算术运算。 - `AS t-alias` - 可选-表或视图名的别名(`table-ref`)。 别名必须是有效的标识符; 它可以是分隔的标识符。 - `AS c-alias` - 可选-列名的别名(选择项)。 别名必须是有效的标识符。 # 描述 `SELECT`语句执行从`IRIS`数据库检索数据的查询。 在其最简单的形式中,它从单个表的一个或多个列(字段)中检索数据。 列由`select-item`列表指定,表由`FROM table-ref`子句指定,`WHERE`子句可选地提供一个或多个限制条件,选择哪些行返回它们的列值。 在更复杂的查询中,`SELECT`可以检索列、聚合和非列数据,可以使用连接从多个表检索数据,也可以使用视图检索数据。 `SELECT`还可以用于从`SQL`函数、宿主变量或字面量返回值。 `SELECT`查询可以将返回这些非数据库值与从表或视图检索值结合起来。 当`SELECT`仅用于返回此类非数据库值时,`FROM`子句是可选的。 从`SELECT`查询返回的值称为结果集。 在动态SQL中,`SELECT`将值检索到%SQL中。 声明类。 IRIS设置一个状态变量`SQLCODE`,它指示`SELECT`的成功或失败。 此外,`SELECT`操作将`%ROWCOUNT`局部变量设置为选定的行数。 成功完成`SELECT`操作通常会将`SQLCODE=0`和`%ROWCOUNT`设置为选中的行数。 在包含简单`SELECT`的嵌入式SQL的情况下,将选择(最多)一行的数据,因此`SQLCODE=0`和`%ROWCOUNT`设置为`0`或`1`。 但是,对于声明游标并从多行获取数据的嵌入式SQL `SELECT`,当游标被推进到数据末尾时(`SQLCODE=100`),操作就完成了; 此时,`%ROWCOUNT`被设置为选中的行总数。 ## Uses of SELECT 可以在以下上下文中使用`SELECT`语句: - 作为一个独立的查询准备作为动态`SQL`查询,嵌入式SQL查询,或类查询。 - 作为子查询,为外围`SELECT`语句的子句提供值的`SELECT`语句。 `SELECT`语句中的子查询可以在选择项列表、`FROM`子句或带`EXISTS`或`in`谓词的`WHERE`子句中指定。 子查询也可以在`UPDATE`或`DELETE`语句中指定。 子查询必须用括号括起来。 - `UNION`语句允许将两个或多个`SELECT`语句组合成一个查询。 - 作为`CREATE VIEW`的一部分,定义视图可用的数据。 - 作为嵌入式SQL中使用的`DECLARE CURSOR`的一部分。 - 作为带有`SELECT`的`INSERT`的一部分。 `INSERT`语句可以使用`SELECT`将多行数据值插入到表中,从另一个表中选择数据。 可以用一组或多组括号将整个`SELECT`语句括起来,如下所示: - 对于独立的`SELECT`查询、`UNION`分支`SELECT`查询、`CREATE VIEW` `SELECT`查询或`DECLARE CURSOR SELECT`查询,括号是可选的。 将`SELECT`查询括在括号中会使它遵循子查询的语法规则; 具体来说,`ORDER BY`子句必须与`TOP`子句配对。 - 对于子查询,括号是必须的。 一组括号是必须的; 可以指定附加的可选括号集。 - `INSERT`语句`SELECT`查询不允许使用括号。 指定可选括号会为添加的每组括号生成一个单独的缓存查询。 ## 权限 要在一个或多个表上执行`SELECT`查询,必须对所有指定的选择项列具有列级`SELECT`权限,或者对指定的表引用表或视图具有表级`SELECT`权限。 使用表别名(如`t.Name`或`“MyAlias”. name`)指定的选择项列只需要列级的`SELECT`特权,而不需要表级的`SELECT`特权。 当使用`SELECT *`时,请注意列级权限覆盖`GRANT`语句中命名的所有表列; 表级权限涵盖所有表列,包括分配权限后添加的列。 没有必要的特权将导致`SQLCODE -99`错误(特权违反)。 可以通过调用`%CHECKPRIV`命令来确定当前用户是否具有`SELECT`权限。 通过调用`$SYSTEM.SQL.Security.CheckPrivilege()`方法,可以确定指定的用户是否具有表级的`SELECT`权限。 注意:对表具有表级`SELECT`特权并不能充分测试该表是否实际存在。 如果指定的用户具有`%All`角色,则`CheckPrivilege()`返回`1`,即使指定的表或视图不存在。 没有`FROM`子句的`SELECT`查询不需要任何`SELECT`特权。 包含`FROM`子句的`SELECT`查询需要`SELECT`特权,即使查询没有访问任何列数据。 ## 必需子句 下面是所有`SELECT`语句的必需子句: - 要从表中检索或以其他方式生成的一个或多个项(`select-item`参数)的以逗号分隔的选择项列表。 最常见的是,这些项是表中列的名称。 选择项由指定一个或多个单独项的标量表达式或引用基表所有列的星号(`*`)组成。 - `FROM`子句指定要从其中检索行的一个或多个表、视图或子查询。 这些表可以通过`JOIN`表达式关联。 在SQL中,对于任何引用表数据的`SELECT`,都需要一个带有有效表引用的`FROM`子句。 对于不访问表数据的`SELECT`, `FROM`子句是可选的。 可选的`FROM`子句在`FROM`子句参考页中有进一步的描述。 ## 可选子句 以下可选子句对`FROM`子句返回的虚表进行操作。 所有都是可选的,但是,如果使用,必须按照指定的顺序出现: - `DISTINCT`子句,指定只返回不同的(非重复的)值。 - 一个`TOP`子句,它指定要返回多少行。 - `WHERE`子句,指定行必须匹配的布尔谓词条件。 `WHERE`子句谓词条件既确定返回哪些行,又将提供给聚合函数的值限制为来自这些行的值。 这些条件由逻辑操作符链接的一个或多个谓词指定; `WHERE`子句返回满足这些谓词条件的所有记录。 `WHERE`子句谓词不能包含聚合函数。 - `GROUP BY`子句,它指定以逗号分隔的列列表。 它们将查询结果集组织为具有匹配一个或多个列值的子集,并确定返回行的顺序。 `groupby`允许标量表达式和列。 - `HAVING`子句,指定行必须匹配的布尔谓词条件。 这些条件由逻辑操作符链接的一个或多个谓词指定。 `HAVING`子句谓词条件确定返回哪些行,但是(默认情况下)它不将提供给聚合函数的值限制为来自这些行的值。 可以使用`%AFTERHAVING`关键字覆盖此默认值。 `HAVING`子句谓词可以指定聚合函数。 这些谓词通常对`group by`子句指定的每个组进行操作。 - `ORDER BY`子句,指定显示行的顺序。 子查询或`CREATE VIEW`查询中的`ORDER BY`子句必须与`TOP`子句配对。 以错误的顺序指定`SELECT`子句将产生`SQLCODE -25`错误。 `SELECT`语法顺序与`SELECT`子句语义处理顺序不同。 # %Keyword 参数 要使用`Keyword`字参数,必须拥有当前名称空间相应的`admin-privilege`。 指定`Keyword`字参数对处理的影响如下: - `%NOFPLAN` -此操作忽略冻结的计划(如果有); 该操作将生成一个新的查询计划。 冻结的计划被保留,但不使用。 - `%NOLOCK` - IRIS将不对任何指定的表执行锁操作。 如果指定此关键字,则查询将以`READ` `UNCOMMITTED`模式检索数据,而不管当前事务的隔离模式如何。 - `%NORUNTIME` -运行时计划选择(`RTPC`)优化没有使用。 - `%PROFILE`或`%PROFILE_ALL` - 如果指定了这些关键字指令中的一个,将生成`SQLStats`收集代码。 这与打开`PTools`时生成的代码相同。 不同之处在于,`SQLStats`收集代码仅为该特定语句生成。 正在编译的例程/类中的所有其他SQL语句将生成代码,就像`PTools`被关闭一样。 这使用户能够分析/检查应用程序中的特定问题SQL语句,而不必为未被调查的SQL语句收集无关的统计信息。 `%PROFILE`为主查询模块收集`SQLStats`。 `%PROFILE_ALL`为主查询模块及其所有子查询模块收集`SQLStats`。 可以以任何顺序指定多个`%Keyword`参数。 多个参数由空格分隔。 # DISTINCT子句 `DISTINCT`关键字子句将消除冗余字段值。 它有两种形式: - `SELECT DISTINCT`:为每个选择项值的唯一组合返回一行。 可以指定一个或多个选择项。 例如,下面的查询返回一行,其中`Home_State`和`Age`值的每个唯一组合都有`Home_State`和`Age`值: ```sql SELECT DISTINCT Home_State,Age FROM Sample.Person ``` `SELECT DISTINCT BY (item)`:为每个项目值的唯一组合返回一行。 可以指定单个项目,也可以指定以逗号分隔的项目列表。 选择项列表可以(但不是必须)包含指定的项。 例如,下面的查询返回一行,其中包含`Home_State`和`Age`值的每个唯一组合的`Name`和`Age`值: ```sql SELECT DISTINCT BY (Home_State,Age) Name,Age FROM Sample.Person ``` 项可以是任何有效的选择项值,星号除外。 它不能是列名别名。 任何类型的`DISTINCT`子句都可以指定多个项来测试唯一性。 列出一个以上的项将检索两个项组合中不同的所有行。 `DISTINCT`认为`NULL`是唯一的值。 # TOP子句 `TOP`关键字子句指定`SELECT`语句只返回指定的行数。 它返回出现在返回的虚拟表的“顶部”的指定行数。 默认情况下,哪些行是表的“顶部”行是不可预测的。 但是, IRIS在选择`TOP`行之前应用`DISTINCT`和`ORDER BY`子句(如果指定了)。