Manpages

NAME

SELECT - 从 表 或 视 图 中 取 出 若 干 行

SYNOPSIS

SELECT [ ALL | DISTINCT [ ON ( expression [, ...] ) ] ]
* | expression [ AS output_name ] [, ...]
[ FROM from_item [, ...] ]
[ WHERE condition ]
[ GROUP BY expression [, ...] ]
[ HAVING condition [, ...] ]
[ { UNION | INTERSECT | EXCEPT } [ ALL ] select ]
[ ORDER BY expression [ ASC | DESC | USING operator ] [, ...] ]
[ LIMIT { count | ALL } ]
[ OFFSET start ]
[ FOR UPDATE [ OF table_name [, ...] ] ]

where from_item can be one of:

[ ONLY ] table_name [ * ] [ [ AS ] alias [ ( column_alias [, ...] ) ] ]
( select ) [ 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 [, ...] ) ]

[Comment: FIXME: This last syntax is incorrect if the join type is an INNER or OUTER join (in which case one of NATURAL, ON ..., or USING ... is mandatory, not optional). What’s the best way to fix this?]

DESCRIPTION 描 述

SELECT 将 从 一 个 或 更 多 表 中 返 回 记 录 行 。 SELECT 通 常 的 处 理 如 下 :

1. 计 算 列 出 在

FROM 中 的 所 有 元 素 。 ( FROM 中 的 每 个 元 素 都 是 一 个 真 正 的

或 者 虚 拟 的 表 。 ) 如 果 在 FROM 列 表 里 声 明 了 多 过 一 个 元 素 , 那 么 他 们 就 交 叉 连 接 在 一 起 。 ( 参 阅 下 面 的 FROM Clause [select(7)] ) 。

2. 如 果 声 明 了

WHERE 子 句 , 那 么 在 输 出 中 消 除 所 有 不 满 足 条 件 的 行 。 (

参 阅 下 面 的 WHERE Clause [select(7)] ) 。

3. 如 果 声 明 了

GROUP BY 子 句 , 输 出 就 分 成 匹 配 一 个 或 多 个 数 值 的 不 同 组

里 。 如 果 出 现 了 HAVING 子 句 , 那 么 它 消 除 那 些 不 满 足 给 出 条 件 的 组 。 ( 参 阅 下 面 的 GROUP BY Clause [select(7)] 和 HAVING Clause [select(7)] ) 。

4. 使 用

UNION, INTERSECT, 和 EXCEPT, 我 们 可 以 把 多 个 SELECT 语 句

的 输 出 合 并 成 一 个 结 果 集 。 UNION 操 作 符 返 回 在 两 个 结 果 集 或 者 其 中 一 个 中 的 行 , INTERSECT 操 作 符 返 回 严 格 地 在 两 个 结 果 集 中 都 有 的 行 。 EXCEPT 操 作 符 返 回 在 第 一 个 结 果 集 中 , 但 是 不 在 第 二 个 结 果 集 中 的 行 。 不 管 哪 种 情 况 , 重 复 的 行 都 被 删 除 , 除 非 声 明 了 ALL。 ( 参 阅 下 面 的 UNION Clause [select(7)], INTERSECT Clause [select(l)], 和 EXCEPT Clause [select(7)] ) 。

5. 实 际 输 出 行 的 时 候 ,

SELECT 先 为 每 个 选 出 的 行 计 算 输 出 表 达 式 ( 参 阅

下 面 的 SELECT List [select(7)] ) 。

6. 如 果 声 明 了

ORDER BY 子 句 , 那 么 返 回 的 行 是 按 照 指 定 的 顺 序 排 序 的 。

如 果 没 有 给 出 ORDER BY, 那 么 数 据 行 是 按 照 系 统 认 为 可 以 最 快 生 成 的 方 法 给 出 的 。 ( 参 阅 下 面 的 ORDER BY Clause [select(7)] ) 。

7. 如 果 给 出 了

LIMIT 或 者 OFFSET 子 句 , 那 么 SELECT 语 句 只 返 回 结 果

行 的 一 个 子 集 。 ( 参 阅 下 面 的 LIMIT Clause [select(7)] ) 。

8.

DISTINCT 从 结 果 中 删 除 那 些 重 复 的 行 。 DISTINCT ON 删 除 那 些 匹 配 所 有 指 定 表 达 式 的 行 。 ALL ( 缺 省 ) 将 返 回 所 有 候 选 行 , 包 括 重 复 的 。 ( 参 阅 下 面 的 DISTINCT Clause [select(7)] ) 。

