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