9.

FOR UPDATE 子 句 导 致 SELECT 语 句 对 并 发 的 更 新 锁 住 选 定 的 行 。 ( 参 阅 下 面 的 FOR UPDATE Clause [select(7)] ) 。

你 必 须 有 SELECT 权 限 用 来 从 表 中 读 取 数 值 。 使 用 FOR UPDATE 还 要 求 UPDATE 权 限 。

PARAMETERS 参 数

FROM 子 句
FROM 子 句 为 SELECT 声 明 一 个 或 者 多 个 源 表 。 如 果 声 明 了 多 个 源 表 , 那 么 结 果 就 是 所 有 源 表 的 笛 卡 儿 积 ( 交 叉 连 接 ) 。 但 是 通 常 我 们 会 添 加 一 些 条 件 , 把 返 回 行 限 制 成 笛 卡 儿 积 的 一 个 小 的 结 果 集 。

FROM-子 句 可 以 包 括 :
table_name
一 个 现 存 的 表 或 视 图 的 名 字 ( 可 以 有 模 式 修 饰 ) 。 如 果 声 明 了 ONLY, 则 只 扫 描 该 表 。 如 果 没 有 声 明 ONLY, 该 表 和 所 有 其 派 生 表 ( 如 果 有 的 话 ) 都 被 扫 描 。 可 以 在 表 名 后 面 跟 一 个 *来 表 示 扫 所 有 其 后 代 表 , 但 在 目 前 的 版 本 里 , 这 是 缺 省 特 性 。 ( 在 PostgreSQL 7.1 以 前 的 版 本 里 , ONLY是 缺 省 特 性 。 ) 缺 省 的 特 性 可 以 通 过 修 改 配 置 选 项 sql_interitance 来 改 变 。

alias 为 那 些 包 含 别 名 的

FROM 项 目 取 的 别 名 。 别 名 用 于 缩 写 或 者 在 自 连 接 中

消 除 歧 义 ( 自 连 接 里 , 同 一 个 表 扫 描 了 多 次 ) 。 如 果 提 供 了 别 名 , 那 么 它 就 会 完 全 隐 藏 表 或 者 函 数 的 实 际 名 字 ; 比 如 , 如 果 给 出 FROM foo AS f, 那 么 SELECT 剩 下 的 东 西 必 须 吧 这 个 FROM 项 以 f 而 不 是 foo 引 用 。 如 果 写 了 别 名 , 我 们 也 可 以 提 供 一 个 字 段 别 名 列 表 , 这 样 可 以 替 换 表 中 一 个 或 者 多 个 字 段 的 名 字 。

select 一 个 子

SELECT 在 FROM 子 句 里 出 现 的 。 它 的 输 出 作 用 好 象 是 为 这 条

SELECT 命 令 在 其 生 存 期 里 创 建 一 个 临 时 表 。 请 注 意 这 个 子 SELECT 必 须 用 园 括 弧 包 围 。 并 且 必 须 给 它 加 别 名 。

function_name 函 数 调 用 可 以 出 现 在 FROM 子 句 里 。 ( 对 于 那 些 返 回 结 果 集 的 函 数 特 别 有 用 , 但 是 任 何 函 数 都 能 用 。 ) 这 么 做 就 好 像 在 这 个 SELECT 命 令 的 生 命 期 中 , 把 函 数 的 输 出 创 建 为 一 个 临 时 表 一 样 。 我 们 也 可 以 使 用 别 名 。 如 果 写 了 别 名 , 我 们 还 可 以 写 一 个 字 段 别 名 列 表 , 为 函 数 返 回 的 复 合 类 型 的 一 个 或 多 个 属 性 提 供 名 字 替 换 。 如 果 函 数 定 义 为 了 record 数 据 类 型 , 那 么 必 须 出 现 一 个 AS 关 键 字 或 者 别 名 , 后 面 跟 着 一 个 字 段 定 义 列 表 , 形 如 : ( column_name data_type [, ... ])。 这 个 字 段 定 义 列 表 必 须 匹 配 函 数 返 回 的 字 段 的 实 际 数 目 和 类 型 。
join_type

[ 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 项 。 必 要 时 使 用 圆 括 弧 以 决 定 嵌 套 的 顺 序 。 如 果 没 有 圆 括 弧 , 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 列 表 的 缩 写 , 这 个 列 表 说 的 是 两 个 表 中 同 名 的 的 字 段 。

WHERE 子 句 可 选 的 WHERE 条 件 有 如 下 常 见 的 形 式 :

WHERE condition 这 里 condition 可 以 是 任 意 生 成 类 型 为 boolean 的 表 达 式 。 任 何 不 满 足 这 个 条 件 的 行 都 会 从 输 出 中 删 除 。 如 果 一 个 行 的 数 值 替 换 到 条 件 的 引 用 中 计 算 出 来 的 条 件 为 真 , 那 么 该 行 就 算 满 足 条 件 。

GROUP BY 子 句 可 选 的 GROUP BY 子 句 的 一 般 形 式

GROUP BY expression [, ...]

GROUP BY 将 把 所 有 在 组 合 了 的 表 达 式 上 共 享 同 样 的 值 的 行 压 缩 成 一 行 。 expression 可 以 是 一 个 输 入 字 段 名 字 , 或 者 是 一 个 输 入 字 段 ( SELECT 列 表 ) 的 序 号 , 或 者 也 可 以 是 任 意 从 输 入 字 段 值 形 成 的 任 意 表 达 式 。 在 有 歧 义 的 情 况 下 , 一 个 GROUP BY 的 名 字 将 被 解 释 成 输 入 字 段 的 名 字 , 而 不 是 输 出 字 段 的 名 字 。 如 果 使 用 了 聚 集 函 数 , 那 么 就 会 对 组 成 一 组 的 所 有 行 进 行 计 算 , 为 每 个 组 生 成 一 个 独 立 的 值 ( 而 如 果 没 有 GROUP BY, 那 么 聚 集 对 选 出 来 的 所 有 行 计 算 出 一 个 值 ) 。 如 果 出 现 了 GROUP BY, 那 么 SELECT 列 表 表 达 式 中 再 引 用 那 些 没 有 分 组 的 字 段 就 是 非 法 的 , 除 非 放 在 聚 集 函 数 里 , 因 为 对 于 未 分 组 的 字 段 , 可 能 会 返 回 多 个 数 值 。

HAVING 子 句 可 选 的 HAVING 子 句 有 如 下 形 式 :

HAVING condition 这 里 condition 和 为 WHERE 子 句 里 声 明 的 相 同 。

HAVING 去 除 了 一 些 不 满 足 条 件 的 组 行 。 HAVING 与 WHERE 不 同 : WHERE 在 使 用 GROUP BY 之 前 过 滤 出 单 独 的 行 , 而 HAVING 过 滤 由 GROUP BY 创 建 的 行 。 在 condition 里 引 用 的 每 个 字 段 都 必 须 无 歧 义 地 引 用 一 个 分 组 的 行 , 除 非 引 用 出 现 在 一 个 聚 集 函 数 里 。

UNION 子 句
UNION 子 句 的 一 般 形 式 是 :

select_statement UNION [ ALL ] select_statement 这 里 select_statement 是 任 意 没 有 ORDER BY, LIMIT, 或 者 FOR UPDATE 子 句 的 SELECT语 句 。 ( 如 果 用 圆 括 弧 包 围 , ORDER BY 和 LIMIT 可 以 附 着 在 子 表 达 式 里 。 如 果 没 有 圆 括 弧 , 这 些 子 句 将 交 给 UNION 的 结 果 使 用 , 而 不 是 给 它 们 右 手 边 的 输 入 表 达 式 。 )

UNION 操 作 符 计 算 那 些 涉 及 到 的 所 有 SELECT 语 句 返 回 的 行 的 结 果 联 合 。 一 个 行 如 果 至 少 在 两 个 结 果 集 中 的 一 个 里 面 出 现 , 那 么 它 就 会 在 这 两 个 结 果 集 的 集 合 联 合 中 。 两 个 做 为 UNION 直 接 操 作 数 的 SELECT必 须 生 成 相 同 数 目 的 字 段 , 并 且 对 应 的 字 段 必 须 有 兼 容 的 数 据 类 型 。 缺 省 地 , UNION 的 结 果 不 包 含 任 何 重 复 的 行 , 除 非 声 明 了 ALL 子 句 。 ALL 制 止 了 消 除 重 复 的 动 作 。 同 一 SELECT语 句 中 的 多 个 UNION 操 作 符 是 从 左 向 右 计 算 的 , 除 非 用 圆 括 弧 进 行 了 标 识 。 目 前 , FOR UPDATE 不 能 在 UNION 的 结 果 或 输 入 中 声 明 。

INTERSECT 子 句
INTERSECT 子 句 的 一 般 形 式 是 :

select_statement INTERSECT [ ALL ] select_statement

select_statement 是 任 何 不 带 ORDER BY, LIMIT, 或 者 FOR UPDATE 子 句 的 SELECT 语 句 。

INTERSECT 计 算 涉 及 的 SELECT 语 句 返 回 的 行 的 集 合 交 集 。 如 果 一 个 行 在 两 个 结 果 集 中 都 出 现 , 那 么 它 就 在 两 个 结 果 集 的 交 集 中 。

NTERSECT 的 结 果 不 包 含 任 何 重 复 行 , 除 非 你 声 明 了 ALL 选 项 。 用 了 ALL 以 后 , 一 个 在 左 手 边 的 表 里 有 m 个 重 复 而 在 右 手 边 表 里 有 n 个 重 复 的 行 将 出 现 min(m,n) 次 。 除 非 用 圆 括 号 指 明 顺 序 , 同 一 SELECT 语 句 中 的 多 个 INTERSECT 操 作 符 是 从 左 向 右 计 算 的 。 INTERSECT 比 UNION 绑 定 得 更 紧 --- 也 就 是 说 A UNION B INTERSECT C 将 读 做 A UNION (B INTERSECT C), 除 非 你 用 圆 括 弧 声 明 。

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

select_statement EXCEPT [ ALL ] select_statement 这 里 fIselect_statement 是 任 何 没 有 ORDER BY, LIMIT, 或 者 FOR UPDATE 子 句 的 SELECT 表 达 式 。

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

EXCEPT 的 结 果 不 包 含 任 何 重 复 的 行 , 除 非 声 明 了 ALL 选 项 。 使 用 ALL 时 , 一 个 在 左 手 边 表 中 有 m 个 重 复 而 在 右 手 边 表 中 有 n 个 重 复 的 行 将 出 现 max(m-n,0) 次 。 除 非 用 圆 括 弧 指 明 顺 序 , 同 一 SELECT 语 句 中 的 多 个 EXCEPT 操 作 符 是 从 左 向 右 计 算 的 。 EXCEPT 和 UNION 绑 定 级 别 相 同 。

SELECT 列 表
SELECT
列 表 ( 在 关 键 字 SELECT 和 FROM) 之 间 的 东 西 ) 声 明 一 个 表 达 式 , 这 个 表 达 式 形 成 SELECT 语 句 的 输 出 行 。 这 个 表 达 式 可 以 ( 通 常 也 的 确 是 ) 引 用 那 些 在 FROM 子 句 里 计 算 的 字 段 。 通 过 使 用 AS output_name, 我 们 可 以 为 一 个 输 出 行 声 明 另 外 一 个 名 字 。 这 个 名 字 主 要 用 做 显 示 该 行 的 标 签 。 它 也 可 以 在 ORDER BY 和 GROUP BY 子 句 里 当 作 字 段 值 的 引 用 , 但 是 不 能 在 WHERE 或 者 HAVING 子 句 里 这 么 用 ; 在 那 里 , 你 必 须 写 出 表 达 式 。 除 了 表 达 式 之 外 , 我 们 也 可 以 在 输 出 列 表 上 写 一 个 * 表 示 选 出 的 行 的 所 有 字 段 的 缩 写 。 同 样 , 我 们 可 以 写 table_name.* 作 为 来 自 某 个 特 定 表 的 字 段 的 缩 写 。

ORDER BY 子 句 可 选 的 ORDER BY 子 句 有 下 面 的 一 般 形 式 :

ORDER BY expression [ ASC | DESC | USING operator ] [, ...]

expression 可 以 是 一 个 输 出 字 段 ( SELECT 列 表 ) 的 名 字 或 者 序 号 , 或 者 也 可 以 是 用 输 入 字 段 的 数 值 组 成 的 任 意 表 达 式 。

ORDER BY 子 句 导 致 结 果 行 根 据 指 定 的 表 达 式 进 行 排 序 。 如 果 根 据 最 左 边 的 表 达 式 , 两 行 的 结 果 相 同 , 那 么 就 根 据 下 一 个 表 达 式 进 行 比 较 , 依 此 类 推 。 如 果 对 于 所 有 声 明 的 表 达 式 他 们 都 相 同 , 那 么 以 随 机 顺 序 返 回 。 序 数 指 的 是 列 /字 段 按 顺 序 ( 从 左 到 右 ) 的 位 置 。 这 个 特 性 让 我 们 可 以 对 没 有 唯 一 名 称 的 列 /字 段 进 行 排 序 。 这 一 点 从 来 不 是 必 须 的 , 因 为 总 是 可 以 通 过 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 子 句 里 每 个 列 /字 段 加 一 个 关 键 字 DESC ( 降 序 ) 或 ASC( 升 序 ) 。 如 果 不 声 明 , ASC 是 缺 省 。 我 们 还 可 以 在 USING 子 句 里 声 明 一 个 排 序 操 作 符 来 实 现 排 序 。 ASC 等 效 于 使 用 USING < 而 DESC 等 效 于 使 用 USING >。 (But the creator of a user-defined data type can define exactly what the default sort ordering is, and it might correspond to operators with other names.) 在 一 个 域 里 , 空 值 排 序 时 排 在 其 它 数 值 前 面 。 换 句 话 说 , 升 序 排 序 时 , 空 值 排 在 末 尾 , 而 降 序 排 序 时 空 值 排 在 开 头 。 字 符 类 型 的 数 据 是 按 照 区 域 相 关 的 字 符 集 顺 序 排 序 的 , 这 个 区 域 是 在 数 据 库 集 群 初 始 化 的 时 候 建 立 的 。

LIMIT 子 句
LIMIT 子 句 由 两 个 独 立 的 子 句 组 成 :

LIMIT { count | ALL }
OFFSET start 这 里 count 声 明 返 回 的 最 大 行 数 , 而 start 声 明 开 始 返 回 行 之 前 忽 略 的 行 数 。
.PP
LIMIT 允 许 你 检 索 由 查 询 其 他 部 分 生 成 的 行 的 某 一 部 分 。 如 果 给 出 了 限 制 计 数 , 那 么 返 回 的 行 数 不 会 超 过 哪 个 限 制 。 如 果 给 出 了 一 个 偏 移 量 , 那 么 开 始 返 回 行 之 前 会 忽 略 那 个 数 量 的 行 。 在 使 用 LIMIT 时 , 一 个 好 习 惯 是 使 用 一 个 ORDER BY 子 句 把 结 果 行 限 制 成 一 个 唯 一 的 顺 序 。 否 则 你 会 得 到 无 法 预 料 的 查 询 返 回 的 子 集 --- 你 可 能 想 要 第 十 行 到 第 二 十 行 , 但 以 什 么 顺 序 ? 除 非 你 声 明 ORDER BY, 否 则 你 不 知 道 什 么 顺 序 。 查 询 优 化 器 在 生 成 查 询 规 划 时 把 LIMIT 考 虑 进 去 了 , 所 以 你 很 有 可 能 因 给 出 的 LIMIT 和 OFFSET 值 不 同 而 得 到 不 同 的 规 划 ( 生 成 不 同 的 行 序 ) 。 因 此 用 不 同 的 LIMIT/OFFSET 值 选 择 不 同 的 查 询 结 果 的 子 集 将 不 会 产 生 一 致 的 结 果 , 除 非 你 用 ORDER BY 强 制 生 成 一 个 可 预 计 的 结 果 顺 序 。 这 可 不 是 毛 病 ; 这 是 SQL 生 来 的 特 点 , 因 为 除 非 用 了 ORDER BY 约 束 顺 序 , SQL 不 保 证 查 询 生 成 的 结 果 有 任 何 特 定 的 顺 序 。

DISTINCT 子 句 如 果 声 明 了 DISTINCT, 那 么 就 从 结 果 集 中 删 除 所 有 重 复 的 行 ( 每 个 有 重 复 的 组 都 保 留 一 行 ) 。 ALL 声 明 相 反 的 作 用 : 所 有 行 都 被 保 留 ; 这 个 是 缺 省 。

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 组 里 面 需 要 的 行 的 优 先 级 。

FOR UPDATE 子 句
FOR UPDATE 子 句 有 下 面 的 形 式

FOR UPDATE [ OF table_name [, ...] ]

FOR UPDATE 令 那 些 被 SELECT 语 句 检 索 出 来 的 行 被 锁 住 , 就 像 要 更 新 一 样 。 这 样 就 避 免 它 们 在 当 前 事 务 结 束 前 被 其 它 事 务 修 改 或 者 删 除 ; 也 就 是 说 , 其 它 视 图 UPDATE, DELETE, 或 者 SELECT FOR UPDATE 这 些 行 的 事 务 将 被 阻 塞 , 直 到 当 前 事 务 结 束 。 同 样 , 如 果 一 个 来 自 其 它 事 务 的 UPDATE, DELETE, 或 者 SELECT FOR UPDATE 已 经 锁 住 了 某 个 或 某 些 选 定 的 行 , SELECT FOR UPDATE 将 等 到 那 些 事 务 结 束 , 并 且 将 随 后 锁 住 并 返 回 更 新 的 行 ( 或 者 不 返 回 行 , 如 果 行 已 经 被 删 除 ) 。 更 多 的 讨 论 参 阅 Chapter 12 ’’Concurrency Control’’ 。 如 果 特 定 的 表 在 FOR UPDATE 中 , 那 么 只 有 来 自 这 些 表 中 的 行 才 被 锁 住 ; 任 何 在 SELECT 中 使 用 的 其 它 表 都 只 是 和 平 常 一 样 读 取 。

FOR UPDATE 不 能 在 那 些 无 法 使 用 独 立 的 表 数 据 行 清 晰 标 识 返 回 行 的 环 境 里 ; 比 如 , 它 不 能 和 聚 集 一 起 使 用 。

FOR UPDATE 可 以 在 LIMIT 前 面 出 现 , 主 要 是 为 了 和 7.3 之 前 的 PostgreSQL 兼 容 。 不 过 , 它 在 LIMIT 后 面 执 行 更 高 效 , 因 此 我 们 建 议 放 在 LIMIT 后 面 。

EXAMPLES 例 子

将 表 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
... 统 计 用 kind 分 组 的 所 有 电 影 和 组 的 列 /字 段 的 len( 长 度 ) 的 和 :

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 统 计 所 有 电 影 ( films) , 组 的 列 /字 段 len( 长 度 ) 的 和 , 用 kind 分 组 并 且 显 示 小 于 5小 时 的 组 总 和 :

SELECT kind, sum(len) AS total
FROM films
GROUP BY kind
HAVING sum(len) < interval ’5 hours’;

kind | total
----------+-------
Comedy | 02:58
Romantic | 04:38 下 面 两 个 例 子 是 根 据 第 二 列 ( name) 的 内 容 对 单 独 的 结 果 排 序 的 经 典 的 方 法 :

SELECT * FROM distributors ORDER BY name;
SELECT * FROM distributors ORDER BY 2;

did | name
-----+------------------
109 | 20th Century Fox
110 | Bavaria Atelier
101 | British Lion
107 | Columbia
102 | Jean Luc Godard
113 | Luso films
104 | Mosfilm
103 | Paramount
106 | Toho
105 | United Artists
111 | Walt Disney
112 | Warner Bros.
108 | Westward 下 面 这 个 例 子 演 示 如 何 获 得 表 distributors 和 actors的 连 接 , 只 将 每 个 表 中 以 字 母 W 开 头 的 取 出 来 。 因 为 只 取 了 不 相 关 的 行 , 所 以 关 键 字 ALL 被 省 略 了 :

distributors: actors:
did | name id | name
-----+-------------- ----+----------------
108 | Westward 1 | Woody Allen
111 | Walt Disney 2 | Warren Beatty
112 | Warner Bros. 3 | Walter Matthau
... ...

SELECT distributors.name
FROM distributors
WHERE distributors.name LIKE ’W%’
UNION
SELECT actors.name
FROM actors
WHERE actors.name LIKE ’W%’;

name
----------------
Walt Disney
Walter Matthau
Warner Bros.
Warren Beatty
Westward
Woody Allen 这 个 例 子 显 示 了 如 何 在 FROM 子 句 中 使 用 一 个 函 数 , 包 括 带 有 和 不 带 字 段 定 义 列 表 的 。

CREATE FUNCTION distributors(int) RETURNS SETOF distributors AS ’
SELECT * FROM distributors WHERE did = $1;
´ LANGUAGE SQL;

SELECT * FROM distributors(111);
did | name
-----+-------------
111 | Walt Disney

CREATE FUNCTION distributors_2(int) RETURNS SETOF record AS ’
SELECT * FROM distributors WHERE did = $1;
´ LANGUAGE SQL;

SELECT * FROM distributors_2(111) AS (f1 int, f2 text);
f1 | f2
-----+-------------
111 | Walt Disney

COMPATIBILITY 兼 容 性

当 然 , SELECT 语 句 和 SQL 标 准 兼 容 。 但 是 还 有 一 些 扩 展 和 一 些 缺 少 的 特 性 。 省 略 FROM 子 句

PostgreSQL 允 许 我 们 在 一 个 查 询 里 省 略 FROM 子 句 。 它 的 最 直 接 用 途 就 是 计 算 简 单 的 常 量 表 达 式 的 结 果 :

SELECT 2+2;

?column?
----------
4 其 它 有 些 SQL 数 据 库 不 能 这 么 做 , 除 非 引 入 一 个 单 行 的 伪 表 做 SELECT 的 数 据 源 。 这 个 特 性 的 另 外 一 个 不 太 明 显 的 用 途 是 把 一 个 普 通 的 从 一 个 或 多 个 表 的 SELECT 缩 写 :

SELECT distributors.* WHERE distributors.name = ’Westward’;

did | name
-----+----------
108 | Westward 这 样 也 可 以 运 行 是 因 为 我 们 给 SELECT 中 引 用 了 但 没 有 在 FROM 中 提 到 的 每 个 表 都 加 了 一 个 隐 含 的 FROM 项 。 尽 管 这 是 个 很 方 便 的 写 法 , 但 它 却 容 易 误 用 。 比 如 , 下 面 的 查 询

SELECT distributors.* FROM distributors d; 可 能 就 是 个 错 误 ; 用 户 最 有 可 能 的 意 思 是

SELECT d.* FROM distributors d; 而 不 是 下 面 的 他 实 际 上 得 到 的 无 约 束 的 连 接

SELECT distributors.* FROM distributors d, distributors distributors; 为 了 帮 助 检 测 这 种 错 误 , PostgreSQL 以 及 以 后 的 版 本 将 在 你 使 用 一 条 即 有 隐 含 FROM 特 性 又 有 明 确 的 FROM 子 句 的 查 询 的 时 候 给 出 警 告 。 Also, it is possible to disable the implicit-FROM feature by setting the ADD_MISSING_FROM parameter to false.

AS 关 键 字 在 SQL 标 准 里 , 可 选 的 关 键 字 AS 是 多 余 的 , 可 以 忽 略 掉 而 不 对 语 句 产 生 任 何 影 响 。 PostgreSQL 分 析 器 在 重 命 名 列 /字 段 时 需 要 这 个 关 键 字 , 因 为 类 型 扩 展 的 特 性 会 导 致 在 这 个 环 境 里 的 歧 义 。 不 过 , AS 在 FROM 项 里 是 可 选 的 。

GROUP BY 和 ORDER BY 里 可 用 的 名 字 空 间 在 SQL92 标 准 里 , ORDER BY 子 句 只 能 使 用 结 果 字 段 名 或 者 编 号 , 而 GROUP BY 子 句 只 能 用 基 于 输 入 字 段 名 的 表 达 式 。 PostgreSQL 对 这 两 个 子 句 都 进 行 了 扩 展 , 允 许 另 外 一 种 选 择 ( 但 是 如 果 存 在 歧 义 , 则 使 用 标 准 的 解 释 ) 。 PostgreSQL 还 允 许 两 个 子 句 声 明 任 意 的 表 达 式 。 请 注 意 在 表 达 式 中 出 现 的 名 字 强 总 是 被 当 作 输 入 字 段 名 , 而 不 是 结 果 字 段 名 。

SQL99 uses a slightly different definition which is not upward compatible with SQL92. In most cases, however, PostgreSQL will interpret an ORDER BY or GROUP BY expression the same way SQL99 does. 非 标 准 子 句
DISTINCT ON, LIMIT, 和 OFFSET 都 没 有 在 SQL 标 准 中 定 义 。

译 者

Postgresql 中 文 网 站 何 伟 平 <laser [AT] pgsqldb.org>

本 页 面 中 文 版 由 中 文 man 手 册 页 计 划 提 供 。 中 文 man 手 册 页 计 划 : https://github.com/man-pages-zh/manpages-zh