经济文库 - 千万精品文档,你想要的都能搜到,下载即用。

KingbaseES_SQL语言参考手册.pdf

What is love1371 页 16.422 MB 访问 612.97下载文档
KingbaseES_SQL语言参考手册.pdfKingbaseES_SQL语言参考手册.pdfKingbaseES_SQL语言参考手册.pdfKingbaseES_SQL语言参考手册.pdfKingbaseES_SQL语言参考手册.pdfKingbaseES_SQL语言参考手册.pdf
当前文档共1371页 2.97
下载后继续阅读

KingbaseES_SQL语言参考手册.pdf

KingbaseES SQL 语言参考手册 金仓数据库管理系统 KingbaseES 文档版本:V9(V009R001C001B0024) 发布日期:2023 年 10 月 12 日 北京人大金仓信息技术股份有限公司 目 目 录 录 第 1 章 前言 1 1.1 适用读者 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 1.2 相关文档 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 1.3 术语 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 1.4 手册约定 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 第 2 章 KingbaseES SQL 介绍 3 2.1 SQL 历史 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 2.2 SQL 标准 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 2.2.1 SQL 工作原理 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 2.2.2 所有关系数据库的通用语言 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 2.3 词汇约定 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 2.4 工具支持 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 第 3 章 KingbaseES SQL 基本元素 3.1 数据类型 3.1.1 6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 KingbaseES 内置数据类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 字符数据类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 3.1.1.1.1 character[(n [char | byte])] 数据类型 . . . . . . . . . . . . . . . . . . . . . . . 8 3.1.1.1.2 character varying[(n [char | byte])] 数据类型 . . . . . . . . . . . . . . . . . . 9 3.1.1.1.3 TEXT 类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 3.1.1.1.4 LONGTEXT 数据类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 3.1.1.1.5 MEDIUMTEXT 类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 3.1.1.1.6 TINYTEXT 类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 数值类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 整数类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 3.1.1.2.1.1 TINYINT 数据类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 3.1.1.2.1.2 SMALLINT 数据类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 3.1.1.2.1.3 MEDIUMINT/MIDDLEINT/INT3 . . . . . . . . . . . . . . . . . . . 15 3.1.1.2.1.4 INTEGER 数据类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 3.1.1.2.1.5 BIGINT 数据类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 3.1.1.1 3.1.1.2 3.1.1.2.1 I 目 录 SIGNED/UNSIGNED 数据类型 . . . . . . . . . . . . . . . . . . . . . 16 精确数值数据类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 3.1.1.2.1.6 3.1.1.2.2 3.1.1.2.2.1 NUMERIC 数据类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 3.1.1.2.2.2 DECIMAL 数据类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 3.1.1.2.2.3 NUMBER 数据类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 3.1.1.2.2.4 FIXED 数据类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 浮点类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 3.1.1.2.3.1 REAL 类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 3.1.1.2.3.2 BIGSERIAL 类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 3.1.1.2.3.3 FLOAT 类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 浮点数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 3.1.1.2.4.1 BINARY_FLOAT 类型 . . . . . . . . . . . . . . . . . . . . . . . . . . 21 3.1.1.2.4.2 BIGSERIAL 类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 3.1.1.2.4.3 取值范围 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 序数类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 3.1.1.2.5.1 SMALLSERIAL 类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 3.1.1.2.5.2 SERIAL 类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 3.1.1.2.5.3 BIGSERIAL 类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 3.1.1.3 货币类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 3.1.1.4 日期/时间类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 3.1.1.4.1 DATE 数据类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 3.1.1.4.2 TIME 数据类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 3.1.1.4.2.1 time [ (p) ] with time zone 类型 . . . . . . . . . . . . . . . . . . . . . 26 3.1.1.4.2.2 time [ (p) ] without time zone 类型 . . . . . . . . . . . . . . . . . . . . 26 3.1.1.4.2.3 time 类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 TIMESTAMP 数据类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 3.1.1.4.3.1 timestamp[ (p)] [ without time zone ] 类型 . . . . . . . . . . . . . . . 27 3.1.1.4.3.2 timestamp[ (p)] with time zone 类型 . . . . . . . . . . . . . . . . . . . 27 3.1.1.4.3.3 timestamp[ (p)] with local time zone 类型 . . . . . . . . . . . . . . . . 28 3.1.1.4.4 DATETIME 数据类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 3.1.1.4.5 INTERVAL 数据类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 3.1.1.4.6 YEAR 类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38 大对象数据类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38 3.1.1.5.1 BLOB 类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38 3.1.1.5.2 CLOB 类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39 3.1.1.5.3 NCLOB 类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39 3.1.1.5.4 BFILE 类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39 3.1.1.5.5 BYTEA 类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40 3.1.1.5.6 RAW 类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40 3.1.1.5.7 LONG RAW 类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40 3.1.1.6 布尔类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40 3.1.1.7 位串类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 3.1.1.2.3 3.1.1.2.4 3.1.1.2.5 3.1.1.4.3 3.1.1.5 II 3.1.1.8 3.1.1.9 目 录 3.1.1.7.1 BIT 类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 3.1.1.7.2 BIT VAYRING 类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 3.1.1.7.3 BINARY 类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 3.1.1.7.4 VARBINARY 类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43 几何类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43 3.1.1.8.1 点 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 3.1.1.8.2 线 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 3.1.1.8.3 线段 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 3.1.1.8.4 方框 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45 3.1.1.8.5 路径 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45 3.1.1.8.6 多边形 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45 3.1.1.8.7 圆 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 网络地址类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 3.1.1.9.1 inet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 3.1.1.9.2 cidr . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 3.1.1.9.3 inet-vs.-cidr . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48 3.1.1.9.4 macaddr . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48 3.1.1.9.5 macaddr8 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48 3.1.1.10 文本搜索类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49 3.1.1.10.1 tsvector . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49 3.1.1.10.2 tsquery . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51 3.1.1.11 UUID 类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52 3.1.1.12 XML 类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53 3.1.1.12.1 创建 XML 值 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53 3.1.1.12.2 编码处理 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54 3.1.1.12.3 访问 XML 值 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54 3.1.1.13 JSON 类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55 3.1.1.13.1 JSON 输入和输出语法 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56 3.1.1.13.2 有效地设计 JSON 文档 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57 3.1.1.13.3 JSONB 包含和存在 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57 3.1.1.13.4 JSONB 索引 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59 3.1.1.13.5 MySQL 模式 JSON 类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62 3.1.1.14 范围类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64 3.1.1.14.1 内建范围类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65 3.1.1.14.2 例子 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65 3.1.1.14.3 包含和排除边界 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65 3.1.1.14.4 无限(无界)范围 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66 3.1.1.14.5 范围输入/输出 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66 3.1.1.14.6 构造范围 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67 3.1.1.14.7 离散范围类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67 3.1.1.14.8 定义新的范围类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68 3.1.1.14.9 索引 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69 III 3.1.2 3.1.3 目 录 3.1.1.14.10 范围上的约束 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69 域类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70 3.1.2.1 对象标识符类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70 3.1.2.2 sys_lsn 类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72 3.1.2.3 伪类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72 用户自定义类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73 枚举类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73 3.1.3.1.1 排序 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74 3.1.3.1.2 类型安全性 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74 3.1.3.1.3 实现细节 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75 SET 类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75 3.1.3.2.1 类型安全性 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78 3.1.3.2.2 实现细节 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78 集合类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79 嵌套表 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79 3.1.3.3.1.1 嵌套表类型的声明 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79 3.1.3.3.1.2 嵌套表类型的使用 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79 3.1.3.3.1.3 示例 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79 可变数组 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80 3.1.3.3.2.1 可变数组的声明 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80 3.1.3.3.2.2 可变数组的使用 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80 3.1.3.3.2.3 示例 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80 组合类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81 3.1.3.4.1 组合类型的声明 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81 3.1.3.4.2 构造组合值 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82 3.1.3.4.3 访问组合类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83 3.1.3.4.4 修改组合类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84 3.1.3.4.5 在查询中使用组合类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84 3.1.3.4.6 组合类型输入和输出语法 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86 对象类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87 对象类型的声明和定义 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87 数组 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92 3.1.3.6.1 数组类型的定义 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92 3.1.3.6.2 数组值输入 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93 3.1.3.6.3 访问数组 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94 3.1.3.6.4 修改数组 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96 3.1.3.6.5 在数组中搜索 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100 3.1.3.6.6 数组输入和输出语法 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101 3.1.3.1 3.1.3.2 3.1.3.3 3.1.3.3.1 3.1.3.3.2 3.1.3.4 3.1.3.5 3.1.3.5.1 3.1.3.6 3.1.4 3.2 Rowid 数据类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102 3.1.4.1 ROWID 数据类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102 3.1.4.2 UROWID 数据类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102 数据类型比较规则 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102 IV 目 3.2.1 数值 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103 3.2.2 日期值 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103 3.2.3 字符值 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103 3.2.3.1 3.2.4 隐式和显式数据转换 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103 类型转换表 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104 3.3.1 3.4 二进制和语言排序规则 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103 数据转换 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103 3.2.4.1 3.3 录 显示数据转换 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105 常量 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105 3.4.1 字符串常量 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105 3.4.1.1 带有 C 型转义的字符串常量 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106 3.4.1.2 带有 Unicode 转义的字符串常量 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107 3.4.1.3 美元引用的字符串常量 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108 3.4.2 位串常量 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109 3.4.3 数字常量 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109 3.4.4 其他类型的常量 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110 3.5 格式模型 3.6 空值 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110 3.6.1 SQL 函数中的空值 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111 3.6.2 比较条件中的空值 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111 3.6.3 条件中的空值 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111 3.7 注释 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111 3.8 数据库对象 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112 3.9 3.8.1 Schema 对象 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112 3.8.2 Nonschema 对象 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113 数据库对象名称和限定符 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113 3.9.1 数据库对象命名规则 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113 3.9.2 模式对象命名规则 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115 3.10 数据库对象引用方式 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116 3.10.1 引用 Schema 对象 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117 3.10.2 引用其他 Schema 中的对象 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118 3.10.3 对远程数据库中对象的引用 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118 3.10.4 引用分区表和索引 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118 3.10.5 引用对象类型的属性和方法 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119 第 4 章 伪列 121 4.1 ROWNUM 伪列 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121 4.2 ROWID 伪列 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123 4.3 层次查询伪列 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123 4.4 闪回版本查询伪列 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124 第 5 章 操作符 5.1 125 SQL 相关操作符 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125 V 目 录 5.2 算术操作符 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126 5.3 逻辑操作符 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128 5.4 比较操作符 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129 5.5 排序规则操作符 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133 5.6 连接操作符 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133 5.7 位串操作符 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134 5.8 文本匹配操作符 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135 5.9 层次查询操作符 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136 5.10 集合操作符 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136 5.11 自定义操作符 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137 第 6 章 表达式 138 6.1 SQL 表达式简介 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138 6.2 简单表达式 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139 6.3 复合表达式 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141 6.4 CASE 表达式 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142 6.5 列表达式 6.6 日期时间表达式 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144 6.7 函数表达式 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146 6.8 占位符表达式 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146 6.9 标量子查询表达式 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144 6.10 类型构造表达式 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148 6.11 表达式列表 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149 第 7 章 条件表达式 152 7.1 SQL 条件简介 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152 7.2 比较条件 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155 7.3 浮点条件 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160 7.4 逻辑条件 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160 7.5 模式匹配条件 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162 7.6 空条件 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167 7.7 SQL/JSON 条件 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167 7.8 复合条件 7.9 BETWEEN 条件 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172 7.10 EXISTS 条件 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174 7.11 IN 条件 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174 第 8 章 函数 8.1 177 关于 SQL 函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 195 8.1.1 SQL 函数中的空值 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 195 8.1.2 SQL 函数的语法 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 195 8.2 数学函数 8.3 字符串函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 195 VI 目 录 8.4 大对象函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 200 8.5 二进制串函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201 8.6 模式匹配函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201 8.7 数据类型格式化函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 202 8.8 时间日期函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 212 8.9 枚举支持函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 215 8.10 SET 支持函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 215 8.11 几何函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 216 8.12 网络地址函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 216 8.13 XML 函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 217 8.14 JSON 函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 218 8.15 序列操作函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 220 8.16 数组函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221 8.17 范围函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221 8.18 聚集函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222 8.19 窗口函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 223 8.20 集合返回函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 225 8.21 系统信息函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 226 8.22 系统管理函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 228 8.23 触发器函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 229 8.24 事件触发器函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 229 8.25 ABBREV . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 229 8.26 ABS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 229 8.27 ACOS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 230 8.28 ACOSH . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 230 8.29 ADDDATE(MySQL 模式) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 231 8.30 ADDTIME(MySQL 模式) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 233 8.31 ADD_MONTHS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 235 8.32 AGE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 235 8.33 APPENDCHILDXML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 236 8.34 ARRAY_AGG . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 236 8.35 ARRAY_APPEND . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 237 8.36 ARRAY_CAT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 237 8.37 ARRAY_DIMS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 238 8.38 ARRAY_FILL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 238 8.39 ARRAY_LENGTH . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 239 8.40 ARRAY_LOWER . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 239 8.41 ARRAY_NDIMS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 239 8.42 ARRAY_POSITION . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 240 8.43 ARRAY_POSITIONS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 240 8.44 ARRAY_PREPEND . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 241 8.45 ARRAY_REMOVE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 241 VII 目 录 8.46 ARRAY_REPLACE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 242 8.47 ARRAY_TO_JSON . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 242 8.48 ARRAY_TO_STRING . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 242 8.49 ARRAY_TO_TSVECTOR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 243 8.50 ARRAY_UPPER . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 243 8.51 ASIN . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 244 8.52 ASINH . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 244 8.53 ATAN . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 245 8.54 ATAN2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 245 8.55 ATANH . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 246 8.56 AVG . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 246 8.57 BFILENAME . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 247 8.58 BIT_AND . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 248 8.59 BIT_LENGTH . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 248 8.60 BIT_OR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 249 8.61 BITAND . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 249 8.62 BITTONUMERIC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 250 8.63 BLOB_EXPORT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 250 8.64 BLOB_IMPORT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 251 8.65 BOOL_AND . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 251 8.66 BOOL_OR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 252 8.67 BOUND_BOX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 252 8.68 BOX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 253 8.69 BTRIM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 253 8.70 CARDINALITY . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 254 8.71 CAST . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 254 8.72 CBRT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 255 8.73 CEIL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 255 8.74 CEILING . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 256 8.75 CENTER . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 256 8.76 CHAR_LENGTH . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 257 8.77 CHARACTER_LENGTH . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 257 8.78 CHARINDEX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 258 8.79 CHARTOROWID . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 258 8.80 CHR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 259 8.81 CIRCLE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 259 8.82 CLOB_EXPORT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 260 8.83 CLOB_IMPORT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 260 8.84 CLOCK_TIMESTAMP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 261 8.85 COALESCE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 261 8.86 COL_DESCRIPTION . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 262 8.87 CONCAT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 262 VIII 目 录 8.88 CONCAT_WS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 263 8.89 CONNECTIONS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 263 8.90 CONTAINS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 264 8.91 CONVERT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 265 8.92 CONVERT(MySQL 模式) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 265 8.93 CONVERT_FROM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 265 8.94 CONVERT_TO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 266 8.95 CONVERT_TZ(MySQL 模式) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 266 8.96 CORR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 267 8.97 COS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 268 8.98 COSH . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 268 8.99 COT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 269 8.100 COUNT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 269 8.101 COVAR_POP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 270 8.102 COVAR_SAMP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 271 8.103 CUME_DIST . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 271 8.104 CURDATE(MySQL 模式) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 272 8.105 CURRENT_DATABASE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 273 8.106 CURRENT_DATE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 273 8.107 CURRENT_QUERY . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 273 8.108 CURRENT_SCHEMA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 274 8.109 CURRENT_SCHEMAS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 274 8.110 CURRENT_SETTING . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 275 8.111 CURRENT_TIME . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 275 8.112 CURRENT_TIME(MySQL 模式) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 276 8.113 CURRENT_TIMESTAMP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 277 8.114 CURRENT_TIMESTAMP(MySQL 模式) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 277 8.115 CURRVAL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 278 8.116 CURSOR_TO_XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 278 8.117 CURTIME(MySQL 模式) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 279 8.118 DATEDIFF(MySQL 模式) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 279 8.119 DAY(MySQL 模式) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 280 8.120 DAYNAME(MySQL 模式) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 281 8.121 DAYOFMONTH(MySQL 模式) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 282 8.122 DAYOFWEEK(MySQL 模式) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 283 8.123 DAYOFYEAR(MySQL 模式) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 284 8.124 DATE_PART . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 284 8.125 DATE_SUB(MySQL 模式) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 285 8.126 DATE_TRUNC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 286 8.127 DAYS_BETWEEN . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 287 8.128 DECODE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 288 8.129 DECODING . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 289 IX 目 录 8.130 DEGREES . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 289 8.131 DELETEXML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 289 8.132 DENSE_RANK . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 290 8.133 DIAMETER . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 291 8.134 DIV . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 291 8.135 EMPTY_BLOB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 292 8.136 EMPTY_CLOB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 292 8.137 EMPTY_NCLOB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 292 8.138 ENCODE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 293 8.139 ENUM_FIRST . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 293 8.140 ENUM_LAST . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 294 8.141 ENUM_RANGE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 294 8.142 EVERY . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 295 8.143 EXISTSNODE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 295 8.144 EXP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 296 8.145 EXPORT_SET . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 296 8.146 EXTRACT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 297 8.147 EXTRACT(MySQL 模式) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 301 8.148 EXTRACTVALUE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 302 8.149 FAMILY . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 303 8.150 FIND_IN_SET . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 303 8.151 FIRST . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 304 8.152 FIRST_VALUE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 307 8.153 FLOOR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 308 8.154 FORMAT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 308 8.155 FORMAT_PICO_TIME(MySQL 模式) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 311 8.156 FORMAT_TYPE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 312 8.157 FROM_BASE64(MySQL 模式) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 313 8.158 FROM_DAYS(MySQL 模式) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 313 8.159 FROM_UNIXTIME(MySQL 模式) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 314 8.160 GENERATE_SERIES . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 317 8.161 GENERATE_SUBSCRIPTS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 318 8.162 GET_BIT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 319 8.163 GET_BYTE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 319 8.164 GET_CURRENT_TS_CONFIG . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 320 8.165 GET_DISK_INFO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 320 8.166 GET_FORMAT(MySQL 模式) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 320 8.167 GET_LICENSE_VALIDDAYS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 322 8.168 GETUSERNAME . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 322 8.169 GREATEST . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 323 8.170 GROUP_CONCAT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 323 8.171 GROUPING . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 324 X 目 录 8.172 GROUPING_ID . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 325 8.173 HAS_ANY_COLUMN_PRIVILEGE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 326 8.174 HAS_COLUMN_PRIVILEGE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 326 8.175 HAS_DATABASE_PRIVILEGE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 327 8.176 HAS_FOREIGN_DATA_WRAPPER_PRIVILEGE . . . . . . . . . . . . . . . . . . . . . . . . . . . 328 8.177 HAS_FUNCTION_PRIVILEGE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 328 8.178 HAS_LANGUAGE_PRIVILEGE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 329 8.179 HAS_SCHEMA_PRIVILEGE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 329 8.180 HAS_SEQUENCE_PRIVILEGE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 330 8.181 HAS_SERVER_PRIVILEGE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 330 8.182 HAS_TABLE_PRIVILEGE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 331 8.183 HAS_TABLESPACE_PRIVILEGE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 331 8.184 HAS_TYPE_PRIVILEGE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 332 8.185 HEIGHT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 332 8.186 HEXTORAW . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 333 8.187 HOUR(MySQL 模式) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 333 8.188 HOST . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 334 8.189 HOSTMASK . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 334 8.190 IF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 335 8.191 IFNULL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 336 8.192 INET_CLIENT_ADDR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 336 8.193 INET_CLIENT_PORT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 336 8.194 INET_MERGE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 337 8.195 INET_SAME_FAMILY . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 337 8.196 INET_SERVER_ADDR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 338 8.197 INET_SERVER_PORT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 338 8.198 INITCAP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 338 8.199 INSERTCHILDXML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 339 8.200 INSERTCHILDXMLAFTER . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 340 8.201 INSERTCHILDXMLBEFORE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 340 8.202 INSERTXMLAFTER . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 341 8.203 INSERTXMLBEFORE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 342 8.204 INSTR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 342 8.205 INSTRB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 343 8.206 ISEMPTY . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 343 8.207 ISFINITE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 344 8.208 ISNULL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 344 8.209 ISNULL(MySQL 模式) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 345 8.210 ISOPEN . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 346 8.211 JSON . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 347 8.212 JSON_AGG . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 348 8.213 JSON_ARRAY . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 348 XI 目 录 8.213.1 用法 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 348 8.213.2 用法 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 350 8.213.3 用法 3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 350 8.214 JSON_ARRAY_ELEMENTS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 352 8.215 JSON_ARRAY_ELEMENTS_TEXT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 352 8.216 JSON_ARRAY_LENGTH . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 353 8.217 JSON_ARRAYAGG . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 353 8.218 JSON_BUILD_ARRAY . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 355 8.219 JSON_BUILD_OBJECT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 355 8.220 JSON_EACH . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 355 8.221 JSON_EACH_TEXT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 356 8.222 JSON_EQUAL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 356 8.223 JSON_EXISTS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 357 8.224 JSON_EXTRACT_PATH . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 359 8.225 JSON_EXTRACT_PATH_TEXT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 359 8.226 JSON_OBJECT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 360 8.226.1 用法 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 360 8.226.2 用法 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 360 8.226.3 用法 3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 361 8.227 JSON_OBJECT_AGG . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 363 8.228 JSON_OBJECT_KEYS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 364 8.229 JSON_OBJECTAGG . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 364 8.229.1 用法 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 364 8.229.2 用法 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 366 8.230 JSON_POPULATE_RECORD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 367 8.231 JSON_QUERY . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 368 8.232 JSON_SCALAR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 371 8.233 JSON_SERIALIZE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 372 8.234 JSON_STRIP_NULLS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 374 8.235 JSON_TABLE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 374 8.236 JSON_TO_RECORD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 385 8.237 JSON_TO_RECORDSET . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 385 8.238 JSON_TYPEOF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 386 8.239 JSON_VALUE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 386 8.240 JSONB_AGG . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 388 8.241 JSONB_ARRAY_ELEMENTS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 389 8.242 JSONB_ARRAY_ELEMENTS_TEXT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 389 8.243 JSONB_ARRAY_LENGTH . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 390 8.244 JSONB_BUILD_ARRAY . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 390 8.245 JSONB_BUILD_OBJECT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 390 8.246 JSONB_EACH . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 391 8.247 JSONB_EACH_TEXT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 391 XII 目 录 8.248 JSONB_EXTRACT_PATH . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 392 8.249 JSONB_EXTRACT_PATH_TEXT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 392 8.250 JSONB_INSERT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 392 8.251 JSONB_OBJECT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 393 8.251.1 用法 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 393 8.251.2 用法 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 394 8.252 JSONB_OBJECT_AGG . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 394 8.253 JSONB_OBJECT_KEYS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 395 8.254 JSONB_PATH_EXISTS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 395 8.255 JSONB_PATH_MATCH . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 396 8.256 JSONB_PATH_QUERY . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 396 8.257 JSONB_PATH_QUERY_ARRAY . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 397 8.258 JSONB_PATH_QUERY_FIRST . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 397 8.259 JSONB_POPULATE_RECORD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 398 8.260 JSONB_POPULATE_RECORDSET . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 398 8.261 JSONB_PRETTY . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 398 8.262 JSONB_SET . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 399 8.263 JSONB_STRIP_NULLS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 399 8.264 JSONB_TO_RECORD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 400 8.265 JSONB_TO_RECORDSET . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 400 8.266 JSONB_TYPEOF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 401 8.267 JUSTIFY_DAYS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 401 8.268 JUSTIFY_HOURS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 402 8.269 JUSTIFY_INTERVAL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 402 8.270 LAG . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 402 8.271 LAST . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 403 8.272 LAST_DAY . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 405 8.273 LAST_VALUE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 405 8.274 LASTVAL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 406 8.275 LCASE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 407 8.276 LEAD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 407 8.277 LEAST . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 409 8.278 LEFT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 409 8.279 LENGTH . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 410 8.280 LENGTHB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 411 8.281 LISTAGG . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 411 8.282 LN . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 412 8.283 LNNVL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 413 8.284 LOCALTIME . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 414 8.285 LOCALTIME(MySQL 模式) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 414 8.286 LOCALTIMESTAMP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 415 8.287 LOCALTIMESTAMP(MySQL 模式) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 416 XIII 目 录 8.288 LOCATE(MySQL 模式) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 417 8.289 LOG . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 418 8.290 LOG10 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 418 8.291 LOWER . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 419 8.292 LOWER_INC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 419 8.293 LOWER_INF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 420 8.294 LPAD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 421 8.295 LSEG . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 421 8.296 LTRIM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 422 8.297 MAKEDATE(MySQL 模式) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 423 8.298 MAKETIME(MySQL 模式) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 424 8.299 MAKE_DATE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 425 8.300 MAKE_INTERVAL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 426 8.301 MAKE_SET(bits,oid) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 427 8.302 MAKE_TIME . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 427 8.303 MAKE_TIMESTAMP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 428 8.304 MAKE_TIMESTAMPTZ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 429 8.305 MAX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 430 8.306 MD5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 432 8.307 MICROSECOND(MySQL 模式) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 433 8.308 MID . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 434 8.309 MIN . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 434 8.310 MINUTE(MySQL 模式) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 436 8.311 MOD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 436 8.312 MODE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 438 8.313 MONTH(MySQL 模式) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 439 8.314 MONTH(Oracle 模式) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 440 8.315 MONTHNAME(MySQL 模式) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 441 8.316 MONTHS_BETWEEN . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 442 8.317 NANVL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 442 8.318 NEW_TIME . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 443 8.319 NEXT_DAY . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 444 8.320 NEXTVAL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 444 8.321 NLSSORT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 445 8.322 NOW . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 448 8.323 NTH_VALUE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 448 8.324 NTILE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 449 8.325 NULLIF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 450 8.326 NUMTODSINTERVAL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 451 8.327 NUMTOYMINTERVAL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 451 8.328 NVL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 452 8.329 NVL2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 453 XIV 目 录 8.330 OCTET_LENGTH . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 454 8.331 ORA_HASH . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 454 8.332 OVERLAY . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 455 8.333 PERCENT_RANK . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 456 8.334 PERCENTILE_CONT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 458 8.335 PERCENTILE_DISC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 459 8.336 PERIOD_ADD(MySQL 模式) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 460 8.337 PERIOD_DIFF(MySQL 模式) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 462 8.338 PI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 463 8.339 POSITION . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 463 8.340 POWER . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 464 8.341 QUARTER(MySQL 模式) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 464 8.342 QUERY_TO_XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 465 8.343 QUOTE_IDENT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 466 8.344 QUOTE_LITERAL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 467 8.345 QUOTE_NULLABLE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 468 8.346 RADIANS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 468 8.347 RADIUS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 469 8.348 RANGE_MERGE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 469 8.349 RANK . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 469 8.350 RAND . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 470 8.351 RANDOM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 471 8.352 RATIO_TO_REPORT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 471 8.353 RAWTOHEX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 472 8.354 RAWTONHEX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 473 8.355 REGEXP_COUNT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 474 8.356 REGEXP_INSTR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 475 8.357 REGEXP_LIKE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 476 8.358 REGEXP_MATCH . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 477 8.359 REGEXP_MATCHES . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 477 8.360 REGEXP_REPLACE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 478 8.361 REGEXP_REPLACE(Oracle 模式) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 479 8.362 REGEXP_SPLIT_TO_ARRAY . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 480 8.363 REGEXP_SPLIT_TO_TABLE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 481 8.364 REMAINDER . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 481 8.365 REPEAT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 482 8.366 REPLACE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 482 8.367 REVERSE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 483 8.368 RIGHT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 483 8.369 ROUND . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 484 8.370 ROW_COUNT(MySQL 模式) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 486 8.371 ROW_NUMBER . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 486 XV 目 录 8.372 ROW_TO_JSON . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 487 8.373 RPAD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 488 8.374 ROWIDTOCHAR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 489 8.375 RTRIM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 490 8.376 SCALE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 490 8.377 SCORE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 491 8.378 SECOND(MySQL 模式) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 492 8.379 SEC_TO_TIME(MySQL 模式) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 493 8.380 SESSION_ID . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 494 8.381 SESSION_USER . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 494 8.382 SESSIONTIMEZONE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 495 8.383 SETSEED . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 496 8.384 SETVAL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 496 8.385 SETWEIGHT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 497 8.386 SHA224 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 497 8.387 SHA256 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 498 8.388 SHA384 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 499 8.389 SHA512 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 499 8.390 SIGN . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 500 8.391 SIN . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 501 8.392 SINH . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 501 8.393 SPLIT_PART . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 502 8.394 SQRT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 503 8.395 STATEMENT_TIMESTAMP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 503 8.396 STDDEV . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 504 8.397 STDDEV(MySQL 模式) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 505 8.398 STDDEV_POP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 506 8.399 STDDEV_SAMP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 508 8.400 STR_TO_DATE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 509 8.401 STR_VALID . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 510 8.402 STRING_AGG . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 510 8.403 STRING_TO_ARRAY . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 511 8.404 STRIP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 512 8.405 STRPOS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 512 8.406 SUBSTR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 513 8.407 SUBSTRB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 514 8.408 SUBSTRING . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 516 8.409 SUBSTRING_INDEX(MySQL 模式) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 517 8.410 SUBTIME(MySQL 模式) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 517 8.411 SUM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 519 8.412 SUPPRESS_REDUNDANT_UPDATES_TRIGGER . . . . . . . . . . . . . . . . . . . . . . . . . . . 520 8.413 SYS_BACKEND_PID . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 521 XVI 目 录 8.414 SYS_CANCEL_BACKEND . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 521 8.415 SYS_COLUMN_SIZE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 522 8.416 SYS_CONTEXT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 523 8.417 SYS_DATABASE_SIZE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 524 8.418 SYS_EVENT_TRIGGER_DDL_COMMANDS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 524 8.419 SYS_EVENT_TRIGGER_DROPPED_OBJECTS . . . . . . . . . . . . . . . . . . . . . . . . . . . 526 8.420 SYS_EVENT_TRIGGER_TABLE_REWRITE_OID . . . . . . . . . . . . . . . . . . . . . . . . . . 528 8.421 SYS_EVENT_TRIGGER_TABLE_REWRITE_REASON . . . . . . . . . . . . . . . . . . . . . . . 529 8.422 SYS_STAT_FILE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 529 8.423 SYS_READ_BINARY_FILE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 530 8.424 SYS_READ_FILE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 530 8.425 SYS_TERMINATE_BACKEND . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 531 8.426 SYS_TOTAL_RELATION_SIZE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 531 8.427 SYS_FUNCTION_IS_VISIBLE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 532 8.428 SYS_GET_CONSTRAINTDEF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 533 8.429 SYS_GET_EXPR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 534 8.430 SYS_GET_FUNCTION_ARGUMENTS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 535 8.431 SYS_GET_FUNCTION_IDENTITY_ARGUMENTS . . . . . . . . . . . . . . . . . . . . . . . . . . 536 8.432 SYS_GET_FUNCTION_RESULT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 537 8.433 SYS_GET_FUNCTIONDEF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 538 8.434 SYS_GET_INDEXDEF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 539 8.435 SYS_GET_KEYWORDS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 540 8.436 SYS_GET_OBJECT_ADDRESS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 540 8.437 SYS_GET_RULEDEF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 541 8.438 SYS_GET_SERIAL_SEQUENCE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 543 8.439 SYS_GET_STATISTICSOBJDEF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 544 8.440 SYS_GET_TRIGGERDEF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 544 8.441 SYS_GET_USERBYID . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 546 8.442 SYS_GET_VIEWDEF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 547 8.443 SYS_GUID . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 548 8.444 SYS_HAS_ROLE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 549 8.445 SYS_IDENTIFY_OBJECT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 550 8.446 SYS_IDENTIFY_OBJECT_AS_ADDRESS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 550 8.447 SYS_INDEXES_SIZE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 551 8.448 SYS_KINGBASE_START_TIME . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 552 8.449 SYS_LS_DIR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 552 8.450 SYS_LS_LOGDIR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 553 8.451 SYS_LS_TMPDIR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 554 8.452 SYS_LS_WALDIR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 554 8.453 SYS_RELATION_FILENODE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 555 8.454 SYS_RELATION_FILEPATH . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 556 8.455 SYS_RELATION_SIZE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 556 XVII 目 录 8.456 SYS_RELOAD_CONF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 557 8.457 SYS_SIZE_BYTES . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 558 8.458 SYS_SIZE_PRETTY . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 558 8.459 SYS_SLEEP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 559 8.460 SYS_SLEEP_FOR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 560 8.461 SYS_SLEEP_UNTIL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 560 8.462 SYS_TABLE_IS_VISIBLE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 561 8.463 SYS_TABLE_SIZE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 561 8.464 SYS_TABLESPACE_DATABASES . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 562 8.465 SYS_TABLESPACE_LOCATION . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 563 8.466 SYS_TABLESPACE_SIZE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 563 8.467 SYSDATE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 564 8.468 TABLE_TO_XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 564 8.469 TAN . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 566 8.470 TANH . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 566 8.471 TIME(MySQL 模式) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 567 8.472 TIMEDIFF(MySQL 模式) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 568 8.473 TIMESTAMP(MySQL 模式) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 569 8.474 TIMESTAMPADD(MySQL 模式) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 571 8.475 TIMESTAMPDIFF(MySQL 模式) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 572 8.476 TIME_FORMAT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 573 8.477 TIME_TO_SEC(MySQL 模式) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 574 8.478 TIMEOFDAY . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 575 8.479 TIMESUB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 575 8.480 TO_ASCII . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 576 8.481 TO_BASE64(MySQL 模式) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 577 8.482 TO_BINARY_DOUBLE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 577 8.483 TO_BLOB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 578 8.484 TO_CHAR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 578 8.484.1 TO_CHAR(bfile|blob) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 578 8.484.2 TO_CHAR(character) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 579 8.484.3 TO_CHAR(datetime) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 581 8.484.4 TO_CHAR(number) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 586 8.485 TO_DATE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 589 8.486 TO_DATETIME . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 591 8.487 TO_DAYS(MySQL 模式) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 592 8.488 TO_DSINTERVAL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 593 8.489 TO_HEX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 595 8.490 TO_JSON . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 595 8.491 TO_JSONB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 596 8.492 TO_MULTI_BYTE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 596 8.493 TO_NUMBER . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 597 XVIII 目 录 8.494 TO_SECONDS(MySQL 模式) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 598 8.495 TO_SINGLE_BYTE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 599 8.496 TO_TIMESTAMP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 600 8.497 TO_TIMESTAMP_TZ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 600 8.498 TO_YMINTERVAL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 601 8.499 TRANSACTION_TIMESTAMP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 602 8.500 TRANSLATE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 603 8.501 TRIM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 604 8.502 TRUNC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 605 8.502.1 TRUNC(date) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 605 8.502.2 TRUNC(number) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 607 8.502.3 TRUNC(text) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 608 8.503 UCASE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 609 8.504 UNICODE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 609 8.505 UNIX_TIMESTAMP(MySQL 模式) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 610 8.506 UNNEST . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 611 8.507 UPDATEXML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 612 8.508 UPPER . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 612 8.509 USER . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 613 8.510 USERENV . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 614 8.511 UTC_DATE(MySQL 模式) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 615 8.512 UTC_TIME(MySQL 模式) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 616 8.513 UTC_TIMESTAMP(MySQL 模式) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 617 8.514 VALUE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 617 8.515 VAR_POP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 618 8.516 VAR_SAMP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 619 8.517 VARIANCE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 619 8.518 VARIANCE(MySQL 模式) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 620 8.519 VERSION . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 621 8.520 WEEK(MySQL 模式) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 621 8.521 WEEKDAY(MySQL 模式) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 623 8.522 WEEKOFYEAR(MySQL 模式) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 624 8.523 WM_CONCAT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 624 8.524 XML_IS_WELL_FORMED . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 625 8.525 XML_IS_WELL_FORMED_DOCUMENT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 626 8.526 XML_IS_WELL_FORMED_CONTENT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 626 8.527 XMLAGG . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 627 8.528 XMLCOMMENT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 628 8.529 XMLCONCAT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 629 8.530 XMLELEMENT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 630 8.531 XMLEXISTS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 633 8.532 XMLFOREST . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 634 XIX 目 录 8.533 XMLPARSE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 635 8.534 XMLPI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 636 8.535 XMLROOT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 636 8.536 XMLSEQUENCE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 637 8.537 XMLSERIALIZE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 638 8.538 XMLTABLE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 639 8.539 XPATH . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 641 8.540 XPATH_EXISTS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 642 8.541 YEAR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 643 8.542 YEARWEEK(MySQL 模式) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 643 8.543 用户自定义函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 644 第 9 章 常见 DDL 子句 648 9.1 约束子句 9.2 LOG 子句 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 655 9.3 存储子句 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 648 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 656 第 10 章 查询和子查询 660 10.1 关于查询和子查询 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 660 10.2 创建简单查询 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 661 10.3 层次查询 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 662 10.3.1 层次查询示例 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 662 10.4 集合操作 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 666 10.4.1 使用连接方式的原则 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 666 10.4.2 复杂查询的原则 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 669 10.5 查询结果排序 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 671 10.6 JOIN 操作 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 672 10.7 使用子查询 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 673 10.8 限制嵌套查询层数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 674 10.9 DUAL 表查询 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 674 10.10 PIVOT 和 UNPIVOT 行列转换 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 674 10.10.1 PIVOT 行转列 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 674 10.10.2 UNPIVOT 列转行 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 676 10.10.3 递归查询求值 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 678 第 11 章 SQL 语句:ABORT 到 ALTER INDEX 684 11.1 SQL 语句类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 685 11.1.1 数据定义语句 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 685 11.1.2 数据操作语句 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 686 11.1.3 事务控制语句 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 686 11.1.4 会话控制语句 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 686 11.1.5 系统控制语句 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 687 11.2 SQL 语句各章节是如何组织的 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 687 XX 目 录 11.3 ABORT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 687 11.4 ALTER AGGREGATE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 688 11.5 ALTER COLLATION . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 691 11.6 ALTER CONVERSION . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 693 11.7 ALTER DATABASE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 694 11.8 ALTER DATABASE LINK . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 696 11.9 ALTER DEFAULT PRIVILEGES . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 697 11.10 ALTER DOMAIN . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 702 11.11 ALTER EVENT TRIGGER . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 706 11.12 ALTER EXTENSION . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 707 11.13 ALTER FOREIGN DATA WRAPPER . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 712 11.14 ALTER FOREIGN TABLE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 714 11.15 ALTER FUNCTION . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 720 11.16 ALTER GROUP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 726 11.17 ALTER INDEX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 728 第 12 章 SQL 语句:ALTER LANGUAGE 到 ALTER SUBSCRIPTION 733 12.1 ALTER LANGUAGE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 734 12.2 ALTER LARGE OBJECT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 735 12.3 ALTER MATERIALIZED VIEW . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 735 12.4 ALTER OPERATOR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 739 12.5 ALTER OPERATOR CLASS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 741 12.6 ALTER OPERATOR FAMILY . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 742 12.7 ALTER PACKAGE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 747 12.8 ALTER POLICY . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 749 12.9 ALTER PROCEDURE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 750 12.10 ALTER PUBLICATION . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 755 12.11 ALTER RESOURCE GROUP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 758 12.12 ALTER ROLE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 758 12.13 ALTER ROUTINE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 764 12.14 ALTER RULE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 766 12.15 ALTER SCHEMA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 767 12.16 ALTER SEQUENCE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 768 12.17 ALTER SERVER . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 771 12.18 ALTER STATISTICS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 773 12.19 ALTER SUBSCRIPTION . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 775 第 13 章 SQL 语句:ALTER SYNONYM 到 COMMENT 779 13.1 ALTER SYNONYM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 780 13.2 ALTER SYSTEM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 781 13.3 ALTER TABLE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 782 13.4 ALTER TABLESPACE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 809 13.5 ALTER TEXT SEARCH CONFIGURATION . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 811 XXI 目 录 13.6 ALTER TEXT SEARCH DICTIONARY . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 813 13.7 ALTER TEXT SEARCH PARSER . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 815 13.8 ALTER TEXT SEARCH TEMPLATE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 816 13.9 ALTER TRIGGER . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 817 13.10 ALTER TYPE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 819 13.11 ALTER USER . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 824 13.12 ALTER USER MAPPING . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 827 13.13 ALTER VIEW . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 829 13.14 ANALYZE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 831 13.15 BEGIN . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 834 13.16 CALL/EXEC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 836 13.17 CHECKPOINT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 837 13.18 CLOSE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 838 13.19 CLUSTER . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 839 13.20 COMMENT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 841 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE 846 14.1 COMMIT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 847 14.2 COMMIT PREPARED . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 847 14.3 COPY . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 848 14.4 CREATE ACCESS METHOD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 860 14.5 CREATE AGGREGATE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 861 14.6 CREATE CAST . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 871 14.7 CREATE COLLATION . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 875 14.8 CREATE CONTEXT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 877 14.9 CREATE CONVERSION . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 878 14.10 CREATE DATABASE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 880 14.11 CREATE DATABASE LINK . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 883 14.12 CREATE DIRECTORY . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 884 14.13 CREATE DOMAIN . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 885 14.14 CREATE EVENT TRIGGER . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 888 14.15 CREATE EXTENSION . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 890 14.16 CREATE FOREIGN DATA WRAPPER . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 892 14.17 CREATE FOREIGN TABLE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 894 14.18 CREATE FUNCTION . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 899 14.19 CREATE GROUP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 913 14.20 CREATE INDEX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 916 14.21 CREATE LANGUAGE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 924 第 15 章 SQL 语句:CREATE MATERIALIZED VIEW 到 CREATE SCHEMA 928 15.1 CREATE MATERIALIZED VIEW . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 928 15.2 CREATE OPERATOR CLASS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 930 15.3 CREATE OPERATOR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 933 XXII 目 录 15.4 CREATE OPERATOR FAMILY . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 936 15.5 CREATE PACKAGE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 937 15.6 CREATE PACKAGE BODY . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 940 15.7 CREATE POLICY . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 943 15.8 CREATE PROCEDURE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 949 15.9 CREATE PUBLICATION . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 955 15.10 CREATE RESOURCE GROUP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 957 15.11 CREATE ROLE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 958 15.12 CREATE RULE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 963 15.13 CREATE SCHEMA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 966 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE 970 16.1 CREATE SEQUENCE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 971 16.2 CREATE SERVER . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 974 16.3 CREATE STATISTICS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 976 16.4 CREATE SUBSCRIPTION . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 978 16.5 CREATE SYNONYM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 980 16.6 CREATE TABLE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 982 16.7 CREATE TABLE AS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1022 16.8 CREATE TABLESPACE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1028 16.9 CREATE TEXT SEARCH CONFIGURATION . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1031 16.10 CREATE TEXT SEARCH DICTIONARY . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1032 16.11 CREATE TEXT SEARCH PARSER . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1033 16.12 CREATE TEXT SEARCH TEMPLATE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1034 16.13 CREATE TRANSFORM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1035 16.14 CREATE TRIGGER . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1038 16.15 CREATE TYPE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1053 16.16 CREATE TYPE BODY . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1066 16.17 CREATE USER . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1069 16.18 CREATE USER MAPPING . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1072 16.19 CREATE VIEW . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1073 16.20 DEALLOCATE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1078 16.21 DECLARE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1079 16.22 DELETE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1082 16.23 DELETE RESOURCE GROUP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1086 第 17 章 SQL 语句: DISCARD 到 DROP LANGUAGE 1087 17.1 DISCARD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1088 17.2 DO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1089 17.3 DROP ACCESS METHOD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1090 17.4 DROP AGGREGATE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1091 17.5 DROP CAST . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1093 17.6 DROP COLLATION . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1093 XXIII 目 录 17.7 DROP CONTEXT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1094 17.8 DROP CONVERSION . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1095 17.9 DROP DATABASE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1096 17.10 DROP DATABASE LINK . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1097 17.11 DROP DIRECTORY . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1097 17.12 DROP DOMAIN . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1098 17.13 DROP EVENT TRIGGER . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1099 17.14 DROP EXTENSION . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1100 17.15 DROP FOREIGN DATA WRAPPER . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1101 17.16 DROP FOREIGN TABLE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1102 17.17 DROP FUNCTION . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1102 17.18 DROP GROUP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1104 17.19 DROP INDEX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1105 17.20 DROP LANGUAGE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1106 第 18 章 SQL 语句: DROP MATERIALIZED VIEW 到 DROP SYNONYM 1108 18.1 DROP MATERIALIZED VIEW . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1109 18.2 DROP OPERATOR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1109 18.3 DROP OPERATOR CLASS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1111 18.4 DROP OPERATOR FAMILY . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1112 18.5 DROP OWNED . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1113 18.6 DROP PACKAGE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1114 18.7 DROP PACKAGE BODY . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1115 18.8 DROP POLICY . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1115 18.9 DROP PROCEDURE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1116 18.10 DROP PUBLICATION . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1117 18.11 DROP ROLE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1118 18.12 DROP ROUTINE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1119 18.13 DROP RULE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1121 18.14 DROP SCHEMA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1122 18.15 DROP SEQUENCE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1123 18.16 DROP SERVER . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1124 18.17 DROP STATISTICS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1125 18.18 DROP SUBSCRIPTION . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1125 18.19 DROP SYNONYM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1126 第 19 章 SQL 语句: DROP TABLE 到 LOAD 1128 19.1 DROP TABLE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1129 19.2 DROP TABLESPACE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1130 19.3 DROP TRANSFORM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1131 19.4 DROP TEXT SEARCH CONFIGURATION . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1132 19.5 DROP TEXT SEARCH DICTIONARY . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1133 19.6 DROP TEXT SEARCH PARSER . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1133 XXIV 目 录 19.7 DROP TEXT SEARCH TEMPLATE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1134 19.8 DROP TRIGGER . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1135 19.9 DROP TYPE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1136 19.10 DROP TYPE BODY . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1137 19.11 DROP USER . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1138 19.12 DROP USER MAPPING . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1139 19.13 DROP VIEW . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1140 19.14 END . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1140 19.15 EXECUTE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1141 19.16 EXPLAIN PLAN . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1143 19.17 FETCH . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1147 19.18 FLASHBACK TABLE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1151 19.19 GRANT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1153 19.20 INSERT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1163 19.21 INSERT ALL FIRST . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1173 19.22 INSERT(MySQL 模式) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1177 19.23 INSERT ON DUPLICATE(MySQL 模式) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1180 19.24 LISTEN . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1184 19.25 LOAD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1185 19.26 LOCK . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1186 第 20 章 SQL 语句: MERGE 到 VALUES 1190 20.1 MERGE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1191 20.2 MOVE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1196 20.3 NOTIFY . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1198 20.4 PREPARE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1200 20.5 PREPARE TRANSACTION . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1202 20.6 PURGE TABLE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1204 20.7 REASSIGN OWNED . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1205 20.8 REFRESH MATERIALIZED VIEW . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1206 20.9 REINDEX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1207 20.10 REPLACE INTO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1211 20.11 RELEASE SAVEPOINT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1214 20.12 RESET . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1215 20.13 REVOKE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1216 20.14 ROLLBACK . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1221 20.15 ROLLBACK PREPARED . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1222 20.16 ROLLBACK TO SAVEPOINT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1223 20.17 SAVEPOINT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1225 20.18 SECURITY LABEL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1226 20.19 SELECT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1229 20.20 SELECT INTO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1255 XXV 目 20.21 SET 录 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1258 20.22 SET CONSTRAINTS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1261 20.23 SET ROLE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1262 20.24 SET SESSION AUTHORIZATION . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1264 20.25 SET TRANSACTION . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1265 20.26 SHOW . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1268 20.27 START TRANSACTION . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1270 20.28 TRUNCATE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1271 20.29 UNLISTEN . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1273 20.30 UPDATE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1274 20.31 UPDATE(MySQL 模式) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1281 20.32 VACUUM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1286 20.33 VALUES . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1290 第 21 章 KingbaseES 正则表达式支持 1294 21.1 正则表达式语法 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1294 21.1.1 POSIX 正则表达式 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1294 21.1.2 正则表达式细节 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1299 21.1.3 方括号表达式 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1302 21.1.4 正则表达式转义 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1303 21.1.5 正则表达式元语法 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1305 21.1.6 正则表达式匹配规则 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1306 21.2 正则表达式兼容性与限制 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1308 21.2.1 ERE 兼容性 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1308 21.2.2 BRE 兼容性 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1309 21.2.3 Perl 正则表达式兼容性 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1309 第 22 章 SQL 保留字和关键字 1310 第 23 章 MySQL 模式索引 1335 23.1 数据类型方面 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1335 23.1.1 整数类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1335 23.1.2 日期与时间类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1335 23.1.3 大对象数据类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1336 23.1.4 JSON 类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1336 23.1.5 用户自定义类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1336 23.2 操作符方面 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1336 23.3 函数方面 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1336 23.3.1 mysql_json 插件相关函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1338 23.4 语法方面 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1339 23.4.1 CREATE TABLE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1339 版权声明 1340 XXVI 目 录 服务周期承诺 1341 Bibliography 1343 XXVII 第 1 章 前言 1 第 章 前言 本文档描述了用于管理 KingbaseES 的结构化查询语言(SQL),KingbaseES 使用的 SQL 是国际标准化组织 (ISO)SQL 标准的超集。 前言部分包含以下主题: • 适用读者 • 相关文档 • 术语 • 手册约定 1.1 适用读者 KingbaseES SQL 语言参考手册面向所有使用 KingbaseES 的用户,主要是数据库管理员和应用程序开发人员。 在开始阅读本文档之前,您需要了解以下内容: 1.2 相关文档 有关文档的更多信息,可访问 KingbaseES 在线文档库 1.3 术语 无 1 第 1 章 前言 1.4 手册约定 本文档中可能出现“注意、提示、警告、另请参阅”等标志,它们所代表的含义如下: 注意: 用于突出重要/关键信息、最佳实践等。 提示: 用于突出小窍门、捷径等。 警告: 用于传递设备或环境安全警示信息,若不避免,可能会导致设备损坏、数据丢失、设备性能降低或其 它不可预知的结果。 另请参阅: 用于突出参考、参阅等。 以下程序代码书写约定适用于本文档: 符号 说明 [] 表示包含一个或多个可选项。不需要输入中括号本身。 {} 表示包含两个以上(含两个)的候选,必须在其中选取一个。不需要输入花括号本身。 | 分割中括号或者花括号中的两个或两个以上选项。不需要输入“|”本身。 ... 表示其之前的元素可以被重复。 斜体 表示占位符或者需要提供特定值的变量。 大写 表示系统提供的元素,以便与用户定义的元素相互区分。除出现在方括号中的元素外,应当按 照顺序逐字输入。当然,部分元素在系统中是大小写不敏感的,因此用户可以根据系统说明以 小写形式输入。 小写 表示由用户提供的元素。 2 第 2 章 KINGBASEES SQL 介绍 2 第 章 KingbaseES SQL 介绍 结构化查询语言(SQL)是一组语句,用户和程序可以通过这些语句访问 KingbaseES 数据库内的数据。应用程 序和 KingbaseES 工具支持用户在不直接使用 SQL 的情况下访问数据库,但是应用程序在执行用户请求时,必须使 用 SQL 语句。本章介绍大多数数据库系统使用的 SQL 背景信息。 本章包含如下主题: • SQL 历史 • SQL 标准 • 词汇约定 • 工具支持 2.1 SQL 历史 E.F. Codd 博士于 1970 年 6 月在计算机机械协会(ACM)期刊《ACM 通信》上发表了题为“A Relational Model of Data for Large Shared Data Banks”的论文。Codd 的模型现在被认为是关系数据库管理系统(RDBMS) 的最终模型。结构化英语查询语言(SEQUEL)由 IBM 公司开发,使用 Codd 的模型。SEQUEL 后来成为 SQL。至 今,SQL 被认为是标准的 RDBMS 语言。 2.2 SQL 标准 KingbaseES 遵守行业公认的标准,并积极参与国内 SQL 标准组织。行业公认的委员会是美国国家标准协会 (ANSI)和国际标准化组织(ISO),该组织隶属于国际电工委员会(IEC)。ANSI 和 ISO/IEC 都将 SQL 作为 关系数据库的标准语言。 3 第 2 章 KINGBASEES SQL 介绍 2.2.1 SQL 工作原理 SQL 为各用户(包括应用程序程序员、数据库管理员和最终用户)提供使用便利。从技术上讲,SQL 是数据子 语言,是访问关系数据库(如 KingbaseES 数据库)的接口,所有 SQL 语句都是对数据库的指令。SQL 语句与 C 或 BASIC 等通用编程语言不同。SQL 的功能包括: • 以组的形式处理数据集而不是单独处理。 • 自动定位到数据。 • 使用独立、复杂且功能强大的语句。流控制语句(如 begin-end、if-then-else、循环和异常条件处理)最初不是 SQL 和 SQL 标准的一部分,但现在就属于 ISO/IEC 9075-4 -持久存储模块(SQL/PSM)中的一部分。KingbaseES SQL 的 PL / SQL 扩展类似于 PSM。 SQL 可以让用户操作数据只需要关注数据的逻辑,只有操作数据时,才需要关系数据的细节。满足条件的所有 行一次性被检索出来,作为一个结果集传给用户、传给另一个 SQL 语句或传给应用程序。无需逐个处理行,也不必 了解其物理存储或检索方式。SQL 语句通过优化器(优化器是 KingbaseES 数据库的一部分)确定访问指定数据的最 有效方法。KingbaseES 还提供了一些技术,通过这些技术使优化器执行效率更高。 SQL 语句可完成各种任务,包括: • 查询数据 • 插入、更新和删除表中的行 • 创建、替换、更改和删除对象 • 控制对数据库及其对象的访问 • 保证数据库的一致性和完整性 SQL 用一套一致性的语言支持上述所有任务。 2.2.2 所有关系数据库的通用语言 所有主要的关系数据库管理系统都支持 SQL,因此一个数据库管理系统的 SQL 使用方法在另外的数据库管理系 统上可以通用。此外,用 SQL 编写的程序是可移植的。通常从一个数据库迁移到另一个数据库,只需很少的修改。 2.3 词汇约定 以下 SQL 的词法约定适用于 KingbaseES 数据库的 SQL 语句,在其他数据库 SQL 语句中通常也是适用的。执行 SQL 语句时,可以在语句定义中空格的任何位置包含一个或多个制表符、回车符、空格或注释。因此,KingbaseES 数据库认为以下两条语句是相同的: SELECT last_name,salary*12,MONTHS_BETWEEN(SYSDATE,hire_date) FROM employees 4 第 2 章 KINGBASEES SQL 介绍 WHERE department_id = 30 ORDER BY last_name; SELECT last_name, salary * 12, MONTHS_BETWEEN( SYSDATE, hire_date ) FROM employees WHERE department_id=30 ORDER BY last_name; 在保留字、关键字、标识符和参数中,大小写无关紧要。但是,大小写在文本常量和引用的名称中却很重要。 注意: SQL 语句在不同的编程环境中以不同的方式终止。本文档使用默认的字符(;)。 2.4 工具支持 kingbaseES 提供了实用工具简化 SQL 开发过程: • KStudio 数据库开发工具是一款图形化工具,可浏览、创建、编辑和删除数据库对象,编辑和调试 PL/SQL 代 码,运行 SQL 语句和脚本,操作和导出数据,以及创建和查看报告。 此开发工具通过数据库认证后,可以连接到 KingbaseES 数据库。DBA 还可以使用 KStudio 来管理数据库,包 括逻辑备份和还原以及审计等。 • KSQL 是 KingbaseES 数据库命令行工具。可以交互方式或批量执行 SQL 和 PL/SQL 脚本。 另请参阅: 有关这些产品的更多信息,请参见《KStudio 快速开发手册》《KStudio 使用手册》和《KingbaseES ksql 工具 用户指南及参考》。 5 第3章 3 第 章 KINGBASEES SQL 基本元素 KingbaseES SQL 基本元素 本章包含 KingbaseES SQL 基本元素的信息。这些元素是 SQL 语句的最简单构建基础。因此,在使用本书中描 述的 SQL 语句之前,应该熟悉本章中介绍的概念。 本章包含以下内容: • 数据类型 • 数据类型比较规则 • 常量 • 格式模型 • 空值 • 注释 • 数据库对象 • 数据库对象名称和限定符 • 数据库对象引用方式 3.1 数据类型 KingbaseES 数据库操作的每个值都有其数据类型。数据类型具有特定的属性,因此对不同数据类型的值 KingbaseES 处理是不同的。例如,可以添加 NUMBER 数据类型的值,就不能添加 RAW 数据类型的值。 创建表时,必须为其每个列指定数据类型。创建过程或存储函数时,必须为其每个参数指定数据类型。数据类型 定义每列的值域或每个参数的值域。例如,DATE 列不能接受值 2 月 29 日(闰年除外)或值 2 或“SHOE”。插入 列中的每个值都认定为该数据类型。例如,如果插入’01-JAN-98’ 值到 DATE 列中,则 KingbaseES 会在验证字符串 转换为有效日期后将其视为 DATE 值。 KingbaseES 数据库提供了许多内置数据类型,和用户自定义类型。下面会逐一介绍各数据类型。本节分为以下 几部分内容: • KingbaseES 内置数据类型 6 第3章 KINGBASEES SQL 基本元素 • 用户自定义类型 • Rowid 数据类型 3.1.1 KingbaseES 内置数据类型 3.1.1.1 字符数据类型 字符数据类型存储字符(字母数字)数据,包括单词和自由格式文本,以数据库字符集或国际字符集形式存储。 比其他数据类型的限制少,具有较少的属性。例如,字符列可以存储所有字母数字值,但数值列只能存储数值。 字符数据存储在字符串中,其字节值与建库时指定的字符集对应,如 7 位 ASCII 或 EBCDIC。KingbaseES 数据 库支持单字节和多字节字符集。 表 3.1.1: 字符类型 名字 描述 character varying[(n [char | byte])]) 有限制的变长 varchar(n [char | byte]) n 取值最小为 1 字节或 1 字符 varchar2(n [char | byte]) 最大 10485760 字节或字符 nvarchar2(n [char | byte]) n 缺省值为 1。 nvarchar(n [char | byte]) char 或 byte 的默认值由 NLS_LENGTH_SEMANTICS 确定。 (n 可以取’*’, 表示不限制长度) character(n [char | byte]) 指定长度的定长字符 char(n [char | byte]) 最大长度是 10485760 个字节或者字符 char(n [char | byte]) n 缺省值为 1 char 或 byte 的默认值由 NLS_LENGTH_SEMANTICS 确定。 text 无限变长,存储任何长度的字符串 存储最大值为 1G。 longtext 无限变长,存储任何长度的字符串 存储最大值为 1G。 mediumtext 指定长度变长,存储长度最大为 16777215 个字节字符串。 tinytext 指定长度变长,存储长度最大为 255 个字节。 7 第3章 KINGBASEES SQL 基本元素 3.1.1.1.1 character[(n [char | byte])] 数据类型 语法: character[(n [char | byte])] 别名: char[(n [char | byte])] 定长字符串,n 限定字符串长度,如果显式指定 char,则表示 n 个字符长度;如果显式指定 byte,则表示 n 个 字节长度; 如果没有显式指定,则以系统参 nls_length_semantics 为准,若系统参数 nls_length_semantics 为 char,则以 字符为单位,否则以字节为单位。 值域: 定长,不足定义长度时在最右边以空格补齐。n 的最大值为 10485760,最小值为 1,默认值为 1。如果字符串的 长度超出 n,则按照 SQL 标准截断 (兼容 PostgreSQL 模式下,超出部分都是空格) 或报错。 示例: 1) nls_length_semantics 为缺省是 char 的情况 set nls_length_semantics = 'char'; create table test_default_char (col char(4)); insert into test_default_char values ('1234'); insert into test_default_char values ('12345'); ERROR: value too large for column "public"."test_default_char"."col" (actual:5, maximum:4) insert into test_default_char values ('一二'); insert into test_default_char values ('一二三'); select col, length(col) from test_default_char; COL | LENGTH ---------+-------1234 | 4 一二 | 4 一二三 | 4 2) nls_length_semantics 缺省是 byte 的情况 set nls_length_semantics = 'byte'; create table test_default_byte (col char(4)); 8 第3章 KINGBASEES SQL 基本元素 insert into test_default_byte values ('1234'); insert into test_default_byte values ('12345'); ERROR: value too large for column "public"."test_default_byte"."col" (actual:5, maximum:4) insert into test_default_byte values ('一'); insert into test_default_byte values ('一二三'); ERROR: value too large for column "public"."test_default_byte"."col" (actual:9, maximum:4) select col, length(col) from test_default_byte; COL | LENGTH ------+-------1234 | 4 一 2 | 3) 显式指定是 byte 的情况 create table test_byte (col char(4 byte)); insert into test_byte values ('1234'); insert into test_byte values ('12345'); ERROR: value too large for column "public"."test_byte"."col" (actual:5, maximum:4) insert into test_byte values ('一'); insert into test_byte values ('一二三'); ERROR: value too large for column "public"."test_byte"."col" (actual:9, maximum:4) select col, length(col) from test_byte; COL | LENGTH ------+-------1234 | 4 一 2 | 4) 显式指定是 char 的情况 create table test_char (col char(4 char)); insert into test_char values ('1234'); insert into test_char values ('12345'); ERROR: value too large for column "public"."test_char"."col" (actual:5, maximum:4) insert into test_char values ('一二三四'); insert into test_char values ('一二三四五'); ERROR: value too large for column "public"."test_char"."col" (actual:5, maximum:4) select col, length(col) from test_char; COL | LENGTH ----------+-------1234 | 4 一二三四 | 4 3.1.1.1.2 character varying[(n [char | byte])] 数据类型 语法: 9 第3章 KINGBASEES SQL 基本元素 character varying[(n [char | byte])] 别名: varchar[(n [char | byte])] varchar2[(n [char | byte])] nvarchar2[(n [char | byte])] nvarchar[(n [char |byte])] 变长字符串,如果显式指定了 char,则表示 n 个字符长度;如果显式指定 byte,则表示 n 个字节长度;如果没 有显式指定,则以系统参数 nls_length_semantics 为准,若系统参数 nls_length_semantics 为 char,则以字符为单 位,否则以字节为单位。 值域: 变长,有长度限制。字符串长度小于 n 时不在字符串右边用空格补齐。n 的最大值为 10485760。如果 n 缺省, 则 character varying 表示接受任何长度的串。 示例: 1) nls_length_semantics 缺省是 char 的情况 set nls_length_semantics = 'char'; create table test_default_varchar (col varchar(4)); insert into test_default_varchar values ('1234'); insert into test_default_varchar values ('12345'); ERROR: value too large for column "public"."test_default_varchar"."col" (actual:5, maximum:4) insert into test_default_varchar values ('一二'); insert into test_default_varchar values ('一二三'); select col, length(col) from test_default_varchar; COL | LENGTH --------+-------1234 | 4 一二 | 2 一二三 | 3 2) nls_length_semantics 缺省是 byte 的情况 10 第3章 KINGBASEES SQL 基本元素 set nls_length_semantics = 'byte'; create table test_default_varbyte (col varchar(4)); insert into test_default_varbyte values ('1234'); insert into test_default_varbyte values ('12345'); ERROR: value too large for column "public"."test_default_varbyte"."col" (actual:5, maximum:4) insert into test_default_varbyte values ('一'); insert into test_default_varbyte values ('一二三'); ERROR: value too large for column "public"."test_default_varbyte"."col" (actual:9, maximum:4) select col, length(col) from test_default_varbyte; COL | LENGTH ------+-------1234 | 4 一 | 1 3) 显式指定是 byte 的情况 create table test_varbyte (col varchar(4 byte)); insert into test_varbyte values ('1234'); insert into test_varbyte values ('12345'); ERROR: value too large for column "public"."test_varbyte"."col" (actual:5, maximum:4) insert into test_varbyte values ('一'); insert into test_varbyte values ('一二三'); ERROR: value too large for column "public"."test_varbyte"."col" (actual:9, maximum:4) select col, length(col) from test_varbyte; COL | LENGTH ------+-------1234 | 4 一 1 | 4) 显式指定是 char 的情况 create table test_varchar (col varchar(4 char)); insert into test_varchar values ('1234'); insert into test_varchar values ('12345'); ERROR: value too large for column "public"."test_varchar"."col" (actual:5, maximum:4) insert into test_varchar values ('一二三四'); insert into test_varchar values ('一二三四五'); ERROR: value too large for column "public"."test_varchar"."col" (actual:15, maximum:4) select col, length(col) from test_varchar; COL | LENGTH ----------+-------1234 | 4 一二三四 | 4 5) 查看字符个数 11 第3章 KINGBASEES SQL 基本元素 CREATE TABLE test1 (a character(4)); INSERT INTO test1 VALUES ('ok'); SELECT a, char_length(a) FROM test1; a | char_length ------+------------ok | 2 CREATE TABLE test2 (b varchar(5)); INSERT INTO test2 VALUES ('ok'); INSERT INTO test2 VALUES ('good ERROR: '); value too large for column "public"."test2"."b" (actual:10, maximum:5) INSERT INTO test2 VALUES ('too long'); ERROR: value too large for column "public"."test2"."b" (actual:8, maximum:5) INSERT INTO test2 VALUES ('too long'::varchar(5)); SELECT b, char_length(b) FROM test2; b | char_length -------+------------ok | 2 too l | 5 在 KingbaseES 里另外还有两种定长字符类型,在 表 3.1.2 里显示。name 类型只用于在内部系统目录中存储标识 符并且不是给一般用户使用的。该类型长度当前定为 64 字节(63 可用字符加结束符)但在 C 源代码应该使用常量 NAMEDATALEN 引用。这个长度是在编译的时候设置的(因而可以为特殊用途调整),缺省的最大长度在以后的版本可 能会改变。类型"char"(注意引号)和 char(1) 是不一样的,它只用了一个字节的存储空间。它在系统内部用于系 统目录当做简化的枚举类型用。 表 3.1.2: 特殊字符类型 名字 存储尺寸 描述 "char" 1 字节 单字节内部类型 name 64 字节 用于对象名的内部类型 3.1.1.1.3 TEXT 类型 语法: TEXT 12 第3章 KINGBASEES SQL 基本元素 变长字符串类型。其字符串的长度最大为 1G。使用该类型存储长的文本串。 3.1.1.1.4 LONGTEXT 数据类型 语法: LONGTEXT 变长字符串类型。其字符串的长度最大为 1G。使用该类型存储长的文本串。 3.1.1.1.5 MEDIUMTEXT 类型 语法: MEDIUMTEXT 变长字符串类型。其字符串的长度最大为 16777215 个字节。使用该类型存储长的文本串。 3.1.1.1.6 TINYTEXT 类型 语法: TINYTEXT 变长字符串类型。其字符串的长度最大为 255 个字节。使用该类型存储文本串。 3.1.1.2 数值类型 数值类型存储正、负定点及浮点数、零、Infinity、-Infinity 以及 NaN。由 2、4 或 8 字节的整数以及 4 或 8 字 节的浮点数和可选精度小数组成。表 3.1.3 列出了所有可用类型。 13 第3章 KINGBASEES SQL 基本元素 表 3.1.3: 数值类型 名字 存储尺寸 描述 范围 tinyint 1 字节 小范围整数 -128 to +127 smallint 2 字节 小范围整数 -32768 to +32767 middleint 3 字节 小范围整数 -8388608 to 8388607 4 字节 整数的典型选择 -2147483648 int1 mediumint int3 integer to +2147483647 bigint 8 字节 大范围整数 -9223372036854775808 to +9223372036854775807 decimal(p,s) 可变 可指定精度和标度 p 精度的取值范围为 1~1000;s 标度的取值范 围为 0~1000 numeric(p,s) 可变 可指定精度和标度 p 精度的取值范围为 1~1000;s 标度的取值范 number(p,s) 围为 0~1000 fixed(p,s) 可变 可指定精度和标度 p 精度的取值范围为 1~1000;s 标度的取值范 围为 0~1000 real 4 字节 可变精度,不精确 6 位十进制精度 double precision 8 字节 可变精度,不精确 15 位十进制精度 smallserial 2 字节 自动增加的小整数 1 到 32767 serial 4 字节 自动增加的整数 1 到 2147483647 bigserial 8 字节 自动增长的大整数 1 到 9223372036854775807 数字类型常量的语法见数字常量 。数字类型有一整套对应的数学操作符和函数。相关信息请参考操作符 和函数 。下面的几节详细描述这些类型。 3.1.1.2.1 整数类型 存储有符号整数,即没有小数部分的数值。 KingbaseES 整数类型包括 tinyint、smallint、integer(或 int)和 bigint 。 14 第3章 KINGBASEES SQL 基本元素 3.1.1.2.1.1 TINYINT 数据类型 语法: TINYINT 有符号整数,取值范围 -128 ~ +127。 3.1.1.2.1.2 SMALLINT 数据类型 语法: SMALLINT 有符号整数,取值范围 -32768 ~ +32767 3.1.1.2.1.3 MEDIUMINT/MIDDLEINT/INT3 语法: MEDIUMINT/MIDDLEINT/INT3 有符号整数,取值范围-8388608 ~ +8388607 3.1.1.2.1.4 INTEGER 数据类型 语法: INTEGER 15 第3章 KINGBASEES SQL 基本元素 别名: INT 有符号整数,取值范围 -2147483648~ +2147483647 3.1.1.2.1.5 BIGINT 数据类型 语法: BIGINT 有符号整数,取值范围 -9223372036854775808~ +9223372036854775807 3.1.1.2.1.6 SIGNED/UNSIGNED 数据类型 语法: unsigned signed [ unsigned] { int | int4 | integer } [ unsigned] { int8 | bigint } { int | int4 | integer } [signed|unsigned] { int8 | bigint } [signed|unsigned] 16 第3章 KINGBASEES SQL 基本元素 在 MySQL 模式下,KingbaseES 支持 signed 和 unsigned 属性,即有符号整数和无符号整数。其中, unsigned int 表示无符号 32 位整数,取值范围为 0-4294967295(0xffffffff)。unsigned bigint 表示无符号 64 位整 数,取值范围为 0-18446744073709551615(0xffffffffffffffff)。 signed 与 unsigned 可以单独使用,当 signed 与 unsigned 单独使用时,等同于 bigint 和 bigint unsigned。 3.1.1.2.2 精确数值数据类型 3.1.1.2.2.1 NUMERIC 数据类型 语法: NUMERIC(precision, scale) 17 第3章 KINGBASEES SQL 基本元素 存储 0 以及绝对值为 [1.0 x 10 -130 , 1.0 x 10 126 ) 的正、负定点数。在算术运算中,如果超出范围,KingbaseES 报错。 precision 表示精度,是整个数中有效位的总数,也就是小数点两边的位数。取值范围为 1~1000。scale 表示标 度,是小数部分的数字位数,也就是小数点右边的部分。取值范围为 0~1000。 使用该数据类型时,最好指定定点数的小数位数和精度,以便在输入时进行额外的完整性检查。指定小数位数和 精度不会强制所有值都达到固定长度。如果某个值超过精度,KingbaseES 将返回错误。如果某个值超过标度,KingbaseES 会对其进行四舍五入。 也可以使用 NUMERIC(precision) 类型,即标度为 0 的定点数,即 NUMERIC(precision, 0) 也可以直接使用 NUMERIC 类型,缺省精度和标度,指定 KingbaseES 数值的最大精度和标度。考虑到移植性, 在使用时最好是显式声明精度和标度。 3.1.1.2.2.2 DECIMAL 数据类型 语法: DECIMAL(precision, scale) 与 NUMERIC 相同。 3.1.1.2.2.3 NUMBER 数据类型 与 NUMERIC 相同。 说明:参数 ora_input_emptystr_isnull 被设置为 true 时可以使 NUMBER 数据类型接受空串,默认值为 true。 除此之外,NUMBER 与 NUMERIC 是等效的。 3.1.1.2.2.4 FIXED 数据类型 语法: FIXED [(precision, scale)] 18 第3章 KINGBASEES SQL 基本元素 FIXED 类型满足小数点前最多支持 131072 位,小数点后最多支持 16383 位。 precision 表示精度,是整个数中有效位的总数,也就是小数点两边的位数。取值范围为 1~1000。scale 表示标 度,是小数部分的数字位数,也就是小数点右边的部分。取值范围为 0~1000。 指定标度 scale 小于-84 时会报错。当标度小于 0 时,会把标度设置为 0,重新设置精度为当前精度值加标度的绝 对值。计算后的精度如果超出了精度范围,则报错,否则告警。当标度大于精度的时候,设置精度与标度相等。设置 之后的精度如果越界则报错。当只设置了精度而没有设置标度的时候,标度默认为 0。当既没有设置精度也没有设置 标度的时候,标度的默认值不为 0。 注意: 仅在 MySQL 模式下支持 FIXED 数据类型。 3.1.1.2.3 浮点类型 real 和 double precision 是近似数值类型,以近似的形式存储的,因此存储和检索一个值可能出现一些偏差。 3.1.1.2.3.1 REAL 类型 语法: REAL 范围在 -1E+37 到 +1E+37 之间,精度至少是 6 位小数。 3.1.1.2.3.2 BIGSERIAL 类型 语法: DOUBLE PRECISION[(精度)] 19 第3章 KINGBASEES SQL 基本元素 范围在 -1E+37 到 +1E+37 之间,精度至少是 15 位小数。 为了与旧版本的 KingbaseES 生成的输出兼容,并允许降低输出精度,可以使用 extra_float_digits 参数来选择 rounded decimal 输出。 将值设置为 0 将恢复先前的默认舍入值为 6(对于 float4) 或 15(对于 float8) 的有效小数位数。设置为负值会进一 步减少位数; 3.1.1.2.3.3 FLOAT 类型 语法: FLOAT 或 FLOAT(p) 当 p 取值为 1-24 时,与 REAL 相同。当 p 取值为 25-53 时,与 DOUBLE PRECISION 相同。没有指定精度 时,与 DOUBLE PRECISION 相同。 注意: 以前,需要精确值的应用程序必须将 extra_float_digits 设置为 3 才能获得这些值。为了实现版本之间的最大 兼容性,它们应该继续这样做。 除了普通的数字值之外,浮点类型还有几个特殊值: • Infinity • -Infinity • NaN 这些值分别表示 IEEE 754 特殊值“正无穷大”、“负无穷大”以及“不是一个数字”。如果在 SQL 命令里把 这些数值当作常量写,你必须在它们周围加上单引号,例如 UPDATE table SET x = '-Infinity'。在输入时,这 些串是以大小写无关的方式识别的。 注意: IEEE754 指定 NaN 不应该与任何其他浮点值(包括 NaN)相等。为了允许浮点值被排序或者在基于树的索引 中使用,KingbaseES 将 NaN 值视为相等,并且比所有非 NaN 值要更大。 3.1.1.2.4 浮点数 浮点数可以从第一个到最后一个数字的任何位置有一个小数点,也可以根本没有小数点。可以选择在数字后面使 用指数来增加范围。KingbaseES 为浮点数提供两种数字数据类型。 20 第3章 KINGBASEES SQL 基本元素 3.1.1.2.4.1 BINARY_FLOAT 类型 语法: REAL 存储单精度的 32 位浮点数,每个 BINARY_FLOAT 值需要 4 个字节。 3.1.1.2.4.2 BIGSERIAL 类型 语法: REAL 存储双精度的 64 位浮点数,每个 BINARY_DOUBLE 值需要 8 个字节。 3.1.1.2.4.3 取值范围 表 3.1.4: 浮点数 值 BINARY_FLOAT BINARY_DOUBLE 最大正有限值 3.40282E+38F 1.79769313486231E+308 最小正有限值 1.17549E-38F 2.22507485850720E-308 3.1.1.2.5 序数类型 smallserial、serial 和 bigserial 类型不是真正的类型,它们只是为了创建唯一标识符列而存在的方便符号(类似 其它一些数据库中支持的 AUTO_INCREMENT 属性)。这是 KingbaseES 特有的创建一个自增列的方法。 3.1.1.2.5.1 SMALLSERIAL 类型 语法: SMALLSERIAL 21 第3章 KINGBASEES SQL 基本元素 相当于创建一个 SMALLINT 列。 3.1.1.2.5.2 SERIAL 类型 语法: SERIAL 相当于创建一个 INT 列。 3.1.1.2.5.3 BIGSERIAL 类型 语法: BIGSERIAL 相当于创建一个 BIGINT 列。 创建了一个整数列并且把它的缺省值设置为从一个序列发生器取值。限定 NOT NULL 约束以确保空值不会被插 入(也许是 UNIQUE 或者 PRIMARY KEY 约束避免意外地插入重复的值,但这不会自动发生)。最后,该序列被 标记为“属于”该列,这样当列或表被删除时该序列也会被删除。在不删除列的情况下也可以删除序列,但是这会强 制删除该列的默认值表达式。 注意: 因为 smallserial、serial 和 bigserial 是用序列实现的,所以即使没有删除过行,在出现在列中的序列值可能 有“空洞”或者间隙。如果一个从序列中分配的值被用在一行中,即使该行最终没有被成功地插入到表中,该值也被 “用掉”了。例如,当插入事务回滚时就会发生这种情况。更多信息参见序列操作函数中的:ref:NEXTVAL 。 3.1.1.3 货币类型 语法: 22 第3章 KINGBASEES SQL 基本元素 MONEY MONEY 类型存储固定小数精度的货币数值。小数的精度由数据库的 lc_monetary 设置决定。 取值范围:-92233720368547758.08 到 +92233720368547758.07。8 字节存储。MONEY 与数值类型可以相互转 换。numeric、int 和 bigint 数据类型的值可以转换成 MONEY。但是浮点数不建议用来处理货币,因为浮点数可能会 有圆整错误。 示例: SELECT '12.34'::float8::numeric::money; SELECT '52093.89'::money::numeric::float8; 3.1.1.4 日期/时间类型 日期时间数据类型为 date、timestamp[ ( p ) ] [ without time zone ]、timestamp[ ( p ) ] with time zone、timestamp[ ( p ) ] with local time zone、time [ ( p ) ] [ without time zone ]、time [ ( p ) ] with time zone、time、year。 间隔数据类型为 interval [field] [to] [field] [(fp)]、yminterval [field][(lp)] [to] [field]、 dsinterval [field][(lp)] [to] [field] [(fp)]。 注意: 其中 yminterval 和 dsinterval 只在 Oracle 模式下可用,兼容 Oracle 的 Interval 类型。 interval 类型各模式下都可用。 year 只在 MySQL 模式下可用,兼容 MySQL 的 year 类型。 表 3.1.5: 日期/时间类型 名字 存 储 描述 最小值 最大值 尺寸 解 析 度 timestamp[ ( p )] [ 8 字 包 括 日 期 和 时 间 (无 without time zone ] 节 时区) timestamp[ ( p ) ] with 8 字 包 括 日 期 和 时 间, 有 time zone 节 时区 4713 BC 294276 AD 1 微 秒 4713 BC 294276 AD 1 微 秒 见续表 23 第3章 KINGBASEES SQL 基本元素 表 3.1.5 – 续表 名字 存 储 描述 最小值 最大值 尺寸 解 析 度 timestamp[ ( p ) ] with 8 字 包 括 日 期 和 时 间, 有 local time zone 节 时区 date 4 字 日 期 (没 有 一 天 中 的 节 时间) time [ ( p ) ] [ without 8 字 一 天 中 的 时 间 (无 日 time zone ] 节 期) time [ ( p ) ] with time 12 字 仅仅是一天中的时间 zone 节 (没 有 日 期), 带 有 4713 BC 294276 AD 1 微 秒 4713 BC 5874897 AD 1日 00:00:00 24:00:00 1 微 秒 00:00:00+1459 24:00:00-1459 1 微 秒 时区 interval [ fields ] [ ( p 16 字 ) ] 节 yminterval 16 字 时间间隔 -178956970 年 178956970 年 1 微 秒 时间间隔 -178956970 年 178956970 年 1月 时间间隔 -999999999 日 999999999 日 1 纳 节 dsinterval 16 字 节 year 4 字 秒 年份 1901 年 2155 年 节 日期时间的输入格式,包括 ISO 8601、SQL-兼容的、传统 KingbaseES 的和其他的形式。对于一些格式,日期 输入里的日、月和年的顺序会让人混淆,支持指定所预期的这些域的顺序。把 DateStyle 参数设置为 MDY,表示” 月-日-年”,设置为 DMY 就是” 日-月-年”,设置为 YMD,表示” 年-月-日”。 KingbaseES 在处理日期/时间输入输出上比 SQL 标准更灵活。 KingbaseES 有四个 STRING 类型的参数,设置日期/时间输入输出格式。 STRING 类型的参数 默认格式 NLS_DATE_FORMAT YYYY-MM-DD HH24:MI:SS ORA_DATE_STYLE YYYY-MM-DD HH24:MI:SS NLS_TIMESTAMP_FORMAT YYYY-MM-DD HH24:mi:ss.FF NLS_TIMESTAMP_TZ_FORMAT YYYY-MM-DD HH24:mi:ss.FF TZH:TZM 24 第3章 KINGBASEES SQL 基本元素 说明:这四个参数需在 Oracle 模式下,且参数 ORA_STYLE_NLS_DATE_FORMAT 处于打开的情况下生 效。 3.1.1.4.1 DATE 数据类型 语法: DATE DATE 数据类型存储日期和时间值。每一个 DATE 日期值 KingbaseES 存储如下值:年、月、日、时、分、秒。 TO_DATE 函数可以将字符或者数值转换为 date 值。日期或者时间的输入需要由单引号括起来。 DATE 类型可能的输入方式: 表 3.1.6: 日期输入 例子 描述 1999-01-08 ISO 8601; 任何模式下的 1 月 8 日(推荐格式) January 8, 1999 在任何 datestyle 输入模式下都无歧义 1/8/1999 MDY 模式中的 1 月 8 日;DMY 模式中的 8 月 1 日 1/18/1999 MDY 模式中的 1 月 18 日;在其他模式中被拒绝 01/02/03 MDY 模式中的 2003 年 1 月 2 日;DMY 模式中的 2003 年 2 月 1 日;YMD 模式中的 2001 年 2 月 3 日 1999-Jan-08 任何模式下的 1 月 8 日 Jan-08-1999 任何模式下的 1 月 8 日 08-Jan-1999 任何模式下的 1 月 8 日 99-Jan-08 YMD 模式中的 1 月 8 日,否则错误 08-Jan-99 1 月 8 日,除了在 YMD 模式中错误 Jan-08-99 1 月 8 日,除了在 YMD 模式中错误 19990108 ISO 8601; 任何模式中的 1999 年 1 月 8 日 990108 ISO 8601; 任何模式中的 1999 年 1 月 8 日 19990108 年和一年中的日子 见续表 25 第3章 KINGBASEES SQL 基本元素 表 3.1.6 – 续表 例子 描述 J2451187 儒略日期 January 8, 99 BC 公元前 99 年 2022-09-02 2022 年 9 月 2 日 22-09-02 2022 年 9 月 2 日 3.1.1.4.2 TIME 数据类型 时间类型包括 time [ (p) ] without time zone 和 time [ (p) ] with time zone。 3.1.1.4.2.1 time [ (p) ] with time zone 类型 语法: time [ (p) ] with time zone 表示一个带时区的 TIME 值,包括时、分、秒信息,定义了一个在’00:00:00.000000’ 和’23:59:59.999999’ 之间的 有效时间。p 表示秒精度即秒字段中小数点后面的位数,取值范围为 0~6,如果未定义,在精度上没有明确的边界。 在 MySQL 模式下,TIME 值的范围可以从’-838:59:59.000000’ 到’838:59:59.000000’,默认精度为 0。 3.1.1.4.2.2 time [ (p) ] without time zone 类型 语法: time [ (p) ] without time zone 表示一个不带带时区的 TIME 值,其他取值与带时区的相同。 26 第3章 KINGBASEES SQL 基本元素 3.1.1.4.2.3 time 类型 语法: time 相当于 time without time zone。 3.1.1.4.3 TIMESTAMP 数据类型 TIMESTAMP 数据类型包含日期和时间部分。包括标准时区类型 timestamp[ (p)] [ without time zone ]、timestamp[ (p) ] with time zone 和本地时类型 timestamp[ (p)] with local time zone。 3.1.1.4.3.1 timestamp[ (p)] [ without time zone ] 类型 语法: timestamp[ (p)] [ without time zone ] 描述一个不带时区的 TIMESTAMP 值,包括年、月、日、时、分、秒信息。p 表示秒精度即秒字段中小数点后 面的位数,取值范围为 0~6,如果未定义,在精度上没有明确的边界。在 MySQL 模式下默认精度为 0。 3.1.1.4.3.2 timestamp[ (p)] with time zone 类型 语法: timestamp[ (p)] with time zone 描述一个带时区的 TIMESTAMP 值,其定义是在 TIMESTAMP 类型的后面加上时区信息。时区的取值范围: 取值范围:-12:59 ~ +14:00 之间。例如:TIMESTAMP WITH TIME ZONE ’2004-10-19 10:23:54+02’。 27 第3章 KINGBASEES SQL 基本元素 对于 timestamp with time zone,内部存储的值总是 UTC (全球统一时间,以前也叫格林威治时间 GMT)。如 果一个输入值有明确的时区声明,那么它将用该时区合适的偏移量转换成 UTC。如果在输入串里没有时区声明,那 么它就被假设是在系统的 TimeZone 参数里的那个时区,然后使用这个 TimeZone 时区的偏移转换成 UTC。 如果一个 timestamp with time zone 值被输出,那么它总是从 UTC 转换成当前的 TimeZone 时区,并且显示为 该时区的本地时间。要看其它时区的时间,要么修改 timezone,要么使用 AT TIME ZONE 。 时区名和缩写从存储在安装目录下的.../ share/ timezone/和.../ share/ timezonesets/子目录中获取的。TimeZone 配置参数可以在文件 kingbase.conf 中被设置,或者通过服务器配置参数参考手册中描述的任何一种标准方法设置。 3.1.1.4.3.3 timestamp[ (p)] with local time zone 类型 语法: timestamp[ (p)] with local time zone 表示本地时区的 TIMESTAMP 值,本地时区可以通过 timezone 参数修改,时区的取值范围:取值范围:-12:59 ~ +14:00 之间。 3.1.1.4.4 DATETIME 数据类型 DATETIME 数据类型仅在 MySQL 模式下支持,是 Date 和 Time 的组合,表示某个时刻,通常以’YYYY-MMDD hh:mm:ss’ 表示。 作为没有分隔符的字符串,格式为“YYYYMMDDhhmmss”或“YYMMDDhhmmss”,前提是该字符串作为 日期有意义。例如,“20070523091528”和“070523091528”被解释为“2007-05-23 09:15:28”作为 YYYYMMDDhhmmss 或 YYMMDDhhmmss 格式的数字,前提是该数字作为日期有意义。DATETIME 默认精度为 0,并支持 设定精度(范围:0~6)。 3.1.1.4.5 INTERVAL 数据类型 语法: interval[(fp)] 28 第3章 KINGBASEES SQL 基本元素 此语法定义全域 interval 类型,可用包含从年月日到时分秒的任何域值。fp 设定秒的小数部分精度,取值范围 0-6,默认为 6,超过 6 则按 6 处理。 语法: interval[(fp)] 'expr' 此语法定义全域 interval 类型的值,expr 可以是任何 IntervalStyle 合法的表达式字符串。如果有秒的小数部分 值,则受 fp 设定的精度限制,超过部分会按四舍五入截断显示。 SELECT interval '3 days'; interval -----------------3 0:00:00.000000 SELECT interval '1 year 2 mons'; interval ---------1-2 SELECT interval(3) '1 23:2:4.1235'; interval ------------------1 23:02:04.124000 语法: interval opt_field 29 第3章 KINGBASEES SQL 基本元素 此语法定义指定域的 interval 类型,分为两组,年月和日时分秒,两组间不能混用。fp 设定秒的小数部分精度, 取值范围 0-6,默认为 6,超过 6 则按 6 处理。 此语法默认在非 Oracle 模式下生效。在 Oracle 模式下,语法分析会识别为 yminterval 或 dsinterval 类型。 如果希望在 Oracle 模式下使用此语法定义 interval 类型或值,则需要加名称空间前缀。但如果在 Oracle 模式下 开启开启 mysql_interval_style 参数,则本语法定义生效,同时会增加支持兼容 MySQL 的域定义。 兼容 MySQL 的域定义包括: • YEAR_MONTH,等价 YEAR TO MONTH • DAY_HOUR,等价 DAY TO HOUR • DAY_MINUTE,等价 DAY TO MINUTE 30 第3章 KINGBASEES SQL 基本元素 • DAY_SECOND,等价 DAY TO SECOND • HOUR_MINUTE,等价 HOUR TO MINUTE • HOUR_SECOND,等价 HOUR TO SECOND • MINUTE_SECOND,等价 MINUTE TO SECOND 语法: interval 'expr' opt_field 此语法定义指定域的 interval 类型的值。expr 可以是任何 IntervalStyle 合法的表达式字符串。如果有秒的小数部 分值,则受 fp 设定的精度限制,超过部分会按四舍五入截断显示。 opt_field 可选项如下: 31 第3章 KINGBASEES SQL 基本元素 opt_field 选项 描述 YEAR 描述若干年的间隔 INTERVAL ’9’ YEAR MONTH 描述若干月的间隔 INTERVAL ’9’ MONTH DAY 描述若干天的间隔 INTERVAL ’9’ DAY HOUR 描述若干小时的间隔 INTERVAL ’9’ HOUR MINUTE 描述若干分钟的间隔 INTERVAL ’9’ MINUTE SECOND 描述若干分钟的间隔 INTERVAL ’9’ MINUTE YEAR TO MONTH 描述若干年若干月间隔 INTERVAL ’10-9’ YEAR TO MONTH YEAR_MONTH 描述若干年若干月间隔,兼容 MySQL DAY TO HOUR 描述若干天若干小时间隔 INTERVAL ’10 9’ DAY TO HOUR DAY_HOUR 描述若干天若干小时间隔,兼容 MySQL DAY TO MINUTE 描述若干天若干分钟间隔 INTERVAL ’10 9:09’ DAY TO MINUTE DAY_MINUTE 描述若干天若干分钟间隔,兼容 MySQL DAY TO SECOND 描述若干天若干秒间隔 INTERVAL ’10 9:09:50’ DAY TO SECOND DAY_SECOND 描述若干天若干秒间隔,兼容 MySQL HOUR TO MINUTE 描述若干小时若干分钟间隔 INTERVAL ’10:09’ HOUR TO MINUTE HOUR_MINUTE 描述若干小时若干分钟间隔,兼容 MySQL HOUR TO SECOND 描述若干小时若干秒间隔 INTERVAL ’10:09:10’ HOUR TO SECOND HOUR_SECOND 描述若干小时若干秒间隔,兼容 MySQL MINUTE TO SECOND 描述若干分钟若干秒间隔 INTERVAL ’09:10’ MINUTE TO SECOND MINUTE_SECOND 描述若干分钟若干秒间隔,兼容 MySQL SELECT interval '1-2' year to month; interval --------------1 year 2 mons SELECT interval '2:3:5' hour to second; interval ----------------- 32 第3章 KINGBASEES SQL 基本元素 02:03:05.000000 语法: interval ymfield1[(lp)] to ymfield2 此语法定义兼容 Oracle 语法的 yminterval 类型。lp 设定年域值的精度,取值范围 0-9,默认为 2,输入或输出 (进位后)超过精度会返回错误。ymfield2 指定的域范围要小于等于 ymfield1 的域范围。 语法: interval 'expr' ymfield1[(lp)] to ymfield2 此语法定义兼容 Oracle 语法的 yminterval 类型的值。expr 应符合 sql 标准格式,其他格式字符串可能不完全兼 容 Oracle。年域值输入输出长度受 lp 精度控制,超过精度返回错误。 SELECT interval '1-2' year to month; yminterval -----------+01-02 SELECT interval '1' year; yminterval -----------+01-00 SELECT interval '14' month; yminterval -----------+01-02 语法: 33 第3章 KINGBASEES SQL 基本元素 interval dsfield1[(lp)] to dsfield2[(fp)] 此语法定义兼容 Oracle 语法的 dsinterval 类型。lp 设定日域值的精度,取值范围 0-9,默认为 2,输入或输出 (进位后)超过精度会返回错误。fp 设定秒的小数部分精度,取值范围 0-9,默认为 6。dsfield2 指定的域范围要小于 等于 dsfield1 的域范围。 语法: interval 'expr' dsfield1[(lp)] to dsfield2[(fp)] 34 第3章 KINGBASEES SQL 基本元素 此语法定义兼容 Oracle 语法的 dsinterval 类型的值。expr 应符合 sql 标准格式,其他格式字符串可能不完全兼 容 Oracle。日域值输入输出长度受 lp 精度控制,超过精度返回错误。秒的小数部分受 fp 精度限制,超出部分会按四 舍五入截断显示。 SELECT interval '2 34:23:11' day to second; dsinterval --------------------+03 10:23:11.000000 select interval '2 34:23:11.1234' day to second(3); dsinterval -----------------+03 10:23:11.123 SELECT interval '14' month; yminterval -----------+01-02 注意: 在 Oracle 模式下,IntervalStyle 参数默认设置为 sql_standard,其他模式默认设置为 kingbase。 语法: 35 第3章 KINGBASEES SQL 基本元素 [@] quantity unit [quantity unit...] [direction] quantity 表示一个可以带符号的数字;unit 是 millisecond、second、minute、hour、day、week、month、year、 decade、century、millennium 或者缩写或者这些单位的复数; direction 取值为 ago 。表示对所有域求反。 如果 IntervalStyle 被设置为 kingbase_verbose,该语法也被用于间隔输出。日、小时、分钟和秒的数量可以不适 用显式的单位标记指定。例如,’1 12:59:10’ 被读作’1 day 12 hours 59 min 10 sec’。同样,一个年和月的组合可以使 用一个横线指定,例如’200-10’ 被读作’200 年 10 个月’。 语法: P quantity unit [ quantity unit ...] [ T [ quantity unit ...]] 该串必须以一个 P 开始,并且可以包括一个当日时间单位的 T。单位可以被忽略,也可以以任何顺序指定,但 是小于一天的单位必须出现在 T 之后。特别地,M 的含义取决于它出现在 T 之前还是之后。 可用的单位缩写如下表: 表 3.1.7: ISO 8601 间隔单位缩写 缩写 含义 Y 年 M 月(在日期部分中) W 周 D 日 H 小时 M 分钟 (在时间部分中) S 秒 36 第3章 KINGBASEES SQL 基本元素 语法: P [ years-months-days ] [ T hours:minutes:seconds ] 以 P 开始,并且 T 将时间间隔的日期和时间部分分隔开。KingbaseES 允许域具有不同的符号,并且认为以常量 表示的每个域具有独立的符号,因此在例子’-1 2:03:04’ 中,日为负数,小时、分钟和秒部分被认为是正值。 如果 IntervalStyle 被设置为 sql_standard,则最前面的符号将被认为是应用于所有域(但是仅当没有额外符号出 现),在例子’-1 2:03:04’ 中,负号会被应用于日、小时、分钟和秒部分。为了避免混淆,我们推荐在任何域为负值时 为每一个域都附加一个显式的符号。 下表展示了一些有效 interval 输入的例子。 表 3.1.8: 间隔输入 例子 描述 1-2 SQL 标准格式:1 年 2 个月 3 4:05:06 SQL 标准格式:3 日 4 小时 5 分钟 6 秒 1 year 2 months 3 days 4 hours 5 minutes 6 seconds 传统 KingbaseES 格式:1 年 2 个月 3 日 4 小时 5 分钟 6 秒 钟 P1Y2M3DT4h4M6S “带标志符的”ISO 8601 格式:含义同上 P0001-02-03T04:05:06 ISO 8601 的“替代格式”:含义同上 在内部,interval 值被存储为 months、days 以及 seconds。之所以这样做是因为一个月中的天数是变化的,并 且在涉及到夏令时调整时一天可以有 23 或者 25 个小时。months 以及 days 域是整数,而 seconds 域可以存储分数。 因为区间通常是从常量字符串或者 timestamp 减法创建而来,这种存储方法在大部分情况下都很好,但是也可能导 致预料之外的结果: SELECT EXTRACT(hours from '80 minutes'::interval); date_part ----------1 SELECT EXTRACT(days from '80 hours'::interval); date_part ----------0 37 第3章 KINGBASEES SQL 基本元素 函数JUSTIFY_DAYS 和JUSTIFY_HOURS 可以用来调整溢出其正常范围之外的 days 和 hours。 3.1.1.4.6 YEAR 类型 语法: year 表示年份值,值域为 1901-2155。year 类型只在 MySQL 模式下可用,兼容 MySQL 的 year 类型。 3.1.1.5 大对象数据类型 内置 LOB 数据类型 BLOB、CLOB、NCLOB 可以存储大型非结构化数据,如文本、图像、视频和空间数据。 表 3.1.9: 大对象数据类型 数据类型 描述 BLOB 二进制大对象,长度最大为 1G CLOB 字符大对象,长度最大为 1G NCLOB 字符大对象,长度最大为 1G BFILE 存储文件的定位符,长度最大为 1G BYTEA 变长二进制串,长度最大为 1G RAW 变长存储二进制或者字符串的类型,长度最大为 1G-4 LONG RAW 变长存储二进制或者字符串的类型,长度最大为 1G-4 3.1.1.5.1 BLOB 类型 语法: BLOB BLOB 类型指定变长的二进制大对象,长度最大为 1G 。 38 第3章 KINGBASEES SQL 基本元素 另外 MySQL 模式还提供一组相关类型可用,分别是 TINYBLOB、MEDUIMBLOB 和 LONGBLOB,长度最大 分别是 255 字节、16777215 字节和 1G 字节。 3.1.1.5.2 CLOB 类型 语法: CLOB CLOB 类型指定变长字符大对象, 长度最大为 1G。 3.1.1.5.3 NCLOB 类型 语法: NCLOB NCLOB 类型指定变长字符大对象, 长度最大为 1G。 3.1.1.5.4 BFILE 类型 语法: BFILE BFILE 类型存储文件的定位符,定位符所指向的是位于数据库外部的二进制文件。长度最大为 1G。BFILE 不支 持操作符,必须利用BFILENAME 来向 BFILE 列插入文件定位符。 注意: BFILE 类型仅在 Oracle 模式下支持。 39 第3章 KINGBASEES SQL 基本元素 3.1.1.5.5 BYTEA 类型 语法: BYTEA BYTEA 类型指定变长二进制串, 长度最大为 1G。二进制串是一个八位位组(或字节)的序列。 3.1.1.5.6 RAW 类型 语法: RAW [(n)] RAW 是一种可变长度的数据类型,可以在具有不同字符集的数据库之间,或者具有不同字符集的服务器和客户 端之间传输二进制数据流,而不需要字符集转换。 RAW 数据类型可以用于存储二进制数据或者字节串。参数 n 表示长度,以字节为单位,长度取值范围为 132767。如果长度超出此范围,则报错“length for type raw must be between 1 and 32767”。如果不指定长度,则无 长度限制,最大存储 1G-4 字节数据。RAW 类型输出显示为十六进制的字符串。 3.1.1.5.7 LONG RAW 类型 语法: LONG RAW LONG RAW 与 RAW 类型相同。 3.1.1.6 布尔类型 语法: 40 第3章 KINGBASEES SQL 基本元素 BOOLEAN KingbaseES 提供标准的 SQL 类型 BOOLEAN。BOOLEAN 取值为“true(真)”、“false(假)”和第三种 状态“unknown(未知)”,未知状态由 SQL 空值表示。 3.1.1.7 数据类型 描述 BOOLEAN 表示真、假的数据类型。1 字节存储。 位串类型 位串就是一串 1 和 0 的串。 KingbaseES 支持 select b’’和 select x’’语法,兼容 MySQL 二进制语法。 • Select b’’语法 判断 b/ B 后的字符串是否为合法的二进制形式串,不是则报错返回。若是,则以右则开始,以字节为单 位转为对应 ASCII 码的字符,不足一个字节的按一个字节算。例如:select b’1000001’ 返回‘A’;select b’10010101010101010101’ 返回‘77’。 • Select X’’语法 判断 x/X 后的字符串是否为合法的十六进制形式串,不是则报错返回。若是,则以右则开始,以字节为单位转 为对应 ASCII 码的字符,若最后不足一个字节,则报错。例如:select X’4D7953514C’返回‘MySQL’; select X‘D7953514C’返回报错。 注意: b’’和 x’’的显示形态 (二进制、十六进制或字符串),由 bit_output 决定。详见《数据库参考手册》。 3.1.1.7.1 BIT 类型 语法: BIT[(n)] 41 第3章 KINGBASEES SQL 基本元素 n 是正整数,数据必须准确匹配长度“n“,如果存储短些或者长一些的位串都会报错。n 缺省,默认为 1。 3.1.1.7.2 BIT VAYRING 类型 语法: BIT VAYRING(n) 变长位串,最长为 n,n 是正整数。如果存储超过 n 则报错。n 缺省,表示该类型没有长度限制。 注意: 如果我们显式地把一个位串值转换成 bit(n),那么它的右边将被截断或者在右边补齐零,直到刚好 “n“位, 而且不会抛出任何错误。类似地,如果我们显式地把一个位串数值转换成 bit varying(n),如果它超过了 “n“位, 那么它的右边将被截断。 请参考位串常量 获取有关位串常量的语法的信息。还有一些位逻辑操作符和串操作函数可用,详见位串操作符 和二进制串函数 。 示例: CREATE TABLE test (a BIT(3), b BIT VARYING(5)); INSERT INTO test VALUES (B'101', B'00'); INSERT INTO test VALUES (B'10', B'101'); ERROR: bit string length 2 does not match type bit(3) INSERT INTO test VALUES (B'10'::bit(3), B'101'); SELECT * FROM test; a | b -----+----101 | 00 100 | 101 一个位串值对于每 8 位的组需要一个字节,外加总共 5 个或 8 个字节,这取决于串的长度(但是长值可能被压 缩或者移到线外,如字符数据类型 中对字符串的解释一样)。 3.1.1.7.3 BINARY 类型 语法: 42 第3章 KINGBASEES SQL 基本元素 binary[(n)] binary 存储定长二进制字符串,兼容 MySQL 的二进制类型。n 是正整数,为可选参数,取值范围为 1-255。 示例: CREATE TABLE t1(a BINARY(3)); INSERT INTO t1(a) VALUES ('abc'),('123'); 3.1.1.7.4 VARBINARY 类型 语法: varbinary(n) varbinary(n) 存储变成二进制字符串,兼容 MySQL 的二进制类型。n 是正整数,为必选参数,取值范围为 165535。 示例: CREATE TABLE t1(a VARBINARY(3)); INSERT INTO t1(a) VALUES ('abc'),('123'); 3.1.1.8 几何类型 几何数据类型表示二维的空间物体。下表展示了 KingbaseES 中可以用的几何类型。 表 3.1.10: 几何类型 名字 存储尺寸 表示 描述 point 16 字节 平面上的点 (x,y) line 32 字节 无限长的线 {A,B,C} lseg 32 字节 有限线段 ((x1,y1),(x2,y2)) box 32 字节 矩形框 ((x1,y1),(x2,y2)) path 16+16n 字节 封闭路径(类似于多边形) ((x1,y1),...) path 16+16n 字节 开放路径 [(x1,y1),...] polygon 40+16n 字节 多边形(类似于封闭路径) ((x1,y1),...) 见续表 43 第3章 KINGBASEES SQL 基本元素 表 3.1.10 – 续表 名字 存储尺寸 表示 描述 circle 24 字节 圆 <(x,y),r>(中心点和半径) KingbaseES 有一系列丰富的函数和操作符可用来进行各种几何操作,如缩放、平移、旋转和计算相交等,详 见几何函数 。 3.1.1.8.1 点 点是几何类型的基本二维构造块。用下面的语法描述 point 类型的值: ( x , y ) x , y 其中 “x“和 “y“分别是坐标,都是浮点数。 点使用第一种语法输出。 3.1.1.8.2 线 线由线性方程 “A“x + “B“y + “C“ = 0 表示,其中 “A“和 “B“都不为零。类型 line 的值采用以下形式输入和输 出: { A, B, C } 另外,还可以用下列任一形式输入: [ ( x1 , y1 ) , ( x2 , y2 ) ] ( ( x1 , y1 ) , ( x2 , y2 ) ) ( x1 , y1 ) , ( x2 , y2 ) x1 , y1 , x2 , y2 其中 “(x1,y1)“和 “(x2,y2)“是线上不同的两点。 3.1.1.8.3 线段 线段用一对线段的端点来表示。lseg 类型的值用下面的语法声明: [ ( x1 , y1 ) , ( x2 , y2 ) ] ( ( x1 , y1 ) , ( x2 , y2 ) ) ( x1 , y1 ) , ( x2 , y2 ) x1 , y1 , x2 , y2 44 第3章 KINGBASEES SQL 基本元素 其中 “(x1,y1)“和 “(x2,y2)“ 是线段的端点。 线段使用第一种语法输出。 3.1.1.8.4 方框 方框用其对角的点对表示。box 类型的值使用下面的语法指定: ( ( x1 , y1 ) , ( x2 , y2 ) ) ( x1 , y1 ) , ( x2 , y2 ) x1 , y1 , x2 , y2 其中 (x1,“y1“) 和 (x2,“y2“) 是方框的对角点。 方框使用第二种语法输出。 在输入时可以提供任意两个对角,但是值将根据需要被按顺序记录为右上角和左下角。 3.1.1.8.5 路径 路径由一系列连接的点组成。路径可能是开放的,也就是认为列表中第一个点和最后一个点没有被连接起来;也 可能是封闭的,这时认为第一个和最后一个点被连接起来。 path 类型的值用下面的语法声明: [ ( x1 , y1 ) , ... , ( xn , yn ) ] ( ( x1 , y1 ) , ... , ( xn , yn ) ) ( x1 , y1 ) , ... , ( xn , yn ) ( x1 , y1 , ... , xn , yn ) x1 , y1 , ... , xn , yn 其中的点是组成路径的线段的端点。方括弧([])表示一个开放的路径,圆括弧(())表示一个封闭的路径。如 第三种到第五种语法所示,当最外面的圆括号被忽略时,路径将被假定为封闭。 路径的输出使用第一种或第二种语法。 3.1.1.8.6 多边形 多边形由一系列点代表(多边形的顶点)。多边形和封闭路径很像,但是存储方式不一样而且有自己的一套支持 例程。 polygon 类型的值用下列语法声明: ( ( x1 , y1 ) , ... , ( xn , yn ) ) ( x1 , y1 ) , ... , ( xn , yn ) ( x1 , y1 , ... , xn , yn ) x1 , y1 , ... , xn , yn 45 第3章 KINGBASEES SQL 基本元素 其中的点是组成多边形边界的线段的端点。 多边形的输出使用第一种语法。 3.1.1.8.7 圆 圆由一个圆心和一个半径代表。circle 类型的值用下面的语法指定: < ( x , y ) , r > ( ( x , y ) , r ) ( x , y ) , r x , y , r 其中 (x,y) 是圆心,而 r 是圆的半径。 圆的输出用第一种语法。 3.1.1.9 网络地址类型 KingbaseES 提供存储 IPv4、IPv6 和 MAC 地址的数据类型,如下表所示。 网络地址类型提供输入错误检查以及特殊的操作符和函数 (见网络地址函数 ),因此使用起来比文本类型便利。 表 3.1.11: 网络地址类型 名字 存储尺寸 描述 cidr 7 或 19 字节 IPv4 和 IPv6 网络 inet 7 或 19 字节 IPv4 和 IPv6 主机以及网络 macaddr 6 字节 MAC 地址 macaddr8 8 bytes MAC 地址(EUI-64 格式) 对 inet 或者 cidr 数据类型进行排序的时候,IPv4 地址将总是排在 IPv6 地址前面,包括那些封装或者是映射 在 IPv6 地址里的 IPv4 地址,例如::10.2.3.4 或者::ffff::10.4.3.2 3.1.1.9.1 inet inet 在一个数据域里保存一个 IPv4 或 IPv6 主机地址,以及一个可选的它的子网。子网由主机地址中表示的 网络地址位数表示(“网络掩码”)。如果网络掩码为 32 并且地址是 IPv4,那么该值不表示任何子网,只是一台主 机。在 IPv6 中地址长度是 128 位,因此 128 位指定一个唯一的主机地址。如果仅表示网络地址,应使用 cidr 类型 而不是 inet。 46 第3章 KINGBASEES SQL 基本元素 该类型的输入格式是地址/y,其中地址是 IPv4 或者 IPv6 地址,y 是网络掩码的位数。如果/y 部分缺失,则网 络掩码对 IPv4 而言是 32,对 IPv6 而言是 128,所以该值表示只有一台主机。在显示时,如果网络掩码表示一台主 机,/y 部分不显示。 3.1.1.9.2 cidr cidr 类型保存 IPv4 或 IPv6 网络地址声明。其输入和输出遵循无类的互联网域路由(Classless Internet Domain Routing)习惯。声明网络的格式是地址/y,其中 address 是 IPv4 或 IPv6 网络地址,y 是网络掩码的位数。如果省 略 y,那么掩码部分用较早的等级网络编号系统推算,除非它大到足以包含输入中的所有字节。声明一个将位设置在 网络掩码右侧的网络地址会导致错误。 表 3.1.12: cidr 类型输入例子 cidr 输入 cidr 输出 abbrev(cidr) 192.168.100.128/25 192.168.100.128/25 192.168.100.128/25 192.168/24 192.168.0.0/24 192.168.0/24 192.168/25 192.168.0.0/25 192.168.0.0/25 192.168.1 192.168.1.0/24 192.168.1/24 192.168 192.168.0.0/24 192.168.0/24 128.1 128.1.0.0/16 128.1/16 128 128.0.0.0/16 128.0/16 128.1.2 128.1.2.0/24 128.1.2/24 10.1.2 10.1.2.0/24 10.1.2/24 10.1 10.1.0.0/16 10.1/16 10 10.0.0.0/8 10/8 10.1.2.3/32 10.1.2.3/32 10.1.2.3/32 2001:4f8:3:ba::/64 2001:4f8:3:ba::/64 2001:4f8:3:ba::/64 2001:4f8:3:ba:2e 0:81ff:fe22:d1f1/128 2001:4f8:3:ba:2e 0:81ff:fe22:d1f1/128 2001:4f8:3:b a:2e0:81ff:fe22:d1f1 ::ffff:1.2.3.0/120 ::ffff:1.2.3.0/120 ::ffff:1.2.3/120 ::ffff:1.2.3.0/128 ::ffff:1.2.3.0/128 ::ffff:1.2.3.0/128 47 第3章 KINGBASEES SQL 基本元素 3.1.1.9.3 inet-vs.-cidr inet 和 cidr 类型之间的本质区别是 inet 接受右边有非零位的网络掩码,而 cidr 不接受。例如,192.168. 0.1/24 对 inet 是有效的,但对 cidr 是无效的。 提示: 如果你不喜欢 inet 或 cidr 值的输出格式,可以尝试函数 host、text 和 abbrev。 3.1.1.9.4 macaddr macaddr 类型存储 MAC 地址,即以太网卡硬件地址(MAC 地址还用于其它用途)。可以接受下列格式的输 入: '08:00:2b:01:02:03' '08-00-2b-01-02-03' '08002b:010203' '08002b-010203' '0800.2b01.0203' '0800-2b01-0203' '08002b010203' 这些例子指定的都是同一个地址。对于位 a 到 f,大小写都可以接受。输出总是使用展示的第一种形式。 IEEE Std 802-2001 指定第二种展示的形式(带有连字符)作为 MAC 地址的标准形式,并且指定第一种形式 (带有分号)作为位翻转的记号,因此 08-00-2b-01-02-03 = 01:00:4D:08:04:0C。这种习惯目前已经被广泛地忽略, 并且它只与废弃的网络协议(如令牌环)相关。KingbaseES 没有对位翻转做任何规定,并且所有可接受的格式都使 用标准的 LSB 顺序。 剩下的五种输入格式不属于任何标准。 3.1.1.9.5 macaddr8 macaddr8 类型以 EUI-64 格式存储 MAC 地址,例如以太网卡的硬件地址(尽管 MAC 地址也被用于其他目 的)。这种类型可以接受 6 字节和 8 字节长度的 MAC 地址,并且将它们存储为 8 字节长度的格式。以 6 字节格式 给出的 MAC 地址被存储为 8 字节长度格式的方式是吧第 4 和第 5 字节分别设置为 FF 和 FE。注意 IPv6 使用一种 修改过的 EUI-64 格式,其中从 EUI-48 转换过来后的第 7 位应该被设置为一。函数 macaddr8_set7bit 被用来做这 种修改。 一般而言,任何由 16 进制数(字节边界上)对构成的输入(可以由':'、'-'或者'.'统一地分隔)都会被接受。 16 进制数的数量必须是 16(8 字节)或者 12(6 字节)。前导和拖尾的空格会被忽略。下面是可以被接受的输入格 48 第3章 KINGBASEES SQL 基本元素 式的例子: '08:00:2b:01:02:03:04:05' '08-00-2b-01-02-03-04-05' '08002b:0102030405' '08002b-0102030405' '0800.2b01.0203.0405' '0800-2b01-0203-0405' '08002b01:02030405' '08002b0102030405' 这些例子都指定相同的地址。数字 a 到 f 的大小写形式都被接受。输出总是以上面显示的第一种形式。上述的 后六种输入格式不属于任何标准。要把 EUI-48 格式的传统 48 位 MAC 地址转换成修改版 EUI-64 格式(包括在 IPv6 地址中作为主机部分),可以使用下面的 macaddr8_set7bit: SELECT macaddr8_set7bit('08:00:2b:01:02:03'); macaddr8_set7bit ------------------------0a:00:2b:ff:fe:01:02:03 (1 row) 3.1.1.10 文本搜索类型 KingbaseES 提供两种数据类型,它们被设计用来支持全文搜索,全文搜索是一种在自然语言的文档集合中搜索 以定位那些最匹配一个查询的文档的活动。tsvector 类型表示一个为文本搜索优化的形式下的文档,tsquery 类型 表示一个文本查询。全文搜索提供了对于这种功能的详细解释,还可参考函数 中的全文搜索相关函数。 3.1.1.10.1 tsvector 一个 tsvector 值是一个排序的可区分词位的列表,词位是被正规化合并了同一个词的不同变种的词。排序和去 重是在输入期间自动完成的,如下例所示: SELECT 'a fat cat sat on a mat and ate a fat rat'::tsvector; tsvector ---------------------------------------------------'a' 'and' 'ate' 'cat' 'fat' 'mat' 'on' 'rat' 'sat' 49 第3章 KINGBASEES SQL 基本元素 要表示包含空白或标点的词位,将它们用引号包围: SELECT $$the lexeme ' ' contains spaces$$::tsvector; tsvector ------------------------------------------' ' 'contains' 'lexeme' 'spaces' 'the' (我们在这个例子中使用美元符号包围的串文字并且下一个用来避免在文字中包含双引号记号产生的混淆)。嵌 入的引号和反斜线必须被双写: SELECT $$the lexeme 'Joe''s' contains a quote$$::tsvector; tsvector -----------------------------------------------'Joe''s' 'a' 'contains' 'lexeme' 'quote' 'the' 可选的,整数位置可以被附加给词位: SELECT 'a:1 fat:2 cat:3 sat:4 on:5 a:6 mat:7 and:8 ate:9 a:10 fat:11 rat:12' ::tsvector; tsvector ----------------------------------------------------------------------------'a':1,6,10 'and':8 'ate':9 'cat':3 'fat':2,11 'mat':7 'on':5 'rat':12 'sat':4 一个位置通常表示源词在文档中的定位。位置信息可以被用于邻近排名。位置值可以从 1 到 16383,更大的数字 会被 16383 替代。对于相同的词位出现的重复位置将被丢弃。 具有位置的词位可以进一步地被标注一个权重,它可以是 A、B、C 或 D。D 是默认值并且因此在输出中不会显 示: SELECT 'a:1A fat:2B,4C cat:5D'::tsvector; tsvector ---------------------------'a':1A 'cat':5 'fat':2B,4C 权重通常被用来反映文档结构,例如将主题词标记成与正文词不同。文本搜索排名函数可以为不同的权重标记器 分配不同的优先级。 了解 tsvector 类型本身并不执行任何词正规化这一点很重要,它假定给它的词已经被恰当地为应用正规化过。 例如, SELECT 'The Fat Rats'::tsvector; tsvector -------------------'Fat' 'Rats' 'The' 对于大部分英语文本搜索应用,上面的词将会被认为是非正规化的,但是 tsvector 并不在乎这一点。原始文档 文本通常应该经过 to_tsvector 以恰当地为搜索正规化其中的词: 50 第3章 KINGBASEES SQL 基本元素 SELECT to_tsvector('english', 'The Fat Rats'); to_tsvector ----------------'fat':2 'rat':3 3.1.1.10.2 tsquery 一个 tsquery 值存储要用于搜索的词位,并且使用布尔操作符 &(AND)、|(OR)和!(NOT)来组合它 们,还有短语搜索操作符<->(FOLLOWED BY)。也有一种 FOLLOWED BY 操作符的变体,其中 “N“是一 个整数常量,它指定要搜索的两个词位之间的距离。<->等效于<1>。 圆括号可以被用来强制对操作符分组。如果没有圆括号,!(NOT)的优先级最高,其次是<->(FOLLOWED BY),然后是 &(AND),最后是 |(OR)。 这里有一些例子: SELECT 'fat & rat'::tsquery; tsquery --------------'fat' & 'rat' SELECT 'fat & (rat | cat)'::tsquery; tsquery --------------------------'fat' & ( 'rat' | 'cat' ) SELECT 'fat & rat & ! cat'::tsquery; tsquery -----------------------'fat' & 'rat' & !'cat' 可选地,一个 tsquery 中的词位可以被标注一个或多个权重字母,这将限制它们只能和具有那些权重之一的 tsvector 词位相匹配: SELECT 'fat:ab & cat'::tsquery; tsquery -----------------'fat':AB & 'cat' 此外,一个 tsquery 中的词位可以被标注为 * 来指定前缀匹配: SELECT 'super:*'::tsquery; tsquery ----------'super':* 51 第3章 KINGBASEES SQL 基本元素 这个查询将匹配一个 tsvector 中以“super”开头的任意词。 词位的引号规则和之前描述的 tsvector 中的词位相同;并且,正如 tsvector,任何请求的词正规化必须在转 换到 tsquery 类型之前完成。to_tsquery 函数可以方便地执行这种正规化: SELECT to_tsquery('Fat:ab & Cats'); to_tsquery -----------------'fat':AB & 'cat' 注意 to_tsquery 将会以和其他词同样的方式处理前缀,这也意味着下面的比较会返回真: SELECT to_tsvector( 'postgraduate' ) @@ to_tsquery( 'post:*' ); ?column? ---------t 因为 kingbase 会被处理成 postgr: SELECT to_tsvector( 'postgraduate' ), to_tsquery( 'post:*' ); to_tsvector | to_tsquery ---------------+-----------'postgradu':1 | 'post':* 这会匹配 postgraduate 被处理后的形式。 3.1.1.11 UUID 类型 数据类型 uuid 存储由 RFC 4122、ISO/IEC 9834-8:2005 以及相关标准定义的通用唯一标识符(UUID)(某些 系统将这种数据类型引用为全局唯一标识符 GUID)。这种标识符是一个 128 位的量,它由一个精心选择的算法产 生,该算法能保证在已知空间中任何其他使用相同算法的人能够产生同一个标识符的可能性非常非常小。因此,对于 分布式系统,这些标识符相比序列生成器而言提供了一种很好的唯一性保障,序列生成器只能在一个数据库中保证唯 一。 一个 UUID 被写成一个小写十六进制位的序列,该序列被连字符分隔成多个组:首先是一个 8 位组,接下来是 三个 4 位组,最后是一个 12 位组。总共的 32 位(十六进制位)表示了 128 个二进制位。一个标准形式的 UUID 类 似于: a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11 KingbaseES 也接受另一种输入形式:使用大写位、标准格式被花括号包围、忽略某些或者全部连字符、在任意 4 位组后面增加一个连字符。例如: A0EEBC99-9C0B-4EF8-BB6D-6BB9BD380A11 {a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11} a0eebc999c0b4ef8bb6d6bb9bd380a11 52 第3章 KINGBASEES SQL 基本元素 a0ee-bc99-9c0b-4ef8-bb6d-6bb9-bd38-0a11 {a0eebc99-9c0b4ef8-bb6d6bb9-bd380a11} 输出总是采用标准形式。 KingbaseES 为 UUID 提供了存储和比较函数,但是核心数据库不包含任何用于产生 UUID 的函数,因为没有一 个单一算法能够很好地适应每一个应用。此外,UUID 可以由客户端应用产生,或者由通过服务器端函数调用的其他 库生成。 3.1.1.12 XML 类型 XML 数据类型可以被用来存储 XML 数据。它比直接在一个 text 域中存储 XML 数据的优势在于,它会检查输 入值的结构是不是良好,并且有支持函数用于在其上执行类型安全的操作,参见XML 函数 。使用这种数据类型要求 在安装时用 configure --with-libxml 选项编译。 XML 类型可以存储结构良好(如 XML 标准所定义)的“文档”,以及“内容”片段,通过引用 XQuery 和 XPath 数据模型中更宽松的“文档节点”来定义。粗略地看,这意味着内容片段中可以有多于一个的顶层元素或字 符节点。表达式 xmlvalue IS DOCUMENT 可以被用来评估一个特定的 XML 值是一个完整文档或者仅仅是一个文档片 段。 3.1.1.12.1 创建 XML 值 要从字符数据中生成一个 XML 类型的值,可以使用函数 xmlparse: XMLPARSE ( { DOCUMENT | CONTENT } value) 例子: XMLPARSE (DOCUMENT 'Manual...') XMLPARSE (CONTENT 'abcbarfoo') 然而根据 SQL 标准这是唯一将字符串转换为 XML 值的方法,KingbaseES 特有的 ** 语法:** xml 'bar' 'bar'::xml 也可以被使用。 即便输入值指定了一个文档类型声明(DTD),XML 类型也不根据 DTD 来验证输入值。目前也没有内建的支持 用于根据其他 XML 模式语言(如 XML 模式)来进行验证。 作为一个逆操作,从 XML 产生一个字符串可以使用函数 xmlserialize: XMLSERIALIZE ( { DOCUMENT | CONTENT } value AS type ) 53 第3章 KINGBASEES SQL 基本元素 “type“可以是 character、character varying 或 text(或者其中之一的一个别名)。再次地,根据 SQL 标 准,这也是在 XML 类型和字符类型间做转换的唯一方法,但是 KingbaseES 也允许你简单地造型这些值。 当一个字符串不是使用 XMLPARSE 造型成 XML 或者不是使用 XMLSERIALIZE 从 XML 造型得到,对于 DOCUMENT 和 CONTENT 两者的选择是根据“XML option”会话配置参数决定的,它可以使用标准命令来设置: SET XML OPTION { DOCUMENT | CONTENT }; 或者是更具有 KingbaseES 风格的语法 SET xmloption TO { DOCUMENT | CONTENT }; 默认值是 CONTENT,因此所有形式的 XML 数据都被允许。 3.1.1.12.2 编码处理 在客户端、服务器以及其中流过的 XML 数据上处理多字符编码时必须要注意。在使用文本模式向服务器传递查 询以及向客户端传递查询结果(在普通模式)时,KingbaseES 将所有在客户端和服务器之间传递的字符数据转换为 目标端的字符编码,参见 字符集支持。这也包括了表示 XML 值的串,正如上面的例子所述。这也通常意味着由于 字符数据会在客户端和服务器之间传递时被转换成其他编码,包含在 XML 数据中的编码声明可能是无效的,因为内 嵌的编码声明没有被改变。为了处理这种行为,包含在表示 XML 类型输入的字符串中包含的编码声明会被忽略,并 且其内容被假定为当前服务器的编码。接着,为了正确处理,XML 数据的字符串必须以当前客户端编码从客户端发 出。客户端负责在把文档发送给服务器之前将它们转换为当前客户端编码,或者适当地调整客户端编码。在输出时, XML 类型的值将不会有一个编码声明,并且客户端将会假设所有数据都是当前客户端编码。 在使用二进制模式传送查询参数给服务器以及传回查询结果给客户端时,不会执行编码转换,因此情况就有所不 同。在这种情况下,XML 数据中的编码声明将被注意到,并且如果缺少编码声明时该数据会被假定为 UTF-8(由于 XML 标准的要求,注意 KingbaseES 不支持 UTF-16)。在输出时,数据将会有一个编码声明来指定客户端编码,除 非客户端编码为 UTF-8(这种情况下编码声明会被忽略)。 不用说,在 KingbaseES 中处理 XML 数据产生错误的可能性更小,并且在 XML 数据编码、客户端编码和服务 器编码三者相同时效率更高。因为 XML 数据在内部是以 UTF-8 处理的,如果服务器编码也是 UTF-8 时,计算效率 将会最高。 当服务器编码不是 UTF-8 时,某些 XML 相关的函数可能在非 ASCII 数据上完全无法工作。尤其在 xmltable() 和 xpath() 上,这是一个已知的问题。 3.1.1.12.3 访问 XML 值 XML 数据类型有些不同寻常,因为它不提供任何比较操作符。这是因为对于 XML 数据不存在良定义的和通用的 比较算法。这种状况造成的后果就是,你无法通过比较一个 XML 和一个搜索值来检索行。XML 值因此通常应该伴随 着一个独立键值域,如一个 ID。另一种比较 XML 值的方案是将它们先转换为字符串,但注意字符串比较对于 XML 比较方法没有什么帮助。 由于没有可以用于 XML 数据类型的比较操作符,因此无法直接在这种类型上创建索引。如果需要在 XML 中快 速的搜索,可能的解决方案包括将表达式构造为一个字符串类型然后索引之,或者在一个 XPath 表达式上索引。当 54 第3章 KINGBASEES SQL 基本元素 然,实际的查询必须被调整为使用被索引的表达式。 KingbaseES 中的文本搜索功能也可以被用来加速 XML 数据的全文搜索。但是,所需的预处理支持目前在 KingbaseES 发布中还不可用。 3.1.1.13 JSON 类型 根据RFC 7159 中的说明,JSON 数据类型是用来存储 JSON(JavaScript Object Notation)数据的。这种数据也 可以被存储为 text,但是 JSON 数据类型的优势在于能强制要求每个被存储的值符合 JSON 规则。也有很多 JSON 相关的函数和操作符可以用于存储在这些数据类型中的数据,见JSON 函数 。 KingbaseES 为存储 JSON 数据提供了两种类型:JSON 和 JSONB。为了实现这些数据类型的高效查询机制,KingbaseES 还在 jsonpath 类型中提供了 jsonpath 数据类型。 JSON 和 JSONB 几乎接受完全相同的值集合作为输入。主要的实际区别之一是效率。JSON 数据类型存储输入文 本的精准拷贝,处理函数必须在每次执行时必须重新解析该数据。而 JSONB 数据被存储在一种分解好的二进制格式 中,它在输入时要稍慢一些,因为需要做附加的转换。但是 JSONB 在处理时要快很多,因为不需要解析。JSONB 也支 持索引,这也是一个令人瞩目的优势。 由于 JSON 类型存储的是输入文本的准确拷贝,其中可能会保留在语法上不明显的、存在于记号之间的空格,还 有 JSON 对象内部的键的顺序。还有,如果一个值中的 JSON 对象包含同一个键超过一次,所有的键/值对都会被 保留(处理函数会把最后的值当作有效值)。相反,JSONB 不保留空格、不保留对象键的顺序并且不保留重复的对象 键。如果在输入中指定了重复的键,只有最后一个值会被保留。 通常,除非有特别特殊的需要(例如遗留的对象键顺序假设),大多数应用应该更愿意把 JSON 数据存储为 JSONB。 KingbaseES 对每个数据库只允许一种字符集编码。因此 JSON 类型不可能严格遵守 JSON 规范,除非数据库编 码是 UTF8。尝试直接包括数据库编码中无法表示的字符将会失败。反过来,能在数据库编码中表示但是不在 UTF8 中的字符是被允许的。 RFC 7159 允许 JSON 字符串包含\uXXXX 所标记的 Unicode 转义序列。在 JSON 类型的输入函数中,不管数据 库编码如何都允许 Unicode 转义,并且只检查语法正确性(即,跟在\u 后面的四个十六进制位)。但是,JSONB 的 输入函数更加严格:它不允许非 ASCII 字符的 Unicode 转义(高于 U+007F 的那些),除非数据库编码是 UTF8。 JSONB 类型也拒绝\u0000(因为 KingbaseES 的 text 类型无法表示它),并且它坚持使用 Unicode 代理对来标记位 于 Unicode 基本多语言平面之外的字符是正确的。合法的 Unicode 转义会被转换成等价的 ASCII 或 UTF8 字符进行 存储,这包括把代理对折叠成一个单一字符。 注意: 很多JSON 函数 中描述的 JSON 处理函数将把 Unicode 转义转换成常规字符,并且将因此抛出和刚才所描述 的同样类型的错误(即使它们的输入是类型 JSON 而不是 JSONB)。JSON 的输入函数不做这些检查是由来已久的, 不过它确实允许将 JSON Unicode 转义简单的(不经处理)存储在一个非 UTF8 数据库编码中。通常,最好尽可能 避免在一个非 UTF8 数据库编码的 JSON 中混入 Unicode 转义。 在把文本 JSON 输入转换成 JSONB 时,RFC 7159 描述的基本类型会被有效地映射到原生的 KingbaseES 类型。 因此,在合法 JSONB 数据的组成上有一些次要额外约束,它们不适合 “JSON“类型和抽象意义上的 JSON,这些约束 55 第3章 KINGBASEES SQL 基本元素 对应于有关哪些东西不能被底层数据类型表示的限制。尤其是,JSONB 将拒绝位于 KingbaseES numeric 数据类型范 围之外的数字,而 JSON 则不会。这类实现定义的限制是 RFC 7159 所允许的。不过,实际上这类问题更可能发生在 其他实现中,因为把 JSON 的 number 基本类型表示为 IEEE 754 双精度浮点是很常见的(这也是 RFC 7159 明确期 待和允许的)。当在这类系统间使用 JSON 作为一种交换格式时,应该考虑丢失数字精度的风险。 相反地,如表中所述,有一些 JSON 基本类型输入格式上的次要限制并不适用于相应的 KingbaseES 类型。 表 3.1.13: JSON 基本类型和对应的 KingbaseES 类型 JSON 基本类型 KingbaseES 类型 注释 string text 不允许\u0000,如果数据库编码不是 UTF8,非 ASCII Unicode 转义也是这样 number numeric 不允许 NaN 和 infinity 值 boolean boolean 只接受小写 true 和 false 拼写 null (无) SQL NULL 是一个不同的概念 3.1.1.13.1 JSON 输入和输出语法 RFC 7159 中定义了 JSON 数据类型的输入/输出语法。 下列都是合法的 JSON(或者 JSONB)表达式: -- 简单标量/基本值 -- 基本值可以是数字、带引号的字符串、true、false 或者 null SELECT '5'::json; -- 有零个或者更多元素的数组(元素不需要为同一类型) SELECT '[1, 2, "foo", null]'::json; -- 包含键值对的对象 -- 注意对象键必须总是带引号的字符串 SELECT '{"bar": "baz", "balance": 7.77, "active": false}'::json; -- 数组和对象可以被任意嵌套 SELECT '{"foo": [true, "bar"], "tags": {"a": 1, "b": null}}'::json; 如前所述,当一个 JSON 值被输入并且接着不做任何附加处理就输出时,JSON 会输出和输入完全相同的文本, 而“JSONB“则不会保留语义上没有意义的细节(例如空格)。例如,注意下面的不同: SELECT '{"bar": "baz", "balance": 7.77, "active":false}'::json; json ------------------------------------------------{"bar": "baz", "balance": 7.77, "active":false} (1 row) 56 第3章 KINGBASEES SQL 基本元素 SELECT '{"bar": "baz", "balance": 7.77, "active":false}'::jsonb; jsonb -------------------------------------------------{"bar": "baz", "active": false, "balance": 7.77} (1 row) 值得一提的一种语义上无意义的细节是,在 JSONB 中数据会被按照底层 numeric 类型的行为来打印。实际上, 这意味着用 E 记号输入的数字被打印出来时就不会有该记号,例如: SELECT '{"reading": 1.230e-5}'::json, '{"reading": 1.230e-5}'::jsonb; json | jsonb -----------------------+------------------------{"reading": 1.230e-5} | {"reading": 0.00001230} (1 row) 不过,如这个例子所示,JSONB 将会保留拖尾的小数点后的零,即便这对于等值检查等目的来说是语义上无意义 的。 有关可用于构造和处理 JSON 值的内置函数和操作符的列表,参见JSON 函数 。 3.1.1.13.2 有效地设计 JSON 文档 将数据表示为 JSON 比传统关系数据模型要灵活得多,在需求不固定时这种优势更加令人感兴趣。在同一个应用 里非常有可能有两种方法共存并且互补。不过,即便是在要求最大灵活性的应用中,我们还是推荐 JSON 文档有固定 的结构。该结构通常是非强制的(尽管可能会强制一些业务规则),但是有一个可预测的结构会使书写概括一个表中 的“文档”(数据)集合的查询更容易。 当被存储在表中时,JSON 数据也像其他数据类型一样服从相同的并发控制考虑。尽管存储大型文档是可行的, 但是要记住任何更新都在整行上要求一个行级锁。为了在更新事务之间减少锁争夺,可考虑把 JSON 文档限制到一个 可管理的尺寸。理想情况下,JSON 文档应该每个表示一个原子数据,业务规则命令不会进一步把它们划分成更小的 可独立修改的数据。 3.1.1.13.3 JSONB 包含和存在 测试包含是 JSONB 的一种重要能力。对 JSON 类型没有平行的功能集。包含测试会测试一个 JSONB 文档是否被 包含在另一个文档中。除了特别注解之外,这些例子都会返回真: -- 简单的标量/基本值只包含相同的值: SELECT '"foo"'::jsonb @> '"foo"'::jsonb; -- 右边的数字被包含在左边的数组中: SELECT '[1, 2, 3]'::jsonb @> '[1, 3]'::jsonb; 57 第3章 KINGBASEES SQL 基本元素 -- 数组元素的顺序没有意义,因此这个例子也返回真: SELECT '[1, 2, 3]'::jsonb @> '[3, 1]'::jsonb; -- 重复的数组元素也没有关系: SELECT '[1, 2, 3]'::jsonb @> '[1, 2, 2]'::jsonb; -- 右边具有一个单一键值对的对象被包含在左边的对象中: SELECT '{"product": "KingbaseES", "version": 9.4, "jsonb": true}'::jsonb @> '{"version": 9.4}'::jsonb; -- 右边的数组不会被认为包含在左边的数组中, -- 即使其中嵌入了一个相似的数组: SELECT '[1, 2, [1, 3]]'::jsonb @> '[1, 3]'::jsonb; -- 得到假 -- 但是如果同样也有嵌套,包含就成立: SELECT '[1, 2, [1, 3]]'::jsonb @> '[[1, 3]]'::jsonb; -- 类似的,这个例子也不会被认为是包含: SELECT '{"foo": {"bar": "baz"}}'::jsonb @> '{"bar": "baz"}'::jsonb; -- 得到假 -- 包含一个顶层键和一个空对象: SELECT '{"foo": {"bar": "baz"}}'::jsonb @> '{"foo": {}}'::jsonb; 一般原则是被包含的对象必须在结构和数据内容上匹配包含对象,这种匹配可以是从包含对象中丢弃了不匹配的 数组元素或者对象键值对之后成立。但是记住做包含匹配时数组元素的顺序是没有意义的,并且重复的数组元素实际 也只会考虑一次。 结构必须匹配的一般原则有一种特殊情况,一个数组可以包含一个基本值: -- 这个数组包含基本字符串值: SELECT '["foo", "bar"]'::jsonb @> '"bar"'::jsonb; -- 反之不然,下面的例子会报告“不包含”: SELECT '"bar"'::jsonb @> '["bar"]'::jsonb; -- 得到假 JSONB 还有一个存在操作符,它是包含的一种变体:它测试一个字符串(以一个 text 值的形式给出)是否出现 在 JSONB 值顶层的一个对象键或者数组元素中。除非特别注解,下面这些例子返回真: -- 字符串作为一个数组元素存在: SELECT '["foo", "bar", "baz"]'::jsonb ? 'bar'; 58 第3章 KINGBASEES SQL 基本元素 -- 字符串作为一个对象键存在: SELECT '{"foo": "bar"}'::jsonb ? 'foo'; -- 不考虑对象值: SELECT '{"foo": "bar"}'::jsonb ? 'bar'; -- 得到假 -- 和包含一样,存在必须在顶层匹配: SELECT '{"foo": {"bar": "baz"}}'::jsonb ? 'bar'; -- 得到假 -- 如果一个字符串匹配一个基本 JSON 字符串,它就被认为存在: SELECT '"foo"'::jsonb ? 'foo'; 当涉及很多键或元素时,JSON 对象比数组更适合于做包含或存在测试,因为它们不像数组,进行搜索时会进行 内部优化,并且不需要被线性搜索。 提示: 由于 JSON 的包含是嵌套的,因此一个恰当的查询可以跳过对子对象的显式选择。例如,假设我们在顶层 有一个 doc 列包含着对象,大部分对象包含着 tags 域,其中有子对象的数组。这个查询会找到其中出现了同时包 含"term":"paris" 和"term":"food" 的子对象的项,而忽略任何位于 tags 数组之外的这类键: SELECT doc->'site_name' FROM websites WHERE doc @> '{"tags":[{"term":"paris"}, {"term":"food"}]}'; 可以用下面的查询完成同样的事情: SELECT doc->'site_name' FROM websites WHERE doc->'tags' @> '[{"term":"paris"}, {"term":"food"}]'; 但是后一种方法灵活性较差,并且常常也效率更低。 在另一方面,JSON 的存在操作符不是嵌套的:它将只在 JSON 值的顶层查找指定的键或数组元素。 JSON 函数 中有关更多 JSON 函数详细情况。 3.1.1.13.4 JSONB 索引 GIN 索引可以被用来有效地搜索在大量 JSONB 文档(数据)中出现的键或者键值对。提供了两种 GIN “操作符 类”,它们在性能和灵活性方面做出了不同的平衡。 JSONB 的默认 GIN 操作符类支持使用 @>、?、?& 以及?| 操作符的查询。使用这种操作符类创建一个索引的例 子: CREATE INDEX idxgin ON api USING gin (jdoc); 非默认的 GIN 操作符类 jsonb_path_ops 只支持索引 @> 操作符。使用这种操作符类创建一个索引的例子: 59 第3章 KINGBASEES SQL 基本元素 CREATE INDEX idxginp ON api USING gin (jdoc jsonb_path_ops); 考虑这样一个例子:一个表存储了从一个第三方 Web 服务检索到的 JSON 文档,并且有一个模式定义。一个典 型的文档: { "guid": "9c36adc1-7fb5-4d5b-83b4-90356a46061a", "name": "Angela Barton", "is_active": true, "company": "Magnafone", "address": "178 Howard Place, Gulf, Washington, 702", "registered": "2009-11-07T08:53:22 +08:00", "latitude": 19.793713, "longitude": 86.513373, "tags": [ "enim", "aliquip", "qui" ] } 我们把这些文档存储在一个名为 api 的表的名为 jdoc 的 jsonb 列中。如果在这个列上创建一个 GIN 索引,下 面这样的查询就能利用该索引: -- 寻找键 "company" 有值 "Magnafone" 的文档 SELECT jdoc->'guid', jdoc->'name' FROM api WHERE jdoc @> '{"company": "Magnafone"}'; 但是,该索引不能被用于下面这样的查询,因为尽管操作符? 是可索引的,但它不能直接被应用于被索引列 jdoc: -- 寻找这样的文档:其中的键 "tags" 包含键或数组元素 "qui" SELECT jdoc->'guid', jdoc->'name' FROM api WHERE jdoc -> 'tags' ? 'qui'; 但是,通过适当地使用表达式索引,上述查询也能使用一个索引。如果对"tags" 键中的特定项的查询很常见, 可能值得定义一个这样的索引: CREATE INDEX idxgintags ON api USING gin ((jdoc -> 'tags')); 现在,WHERE 子句 jdoc -> 'tags' ? 'qui' 将被识别为可索引操作符? 在索引表达式 jdoc -> 'tags' 上的应 用。 此外,GIN 索引也支持 @@ and @? 操作符,执行 jsonpath 匹配。 SELECT jdoc->'guid', jdoc->'name' FROM api WHERE jdoc @@ '$.tags[*] == "qui"'; 60 第3章 KINGBASEES SQL 基本元素 SELECT jdoc->'guid', jdoc->'name' FROM api WHERE jdoc @@ '$.tags[*] ? (@ == "qui")'; GIN 索引提取下列形式的语句 jsonpath: “accessors_chain“ = “const“. 存取器链可以由.key, [*], 和 [index] 存取器组成。jsonb_ops 另外支持.* 和.** 存取器。 另一种查询的方法是利用包含,例如: -- 寻找这样的文档:其中键 "tags" 包含数组元素 "qui" SELECT jdoc->'guid', jdoc->'name' FROM api WHERE jdoc @> '{"tags": ["qui"]}'; jdoc 列上的一个简单 GIN 索引就能支持这个查询。但是注意这样一个索引将会存储 jdoc 列中每一个键和值的 拷贝,然而前一个例子的表达式索引只存储 tags 键下找到的数据。虽然简单索引的方法更加灵活(因为它支持有关 任意键的查询),定向的表达式索引更小并且搜索速度比简单索引更快。 尽管 jsonb_path_ops 操作符类只支持用 @> 、@@ 和 @? 操作符的查询,但它比起默认的操作符类 jsonb_ops 有 更客观的性能优势。一个 jsonb_path_ops 索引通常也比一个相同数据上的 jsonb_ops 要小得多,并且搜索的专一性 更好,特别是当查询包含频繁出现在该数据中的键时。因此,其上的搜索操作通常比使用默认操作符类的搜索表现更 好。 jsonb_ops 和 jsonb_path_ops GIN 索引之间的技术区别是前者为数据中的每一个键和值创建独立的索引项, 而后者值为该数据中的每个值创建索引项。1 基本上,每一个 jsonb_path_ops 索引项是其所对应的值和键的哈希。 例如要索引 {"foo": {"bar": "baz"}},将创建一个单一的索引项,它把所有三个 foo、bar、和 baz 合并到哈希 值中。因此一个查找这个结构的包含查询可能导致极度详细的索引搜索。但是根本没有办法找到 foo 是否作为一 个键出现。在另一方面,一个 jsonb_ops 会创建三个索引项分别表示 foo、bar 和 baz。那么要做同样的包含查 询,它将会查找包含所有三个项的行。虽然 GIN 索引能够相当有效地执行这种 AND 搜索,它仍然不如等效的 jsonb_path_ops 搜索那样详细和快速(特别是如果有大量行包含三个索引项中的任意一个时)。 jsonb_path_ops 方法的一个不足是它不会为不包含任何值的 JSON 结构创建索引项,例如 {"a": {}}。如果需 要搜索包含这样一种结构的文档,它将要求一次全索引扫描,那就非常慢。因此 jsonb_path_ops 不适合经常执行这 类搜索的应用。 JSONB 也支持 btree 和 hash 索引。这通常值用于检查完整 JSON 文档等值非常重要的场合。JSONB 数据的 btree 顺序很少有人关心,但是为了完整性其顺序是: 对象 > 数组 > 布尔 > 数字 > 字符串 > 空值 带有 n 对的对象 > 带有 n - 1 对的对象 带有 n 个元素的数组 > 带有 n - 1 个元素的数组 具有相同数量对的对象这样比较: key-1, value-1, key-2 ... 1 对于这种目的,术语“值”包括数组元素,尽管 JSON 的术语有时认为数组元素与对象内的值不同。 61 第3章 KINGBASEES SQL 基本元素 注意,对象键按照它们的存储顺序进行比较,特别是由于较短的键被存储在较长的键之前,这可能导致结果不直 观,例如: { "aa": 1, "c": 1} > {"b": 1, "d": 1} 相似地,具有相同元素数量的数组按照以下顺序比较: element-1, element-2 ... 基本 JSON 值的比较会使用底层 KingbaseES 数据类型相同的比较规则进行。字符串的比较会使用默认的数据库 排序规则。 3.1.1.13.5 MySQL 模式 JSON 类型 MySQL 模式下 JSON 类型与 KES 默认模式的 JSON、JSONB 类型的差异如下: 特性差异 表 3.1.14: 特性差异 特性 MySQL 模式 JSON 类型 默认模式 JSON 类 默认模式 JSONB 类 型 型 是否覆盖重复键值对 是 否 是 是否为 json 对象的键重新排序 是 否 是 输出时是否在逗号或冒号后留下一个空 是 否 是 是否丢弃键、值或元素之间的额外空格 是 否 是 是否支持转义符 是 是 是 是否支持索引 是 否 是 格 操作符差异 注意: 对于操作符 -> 和 ->> ,在 mysql 的 json 类型和 kes 的 jsonb 类型中左右操作数稍微有些区别。在 mysql 的 json 中它们的左操作数为列标识符,右操作数为 json 路径(字符串文本);kes 的 jsonb 中他们的左操作数为 jsonb, 右操作数为 int 或者 text。但是它们功能及返回结果是一致的。 62 第3章 KINGBASEES SQL 基本元素 表 3.1.15: 操作符 操作符 MySQL 模式 JSON 类型 默认模式 JSON 类型 默认模式 JSONB 类型 -> 支持 支持 支持 -» 支持 支持 支持 = 支持 不支持 支持 < 支持 不支持 支持 <= 支持 不支持 支持 > 支持 不支持 支持 >= 支持 不支持 支持 <> 支持 不支持 支持 != 支持 不支持 支持 <=> 不支持 不支持 不支持 #> 支持 支持 支持 #» 支持 支持 支持 @> 支持 不支持 支持 <@ 支持 不支持 支持 ? 支持 不支持 支持 ?| 支持 不支持 支持 ?& 支持 不支持 支持 || 支持 不支持 支持 - 支持 不支持 支持 #- 支持 不支持 支持 @? 支持 不支持 支持 @@ 支持 不支持 支持 函数差异 63 第3章 KINGBASEES SQL 基本元素 表 3.1.16: 函数差异 函数 MySQL 模式 JSON 类型 默认模式 JSON 类型 默认模式 JSONB 类型 json_object 支持 支持 支持 jsonb_object json_pretty 支持 不支持 支持 jsonb_pretty json_quote 支持 不支持 支持 json_contains 支持 不支持 支持 json_contains_path 支持 不支持 支持 json_extract 支持 不支持 支持 json_keys 支持 不支持 支持 json_search 支持 不支持 支持 json_array_append 支持 不支持 支持 json_array_insert 支持 不支持 支持 json_insert 支持 不支持 支持 json_merge_patch 支持 不支持 支持 json_merge_preserve 支持 不支持 支持 json_replace 支持 不支持 支持 json_remove 支持 不支持 支持 json_set 支持 不支持 支持 json_unquote 支持 不支持 支持 json_depth 支持 不支持 支持 json_length 支持 不支持 支持 json_type 支持 不支持 支持 json_valid 支持 不支持 支持 3.1.1.14 范围类型 范围类型是表达某种元素类型(称为范围的 subtype)的一个值的范围的数据类型。例如,timestamp 的范围可 以被用来表达一个会议室被保留的时间范围。在这种情况下,数据类型是 tsrange(“timestamp range”的简写) 而 timestamp 是 subtype。subtype 必须具有一种总体的顺序,这样对于元素值是在一个范围值之内、之前或之后就 64 第3章 KINGBASEES SQL 基本元素 是界线清楚的。 范围类型非常有用,因为它们可以表达一种单一范围值中的多个元素值,并且可以很清晰地表达诸如范围重叠等 概念。用于时间安排的时间和日期范围是最清晰的例子;但是价格范围、一种仪器的量程等等也都有用。 3.1.1.14.1 内建范围类型 KingbaseES 带有下列内建范围类型: • int4range —integer 的范围 • int8range —bigint 的范围 • numrange —numeric 的范围 • tsrange —不带时区的 timestamp 的范围 • tstzrange —带时区的 timestamp 的范围 • daterange —date 的范围 此外,还可以自定义范围类型,详见CREATE TYPE 。 3.1.1.14.2 例子 CREATE TABLE reservation (room int, during tsrange); INSERT INTO reservation VALUES (1108, '[2010-01-01 14:30, 2010-01-01 15:30)'); -- 包含 SELECT int4range(10, 20) @> 3; -- 重叠 SELECT numrange(11.1, 22.2) && numrange(20.0, 30.0); -- 抽取上界 SELECT upper(int8range(15, 25)); -- 计算交集 SELECT int4range(10, 20) * int4range(15, 25); -- 范围为空吗? SELECT isempty(numrange(1, 5)); 3.1.1.14.3 包含和排除边界 每一个非空范围都有两个界限,下界和上界。这些值之间的所有点都被包括在范围内。一个包含界限意味着边界 点本身也被包括在范围内,而一个排除边界意味着边界点不被包括在范围内。 65 第3章 KINGBASEES SQL 基本元素 在一个范围的文本形式中,一个包含下界被表达为“[”而一个排除下界被表达为“(”。同样,一个包含上界被 表达为“]”而一个排除上界被表达为“)”(详见范围输入/输出 )。 函数 lower_inc 和 upper_inc 分别测试一个范围值的上下界。 3.1.1.14.4 无限(无界)范围 一个范围的下界可以被忽略,意味着所有小于上界的点都被包括在范围中。同样,如果范围的上界被忽略,那么 所有比上界大的的都被包括在范围中。如果上下界都被忽略,该元素类型的所有值都被认为在该范围中。 这等效于把下界当作“负无穷”,或者把上界当作“正无穷”。但是注意这些无穷值绝不是范围的元素类型的 值,并且绝不是范围的一部分(因此没有所谓的包含无限界限—如果你尝试写一个,它将被自动转换成一个排除界 限)。 还有,有一些元素类型具有一种“无限”概念,但是那只是范围类型机制所关心的之外的另一种值。例如,在时 间戳范围中,[today,] 意味着与 [today,) 相同的东西。但是 [today,infinity] 意味着与 [today,infinity) 不 同的某种东西—后者排除了特殊的 timestamp 值 infinity。 函数 lower_inf 和 upper_inf 分别测试一个范围的无限上下界。 3.1.1.14.5 范围输入/输出 一个范围值的输入必须遵循下列模式之一: (lower-bound,upper-bound) (lower-bound,upper-bound] [lower-bound,upper-bound) [lower-bound,upper-bound] empty 圆括号或方括号指示上下界是否为排除的或者包含的。注意最后一个模式是 empty,它表示一个空范围(一个不 包含点的范围)。 lower-bound 可以是作为 subtype 的合法输入的一个字符串,或者是空表示没有下界。同样,upper-bound 可以 是作为 subtype 的合法输入的一个字符串,或者是空表示没有上界。 每个界限值可以使用"(双引号)字符引用。如果界限值包含圆括号、方括号、逗号、双引号或反斜线时,这样 做是必须的,因为否则那些字符会被认作范围语法的一部分。要把一个双引号或反斜线放在一个被引用的界限值中, 就在它前面放一个反斜线(还有,在一个双引号引用的界限值中的一对双引号表示一个双引号字符,这与 SQL 字符 串中的单引号规则类似)。此外,你可以避免引用并且使用反斜线转义来保护所有数据字符,否则它们会被当做返回 语法的一部分。还有,要写一个是空字符串的界限值,则可以写成"",因为什么都不写表示一个无限界限。 范围值前后允许有空格,但是圆括号或方括号之间的任何空格会被当做上下界值的一部分(取决于元素类型,它 可能是也可能不是有意义的)。 注意: 这些规则与组合类型文字中书写域值的规则非常相似。更多注解请见组合类型输入和输出语法 。 66 第3章 KINGBASEES SQL 基本元素 例子: -- 包括 3,不包括 7,并且包括 3 和 7 之间的所有点 SELECT '[3,7)'::int4range; -- 既不包括 3 也不包括 7,但是包括之间的所有点 SELECT '(3,7)'::int4range; -- 只包括单独一个点 4 SELECT '[4,4]'::int4range; -- 不包括点(并且将被标准化为 '空') SELECT '[4,4)'::int4range; 3.1.1.14.6 构造范围 每一种范围类型都有一个与其同名的构造器函数。使用构造器函数常常比写一个范围文字常数更方便,因为它避 免了对界限值的额外引用。构造器函数接受两个或三个参数。两个参数的形式以标准的形式构造一个范围(下界是包 含的,上界是排除的),而三个参数的形式按照第三个参数指定的界限形式构造一个范围。第三个参数必须是下列字 符串之一: “()”、“(]”、“[)”或者“[]”。例如: -- 完整形式是:下界、上界以及指示界限包含性/排除性的文本参数。 SELECT numrange(1.0, 14.0, '(]'); -- 如果第三个参数被忽略,则假定为 '[)'。 SELECT numrange(1.0, 14.0); -- 尽管这里指定了 '(]',显示时该值将被转换成标准形式,因为 int8range 是一种离散范围类型。 SELECT int8range(1, 14, '(]'); -- 为一个界限使用 NULL 导致范围在那一边是无界的。 SELECT numrange(NULL, 2.2); 3.1.1.14.7 离散范围类型 一种范围的元素类型具有一个良定义的“步长”,例如 integer 或 date。在这些类型中,如果两个元素之间没 有合法值,它们可以被说成是相邻。这与连续范围相反,连续范围中总是(或者几乎总是)可以在两个给定值之间标 识其他元素值。例如,numeric 类型之上的一个范围就是连续的,timestamp 上的范围也是(尽管 timestamp 具有 有限的精度,并且在理论上可以被当做离散的,最好认为它是连续的,因为通常并不关心它的步长)。 另一种考虑离散范围类型的方法是对每一个元素值都有一种清晰的“下一个”或“上一个”值。了解了这种思想 之后,通过选择原来给定的下一个或上一个元素值来取代它,就可以在一个范围界限的包含和排除表达之间转换。例 如,在一个整数范围类型中,[4,8] 和 (3,9) 表示相同的值集合,但是对于 numeric 上的范围就不是这样。 67 第3章 KINGBASEES SQL 基本元素 一个离散范围类型应该具有一个正规化函数,它知道元素类型期望的步长。正规化函数负责把范围类型的相等值 转换成具有相同的表达,特别是与包含或者排除界限一致。如果没有指定一个正规化函数,那么具有不同格式的范围 将总是会被当作不等,即使它们实际上是表达相同的一组值。 内建的范围类型 int4range、int8range 和 daterange 都使用一种正规的形式,该形式包括下界并且排除上 界,也就是 [)。不过,用户定义的范围类型可以使用其他习惯。 3.1.1.14.8 定义新的范围类型 用户可以定义他们自己的范围类型。这样做最常见的原因是为了使用内建范围类型中没有提供的 subtype 上的范 围。例如,要创建一个 subtype float8 的范围类型: CREATE TYPE floatrange AS RANGE ( subtype = float8, subtype_diff = float8mi ); SELECT '[1.234, 5.678]'::floatrange; 注意: 创建新的范围类型前,需要关闭禁用多态函数参数,执行’set ora_forbid_func_polymorphism to off;’ 。 因为 float8 没有有意义的“步长”,我们在这个例子中没有定义一个正规化函数。 定义自己的范围类型也允许你指定使用一个不同的子类型 B-树操作符类或者集合,以便更改排序顺序来决定哪 些值会落入到给定的范围中。 如果 subtype 被认为是具有离散值而不是连续值,CREATE TYPE 命令应当指定一个 canonical 函数。正规化函 数接收一个输入的范围值,并且必须返回一个可能具有不同界限和格式的等价的范围值。对于两个表示相同值集合的 范围(例如 [1, 7] 和 [1, 8)),正规的输出必须一样。选择哪一种表达作为正规的没有关系,只要两个具有不同 格式的等价值总是能被映射到具有相同格式的相同值就行。除了调整包含/排除界限格式外,假使期望的补偿比 subtype 能够存储的要大,一个正规化函数可能会舍入边界值。例如,一个 timestamp 之上的范围类型可能被定义为具 有一个一小时的步长,这样正规化函数可能需要对不是一小时的倍数的界限进行舍入,或者可能直接抛出一个错误。 另外,任何打算要和 GiST 或 SP-GiST 索引一起使用的范围类型应当定一个 subtype 差异或 subtype_diff 函 数(没有 subtype_diff 时索引仍然能工作,但是可能效率不如提供了差异函数时高)。subtype 差异函数采用两 个 subtype 输入值,并且返回表示为一个 float8 值的差(即 “X“减 “Y“)。在我们上面的例子中,可以使用常规 float8 减法操作符之下的函数。但是对于任何其他 subtype,可能需要某种类型转换。还可能需要一些关于如何把差 异表达为数字的创新型想法。为了最大的可扩展性,subtype_diff 函数应该同意选中的操作符类和排序规则所蕴含 的排序顺序,也就是说,只要它的第一个参数根据排序顺序大于第二个参数,它的结果就应该是正值。 subtype_diff 函数的一个不那么过度简化的例子: CREATE FUNCTION time_subtype_diff(x time, y time) RETURNS float8 AS 'SELECT EXTRACT(EPOCH FROM (x - y))' LANGUAGE sql STRICT IMMUTABLE; 68 第3章 KINGBASEES SQL 基本元素 CREATE TYPE timerange AS RANGE ( subtype = time, subtype_diff = time_subtype_diff ); SELECT '[11:10, 23:00]'::timerange; 更多关于创建范围类型的信息请参考CREATE TYPE 。 索引 3.1.1.14.9 可以为范围类型的表列创建 GiST 和 SP-GiST 索引。例如,要创建一个 GiST 索引: CREATE INDEX reservation_idx ON reservation USING GIST (during); 一个 GiST 或 SP-GiST 索引可以加速涉及以下范围操作符的查询:=、&&、<@、@>、<<、>>、-|-、&< 以及 &>。 此外,B-树和哈希索引可以在范围类型的表列上创建。对于这些索引类型,基本上唯一有用的范围操作就是等 值。使用相应的< 和 > 操作符,对于范围值定义有一种 B-树排序顺序,但是该顺序相当任意并且在真实世界中通常 不怎么有用。范围类型的 B-树和哈希支持主要是为了允许在查询内部进行排序和哈希,而不是创建真正的索引。 3.1.1.14.10 范围上的约束 虽然 UNIQUE 是标量值的一种自然约束,它通常不适合于范围类型。反而,一种排除约束常常更加适合 (见CREATE TABLE 中的 CREATE TABLE ... CONSTRAINT ... EXCLUDE )。排除约束允许在一个范围类 型上说明诸如“non-overlapping”的约束。例如: CREATE TABLE reservation ( during tsrange, EXCLUDE USING GIST (during WITH &&) ); 该约束将阻止任何重叠值同时存在于表中: INSERT INTO reservation VALUES ('[2010-01-01 11:30, 2010-01-01 15:00)'); INSERT 0 1 INSERT INTO reservation VALUES ('[2010-01-01 14:45, 2010-01-01 15:45)'); ERROR: conflicting key value violates exclusion constraint " reservation_during_excl" DETAIL: Key (during)=(["2010-01-01 14:45:00","2010-01-01 15:45:00")) conflicts with existing key (during)=(["2010-01-01 11:30:00","2010-01-01 15:00:00")). 69 第3章 3.1.2 KINGBASEES SQL 基本元素 域类型 域是一种用户定义的数据类型,它基于另一种底层类型。根据需要,它可以有约束来限制其有效值为底层类型所 允许值的一个子集。如果没有约束,它的行为就和底层类型一样。例如,任何适用于底层类型的操作符或函数都对该 域类型有效。底层类型可以是任何内建或者用户定义的基础类型、枚举类型、数组类型、组合类型、范围类型或者另 一个域。 例如,我们可以在整数之上创建一个域,它只接受正整数: CREATE DOMAIN posint AS integer CHECK (VALUE > 0); CREATE TABLE mytable (id posint); INSERT INTO mytable VALUES(1); -- works INSERT INTO mytable VALUES(-1); -- fails 当底层类型的一个操作符或函数适用于一个域值时,域会被自动向下造型为底层类型。因此,mytable.id 1 的结果会被认为是类型 integer 而不是 posint。我们可以写成 (mytable.id - 1)::posint 来把结果转换回 posint,这会导致域的约束被重新检查。在这种情况下,如果该表达式被应用于一个值为 1 的 id 就会错误。把底 层类型的值赋给域类型的一个字段或者变量不需要写显式的造型,但是域的约束将会被检查。 更多信息请参考CREATE DOMAIN 。 3.1.2.1 对象标识符类型 对象标识符(OID)被 KingbaseES 用来在内部作为多个系统表的主键。类型 OID 表示一个对象标识符。 也有多个 OID 的别名类型:regproc、regprocedure、regoper、regoperator、regclass、regtype、regrole、 regnamespace、regconfig 和 regdictionary。 OID 类型目前被实现为一个无符号 4 字节整数。因此,在大型数据库中它并不足以提供数据库范围内的唯一性, 甚至在一些大型的表中也无法提供表范围内的唯一性。 OID 类型本身除了比较之外只有很少的操作。不过,它可以被造型成整数,并且接着可以使用标准的整数操作符 进行操纵(这样做时要注意有符号和无符号之间可能出现的混乱)。 OID 的别名类型除了特定的输入和输出例程之外没有别的操作。这些例程可以接受并显示系统对象的符号名,而 不是类型 OID 使用的原始数字值。别名类型使查找对象的 OID 值变得简单。例如,要检查与一个表 mytable 有关 的 sys_attribute 行,可以写为: SELECT * FROM sys_attribute WHERE attrelid = 'mytable'::regclass; 而不是: SELECT * FROM sys_attribute WHERE attrelid = (SELECT oid FROM sys_class WHERE relname = 'mytable'); 虽然从它本身看起来并没有那么糟,它仍然被过度简化了。如果有多个名为 mytable 的表存在于不同的模式 中,就可能需要一个更复杂的子选择来选择右边的 OID。regclass 输入转换器会根据模式路径设置处理表查找,并 70 第3章 KINGBASEES SQL 基本元素 且因此它会自动地完成这种“右边的事情”。类似地,对于一个数字 OID 的符号化显示可以很方便地通过将表 OID 造型成 regclass 来实现。 表 3.1.17: 对象标识符类型 名字 引用 描述 值示例 oid 任意 数字形式的对象标识符 564182 regproc sys_proc 函数名字 sum regprocedure sys_proc 带参数类型的函数 sum(int4) regoper sys_operator 操作符名字 + regoperator sys_operator 带参数类型的操作符 *(integer,integer) or -(NONE, integer) regclass sys_class 关系名字 sys_type regtype sys_type 数据类型名字 integer regrole sys_authid 角色名 smithee regnamespace sys_namespace 名字空间名称 sys_catalog regconfig sys_ts_config 文本搜索配置 english regdictionary sys_ts_dict 文本搜索字典 simple 所有用于由名字空间组织的对象的 OID 别名类型都接受模式限定的名字,如果没有被限定的对象在当前搜 索路径中无法找到时,将会在输出时显示模式限定的名字。regproc 和 regoper 别名类型将只接受唯一的(非 重载的)输入名字,因此它们的使用是受限的;对于大多数使用,regprocedure 或 regoperator 更合适。对于 regoperator,通过使用 NONE 来替代未使用的操作数可以标识一元操作符。 大部分 OID 别名类型的一个附加性质是依赖性的创建。如果这些类型之一的一个常量出现在一个存储的表达式 (如一个列默认值表达式或视图)中,它会在被引用的对象上创建一个依赖。例如,如果一个列有一个默认值表达式 nextval('my_seq'::regclass),KingbaseES 会理解该默认值表达式是依赖于序列 my_seq 的,在删除该默认值表 达式之前系统将不允许删除该序列。regrole 是这个性质的唯一例外。这种类型的常量不允许出现在这类表达式中。 注意: OID 别名类型不完全遵循事务隔离规则。规划器也把它们当做简单常量,这可能会导致次优的规划。 另一种系统中使用的标识符类型是 xid,或者称为事务(简写为 xact)标识符。这是系统列 xmin 和 xmax 使用 的数据类型。事务标识符是 32 位量。 系统使用的第三种标识符类型是 cid,或者称为命令标识符。这是系统列 cmin 和 cmax 使用的数据类型。命令 标识符也是 32 位量。 71 第3章 KINGBASEES SQL 基本元素 系统使用的最后一种标识符类型是 tid,或者称为元组标识符(行标识符)。这是系统列 ctid 使用的数据类 型。一个元组 ID 是一个(块号,块内元组索引)对,它标识了行在它的表中的物理位置。 3.1.2.2 sys_lsn 类型 sys_lsn 数据类型可以被用来存储 LSN(日志序列号)数据,LSN 是一个指向 WAL 中的位置的指针。这个类 型是 XLogRecPtr 的一种表达并且是 KingbaseES 的一种内部系统类型。 在内部,一个 LSN 是一个 64 位整数,表示在预写式日志流中的一个字节位置。它被打印成两个最高 8 位的十 六进制数,中间用斜线分隔,例如 16/B374D848。sys_lsn 类型支持标准的比较操作符,如 = 和 >。两个 LSN 可以 用-操作符做减法,结果将是分隔两个预写式日志位置的字节数。 3.1.2.3 伪类型 KingbaseES 类型系统包含了一些特殊目的的项,它们被统称为伪类型。一个伪类型不能被用作一个列的数据类 型,但是它可以被用来定义一个函数的参数或者结果类型。每一种可用的伪类型都有其可以发挥作用的情况,这些 情况的特点是一个函数的行为并不能符合于简单使用或者返回一种特定 SQL 数据类型的值。下表列出了现有的伪类 型。 表 3.1.18: 伪类型 名字 描述 any 表示一个函数可以接受任意输入数据类型。 anyelement 表示一个函数可以接受任意数据类型 anyarray 表示一个函数可以接受任意数组数据类型 anynonarray 表示一个函数可以接受任意非数组数据类型 anyenum 表示一个函数可以接受任意枚举数据类型 anyset 表示一个函数可以接受任意 SET 数据类型 anyrange 表示一个函数可以接受任意范围数据类型 cstring 表示一个函数接受或者返回一个非空结尾的 C 字符串。 internal 表示一个函数接受或返回一个服务器内部数据类型。 language_handler 一个被声明为返回 language_handler 的过程语言调用处理器。 fdw_handler 一个被声明为返回 fdw_handler 的外部数据包装器处理器。 index_am_handler 一个被声明为返回 index_am_handler 索引访问方法处理器。 见续表 72 第3章 KINGBASEES SQL 基本元素 表 3.1.18 – 续表 名字 描述 tsm_handler 一个被声明为返回 tsm_handler 的表采样方法处理器。 record 标识一个接收或者返回一个未指定的行类型的函数。 trigger 一个被声明为返回 trigger 的触发器函数。 event_trigger 一个被声明为返回 event_trigger 的事件触发器函数。 sys_ddl_command 标识一种对事件触发器可用的 DDL 命令的表达。 void 表示一个函数不返回值。 unknown 标识一种还未被解析的类型,例如一个未修饰的字符文本。 opaque 一种已被废弃的类型名称,以前它用于实现以上的很多种目的。 用 C 编写的函数(不管是内建的还是动态载入的)可以被声明为接受或返回这些为数据类型的任意一种。函数 的作者应当保证当一个伪类型被用作一个参数类型时函数的行为是安全的。 用过程语言编写的函数只有在其实现语言允许的情况下才能使用伪类型。目前大部分过程语言都禁止使用伪 类型作为一种参数类型,并且只允许使用 void 和 record 作为结果类型(如果函数被用于一个触发器或者事件 触发器,trigger 或者 event_trigger 也被允许作为结果类型)。某些过程语言也支持在多态函数中使用类型 anyelement、anyarray、anynonarray、anyenum、anyset 和 anyrange。 internal 伪类型用于定义只在数据库系统内部调用的函数,这些函数不会被 SQL 直接调用。如果一个函数拥有 至少一个 internal 类型的参数,则它不能从 SQL 中被调用。为了保持这种限制的类型安全性,遵循以下编码规则 非常重要:不要创建任何被声明要返回 internal 的函数,除非它有至少一个 internal 参数。 3.1.3 用户自定义类型 用户自定义的数据类型由 KingbaseES 内置数据类型和其他用户自定义数据类型构成,用户自定义类型对应用程 序中数据的结构和行为进行建模。以下各节介绍用户定义类型的各种类别。 自定义类型可以使用CREATE TYPE 和CREATE TYPE BODY 命令创建。 3.1.3.1 枚举类型 枚举(enum)类型是由一个静态、值的有序集合构成的数据类型。与很多编程语言所支持的 enum 类型相似。 枚举类型可以使用CREATE TYPE 命令创建,例如: CREATE TYPE mood AS ENUM ('sad', 'ok', 'happy'); 一旦被创建,枚举类型可以像很多其他类型一样在表和函数定义中使用: 73 第3章 KINGBASEES SQL 基本元素 CREATE TYPE mood AS ENUM ('sad', 'ok', 'happy'); CREATE TABLE person ( name text, current_mood mood ); INSERT INTO person VALUES ('Moe', 'happy'); SELECT * FROM person WHERE current_mood = 'happy'; name | current_mood ------+-------------Moe | happy (1 row) 3.1.3.1.1 排序 一个枚举类型的值的排序是该类型被创建时所列出的值的顺序。枚举类型的所有标准的比较操作符以及相关聚集 函数都被支持。例如: INSERT INTO person VALUES ('Larry', 'sad'); INSERT INTO person VALUES ('Curly', 'ok'); SELECT * FROM person WHERE current_mood > 'sad'; name | current_mood -------+-------------Moe | happy Curly | ok (2 rows) SELECT * FROM person WHERE current_mood > 'sad' ORDER BY current_mood; name | current_mood -------+-------------Curly | ok Moe | happy (2 rows) SELECT name FROM person WHERE current_mood = (SELECT MIN(current_mood) FROM person); name ------Larry (1 row) 3.1.3.1.2 类型安全性 每一种枚举数据类型都是独立的并且不能和其他枚举类型相比较。看这样一个例子: 74 第3章 KINGBASEES SQL 基本元素 CREATE TYPE happiness AS ENUM ('happy', 'very happy', 'ecstatic'); CREATE TABLE holidays ( num_weeks integer, happiness happiness ); INSERT INTO holidays(num_weeks,happiness) VALUES (4, 'happy'); INSERT INTO holidays(num_weeks,happiness) VALUES (6, 'very happy'); INSERT INTO holidays(num_weeks,happiness) VALUES (8, 'ecstatic'); INSERT INTO holidays(num_weeks,happiness) VALUES (2, 'sad'); ERROR: invalid input value for enum happiness: "sad" SELECT person.name, holidays.num_weeks FROM person, holidays WHERE person.current_mood = holidays.happiness; ERROR: operator does not exist: mood = happiness 如果您确实需要做这样的事情,可以写一个自定义的操作符或者在查询中加上显式造型: SELECT person.name, holidays.num_weeks FROM person, holidays WHERE person.current_mood::text = holidays.happiness::text; name | num_weeks ------+----------Moe | 4 (1 row) 3.1.3.1.3 实现细节 枚举标签是大小写敏感的,因此'happy'与'HAPPY'是不同的。标签中的空格也是有意义的。 尽管枚举类型的主要目的是用于值的静态集合,但也有方法在现有枚举类型中增加新值和重命名值(见ALTER TYPE )。不能从枚举类型中去除现有的值,也不能更改这些值的排序顺序,如果要那样做可以删除并且重建枚举类 型。 一个枚举值在磁盘上占据 4 个字节。一个枚举值的文本标签的长度受限于 NAMEDATALEN 设置,该设置被编译在 KingbaseES 中,在标准编译下它表示最多 63 字节。 从内部枚举值到文本标签的翻译被保存在系统目录 sys_enum 中。可以直接查询该目录。 3.1.3.2 SET 类型 SET 类型是可以具有 0 到 64 个值的自定义类型,每个值都必须在定义时指定的值列表中选取。指定包括多个 SET 成员的 SET 列值时各成员之间使用逗号 (‘,’) 分隔。所以 SET 成员值本身不能包含逗号。特别地,SET 成 员值本身不能为 NULL。SET 和 ENUM 最主要的区别在于 SET 类型一次可以使用多个成员,而 ENUM 则只能一 个。 SET 类型可以使用CREATE TYPE 命令创建,例如: 75 第3章 KINGBASEES SQL 基本元素 CREATE TYPE rainbow AS SET ('R', 'O', 'Y', 'G', 'B', 'P'); 一旦被创建,SET 类型可以像很多其他类型一样在表和函数定义中使用: CREATE TYPE rainbow AS SET ('R', 'O', 'Y', 'G', 'B', 'P'); CREATE TABLE colors (col rainbow); INSERT INTO colors values ('R'),('G'),('R,G,G'),('r,y,p'),('P,B,O'); SELECT * FROM colors; col ------R G R,G R,Y,P O,B,P (5 rows) 通过上面的例子可以看到,对于包含多个 SET 成员的值: • 值中的每个成员都只会出现一次; • 插入时成员的顺序无关紧要,会按照类型创建类型时指定的顺序列出; • 大小写不敏感,在存储时都转换为创建类型时定义的大写或小写。 SET 类型支持的比较操作符有:= 、!=(或 <>) 、>、< 、>= 、<=。SET 类型的值转为字符串进行大小比 较,规则如下: • 字符串大小比较的时候,两个字符串自左向右逐个字符相比(按 ASCII 值大小相比较),直到出现不同的字符 或“0”为止。若在某位置上已经有大小之分,则结束比较。 • 当其中任一字符串为 NULL 时,返回 NULL。 例如: SELECT * FROM colors WHERE col = 'O,B,P'; col ------O,B,P (1 row) SELECT * FROM colors WHERE col <= 'O,B,P'; col ------G O,B,P (2 rows) SELECT * FROM colors WHERE col > 'O,B,P'; col ------- 76 第3章 KINGBASEES SQL 基本元素 R R,G R,Y,P (3 rows) SET 类型支持的模糊匹配操作符有:LIKE、NOT LIKE。通常使用 LIKE 操作符搜索 SET 值。例如: SELECT * FROM colors WHERE col LIKE 'R'; col ----R (1 row) SELECT * FROM colors WHERE col NOT LIKE 'R'; col ------G R,G R,Y,P O,B,P (4 rows) 通过上面的例子可以看到,通过 LIKE 操作符可以找到 col 列中值为’R’ 的行。 此外,还可以使用 &、= 操作符搜索 SET 值。例如: SELECT * FROM colors WHERE col&1 != 0; col ------R R,G R,Y,P (3 rows) SELECT * FROM colors WHERE col = 'R,G'; col ----R,G (1 row) SELECT * FROM colors WHERE col = 'G,R'; col ----(0 row) 上面的例子中,第 1 个语句寻找包含第 1 个 set 成员的值。第 2 语句寻找一个确切匹配的值。注意第 2 类的比 较。将 set 值与’val1,val2’ 比较返回的结果与同’val2,val1’ 比较返回的结果不同。指定值时的顺序应与在列定义中所列 的顺序相同。 77 第3章 KINGBASEES SQL 基本元素 SET 类型支持聚集函数 max() 和 min()。例如: SELECT max(col) FROM colors; max ------R,Y,P (1 row) SELECT min(col) FROM colors; min ----G (1 row) 3.1.3.2.1 类型安全性 每一种 SET 数据类型都是独立的并且不能和其他 SET 类型相比较。看这样一个例子: CREATE TYPE basic_colors AS SET ('R', 'G', 'B'); CREATE TABLE color_mixing (col basic_colors); INSERT INTO color_mixing values ('R'),('G'),('R,G'),('R,G,B'); SELECT * FROM colors, color_mixing WHERE colors.col = color_mixing.col; ERROR: operator does not exist: rainbow = basic_colors LINE 1: ...LECT * FROM colors, color_mixing WHERE colors.col = color_mi... ^ HINT: No operator matches the given name and argument types. You might need to add explicit type casts. 如果您确实需要做这样的事情,可以写一个自定义的操作符或者在查询中加上显式造型: SELECT * FROM colors, color_mixing WHERE colors.col::text = color_mixing.col::text; col | col -----+----G | G R | R R,G | R,G (3 rows) 3.1.3.2.2 实现细节 SET 类型标签默认是大小写不敏感的,标签尾部的空格会自动删除,定义重复的值会导致报错。SET 类型的字 符串可以包含除’,’以外的各类特殊字符,如’/’,’{}’等。SET 类型仅在 MySQL 模式下有效。 尽管 SET 类型的主要目的是用于值的静态集合,但也有方法在现有 SET 类型中增加新值和重命名值 (见ALTER TYPE )。不能从 SET 类型中去除现有的值,如果要那样做可以删除并且重建 SET 类型。 SET 类型中每个成员的文本标签的长度受限于 NAMEDATALEN 设置,该设置被编译在 KingbaseES 中,在标准编 译下它表示最多 63 字节,一个 SET 类型最多有 64 个标签。 78 第3章 KINGBASEES SQL 基本元素 从内部 SET 值到文本标签的翻译被保存在系统目录 sys_set 中。可以直接查询该目录。 3.1.3.3 集合类型 集合类型包括三种具体的类型:关联数组(AssociativeArray)、嵌套表(Nested Table)和可变数组(Varray)。其中嵌套表和可变数组类型可以在 SQL 端通过 CREATE TYPE 创建,用于 PL/SQL 变量的数据类型, 参数或者函数返回值,但不能用作数据表的列类型。 3.1.3.3.1 嵌套表 嵌套表给定数据连续的索引,并从 1 开始。使用这些索引,用户可以访问各个嵌套表数据。 3.1.3.3.1.1 嵌套表类型的声明 嵌套表类型可以使用CREATE TYPE 命令创建,例如: CREATE TYPE NestedTable_Int AS TABLE OF INT; 3.1.3.3.1.2 嵌套表类型的使用 嵌套表适用于以下几种情况: • 元素数不确定; • 索引值可能出现不连续的情况; • 必须单独删除或更新某些元素的情况; • 嵌套表可以看做是 index 为 int 的关联数组。 3.1.3.3.1.3 示例 CREATE TYPE Nested_Table_Int AS TABLE OF INT; \set SQLTERM / DO $$DECLARE a Nested_Table_Int; BEGIN a = Nested_Table_Int(1, 2, 3); END$$; / CREATE Function test_nestedtable1() return Nested_Table_Int AS result Nested_Table_Int = Nested_Table_Int(1, 2, 5); BEGIN return result; 79 第3章 KINGBASEES SQL 基本元素 end; / Create PROCEDURE test_nestedtable2(nest_int Nested_Table_Int) AS DECLARE i INT; BEGIN i := nest_int.first(); WHILE i IS NOT NULL LOOP RAISE NOTICE 'nest_int(%) is %', i, nest_int(i); i := nest_int.next(i); END LOOP; END; / call test_nestedtable2(test_nestedtable1()); / \set SQLTERM ; 3.1.3.3.2 可变数组 可变数组的下标索引类型为 INT 并且从 1 开始。与嵌套表不同,可变数组在定义的时候需要指定最大元素个 数,使用中不能超过该限制。并且可变数组的下标是连续的,为了保证其连续性,可变数组不能通过 delete(index) 和 delete(index1,index2) 方法删除任何元素。 3.1.3.3.2.1 可变数组的声明 可变数组类型可以使用CREATE TYPE 命令创建,例如: CREATE TYPE Varray_Int AS VARRAY(50) OF INT; 3.1.3.3.2.2 可变数组的使用 嵌套表适用于以下几种情况: • 元素数有最大限制; • 索引值必须是连续的情况。 3.1.3.3.2.3 示例 CREATE TYPE Varray_Int AS VARRAY(5) OF INT; \set SQLTERM / DO $$DECLARE a Varray_Int; 80 第3章 KINGBASEES SQL 基本元素 BEGIN a = Varray_Int(1, 2, 3); END$$; / CREATE Function test_varray1() return Varray_Int AS result Varray_Int = Varray_Int(1, 2, 5); BEGIN return result; end; / Create PROCEDURE test_varray2(v_int Varray_Int) AS DECLARE i INT; BEGIN i := v_int.first(); WHILE i IS NOT NULL LOOP RAISE NOTICE 'varray_int(%) is %', i, v_int(i); i := v_int.next(i); END LOOP; END; / call test_varray2(test_varray1()); / \set SQLTERM ; 3.1.3.4 组合类型 一个组合类型表示一行或一个记录的结构,它本质上就是一个域名和它们数据类型的列表。KingbaseES 允许把 组合类型用在很多能用简单类型的地方。例如,一个表的一列可以被声明为一种组合类型。 3.1.3.4.1 组合类型的声明 这里有两个定义组合类型的简单例子: CREATE TYPE complex AS ( r double precision, i double precision ); CREATE TYPE inventory_item AS ( name text, supplier_id integer, 81 第3章 price KINGBASEES SQL 基本元素 numeric ); 该语法堪比 CREATE TABLE,不过只能指定域名和类型,当前不能包括约束(例如 NOT NULL)。注意 AS 关键 词是必不可少的,如果没有它,系统将认为用户想要的是一种不同类型的 CREATE TYPE 命令,并且你将得到奇怪的 语法错误。 定义了类型之后,我们可以用它们来创建表: CREATE TABLE on_hand ( item inventory_item, count integer ); INSERT INTO on_hand VALUES (ROW('fuzzy dice', 42, 1.99), 1000); 或者创建函数: CREATE FUNCTION price_extension(inventory_item, integer) RETURNS numeric AS 'SELECT $1.price * $2' LANGUAGE SQL; SELECT price_extension(item, 10) FROM on_hand; 只要你创建了一个表,也会自动创建一个组合类型来表示表的行类型,它具有和表一样的名称。例如,如果我们 说: CREATE TABLE inventory_item ( name text, supplier_id integer REFERENCES suppliers, price numeric CHECK (price > 0) ); 那么和上面所示相同的 inventory_item 组合类型将成为一种副产品,并且可以按上面所说的进行使用。不过要 注意当前实现的一个重要限制:因为没有约束与一个组合类型相关,显示在表定义中的约束不会应用于表外组合类型 的值(要解决这个问题,可以在该组合类型上创建一个域,并且把想要的约束应用为这个域上的 CHECK 约束)。 3.1.3.4.2 构造组合值 要把一个组合值写作一个文字常量,将该域值封闭在圆括号中并且用逗号分隔它们。你可以在任何域值周围放上 双引号,并且如果该域值包含逗号或圆括号则必须这样做(更多细节见下文)。这样,一个组合常量的一般格式是下 面这样的: '( val1 , val2 , ... )' 一个例子是: 82 第3章 KINGBASEES SQL 基本元素 '("fuzzy dice",42,1.99)' 这将是上文定义的 inventory_item 类型的一个合法值。要让一个域为 NULL,在列表中它的位置上根本不写字 符。例如,这个常量指定其第三个域为 NULL: '("fuzzy dice",42,)' 如果你写一个空字符串而不是 NULL,写上两个引号: '("",42,)' 这里第一个域是一个非 NULL 空字符串,第三个是 NULL。 (这些常量实际上只是其他类型的常量 中讨论的一般类型常量的特殊类型。该常量最初被当做一个字符串并且 被传递给组合类型输入转换例程。有必要用一次显式类型说明来告知要把该常量转换成何种类型。)。 ROW 表达式也能被用来构建组合值。在大部分情况下,比起使用字符串语法,这相当简单易用,因为你不必担心 多层引用。我们已经在上文用过这种方法: ROW('fuzzy dice', 42, 1.99) ROW('', 42, NULL) 只要在表达式中有多于一个域,ROW 关键词实际上就是可选的,因此这些可以被简化成: ('fuzzy dice', 42, 1.99) ('', 42, NULL) 3.1.3.4.3 访问组合类型 要访问一个组合列的一个域,可以写成一个点和域的名称,更像从一个表名中选择一个域。事实上,它太像从一 个表名中选择,这样我们不得不使用圆括号来避免让解析器混淆。例如,你可能尝试从例子表 on_hand 中选取一些 子域: SELECT item.name FROM on_hand WHERE item.price > 9.99; 这不会有用,因为名称 item 会被当成是一个表名,而不是 on_hand 的一个列名。你必须写成这样: SELECT (item).name FROM on_hand WHERE (item).price > 9.99; 或者你还需要使用表名(例如在一个多表查询中),像这样: SELECT (on_hand.item).name FROM on_hand WHERE (on_hand.item).price > 9.99; 现在加上括号的对象就被正确地解释为对 item 列的引用,然后可以从中选出子域。 只要你从一个组合值中选择一个域,相似的语法问题就适用。例如,要从一个返回组合值的函数的结果中选取一 个域,你需要这样写: 83 第3章 KINGBASEES SQL 基本元素 SELECT (my_func(...)).field FROM ... 如果没有额外的圆括号,这将生成一个语法错误。 特殊的域名称 * 表示“所有的域”,在查询中使用组合类型 中有进一步的解释。 3.1.3.4.4 修改组合类型 这里有一些插入和更新组合列的正确语法的例子。首先,插入或者更新一整个列: INSERT INTO mytab (complex_col) VALUES((1.1,2.2)); UPDATE mytab SET complex_col = ROW(1.1,2.2) WHERE ...; 第一个例子忽略 ROW,第二个例子使用它,我们可以用两者之一完成。 我们能够更新一个组合列的单个子域: UPDATE mytab SET complex_col.r = (complex_col).r + 1 WHERE ...; 注意这里我们不需要(事实上也不能)把圆括号放在正好出现在 SET 之后的列名周围,但是当在等号右边的表 达式中引用同一列时确实需要圆括号。 并且我们也可以指定子域作为 INSERT 的目标: INSERT INTO mytab (complex_col.r, complex_col.i) VALUES(1.1, 2.2); 如果我们没有为该列的所有子域提供值,剩下的子域将用空值填充。 3.1.3.4.5 在查询中使用组合类型 对于查询中的组合类型有各种特殊的语法规则和行为。这些规则提供了有用的捷径,但是如果你不懂背后的逻辑 就会被此困扰。 在 KingbaseES 中,查询中对一个表名(或别名)的引用实际上是对该表的当前行的组合值的引用。例如,如果 我们有一个如上所示的表 inventory_item,我们可以写: SELECT c FROM inventory_item c; 这个查询产生一个单一组合值列,所以我们会得到这样的输出: c -----------------------("fuzzy dice",42,1.99) (1 row) 84 第3章 KINGBASEES SQL 基本元素 不过要注意简单的名称会在表名之前先匹配到列名,因此这个例子可行的原因仅仅是因为在该查询的表中没有名 为 c 的列。 普通的限定列名语法 “table_name“.“column_name“可以理解为把字段选择应用在该表的当前行的组合值上(由 于效率的原因,实际上不是以这种方式实现)。 当我们写 SELECT c.* FROM inventory_item c; 时,根据 SQL 标准,我们应该得到该表展开成列的内容: name | supplier_id | price ------------+-------------+------fuzzy dice | 42 | 1.99 (1 row) 就好像查询是 SELECT c.name, c.supplier_id, c.price FROM inventory_item c; 尽管如上所示,KingbaseES 将对任何组合值表达式应用这种展开行为,但只要.* 所应用的值不是一个简单的表 名,你就需要把该值写在圆括号内。例如,如果 myfunc() 是一个返回组合类型的函数,该组合类型由列 a、b 和 c 组成,那么这两个查询有相同的结果: SELECT (myfunc(x)).* FROM some_table; SELECT (myfunc(x)).a, (myfunc(x)).b, (myfunc(x)).c FROM some_table; 提示: KingbaseES 实际上通过将第一种形式转换为第二种来处理列展开。因此,在这个例子中,用两种语法时对每 行都会调用 myfunc() 三次。如果它是一个开销很大的函数,你可能希望避免这样做,所以可以用一个这样的查询: SELECT m.* FROM some_table, LATERAL myfunc(x) AS m; 把该函数放在一个 LATERAL FROM 项中会防止它对每一行被调用超过一次。m.* 仍然会被展开为 m.a, m.b, m. c,但现在那些变量只是对这个 FROM 项的输出的引用(这里关键词 LATERAL 是可选的,但我们在这里写上它是为了 说明该函数从 some_table 中得到 x)。 当 “composite_value“.* 出现在一个 SELECT 输出列表选择列表的顶层中、INSERT/UPDATE/DELETE 中的一个 RETURNING 列表中、一个 VALUES 子句中或者一个行构造器中时,该语法会导致这种类型的列展开。在所有其他上 下文(包括被嵌入在那些结构之一中时)中,把.* 附加到一个组合值不会改变该值,因为它表示“所有的列”并且 因此同一个组合值会被再次产生。例如,如果 somefunc() 接受一个组合值参数,这些查询是相同的: SELECT somefunc(c.*) FROM inventory_item c; SELECT somefunc(c) FROM inventory_item c; 85 第3章 KINGBASEES SQL 基本元素 在两种情况中,inventory_item 的当前行被传递给该函数作为一个单一的组合值参数。即使.* 在这类情况中什 么也不做,使用它也是一种好的风格,因为它说清了一个组合值的目的是什么。特别地,解析器将会认为 c.* 中的 c 是引用一个表名或别名,而不是一个列名,这样就不会出现混淆。而如果没有.*,就弄不清楚 c 到底是表示一个表 名还是一个列名,并且在有一个名为 c 的列时会优先选择按列名来解释。 另一个演示这些概念的例子是下面这些查询,它们表示相同的东西: SELECT * FROM inventory_item c ORDER BY c; SELECT * FROM inventory_item c ORDER BY c.*; SELECT * FROM inventory_item c ORDER BY ROW(c.*); 所有这些 ORDER BY 子句指定该行的组合值,导致根据组合类型比较的规则对行进行排序。不过,如果 inventory_item 包含一个名为 c 的列,第一种情况会不同于其他情况,因为它表示仅按那一列排序。给定之前所 示的列名,下面这些查询也等效于上面的那些查询: SELECT * FROM inventory_item c ORDER BY ROW(c.name, c.supplier_id, c.price); SELECT * FROM inventory_item c ORDER BY (c.name, c.supplier_id, c.price); (最后一种情况使用了一个省略关键字 ROW 的行构造器)。 另一种与组合值相关的特殊语法行为是,我们可以使用函数记法来抽取一个组合值的字段。解释这种行为的简单 方式是记法 field(“table“) 和 table.“field“是可以互换的。例如,这些查询是等效的: SELECT c.name FROM inventory_item c WHERE c.price > 1000; SELECT name(c) FROM inventory_item c WHERE price(c) > 1000; 此外,如果我们有一个函数接受单一的组合类型参数,我们可以以任意一种记法来调用它。这些查询全都是等效 的: SELECT somefunc(c) FROM inventory_item c; SELECT somefunc(c.*) FROM inventory_item c; SELECT c.somefunc FROM inventory_item c; 这种函数记法和字段记法之间的等效性使得我们可以在组合类型上使用函数来实现“计算字段”。一个使用上述 最后一种查询的应用不会直接意识到 somefunc 不是一个真实的表列。 提示: 由于这种行为,让一个接受单一组合类型参数的函数与该组合类型的任意字段具有相同的名称是不明智的。 出现歧义时,如果使用了字段名语法,则字段名解释将被选择,而如果使用的是函数调用语法则会选择函数解释。不 过,KingbaseES V8R3 版本之前总是选择字段名解释,除非该调用的语法要求它是一个函数调用。在老的版本中强 制函数解释的一种方法是用方案限定函数名,也就是写成 schema.“func“(“compositevalue“)。 3.1.3.4.6 组合类型输入和输出语法 一个组合值的外部文本表达由根据域类型的 I/O 转换规则解释的项,外加指示组合结构的装饰组成。装饰由整 个值周围的圆括号((和)),外加相邻项之间的逗号(,)组成。圆括号之外的空格会被忽略,但是在圆括号之内空 86 第3章 KINGBASEES SQL 基本元素 格会被当成域值的一部分,并且根据域数据类型的输入转换规则可能有意义,也可能没有意义。例如,在 '( 42)' 中,如果域类型是整数则空格会被忽略,而如果是文本则空格不会被忽略。 如前所示,在写一个组合值时,你可以在任意域值周围写上双引号。如果不这样做会让域值迷惑组合值解析器, 你就必须这么做。特别地,包含圆括号、逗号、双引号或反斜线的域必须用双引号引用。要把一个双引号或者反斜线 放在一个被引用的组合域值中,需要在它前面放上一个反斜线(还有,一个双引号引用的域值中的一对双引号被认为 是表示一个双引号字符,这和 SQL 字符串中单引号的规则类似)。另一种办法是,你可以避免引用以及使用反斜线 转义来保护所有可能被当作组合语法的数据字符。 一个全空的域值(在逗号或圆括号之间完全没有字符)表示一个 NULL。要写一个空字符串值而不是 NULL,可 以写成""。 如果域值是空串或者包含圆括号、逗号、双引号、反斜线或空格,组合输出例程将在域值周围放上双引号(对空 格这样处理并不是不可缺少的,但是可以提高可读性)。嵌入在域值中的双引号及反斜线将被双写。 注意: 记住你在一个 SQL 命令中写的东西将首先被解释为一个字符串,然后才会被解释为一个组合。这就让你所需 要的反斜线数量翻倍(假定使用了转义字符串语法)。例如,要在组合值中插入一个含有一个双引号和一个反斜线的 text 域,你需要写成: INSERT ... VALUES ('("\"\\")'); 字符串处理器会移除一层反斜线,这样在组合值解析器那里看到的就会是 ("\"\\")。接着,字符串被交给 text 数据类型的输入例程并且变成"\(如果我们使用的数据类型的输入例程也会特别处理反斜线,例如 bytea,在 命令中我们可能需要八个反斜线用来在组合域中存储一个反斜线)。美元引用(见美元引用的字符串常量 )可以被 用来避免双写反斜线。 提示: 当在 SQL 命令中书写组合值时,ROW 构造器语法通常比组合文字语法更容易使用。在 ROW 中,单个域值可以 按照平时不是组合值成员的写法来写。 3.1.3.5 对象类型 对象类型和组合类型在定义和使用上都有很多相似性,可以认为对象类型是组合类型的增强。不同于组合类型的 是,对象类型除了支持组合类型的行记录结构外,还支持声明和定义一些内部方法,并在创建相应的对象后在具体的 对象上使用这些方法。此外,对象类型还支持连续多段调用功能。 3.1.3.5.1 对象类型的声明和定义 详细的创建规则和说明可参见CREATE TYPE 和CREATE TYPE BODY 。 87 第3章 KINGBASEES SQL 基本元素 这里有个定义对象类型的简单例子: CREATE OR REPLACE TYPE objtype FORCE AUTHID CURRENT_USER AS OBJECT( f1 int, f2 varchar2(10), MEMBER FUNCTION memfunc(i int) RETURN INT, STATIC PROCEDURE staproc, CONSTRUCTOR FUNCTION objtype(self in out objtype) RETURN SELF AS RESULT ); \set SQLTERM / CREATE OR REPLACE TYPE BODY objtype AS MEMBER FUNCTION memfunc(i int) RETURN INT AS BEGIN RAISE NOTICE 'self.f1 is %', self.f1; RAISE NOTICE 'self.f2 is %', f2; RETURN i; END; STATIC PROCEDURE staproc AS BEGIN RAISE NOTICE 'this is a static procedure in object type'; END; CONSTRUCTOR FUNCTION objtype(self in out objtype) RETURN SELF AS RESULT AS BEGIN f1 := 1; self.f2 := 'a'; RETURN ; END; END; / \set SQLTERM ; 可以用它作为主体直接创建表: CREATE TABLE tab2 OF objtype; INSERT INTO tab2 VALUES (1, 'test'); SELECT * FROM tab2; f1 | f2 ----+-----1 | test (1 row) 88 第3章 KINGBASEES SQL 基本元素 SELECT t.memfunc(1) FROM tab2 t; -- 使用表的成员函数 NOTICE: self.f1 is 1 NOTICE: self.f2 is test objtype.memfunc ----------------1 (1 row) CALL objtype.staproc(); -- 使用对象类型的静态存储过程 NOTICE: this is a static procedure in object type 也可以在 PL/SQL 块中直接使用: \set SQLTERM / DECLARE item objtype:= objtype(); item2 objtype; BEGIN item2 := objtype(2, 'test'); RAISE NOTICE 'item''s member function return %', item.memfunc(1); -- 使用 PL/SQL 中对象的成员函数 RAISE NOTICE 'item2''s member function return %', item2.memfunc(2); -- 使用 PL/SQL 中对象的成员函数 objtype.staproc(); -- 使用对象类型的静态存储过程 END; / \set SQLTERM ; NOTICE: self.f1 is 1 NOTICE: self.f2 is a NOTICE: item's member function return 1 NOTICE: self.f1 is 2 NOTICE: self.f2 is test NOTICE: item2's member function return 2 NOTICE: this is a static procedure in object type 对象类型连续调用功能的例子如下: CREATE OR REPLACE TYPE objtype3 AS OBJECT( i INT, MEMBER FUNCTION func3() RETURN INT, CONSTRUCTOR FUNCTION objtype3(SELF IN OUT objtype3) RETURN SELF AS RESULT ); \set SQLTERM / 89 第3章 KINGBASEES SQL 基本元素 CREATE OR REPLACE TYPE BODY objtype3 AS MEMBER FUNCTION func3() RETURN INT AS BEGIN RETURN i; END; CONSTRUCTOR FUNCTION objtype3(SELF IN OUT NOCOPY objtype3) RETURN SELF AS RESULT IS BEGIN SELF.i := 2; RETURN; END; END; / \set SQLTERM ; CREATE OR REPLACE TYPE objtype2 AS OBJECT( objvar2 objtype3, MEMBER FUNCTION func2() return objtype3, CONSTRUCTOR FUNCTION objtype2(SELF IN OUT objtype2) RETURN SELF AS RESULT ); \set SQLTERM / CREATE OR REPLACE TYPE BODY objtype2 AS MEMBER FUNCTION func2() RETURN objtype3 AS var objtype3 := objtype3(); BEGIN RETURN var; END; CONSTRUCTOR FUNCTION objtype2(SELF IN OUT NOCOPY objtype2) RETURN SELF AS RESULT IS BEGIN SELF.objvar2 := objtype3(); RETURN; END; END; / \set SQLTERM ; CREATE OR REPLACE TYPE objtype1 AS OBJECT( objvar1 objtype2, MEMBER FUNCTION func1() RETURN objtype2, CONSTRUCTOR FUNCTION objtype1(SELF IN OUT objtype1) RETURN SELF AS RESULT ); \set SQLTERM / CREATE OR REPLACE TYPE BODY objtype1 AS MEMBER FUNCTION func1() return objtype2 AS var objtype2 := objtype2(); 90 第3章 KINGBASEES SQL 基本元素 BEGIN return var; END; CONSTRUCTOR FUNCTION objtype1(SELF IN OUT NOCOPY objtype1) RETURN SELF AS RESULT IS BEGIN SELF.objvar1 := objtype2(); RETURN; END; END; / \set SQLTERM ; plsql 中定义的 object type 变量: \set SQLTERM / DECLARE objvar1 objtype1 = objtype1(); result int; BEGIN result = objvar1.func1().func2().func3(); raise notice 'result = %', result; result = objvar1.func1().objvar2.func3(); raise notice 'result = %', result; END; / \set SQLTERM ; 表中的列为 object type 变量: CREATE TABLE objtab1(objcol objtype1); INSERT INTO objtab1 VALUES (objtype1()); SELECT objcol.func1().func2().func3() FROM objtab1; SELECT objcol.func1().objvar2.func3() FROM objtab1; 非 object type 函数返回值为 object type 作为多段调用的第一段: \set SQLTERM / CREATE OR REPLACE FUNCTION func() RETURN objtype1 AS objvar1 objtype1 := objtype1(); BEGIN RETURN objvar1; END; 91 第3章 KINGBASEES SQL 基本元素 / BEGIN raise notice '%', func().func1().func2().func3(); raise notice '%', func().objvar1.objvar2.func3(); END; / \set SQLTERM ; SELECT func().func1().func2().func3(); SELECT func().objvar1.objvar2.func3(); 需要注意的是,plsql 调用不支持 2 段以上 (不包括函数段) 的多段变量在开头连续调用,sql 调用不支持 1 段以 上的多段变量在开头调用。 3.1.3.6 数组 KingbaseES 允许一个表中的列定义为变长多维数组。可以创建任何内建或用户定义的基类、枚举类型、组合类 型或者域的数组。 3.1.3.6.1 数组类型的定义 为了展示数组类型的使用,我们创建这样一个表: CREATE TABLE sal_emp ( name text, pay_by_quarter integer[], schedule text[][] ); 如上所示,一个数组数据类型可以通过在数组元素的数据类型名称后面加上方括号([])来命名。上述命令将创 建一个名为 sal_emp 的表,它有一个类型为 text 的列(name),一个表示雇员的季度工资的一维 integer 类型数 组(pay_by_quarter),以及一个表示雇员每周日程表的二维 text 类型数组(schedule)。 CREATE TABLE 的语法允许指定数组的确切大小,例如: CREATE TABLE tictactoe ( squares integer[3][3] ); 然而,当前的实现忽略任何提供的数组尺寸限制,即其行为与未指定长度的数组相同。 当前的实现也不会强制所声明的维度数。一个特定元素类型的数组全部被当作是相同的类型,而不论其尺寸或维 度数。因此,在 CREATE TABLE 中声明数组的尺寸或维度数仅仅只是文档而已,它并不影响运行时的行为。 另一种符合 SQL 标准的语法是使用关键词 ARRAY,可以用来定义一维数组。pay_by_quarter 可以这样定义: 92 第3章 pay_by_quarter KINGBASEES SQL 基本元素 integer ARRAY[4], 或者,不指定数组尺寸: pay_by_quarter integer ARRAY, 但是和前面一样,KingbaseES 在任何情况下都不会强制尺寸限制。 3.1.3.6.2 数组值输入 要把一个数组值写成一个文字常数,将元素值用花括号包围并用逗号分隔。在任意元素值周围可以使用双引号, 并且在元素值包含逗号或花括号时必须这样做(更多细节如下所示)。因此,一个数组常量的一般格式如下: '{ val1 delim val2 delim ... }' 这里 delim 是类型的定界符,记录在类型的 sys_type 项中。在 KingbaseES 发行提供的标准数据类型中,所 有的都使用一个逗号(,),除了类型 box 使用一个分号(;)。每个 val 可以是数组元素类型的一个常量,也可以 是一个子数组。一个数组常量的例子是: '{{1,2,3},{4,5,6},{7,8,9}}' 该常量是一个二维的,3 乘 3 数组,它由 3 个整数子数组构成。 要设置一个数组常量的一个元素为 NULL,在该元素值处写 NULL(任何 NULL 的大写或小写变体都有效)。如 果你需要一个真正的字符串值“NULL”,你必须在它两边放上双引号。 (这些种类的数组常数实际是其他类型的常量 中讨论的一般类型常量的一种特殊形式。常数最初被当做一个字 符串,然后被传给数组的输入转换例程。有必要时可能需要一个显式的类型指定。) 现在我们可以展示一些 INSERT 语句: INSERT INTO sal_emp VALUES ('Bill', '{10000, 10000, 10000, 10000}', '{{"meeting", "lunch"}, {"training", "presentation"}}'); INSERT INTO sal_emp VALUES ('Carol', '{20000, 25000, 25000, 25000}', '{{"breakfast", "consulting"}, {"meeting", "lunch"}}'); 前两个插入的结果看起来像这样: SELECT * FROM sal_emp; name | pay_by_quarter | schedule -------+---------------------------+------------------------------------------Bill | {10000,10000,10000,10000} | {{meeting,lunch},{training,presentation}} 93 第3章 KINGBASEES SQL 基本元素 Carol | {20000,25000,25000,25000} | {{breakfast,consulting},{meeting,lunch}} (2 rows) 多维数组的每一维都必须有相匹配的长度。不匹配会造成错误,例如: INSERT INTO sal_emp VALUES ('Bill', '{10000, 10000, 10000, 10000}', '{{"meeting", "lunch"}, {"meeting"}}'); ERROR: Multidimensional arrays must have sub-arrays with matching dimensions. ARRAY 构造器语法也可以被用于: INSERT INTO sal_emp VALUES ('Bill', ARRAY[10000, 10000, 10000, 10000], ARRAY[['meeting', 'lunch'], ['training', 'presentation']]); INSERT INTO sal_emp VALUES ('Carol', ARRAY[20000, 25000, 25000, 25000], ARRAY[['breakfast', 'consulting'], ['meeting', 'lunch']]); 注意数组元素是普通 SQL 常数或表达式,例如,字符串文字使用单引号而不是双引号包围,因为双引号可以出 现在一个数组文字中。 3.1.3.6.3 访问数组 现在,我们可以在该表上运行一些查询。首先,我们展示如何访问一个数组中的一个元素。下面的查询检索在第 二季度工资发生变化的雇员的名字: SELECT name FROM sal_emp WHERE pay_by_quarter[1] <> pay_by_quarter[2]; name ------Carol (1 row) 数组下标写在方括号内。默认情况下,KingbaseES 为数组使用了一种从 1 开始的编号习惯,即一个具有 “n“个 元素的数组从 array[1] 开始,结束于 array[n]。 下面的查询检索所有员工第三季度的工资: SELECT pay_by_quarter[3] FROM sal_emp; pay_by_quarter 94 第3章 KINGBASEES SQL 基本元素 ---------------10000 25000 (2 rows) 我们也可以访问一个数组的任意矩形切片或者子数组。一个数组切片可以通过在一个或多个数组维度上指定 “下 界: 上界 “来定义,例如,下面的查询检索 Bill 在本周头两天日程中的第一项: SELECT schedule[1:2][1:1] FROM sal_emp WHERE name = 'Bill'; schedule -----------------------{{meeting},{training}} (1 row) 如果任何维度被写成一个切片,即包含一个冒号,那么所有的维度都被看成是切片对待。其中任何只有一个数字 (无冒号)的维度被视作是从 1 到指定的数字。例如,下面例子中的 [2] 被认为是 [1:2]: SELECT schedule[1:2][2] FROM sal_emp WHERE name = 'Bill'; schedule ------------------------------------------{{meeting,lunch},{training,presentation}} (1 row) 为了避免和非切片情况搞混,最好在所有的维度上都使用切片语法,例如 [1:2][1:1] 而不是 [2][1:1]。 可以省略切片说明符的 “lower-bound“或者 “upper-bound“(如果存在上边界,则不可省略下边界),缺失的边 界会被数组下标的上下限所替代。例如: SELECT schedule[:][1:1] FROM sal_emp WHERE name = 'Bill'; schedule -----------------------{{meeting},{training}} (1 row) 如果数组本身为空或者任何一个下标表达式为空,访问数组下标表达式将会返回空值。如果下标超过了数组边 界,下标表达式也会返回空值(这种情况不会抛出错误)。例如,如果 schedule 目前具有的维度是 [1:3][1:2], 那么引用 schedule[3][3] 将得到 NULL。相似地,使用错误的下标号引用一个数组会得到空值而不是错误。 如果数组本身或者任何一个下标表达式为空,则一个数组切片表达式也会得到空值。但是,在其他情况例如选择 一个完全位于当前数组边界之外的切片时,一个切片表达式会得到一个空(零维)数组而不是空值(由于历史原因, 这并不符合非切片行为)。如果所请求的切片和数组边界重叠,那么它会被缩减为重叠的区域而不是返回空。 任何数组值的当前维度可以使用 array_dims 函数获得: 95 第3章 KINGBASEES SQL 基本元素 SELECT array_dims(schedule) FROM sal_emp WHERE name = 'Carol'; array_dims -----------[1:2][1:2] (1 row) array_dims 产生一个 text 结果,它便于人类阅读但是不便于程序读取。Dimensions can also be retrieved with 也可以通过 array_upper 和 array_lower 来获得维度,它们将分别返回一个指定数组的上界和下界: SELECT array_upper(schedule, 1) FROM sal_emp WHERE name = 'Carol'; array_upper ------------2 (1 row) array_length 将返回一个指定数组维度的长度: SELECT array_length(schedule, 1) FROM sal_emp WHERE name = 'Carol'; array_length -------------2 (1 row) cardinality 返回一个数组中在所有维度上的元素总数。这实际上是调用 unnest 将会得到的行数: SELECT cardinality(schedule) FROM sal_emp WHERE name = 'Carol'; cardinality ------------4 (1 row) 3.1.3.6.4 修改数组 一个数组值可以被整个替换: UPDATE sal_emp SET pay_by_quarter = '{25000,25000,27000,27000}' WHERE name = 'Carol'; 或者使用 ARRAY 表达式 ** 语法:** 96 第3章 KINGBASEES SQL 基本元素 UPDATE sal_emp SET pay_by_quarter = ARRAY[25000,25000,27000,27000] WHERE name = 'Carol'; 一个数组也可以在一个元素上被更新: UPDATE sal_emp SET pay_by_quarter[4] = 15000 WHERE name = 'Bill'; 或者在一个切片上被更新: UPDATE sal_emp SET pay_by_quarter[1:2] = '{27000,27000}' WHERE name = 'Carol'; 也可以使用省略 “lower-bound“或者 “upper-bound“的切片语法,但是只能用于更新一个不是 NULL 或者零维的 数组值(否则无法替换现有的下标界线)。 可以通过赋值一个不存在的元素来扩大一个已有存储值的数组。任何位于之前已存在的元素和新元素之间的位 置都将被空值填充。例如,如果数组 myarray 目前有 4 个元素,在对 myarray[6] 赋值后它将有 6 个元素,其中 myarray[5] 为空值。目前,采用这种方式扩大数组只允许使用在一维数组上。 带下标的赋值方式允许创建下标不是从 1 开始的数组。例如,我们可以为 myarray[-2:7] 赋值来创建一个下标 值从-2 到 7 的数组。 新的数组值也可以通过串接操作符 || 构建: SELECT ARRAY[1,2] || ARRAY[3,4]; ?column? ----------{1,2,3,4} (1 row) SELECT ARRAY[5,6] || ARRAY[[1,2],[3,4]]; ?column? --------------------{{5,6},{1,2},{3,4}} (1 row) 串接操作符允许把一个单独的元素加入到一个一维数组的开头或末尾。它也能接受两个 “N“维数组,或者一个 “N“维数组和一个 “N+1“维数组。 当一个单独的元素被加入到一个一维数组的开头或末尾时,其结果是一个和数组操作数具有相同下界下标的新数 组。例如: SELECT array_dims(1 || '[0:1]={2,3}'::int[]); array_dims -----------[0:2] 97 第3章 KINGBASEES SQL 基本元素 (1 row) SELECT array_dims(ARRAY[1,2] || 3); array_dims -----------[1:3] (1 row) 当两个具有相同维度数的数组被串接时,其结果保留左操作数的外维度的下界下标。结果将是一个数组,它由左 操作数的每一个元素以及紧接着的右操作数的每一个元素。例如: SELECT array_dims(ARRAY[1,2] || ARRAY[3,4,5]); array_dims -----------[1:5] (1 row) SELECT array_dims(ARRAY[[1,2],[3,4]] || ARRAY[[5,6],[7,8],[9,0]]); array_dims -----------[1:5][1:2] (1 row) 当一个 “N“维数组被放在另一个 “N+1“维数组的前面或者后面时,结果和上面的例子相似。每一个 “N“维子数组 实际上是 “N+1“维数组外维度的一个元素。例如: SELECT array_dims(ARRAY[1,2] || ARRAY[[3,4],[5,6]]); array_dims -----------[1:3][1:2] (1 row) 一个数组也可以通过使用函数 array_prepend、array_append 或 array_cat 构建。前两个函数仅支持一维数 组,但 array_cat 支持多维数组。一些例子: SELECT array_prepend(1, ARRAY[2,3]); array_prepend --------------{1,2,3} (1 row) SELECT array_append(ARRAY[1,2], 3); array_append -------------{1,2,3} 98 第3章 KINGBASEES SQL 基本元素 (1 row) SELECT array_cat(ARRAY[1,2], ARRAY[3,4]); array_cat ----------{1,2,3,4} (1 row) SELECT array_cat(ARRAY[[1,2],[3,4]], ARRAY[5,6]); array_cat --------------------{{1,2},{3,4},{5,6}} (1 row) SELECT array_cat(ARRAY[5,6], ARRAY[[1,2],[3,4]]); array_cat --------------------{{5,6},{1,2},{3,4}} 在简单的情况中,上面讨论的串接操作符比直接使用这些函数更好。不过,由于串接操作符需要服务于所有三种 情况,所以它的负担比较重,在有些情况下使用这些函数之一有助于避免混淆。例如: SELECT ARRAY[1, 2] || '{3, 4}'; -- 没有指定类型的文字被当做一个数组 ?column? ----------{1,2,3,4} SELECT ARRAY[1, 2] || '7'; ERROR: -- 这个也是 malformed array literal: "7" SELECT ARRAY[1, 2] || NULL; -- 未修饰的 NULL 也是如此 ?column? ---------{1,2} (1 row) SELECT array_append(ARRAY[1, 2], NULL); -- 这可能才是想要的意思 array_append -------------{1,2,NULL} 在上面的例子中,解析器看到在串接操作符的一遍看到了一个整数数组,并且在另一边看到了一个未确定类型的 常量。它用来决定该常量类型的启发式规则是假定它和该操作符的另一个输入具有相同的类型—在这种情况中是整数 数组。因此串接操作符表示 array_cat 而不是 array_append。如果这样做是错误的选择,它可以通过将该常量造型 成数组的元素类型来修复。但是显式地使用 array_append 可能是一种最好的方案。 99 第3章 KINGBASEES SQL 基本元素 3.1.3.6.5 在数组中搜索 要在一个数组中搜索一个值,每一个值都必须被检查。这可以手动完成,但是我们必须知道数组的尺寸。例如: SELECT * FROM sal_emp WHERE pay_by_quarter[1] = 10000 OR pay_by_quarter[2] = 10000 OR pay_by_quarter[3] = 10000 OR pay_by_quarter[4] = 10000; 但是这对于大型数组来说太过冗长,且在数组尺寸未知时无法使用。上面的查询可以被替换为: SELECT * FROM sal_emp WHERE 10000 = ANY (pay_by_quarter); 此外,我们还可以查找所有元素值都为 10000 的数组所在的行: SELECT * FROM sal_emp WHERE 10000 = ALL (pay_by_quarter); 另外,generate_subscripts 函数也可以用来完成类似的查找。例如: SELECT * FROM (SELECT pay_by_quarter, generate_subscripts(pay_by_quarter, 1) AS s FROM sal_emp) AS foo WHERE pay_by_quarter[s] = 10000; 我们也可以使用 && 操作符来搜索一个数组,它会检查左操作数是否与右操作数重叠。例如: SELECT * FROM sal_emp WHERE pay_by_quarter && ARRAY[10000]; 你也可以使用 array_position 和 array_positions 在一个数组中搜索特定值。前者返回值在数组中第一次出 现的位置的下标。后者返回一个数组,其中有该值在数组中的所有出现位置的下标。例如: SELECT array_position(ARRAY['sun','mon','tue','wed','thu','fri','sat'], 'mon'); array_positions ----------------2 SELECT array_positions(ARRAY[1, 4, 3, 1, 3, 4, 2, 1], 1); array_positions ----------------{1,4,8} 提示: 数组不是集合,在其中搜索指定数组元素可能是数据设计失误的表现。考虑使用一个独立的表来替代,其中每 一行都对应于一个数组元素。这将更有利于搜索,并且对于大量元素的可扩展性更好。 100 第3章 KINGBASEES SQL 基本元素 3.1.3.6.6 数组输入和输出语法 一个数组值的外部文本表现由根据数组元素类型的 I/O 转换规则解释的项构成,并在其上加上修饰用于指示数 组结构。修饰包括数组值周围的花括号({和})以及相邻项之间的定界字符。定界字符通常是一个逗号(,),但是 也可能是别的:它由数组元素类型的 typdelim 设置决定。在 KingbaseES 发行版提供的标准数据类型中,除了 box 类型使用分号(;)之外,其他都是用逗号。在一个多维数组中,每一个维度(行、平面、方体等)都有其自己的花 括号层次,且同层的被花括号限定的相邻实体之间也必须有定界符。 如果元素值是空字符串、包含花括号、包含定界字符、包含双引号、包含反斜线、包含空白或者匹配词 NULL, 数组输出例程将在元素值周围放上双引号。嵌在元素值中的双引号以及反斜线将被反斜线转义。对于数字数据类型可 以安全地假设双引号绝不会出现,但是对于文本数据类型我们必须准备好处理可能出现亦可能不出现的引号。 默认情况下,一个数组的一个维度的下界索引值被设置为 1。要表示具有其他下界的数组,数组下标的范围应在 填充数组内容之前被显式地指定好。这种修饰包括在每个数组维度上下界周围的方括号([]),以及上下界之间的一 个冒号(:)定界符。数组维度修饰后面要跟一个等号(=)。例如: SELECT f1[1][-2][3] AS e1, f1[1][-1][5] AS e2 FROM (SELECT '[1:1][-2:-1][3:5]={{{1,2,3},{4,5,6}}}'::int[] AS f1) AS ss; e1 | e2 ----+---1 | 6 (1 row) 只有当数组的维度中有一个或多个的下界不为 1 时,数组输出例程才会在结果中包括维度。 如果为一个元素给定的值是 NULL(或者是任何变体),该元素将被设置为 NULL。任何引号或反斜线的存在将 阻止这种行为,而允许为元素值输入“NULL”的字面意思。为了向后兼容 KingbaseES V9 之前的版本,可将 array_nulls 配置参数设置为 off 来阻止将 NULL 识别为 NULL。 如前所示,在写一个数组值时我们可以在任何单独数组元素周围使用引号。如果元素值可能混淆数组值分析器 时,我们必须这样做。例如,包含花括号、逗号(或者数据类型的定界符)、双引号、反斜线或首尾有空白的元素必 须使用双引号。空字符串和匹配单词 NULL 的字符串也必须使用双引号。要把一个双引号或反斜线放在一个使用了双 引号的数组元素值中,需要在它前面放一个反斜线。作为一种选择,我们可以免去使用引号而使用反斜线转义的方式 来保护可能被认为是数组语法的所有数据字符。 我们可以在左括号前面或右括号后面增加空白。我们也可以在任何单独的项之前或之后加上空白。在所有这些情 况中空白将被忽略。但是,在被使用了双引号的元素中的空白以及周围有其他非空白字符的空白不会被忽略。 提示: 在 SQL 命令中写数组值时,ARRAY 构造器语法常常比数组文字语法要更容易使用。在 ARRAY 中,单独的元素 值可以使用不属于数组成员时的方式来书写。 101 第3章 KINGBASEES SQL 基本元素 3.1.4 Rowid 数据类型 3.1.4.1 ROWID 数据类型 KES 的 ROWS 在数据库中存在逻辑上的唯一标识(并非物理地址)通过 ROWID 类型的数据进行表示, ROWID 一般的表示方法通过 64 进制的字符进行表示,总长度为 23 个字符(仅显示的字符数,并非实际存储数), 但实际上的存储采用了一种变长的方式进行,其实际存储在 4 ~ 18 个字节。 ROWID type 类型的数据是通过内部的复合结构在数据库存储,也通过不同的成员标识不同信息。 ROWID type 的输入、输出都以 64 位编码格式,包含 A-Z,a-z,0-9,+ 以及/符号。 ROWID 的范围如下: 存储 事务的回卷次数 [0 ~ 5] 元组插入时的 xid [6 ~ 11] 事务内已插入元组的个数 [12 ~ 22] 编码格式 32 位 32 位 64 位 Min AAAAAA AAAAAB AAAAAAAAAAA Max D////// D////// P////////// 超出以上范围的 ROWID 都属于非法格式的 ROWID。 注:每次开启一个新的事务(包含子事务),事务内已插入元组的个数都重新计算。 支持数据比较操作符 ROWID 仅支持 =,>, >=,<, <=, != 以及同类型的比较操作符。可通过 where 条件,表达式比较操作符可以 指定 rowid 类型,并且具有实际的逻辑意义。 • =: rowid 上各个位置信息严格相等。 • !=: rowid 上各个列位置信息严格不相等。 • >= (类): 先比较高位的事务回卷次数,在通过事务 xid 进行逻辑大小比较,最后比较事务内插入的次数。 原则上,后插入的数据的 rowid 要大于先插入的 rowid,即 rowid 属于单调递增的数据。 3.1.4.2 UROWID 数据类型 UROWID 支持可变长度定义,可以通过 UROWID(XX) 的方式指定 UROWID 的精度。 具体使用可参考字符数据类型 中的 VARCHAR 类型。 3.2 数据类型比较规则 本节介绍 KingbaseES 每种数据类型的值如何进行比较的。 102 第3章 3.2.1 KINGBASEES SQL 基本元素 数值 较大值比较小值大,负数小于零及所有正数。即-1 小于 100;-100 小于-1。浮点值 NaN(非数值)比任何其他数 值大,和自身相比是相等的。 了解更多比较信息,请参见FLOAT 类型 。 3.2.2 日期值 较后的日期比较早日期大。例如,日期值‘29-MAR-2005’比日期值‘05-JAN-2006’值小,日期时间值‘05JAN-2006 1:35pm’比日期时间值‘05-JAN-2005 10:09am’大。 3.2.3 字符值 根据如下方式比较字符值: • 二进制或语言排序规则 3.2.3.1 二进制和语言排序规则 在默认的二进制排序规则中,KingbaseES 会像二进制值一样比较字符值。字符值在字符集中的编码字节被当作 二进制值,因此两个字符的比较按照两个字符的二进制值进行比较,比较结果就是源字符值的二进制比较结果。 语言排序规则的限制 比较条件、ORDER BY、GROU PBY 和查询子句以及 COUNT(DISTINCT) 和统计聚合函数、LIKE 条件和 PARTITION BY 分析子句在使用语言排序规则时会生成排序规则键。排序规则键与 NLSSORT 函数返回的值相同, 并且受 NLSSORT 限制的约束。 3.2.4 数据转换 通常,表达式不能包含不同数据类型的值。例如,表达式不能将 5 乘以 10,然后加上“JAMES”。但是,KingbaseES 支持将值从一种数据类型隐式和显式转换为另一种数据类型。 3.2.4.1 隐式和显式数据转换 KingbaseES 推荐使用显式转换,而不是依赖隐式转换或自动转换,原因如下: • 使用显式数据类型转换函数时,SQL 语句更易于理解。 • 隐式数据类型转换可能会对性能产生负面影响,尤其是当列值的数据类型转换为常量的数据类型而不是相反 时。 103 第3章 KINGBASEES SQL 基本元素 • 如果隐式数据类型转换发生在索引表达式中,数据库可能不使用索引,因为它是为转换前数据类型定义的。这 可能会对性能产生负面影响。 3.3 类型转换表 下表是数据类型的转换表, 表中所列数据类型转换方式为横向转换为纵向。例:char 转换为 text 为隐式转换, text 转 char 为赋值转换 表 3.3.1: 数据类型的转换表 char bpc bpc var har char var har char char byte byte a a text int2 int4 int8 num floa floa time time date time time by eric t4 t8 tz sta sta mp mptz i e e e e e e e e e e e raw tea bpchar a i i i i i i i i i i i e e i i i a bpchar a a i i i i i i i i i i e e i i i varchar a a a i i i i i i i i i e e i i i a varchar a a a a i i i i i i i i e e i i i a text a i i i i i i i i i i e e i i i a int2 a a a a a i i i i i i int4 e a a a a i a i i i i int8 a a a a a i a a i i i numeric a a a a a i a a a i i i float4 a a a a a i a a a a float8 a a a a a i a a a a time a a a a a a i i timetz a a a a a a a i date a a a a a a timestamp a a a a a i i i i byte byte i a a 见续表 104 第3章 KINGBASEES SQL 基本元素 表 3.3.1 – 续表 char bpc bpc var har time- var har char char byte byte text int2 int4 int8 num floa floa time time date time time by eric t4 t8 tz a a a a a i a interval a a a a a a a bit a a a a a a varbit a a a a a a bytea a a a a a a bool a a a a a a a a a a a sta sta mp mptz a i raw tea stamptz raw 3.3.1 e e a e i 显示数据转换 通过 SQL 转换函数,可以显示指定数据类型转换。具体细节请参见函数。 3.4 常量 常量指的是固定的数据值。例如,’杰克’,’abc’和’101’都是字符常量;5001 是数字常量。字符常量用单 引号引起来,将它们与对象名区分开来。 本节包含以下主题: • 字符串常量 • 位串常量 • 数字常量 • 其他类型的常量 3.4.1 字符串常量 在 SQL 中,一个字符串常量是一个由单引号(')包围的任意字符序列,例如'This is a string'。为了在 一个字符串中包括一个单引号,可以写两个相连的单引号,例如'Dianne''s horse'。注意这和一个双引号(")不 同。 105 第3章 KINGBASEES SQL 基本元素 两个只由空白及至少一个新行分隔的字符串常量会被连接在一起,并且将作为一个写在一起的字符串常量来对 待。例如: SELECT 'foo' 'bar'; 等同于: SELECT 'foobar'; 但是: SELECT 'foo' 'bar'; 不是合法的语法(此行为由 SQL 指定,KingbaseES 遵循了该标准)。 3.4.1.1 带有 C 型转义的字符串常量 KingbaseES 也接受“转义”字符串常量,这是对 SQL 标准的扩展。转义字符串常量是通过在开始的单引号之前 写入字母 E(大写或小写)来指定的,例如 E'foo'。(当一个转义字符串常量跨行时,E 只写在第一个开始的引号之 前。)在转义字符串中,反斜线字符(\)会开始一个类似 C 型的反斜线转义序列,其中反斜线和后续字符的组合表 示一个特殊的字节值,如 表 3.4.1 。 表 3.4.1: 反斜线转义序列 反斜线转义序列 解释 \b 退格 \f 换页 \n 换行 \r 回车 \t 制表符 \o, \oo, \ooo (o = 0 - 7) 八进制字节值 \xh, \xhh (h = 0 - 9, A - F) 十六进制字节值 \uxxxx, \Uxxxxxxxx (x = 0 - 9, A - F) 16 或 32 位十六进制 Unicode 字符值 反斜线后面的任何其他字符都按照其字面意思理解。因此,要书写反斜线字符本身,请写两个反斜线(\\)。除 了正常的方式,要书写单引号时也可以在单引号前加上转义字符串,写成\'。 确保创建的字节序列,特别是在使用八进制或十六进制转义时,构成服务器字符集编码的有效字符。当服务器编 106 第3章 KINGBASEES SQL 基本元素 码为 UTF-8 时,应该使用 Unicode 转义或替代的 Unicode 转义语法(见带有 Unicode 转义的字符串常量 )。另一 种方案是手工进行 UTF-8 编码并写出字节。 只有当服务器编码是 UTF8 时,Unicode 转义语法才能完全发挥作用。当使用其他服务器编码时,只能指定 ASCII 范围(低于\u007F)内的代码点。4 位数和 8 位数形式都可以用来指定 UTF-16 代理对,用来组成代码点超过 U+FFFF 的字符,尽管 8 位数形式的可用性从技术上使得这种做法不再是必须的。(当服务器编码为 UTF8 并使用 代理对时,它们首先被组合成一个单一的代码点,然后被编码为 UTF-8)。 警告: 如果配置参数 standard_conforming_strings 为 off,那么 KingbaseES 在常规字符串常量和转义字 符串常量中都能识别反斜线转义。然而,从 KingbaseES V8R2 开始,该参数的默认值为 on,意味着反斜线转义 只能在转义字符串常量中被识别。这种行为更符合标准,但是可能会破坏那些依赖历史行为的应用,因为在历史 上反斜线转义总是会被识别。作为一种变通方法,你可以设置该参数为 off,但还是不建议使用反斜线转义。如 果你需要使用一个反斜线转义来表示一个特殊字符,请用 E 来写字符串常量。 在 standard_conforming_strings 之外,配置参数 escape_string_warning 和 backslash_quote 也控制字 符串常量中反斜线的处理方式。 代码为零的字符不能出现在一个字符串常量中。 3.4.1.2 带有 Unicode 转义的字符串常量 KingbaseES 也支持另一种类型的字符串转义语法,它允许用代码点指定任意 Unicode 字符。一个 Unicode 转 义字符串常量开始于 U&(大写或小写形式的字母 U,后跟花号),后面紧跟着开引号,之间没有任何空白,例如 U&'foo'(注意这产生了与操作符 & 的混淆。在操作符周围使用空白来避免这个问题)。在引号内,Unicode 字符可 以通过写一个后跟 4 位十六进制代码点编号或者一个前面有加号的 6 位十六进制代码点编号的反斜线来指定。例如, 字符串'data'可以被写为 U&'d\0061t\+000061' 下面的例子用斯拉夫字母写出了俄语的单词“slon”(大象): U&'\0441\043B\043E\043D' 如果想要一个不是反斜线的转义字符,可以在字符串之后使用 UESCAPE 子句来指定,例如: U&'d!0061t!+000061' UESCAPE '!' 转义字符可以是出一个十六进制位、加号、单引号、双引号或空白字符之外的任何单一字符。 只有当服务器编码是 UTF8 时,Unicode 转义语法才能完全工作。当使用其他服务器编码时,只有在 ASCII 范 围(低于\u007F)内的代码点能够被指定。4 位和 8 位形式都能被用来指定 UTF-16 代理对,用来组成代码点超过 U+FFFF 的字符,不过 8 位形式的可用从技术上使得这种做法不再是必须的(当服务器编码为 UTF8 并使用代理对 时,它们首先被结合到一个单一代码点,然后会被用 UTF-8 编码)。 107 第3章 KINGBASEES SQL 基本元素 还有,只有当配置参数 standard_conforming_strings 被打开时,用于字符串常量的 Unicode 转义语法才能工 作。这是因为否则这种语法将迷惑客户端中肯地解析 SQL 语句,进而会导致 SQL 注入以及类似的安全性问题。如果 这个参数被设置为关闭,这种语法将被拒绝并且报告一个错误消息。 要在一个字符串中包括一个表示其字面意思的转义字符,把它写两次。 3.4.1.3 美元引用的字符串常量 虽然用于指定字符串常量的标准语法通常都很方便,但是当字符串中包含了很多单引号或反斜线时很难理解它, 因为每一个都需要被双写。要在这种情形下允许可读性更好的查询,KingbaseES 提供了另一种被称为“美元引用” 的方式来书写字符串常量。一个美元引用的字符串常量由一个美元符号($)、一个可选的零个或更多字符的“标 签”、另一个美元符号、一个构成字符串内容的任意字符序列、一个美元符号、开始这个美元引用的相同标签和一个 美元符号组成。例如,这里有两种不同的方法使用美元引用指定字符串“Dianne’s horse”: $$Dianne's horse$$ $SomeTag$Dianne's horse$SomeTag$ 注意在美元引用字符串中,单引号可以在不被转义的情况下使用。事实上,在一个美元引用字符串中不需要对字 符进行转义:字符串内容总是按其字面意思写出。反斜线不是特殊的,并且美元符号也不是特殊的,除非它们是匹配 开标签的一个序列的一部分。 可以通过在每一个嵌套级别上选择不同的标签来嵌套美元引用字符串常量。这最常被用在编写函数定义上。例 如: $function$ BEGIN RETURN ($1 ~ $q$[\t\r\n\v\\]$q$); END; $function$ 这里,序列 $q$[\t\r\n\v\\]$q$ 表示一个美元引用的文字串 [\t\r\n\v\\],当该函数体被 KingbaseES 执行 时它将被识别。但是因为该序列不匹配外层的美元引用的定界符 $function$,它只是一些在外层字符串所关注的常 量中的字符而已。 一个美元引用字符串的标签(如果有)遵循一个未被引用标识符的相同规则,除了它不能包含一个美元符号之 外。标签是大小写敏感的,因此 $tag$String content$tag$ 是正确的,但是 $TAG$String content$tag$ 不正 确。 一个跟着一个关键词或标识符的美元引用字符串必须用空白与之分隔开,否则美元引用定界符可能会被作为前面 标识符的一部分。 美元引用不是 SQL 标准的一部分,但是在书写复杂字符串文字方面,它常常是一种比兼容标准的单引号语法更 方便的方法。当要表示的字符串常量位于其他常量中时它特别有用,这种情况常常在过程函数定义中出现。如果用单 引号语法,上一个例子中的每个反斜线将必须被写成四个反斜线,这在解析原始字符串常量时会被缩减到两个反斜 线,并且接着在函数执行期间重新解析内层字符串常量时变成一个。 108 第3章 3.4.2 KINGBASEES SQL 基本元素 位串常量 位 串 常 量 看 起 来 像 常 规 字 符 串 常 量 在 开 引 号 之 前 (中 间 无 空 白) 加 了 一 个 B(大 写 或 小 写 形 式), 例 如 B'1001'。位串常量中允许的字符只有 0 和 1。 作为一种选择,位串常量可以用十六进制记号法指定,使用一个前导 X(大写或小写形式), 例如 X'1FF'。这 种记号法等价于一个用四个二进制位取代每个十六进制位的位串常量。 两种形式的位串常量可以以常规字符串常量相同的方式跨行继续。美元引用不能被用在位串常量中。 3.4.3 数字常量 在这些一般形式中可以接受数字常量: digits digits.[digits][e[+-]digits] [digits].digits[e[+-]digits] digitse[+-]digits 其中 “digits“是一个或多个十进制数字(0 到 9)。如果使用了小数点,在小数点前面或后面必须至少有一个数 字。如果存在一个指数标记(e),在其后必须跟着至少一个数字。在该常量中不能嵌入任何空白或其他字符。注意 任何前导的加号或减号并不实际被考虑为常量的一部分,它是一个应用到该常量的操作符。 这些是合法数字常量的例子: | 42 | 3.5 | 4. | .001 | 5e2 | 1.925e-3 如果一个不包含小数点和指数的数字常量的值适合类型 integer(32 位),它首先被假定为类型 integer。否 则如果它的值适合类型 bigint(64 位),它被假定为类型 bigint。再否则它会被取做类型 numeric。包含小数点 和/或指数的常量总是首先被假定为类型 numeric。 一个数字常量初始指派的数据类型只是类型转换算法的一个开始点。在大部分情况中,常量将被根据上下文自动 被强制到最合适的类型。必要时,你可以通过造型它来强制一个数字值被解释为一种指定数据类型。例如,你可以这 样强制一个数字值被当做类型 real(float4): REAL '1.23' -- string style 1.23::REAL -- KingbaseES (historical) style 这些实际上只是接下来要讨论的一般造型记号的特例。 109 第3章 3.4.4 KINGBASEES SQL 基本元素 其他类型的常量 一种任意类型的一个常量可以使用下列记号中的任意一种输入: type 'string' 'string'::type CAST ( 'string' AS type ) 字符串常量的文本被传递到名为 “type“的类型的输入转换例程中。其结果是指定类型的一个常量。如果对该常 量的类型没有歧义(例如,当它被直接指派给一个表列时),显式类型造型可以被忽略,在那种情况下它会被自动强 制。 字符串常量可以使用常规 SQL 记号或美元引用书写。 也可以使用一个类似函数的语法来指定一个类型强制: typename ( 'string' ) 但是并非所有类型名都可以用在这种方法中。 ::、CAST() 以及函数调用语法也可以被用来指定任意表达式的运行时类型转换。要避免语法歧义,type 'string'语法只能被用来指定简单文字常量的类型。type 'string'语法上的另一个限制是它无法对数组类型工作, 指定一个数组常量的类型可使用:: 或 CAST()。 CAST() 语法符合 SQL。type 'string'语法是该标准的一般化:SQL 指定这种语法只用于一些数据类型,但是 KingbaseES 允许它用于所有类型。带有:: 的语法是 KingbaseES 的历史用法,就像函数调用语法一样。 3.5 格式模型 格式模型是一种字符常量,它描述了存储在字符串中的日期时间或数值的格式。格式模型不会更改数据库中值的 内部表示。将字符串转换为日期或数字时,格式模型确定 KingbaseES 数据库如何解释字符串。 在 SQL 语句中,可以通过”TO_CHAR” 和”TO_DATE” 函数的参数来指定格式模型: • 指定从数据库返回值的格式 • 指定存储在数据库中的值的格式 例如: 字符串’17:45:29’ 的日期时间格式模型是’HH24:MI:SS’。 字符串’11-Nov-1999’ 的日期时间格式模型是’DD-Mon-YYYY’。 字符串’$2,304.25’ 的数字格式模型是’$9,999.99’。 有关数字和日期时间格式模型元素的列表,请参见 日期时间类型和数据类型格式化函数 。 某些格式的值由初始化参数的值决定。对于此类格式,可以使用初始化参数 NLS_TERRITORY 隐式指定这些 格式元素返回的字符。 110 第3章 KINGBASEES SQL 基本元素 ALTER SESSION 语句可以更改会话的默认日期格式。 3.6 空值 如果某列中没有值,则该列值称为 null,即空值。任何数据类型的列都可以输入 Null 值,除非该列被限定为 not null 或者是主键约束。当实际列值未知或者无意义可以输入 null 值。 KingbaseES 数据库将长度为 0 的字符值表示为 null。但是,不要用 null 表示数值 0,这两者不等。 任何包含 null 值的算术表达式结果为 null。例如:null 加 10 结果为 null。 3.6.1 SQL 函数中的空值 SQL 函数中对 NULL 的处理,请参见SQL 函数中的空值 。 3.6.2 比较条件中的空值 通过条件比较 IS NULL 或者 IS NOT NULL 验证值是否为空值。如果使用了其他条件来对空值进行比较,该条 件结果也依赖该空值进行判断,则该条件结果为 unknown。应为空值表示缺乏数据,空值不能与其他值或者其他空 值进行等值或者不等值比较。KingbaseES 支持 DECODE 函数判断两个空值是否相等,请参考 DECODE 函数了解 具体语法。 3.6.3 条件中的空值 条件中把 unknown 判断为 flase。例如,带有条件的查询语句,where 子句条件结果为 unknown,则该查询语句 不返回任何结果。但是,unknown 与 false 也不同,not false 判断为真,但是 not unknown 判断为 unknown。 3.7 注释 一段注释是以双斜线开始并且延伸到行结尾的一个字符序列,例如: -- This is a standard SQL comment 另外,也可以使用 C 风格注释块: /* multiline comment * with nesting: */ 111 第3章 KINGBASEES SQL 基本元素 这里该注释开始于。这些注释块可按照 SQL 标准中指定的方式嵌套,但和 C 中不 同。这样我们可以注释掉一大段可能包含注释块的代码。 在进一步的语法分析前,注释会被从输入流中移除并且实际被替换为空白。 3.8 数据库对象 3.8.1 Schema 对象 Schema 是数据的逻辑结构和 Schema 对象的集合。Schema 对象是指在某个 Schema 中的数据库对象。KingbaseES Schema 是指一个用户所拥有的数据库对象的集合,用于权限管理和命名空间隔离。 一个模式本质上是一个名字空间:它包含命令对象(表、数据类型、函数以及操作符),对象可以与在其他模式 中存在的对象重名。可以通过用模式名作为一个前缀” 限定” 命名对象的名称来访问它们, 或者通过把要求的模式包括在搜索路径中来访问命名对象。 用户还可以访问和使用其他的 Schema。在访问一个 Schema 中的对象时,如果没有指明该对象属于哪一个 Schema,系统就会自动给对象加上缺省的 Schema 名称。 Schema 对象一般包括: • 表(Tables) • 视图(Views) • 索引(Indexes) • 约束(constraints) • 分区(Partitions) • 序列(Sequences) • 数据库链接(Database links) • 物化视图(Materialized views) • 类型(Types) • 操作符(Operators) • 同义词(Synonyms) • 触发器(Triggers) • 函数(Functions) • 存储过程(Procedures) • 包(Packages) 112 第3章 KINGBASEES SQL 基本元素 3.8.2 Nonschema 对象 其他类型的对象也存储在数据库中,可以通过 SQL 创建和操作,但不包含在模式中: • 上下文(Contexts) • 目录(Directories) • 表空间(Tablespaces) • 角色(Roles) • 用户(Users) 3.9 数据库对象名称和限定符 部分数据库对象名由用户命名,例如表或视图中的列、索引、表分区、子分区、约束以及存储在包中的对象,包 括过程和存储函数等。 • 命名数据库对象和数据库对象位置限定符的规则 • 命名数据库对象和限定符的准则 3.9.1 数据库对象命名规则 每个数据库对象都有名称。在 SQL 语句中,用带引号的标识符或不带引号的标识符来表示对象的名称。 • 带引号的标识符以双引号 (”) 开头和结尾。如使用带引号的标识符命名模式对象,则在引用该对象时必须使用 双引号。 • 不带引号的标识符两边没有任何标点符号限定。 • 支持带反引号的标识符形式,其规则与双引号一样。同时在 oracle 模式下需通过设置参数 enable_backquote 来 控制反引号的使用。此参数默认为 off,在 mysql 模式下无效。 使用带引号或不带引号的标识符来命名任何数据库对象。但是,数据库名称、数据库链接名称始终不区分大小 写并以大写形式存储。如果将此类名称指定为带引号的标识符,则引号将被静默忽略。有关用户的命名方式,请参 见CREATE USER 。 如下规则同时适用于带引号和不带引号的标识符: 1. 标识符名称的最大长度 2. 不带引号的标识符不能是 KingbaseES SQL 保留字。带引号的标识符可以是保留字,但不建议这样做。 参见”SQL 保留字” 章节查看SQL 保留字和关键字 。 3. SQL 语言包含其他具有特殊含义的词 113 第3章 KINGBASEES SQL 基本元素 这些词包括数据类型、模式名、函数名、虚拟系统表 DUAL 和关键字,这些词不是保留的,但是数据库以指定 方式在内部使用它们。 如果使用这些词作为对象和对象部分的名称,那么 SQL 语句可能导致不可预知的结果。因此,不建议将这些词 用作对象名称。特别是,不要使用以 SYS_ 或 ORA_ 作为开头的模式对象名称,也不要使用 SQL 内置函数的 名称作为模式对象或用户定义函数的名称。 4. ASCII 字符做标识符 在数据库名称和数据库链接名称中可以使用 ASCII 字符,ASCII 字符可提供跨不同平台和操作系统的最佳兼容 性。 5. 密码中的字符 密码中可以包含多字节字符,例如汉字或中文标点等。 6. 标识符的可用字符字符 未加引号的标识符必须以数据库字符集中的字母开头。带引号的标识符可以以任何字符开头。 未加引号的标识符只能包含数据库字符集中的字母数字以及下划线 (_)、美元符号 ($) 和井号 (#)。数据库链接 还可以包含句点 (.) 和 @ 符号。建议用户不要在不带引号的标识符中使用 $ 和 #。 带引号的标识符可以包含任何字符、标点符号以及空格。但是,带引号或不带引号的标识符都不能包含双引号 或空字符 (0)。 7. 命名空间限制 在同一命名空间内,任意两个对象的名称都不能相同。例如,由于表和序列位于同一个命名空间中,因此同一 Schema 中的表和序列不能具有相同的名称。 而表和索引位于不同的命名空间中,所以同一 Schema 中的表和索引可以具有相同的名称。数据库中的每个 Schema 对于它所包含的对象都有自己的命名空间。 这意味着,如果不同 Schema 中的两个表位于不同的命名空间中是可以具有相同名称的。 8. 列的名称 同一表或视图中的列不能具有相同的名称。但是,不同表或视图中的列可以具有相同的名称。 9. 过程和函数的名称 对于包含在同一包中的过程或函数,如果它们的参数的数量和数据类型不同,则可以具有相同的名称。在同一 个包中使用不同的参数创建多个同名的过程或函数被称为重载过程或函数。 模式对象命名示例: last_name horse hr.hire_date "EVEN THIS & THAT!" 114 第3章 KINGBASEES SQL 基本元素 a_very_long_and_valid_name 如下规则适用于带反引号的标识符: 1. 保留关键字作别名标识符时可以不加引号,作其他标识符时必须加引号。 2. 可作为类型函数名的关键字作别名、函数、类型名时可以不加引号,作其他标识符时必须加引号。 3. 可作为列名的关键字作函数、类型名时必须加引号,作其他标识符时可加可不加。 4. 非保留关键字和普通字符作标识符时可加可不加。 5. 对于字符串、时间日期等字段值是不支持使用的。 6. 带反引号的标识符可以以任何字符开头。包含任何字符、标点符号、双引号以及空格,不能包含单个反引号或 空字符。 7. 标识符对大小写不敏感,输入全大写或全小写时,访问或者显示都是全小写;输入大小写混合时,访问或者显 示与输入一致。 8. dump 备份后,标识符两端的反引号会在词法解析后被丢弃,并在备份时自动为其加上双引号。如果标识符内 部带有双引号,则该双引号会被另一个双引号 (”) 转义;还原后其表示形式与输入时一致,标识符两端的反引 号会被丢弃。 9. 如果标识符本身也包括反引号,可以通过双写反引号进行转义,但不能通过转义符()进行转义。而且标识符 内部不能出现奇数个反引号,但是即使是偶数个反引号也不允许其单独出现。 10. 在使用 d[S+] name 等转义命令查询表、视图等对象信息时,name 两端可用双引号但不可用反引号,因为在该 命令中带反引号的部分被认为是一个 shell 命令。 示例: select 1 as `id`; create table t(`a` int); create index `t_idx` on t(a); create table `select`(`insert` int); create table `a``b``c`(a int); select 1 as `123`; 3.9.2 模式对象命名规则 本节提供一些 Schema 对象的命名建议。KingbaseES 数据库的对象命名建议如下: 1. 使用完整的、描述性的、易拼写的名称或众所周知的缩写。 2. 使用一致的命名规则。 3. 使用相同的名称来描述跨表的同一实体或属性。 115 第3章 KINGBASEES SQL 基本元素 在命名对象时,如果无法平衡简单易用性和描述性,请选择更具描述性的名称,因为数据库中的对象可能会被使 用很长一段时间, 这样可以避免十年后的用户可能难以理解名称为 pmdd 的表的列是用来存储什么信息的,相比之下,payment_due_date 的名称却更清楚明了。 使用一致的命名规则可以帮助用户理解每个表在应用程序中扮演的角色。例如,以fin_ 为开头命名所有属于 FINANCE 应用程序的表的名称。 使用相同的名称描述表中的相同内容。例如,雇员表和部门表的具有相同的部门号,这一列其实存储的是一样的 值,那么在雇员表和部门表中这一列均被命名为 department_id 。 3.10 数据库对象引用方式 KingbaseES 数据库支持在 SQL 语句的上下文中引用 Schema 对象。KingbaseES 数据库当前版本支持如下引用 类型: • 引用 Schema 对象 • 引用分区表和索引 • 引用对象类型属性和方法 引用的一般语法如下: [ schema. ] object [ .part ] 其中: object 是指对象的名称。 schema 是包含对象的 Schema。此限定符允许用户在被授予权限后引用其他 Schema 的对象。如果省略,则默认 为用户默认 Schema 中的对象。 schema 只适用于 Schema 对象,例如表(Table)、视图(View)、索引(Index)、分区(Partition)、序列 (Sequence)、同义词(Synonyms)、触发器(Trigger)、自定义函数、存储过程、包和触发器等。 非 Schema 对象不能使用,例如用户(User)、角色(Role)、表空间(Tablespace)和目录(Directory)。但 公有同义词除外,它可以选择使用“PUBLIC ”进行限定,必须带有引号。 part 是对象的一部分。此标识符让用户可以引用 Schema 对象的一部分,例如表的列或分区。但并不适用于所有 类型的对象。 当在 SQL 语句中引用对象时,KingbaseES 数据库会考虑 SQL 语句的上下文并在命名空间中找到该对象,然后 执行对该对象的指定操作。如果在命名空间中找不到命名对象,则返回错误。 116 第3章 3.10.1 KINGBASEES SQL 基本元素 引用 Schema 对象 当在 SQL 语句中引用对象时,KingbaseES 数据库会考虑 SQL 语句的上下文并在命名空间中找到该对象,然后 执行对该对象的指定操作。如果在命名空间中找不到命名对象,则返回错误。 以下示例说明 KingbaseES 如何解析 SQL 语句中对象的引用。如下语句,将一行数据添加到 departments 表中: INSERT INTO departments VALUES (280, 'ENTERTAINMENT_CLERK', 206, 1700); 根据 SQL 语句的上下文,departments 在数据库中可能是如下情况: • 一张在默认 Schema 中的表 • 一个在默认 Schema 中的视图 • 一个表或视图的私有同义词 • 一个公有同义词 KingbaseES 数据库会先尝试在默认的 Schema 中的命名空间里解析被引用对象,然后再考虑该 Schema 之外的 命名空间。 在此示例中,KingbaseES 数据库的解析流程如下: 1. KingbaseES 数据库首先尝试在默认的 Schema 的名称空间里去定位对象。如果对象是私有同义词,则 KingbaseES 数据库会找到该同义词所代表的对象。 该对象可以在默认的 Schema 中,也可以在其他 Schema 中或者在另一个数据库中。该对象也可以是其他的同 义词,在这种情况下,KingbaseES 数据库会找到同义词所代表的对象。 2. 如果对象在命名空间中被找到,则 KingbaseES 数据库尝试执行该 SQL 语句。 在此示例中,KingbaseES 数据库尝试将一行数据添加到 departments 中。如果此对象的类型不是该 SQL 语句 所需要的类型,则 KingbaseES 数据库返回错误。 departments 必须是表、视图或者可以是可以解析为表或视图的私有同义词。如果 departments 是序列,则 KingbaseES 数据库返回错误。 3. 如果该对象到目前为止没有在任何名称空间中被搜索到,则 KingbaseES 数据库将搜索包含公有同义词的命名 空间。 如果对象在包含公有同义词的命名空间中,则 KingbaseES 数据库尝试执行 SQL 语句。如果此对象的类型不是 该 SQL 语句所需要的类型,则 KingbaseES 数据库返回错误。 在此示例中,如果 departments 是一个代表了序列的公有同义词,那么 KingbaseES 数据库将返回错误。 如果公有同义词包含任何依赖表或用户自定义类型,则不能在与依赖对象相同的 Schema 中创建与同义词同名 的对象。 反之,如果同义词没有任何依赖表或用户定义的类型,则可以在与依赖对象相同的 Schema 中创建具有相同名 称的对象。 KingbaseES 数据库会使所有依赖对象无效,并在下一次访问它们时进行重新验证。 117 第3章 3.10.2 KINGBASEES SQL 基本元素 引用其他 Schema 中的对象 如果要引用的对象属于其他 Schema,需要在对象名称前添加对应的 Schema 名称。 语法如下: schema.object 以下示例展示了在名称为 hr 的 Schema 中删除表 employees: DROP TABLE hr.employees; 3.10.3 对远程数据库中对象的引用 要引用本地数据库以外的数据库中的对象,请在对象名称后面加上指向该数据库的数据库链接。数据库链接 (database link)是一个模式对象,它能让 KingbaseES 连接到远程数据库以访问那里的对象。 示例: select * from departments@mydblink 具体 database link 创建,请参见CREATE DATABASE LINK 。 3.10.4 引用分区表和索引 表和索引可以分区。分区时,这些模式对象由许多称为 partitions 的部分组成,所有这些部分都具有相同的逻辑 属性。 例如,表中的所有分区共享相同的列和约束定义,索引中的所有分区共享相同的索引列。 分区扩展名和子分区扩展名允许用户仅在一个分区或子分区上执行一些分区级和子分区级操作,例如从一个分区 或子分区中删除所有行。 分区扩展名称让用户可以像使用表一样使用分区。 用户可以通过如下 SQL 语法指定分区扩展表名和子分区扩展表名。 • 分区扩展表名的语法如下:PARTITION partition • 子分区扩展表名的语法如下:SUBPARTITION subpartition DML 语句 INSERT、UPDATE、DELETE 和 ANALYZE 语句需要在分区或子分区名称的周围加上括号。 • 扩展名称的限制 使用分区扩展表名和子分区扩展表名时有以下限制: 名称中没有同义词。必须使用基表指定分区或子分区扩展名,不能使用同义词、视图或任何其他对象。 在 PARTITION 和 SUBPARTITION 子句中,不能为分区或子分区名称指定绑定变量。 118 第3章 KINGBASEES SQL 基本元素 示例: 分区表 sales 具有分区 sales_q1_2021 ,并为其创建视图,然后从分区中删除一些行。 /为分区 sales_q1_2000 创建视图 Q1_2021_sales/ CREATE VIEW Q1_2021_sales ASSELECT * FROM sales PARTITION (SALES_Q1_2021); /删除视图 Q1_2021_sales 中符合条件 amount_sold < 0 的值/ DELETE FROM Q1_2021_sales WHERE amount_sold < 0; 3.10.5 引用对象类型的属性和方法 在 SQL 语句中引用对象类型属性或方法,必须使用表别名完全限定引用。 如下 ** 示例:** 包含一个类型 cust_address_typ 和一个表 customers,其中的 cust_address 列类型是 cust_address_typ: CREATE TYPE cust_addr_typ AS OBJECT ( street_address VARCHAR2(40), postal_code VARCHAR2(10), city VARCHAR2(30), state_province VARCHAR2(10), country_id CHAR(2) ); CREATE TABLE customers ( customer_id NUMBER(6), cust_first_name VARCHAR2(20) CONSTRAINT cust_fname_nn NOT NULL, cust_last_name VARCHAR2(20) CONSTRAINT cust_lname_nn NOT NULL, cust_address cust_address_typ, . . . 在 SQL 语句中,对 postal_code 属性的引用必须使用表别名进行完全限定,如下所示: SELECT c.cust_address.postal_code FROM customers c; UPDATE customers c SET c.cust_address.postal_code = '610000' WHERE c.cust_address.city = 'chengdu' AND c.cust_address.state_province = 'SICHUAN'; 要引用不接受参数的成员方法,必须提供空括号。 119 第3章 KINGBASEES SQL 基本元素 例如,一个基于 catalog_typ 的对象表 category_tab,该表包含成员函数 getCatalogName。为了在 SQL 语句中 调用此方法,必须提供空括号。 如下所示: SELECT TREAT(VALUE(c) AS catalog_typ).getCatalogName() "Catalog Type" FROM categories_tab c WHERE category_ id = 10; 120 第 4 章 伪列 4 第 章 伪列 伪列的行为与普通的列十分相似,但伪列的值并非与表存储在一起。用户可以使用 SELECT 来选择伪列,但不 能对伪列进行任何的修改。伪列与不带参数的函数十分相似,但没有参数的函数其函数返回结果对于结果集中每条记 录一般都是固定不变的,而伪列对于同一记录集在不同查询条件下所返回的结果可能是不相等的。 4.1 ROWNUM 伪列 ROWNUM 伪列返回一个数值指示该条记录在 KingbaseES 从表取得或连接产生时的顺序。第一条被选择的记录 的 ROWNUM 值是 1,第二条的值是 2,以此类推。 可以使用 ROWNUM 来限制查询返回的记录数量: create table student(sno int, name varchar(10), birthday date, department varchar(10), sex varchar(10)); insert into student values(1, 'li', '2018-1-1', 'physics', 'boy'); insert into student values(5, 'lu', '2018-1-2', 'chinese', 'boy'); insert into student values(3, 'wang', '2018-1-3', 'english', 'girl'); insert into student values(4, 'zhang', '2018-1-4', 'history', 'boy'); insert into student values(2, 'jack', '2018-1-5', 'history', 'boy'); select name from student where rownum < 5; NAME ------li lu wang zhang (4 rows) 在查询语句中,如果使用 ORDER BY 进行排序,那么查询的结果将会被 ORDER BY 重新排列。最终的结果将 根据 KingbaseES 访问记录的顺序不同而改变。例如: 121 第 4 章 伪列 select name from student where rownum < 5 order by sno; NAME ------li wang zhang lu (4 rows) 如果将 ORDER BY 嵌入到子查询中,并将 ROWNUM 的条件放在上层查询中,就可以强制 ROWNUM 条件在 结果集被排序后被应用。例如下面的例子将会返回四个最小的学号。通常这也被称为 TOP-N 报表: select name from (select name from student order by sno) as foo where rownum < 5; NAME ------li jack wang zhang (4 rows) 在上面的例子中,ROWNUM 的值是属于上层 SELECT 语句的,也就是说它们是在子查询对学号进行排序后生 成的。 测试 ROWNUM 的值大于任何一个正数的返回结果都是 false。例如,下面的查询不会返回任何记录: select * from student where rownum > 1; SNO | NAME | BIRTHDAY | DEPARTMENT | SEX -----+------+----------+------------+----(0 rows) 第一条被取得的元组的 ROWNUM 被赋予 1,这将会导致上面的条件测试返回 false。第二条被取得的元组就成 为新的第一条元组,因此 ROWNUM 还将被赋予 1,条件测试的结果依然是 false。因此上面的查询语句没有任何结 果返回。 可以将 ROWNUM 作为唯一值赋予表中的所有元组: CREATE TABLE t_rownum(c INT); INSERT INTO t_rownum VALUES(0); INSERT INTO t_rownum VALUES(0); INSERT INTO t_rownum VALUES(0); 122 第 4 章 伪列 UPDATE t_rownum SET c = ROWNUM; SELECT * FROM t_rownum; C --1 2 3 ROWNUM 伪列是为了兼容 Oracle 数据库而添加的。 4.2 ROWID 伪列 ROWID 目前是 ORACLE 模式数据库下的行逻辑 ID,具有数据库实例级别的全局唯一性。使用时,需要注意以 下事项: 1. 支持在投影列中,使用 ROWID 伪列关键字,查询数据的当前行的逻辑 id。 2. 支持在过滤条件(WHERE)中使用 ROWID OP CONST(历史行版本)或者 CONST OP ROWID 的形 式,用于条件过滤查询当前行最新的行逻辑 id。可以与其它过滤条件组成使用。OP 只支持关系运算符,即 >,<,>=,<=,<> 等。 3. 支持在 ORDER BY 和 GROUP BY 中使用 ROWID。 4. 可以在存储过程中,使用 1,2,3 或者是 1,2,3 的组合形式。 5. 不支持 ROWID 与其它(2 中 OP)以外的运算符进行运算。 6. ROWID 支持 BTREE、HASH 索引。 4.3 层次查询伪列 层次查询提供一些伪列用于数据查询,详情可参考层次查询 。KingbaseES 目前支持的层次查询伪列如下表: 123 第 4 章 伪列 表 4.3.1: 层次查询的伪列列表 伪列 描述 LEVEL 伪列 描述当前元组的所在的层。 CONNECT_BY_ISLEAF 伪列 描述当前节点是否为叶节点。若是为 1,否则为 0。 CONNECT_BY_ISCYCLE 伪列 如果一个元组的 CONNECT_BY_ISCYCLE 值是 1,则代表这 个元组有子元组,并且这个子元组又是它的祖先元组,即数据 库中的数据成环;否则为 0。 4.4 闪回版本查询伪列 闪回版本查询拥有和 Oracle 相同的参考伪列,伪列和功能参考下表。详情可参考插件 kdb_flashback 。 表 4.4.1: 闪回版本查询的伪列 伪列名 描述 VERSIONS_STARTTIME 元组被创建的时间戳 VERSIONS_ENDTIIME 元组被删除的时间戳 VERSIONS_STARTCSN 元组被创建的 commit seqno VERSIONS_ENDCSN 元组被删除的 commit seqno VERSIONS_OPERATION 对应的操作 D 表示该元组被删除,I 表示该元组被插入 VEERSIONS_XID 元组被创建的事务 ID 124 第5章 操作符 5 第 章 操作符 操作符操作数据项并返回结果。从语法上讲,操作符出现在操作数之前或之后或两个操作数之间。 本章包含以下部分: • SQL 相关操作符 • 算术操作符 • 逻辑操作符 • 比较操作符 • 排序规则操作符 • 连接操作符 • 位串操作符 • 文本匹配操作符 • 层次查询操作符 • 集合操作符 • 自定义操作符 其中,非逻辑(非布尔)操作符本身不能用作查询或子查询中的 WHERE 或者 HAVING 子句的条件。 5.1 SQL 相关操作符 操作符操纵的独立数据称为操作数或参数。操作符由特殊字符或关键字组成。例如,乘法操作符由星号 (*) 表 示。 • 一元和二元操作符 两种通用类型的操作符是: unary:一元操作符仅对一个操作数进行操作。一元操作符通常以下列格式与其操作数一起出现: 125 第5章 操作符 operator operand binary:二元操作符对两个操作数进行操作。二元操作符及其操作数以这种格式出现: operand1 operator operand2 其他具有特殊格式的操作符接受两个以上的操作数。如果给操作符一个空操作数,则结果始终为空。唯一不遵 循此规则的操作符是连接 (||)。 • 操作符优先级 优先级是 KingbaseES 数据库在同一表达式中计算不同操作符的顺序。在计算包含多个操作符的表达式时, Kingbase 在计算优先级较低的操作符之前先计算优先级较高的操作符。Kingbase 在表达式中从左到右计算具 有相同优先级的操作符。以下列出了 SQL 操作符的优先级从高到低。列在同一行的操作符具有相同的优先级。 – 操作符:+, -,(作为一元操作符), PRIOR, CONNECT_BY_ROOT,COLLATE 身份、否定、层次结构 中的位置 – 操作符:*, /,乘法、除法 – 操作符:+, -,(作为二元操作符), || 加法、减法、连接 在下面的表达式中,乘法的优先级高于加法,因此 KingbaseES 先计算 2 乘以 3,然后将结果加 1。 1+2*3 您可以在表达式中使用括号来覆盖操作符优先级。KingbaseES 在计算括号外的表达式之前先计算括号内的表达 式。 SQL 还支持集合操作符(UNION、UNION ALL、INTERSECT 和 MINUS),它们组合查询返回的行集合, 而不是单个数据项。所有集合操作符具有相同的优先级。 5.2 算术操作符 您可以使用带有一个或两个参数的算术操作符来对数值进行求反、加法、减法、乘法和除法等。其中一些操作符 也用于时间日期和时间间隔类型的计算。操作符的参数必须解析为数字数据类型或任何可以隐式转换为数字数据类型 的数据类型。 一元算术操作符返回与参数的数值数据类型相同的数据类型。对于二元算术操作符,KingbaseES 确定具有最高 数值优先级的参数,将其余参数隐式转换为该数据类型,并返回该数据类型。 下表展示了所有可用的算术操作符。 126 第5章 操作符 表 5.2.1: 算术操作符 操作符 描述 例子 结果 + 加 2 + 3 5 - 减 2 - 3 -1 * 乘 2 * 3 6 / 除(整数除法截断结果) 4 / 2 2 % 模(取余) 5 % 4 1 ^ 指数(从左至右结合) 2.0 ^ 3.0 8 |/ 平方根 |/ 25.0 5 ||/ 立方根 ||/ 27.0 3 ! 阶乘 5 ! 120 !! 阶乘(前缀操作符) !! 5 120 @ 绝对值 @ -5.0 5 & 按位与 91 & 15 11 | 按位或 32 | 3 35 # 按位异或 17 # 5 20 ~ 按位求反 ~1 -2 << 按位左移 1 << 4 16 >> 按位右移 8 >> 2 2 DIV 整除(兼容 MySQL 操作符) 4 DIV 2 2 MOD 取余(兼容 MySQL 操作符) 5 MOD 4 1 注意: 使用兼容 MySQL 操作符 DIV 和 MOD 时,若操作数为 NULL,需保持参数 ora_input_emptystr_isnull 为 off 状态。 • 操作符:+,-,当这些表示正或负表达式时,它们是一元操作符。 示例: 127 第5章 操作符 CREATE TABLE students( student_id int, first_name varchar(20), last_name varchar(25) CONSTRAINT stu_last_name_nn NOT NULL, email varchar(25) CONSTRAINT stu_email_nn NOT NULL, phone_number varchar(20), entrance_date Date DEFAULT SYSDATE CONSTRAINT stu_entrance_data_NN NOT NULL, major_id varchar(10) CONSTRAINT stu_major_nn NOT NULL, score int CONSTRAINT stu_sco_nn NOT NULL, monitor_id int, class_id int ); SELECT * FROM students where -score < 0 ORDER BY student_id; • 操作符:+,-,当它们加或减时,它们是二元操作符。 示例: SELECT entrance_date FROM students WHERE SYSDATE - entrance_date > 365 ORDER BY entrance_date; • 操作符:*, / (乘,除)。这些是二元操作符。 示例: Update students SET score = score * 1.1; 5.3 逻辑操作符 常用的逻辑操作符有: AND OR NOT SQL 使用三值的逻辑系统,包括真、假和 null,null 表示“未知”。如下面的真值表所示: 128 第5章 操作符 表 5.3.1: 真值表(AND 和 OR) “a“ “b“ “a“ AND “b“ “a“ OR “b“ TRUE TRUE TRUE TRUE TRUE FALSE FALSE TRUE TRUE NULL NULL TRUE FALSE FALSE FALSE FALSE FALSE NULL FALSE NULL NULL NULL NULL NULL 表 5.3.2: 真值表(NOT) “a“ NOT “a“ TRUE FALSE FALSE TRUE NULL NULL 操作符 AND 和 OR 是可交换的,即交换左右操作数而不影响结果。 KingbaseES MySQL 模式下兼容如下逻辑操作符: 表 5.3.3: 兼容 MySQL 操作符 操作符 描述 XOR 逻辑异或 && 逻辑与 || 逻辑或 ! 逻辑非 需要注意的是,若操作数为 NULL,需保持参数 ora_input_emptystr_isnull 为 off 状态。 5.4 比较操作符 常见的比较操作符都可用,如下表所示。 129 第5章 操作符 表 5.4.1: 比较操作符 操作符 描述 < 小于 >大于<= 小于等于 >= 大于等于 = or <=>等于<> or != or^= 不等于 注意: != 操作符在分析器阶段被转换成<>。<=> 操作符兼容 MySQL 比较操作符,其基本功能与 = 操作符相同。需要注意的是,操作数为 NULL 时,需保 持参数 ora_input_emptystr_isnull 的关闭状态。 对于<=,>=,<>,!=,^= 这几个操作符,支持两个字符之间输入若干空格或者换行的字符,效果和不加空格或换行一 致。 比较操作符可以用于所有可以比较的数据类型。所有比较操作符都是双目操作符,它们返回 boolean 类型;类 似于 1 < 2 < 3 的表达式是非法的(因为没有< 操作符可以比较一个布尔值和 3)。 如下表所示,也有一些比较谓词。它们的行为和操作符相似,但是具有 SQL 标准所要求的特殊语法。 表 5.4.2: 比较谓词 谓词 描述 “a“ BETWEEN “x“ AND “y“ 在 “x“和 “y“之间 “a“ NOT BETWEEN “x“ AND “y“ 不在 “x“和 “y“之间 “a“ BETWEEN SYMMETRIC “x“ AND “y“ 在对比较值排序后位于 “x“和 “y“之间 “a“ NOT BETWEEN SYMMETRIC “x“ AND “y“ 在对比较值排序后不位于 “x“和 “y“之间 “a“ IS DISTINCT FROM “b“ 不等于,空值被当做一个普通值 “a“ IS NOT DISTINCT FROM “b“ 等于,空值被当做一个普通值 “expression“ IS NULL 是空值 见续表 130 第5章 操作符 表 5.4.2 – 续表 谓词 描述 “expression“ IS NOT NULL 不是空值 “expression“ ISNULL 是空值(非标准语法) IS INFINITE 是 NAN IS NOT NAN 不是 NAN IS INFINITE 是无限值 IS NOT INFINITE 不是无限值 “expression“ NOTNULL 不是空值(非标准语法) “boolean_expression“ IS TRUE 为真 “boolean_expression“ IS NOT TRUE 为假或未知 “boolean_expression“ IS FALSE 为假 “boolean_expression“ IS NOT FALSE 为真或者未知 “boolean_expression“ IS UNKNOWN 值为未知 “boolean_expression“ IS NOT UNKNOWN 为真或者为假 BETWEEN 谓词可以简化范围测试: a BETWEEN x AND y 等效于 a >= x AND a <= y 注意 BETWEEN 认为终点值是包含在范围内的。NOT BETWEEN 可以做相反比较: a NOT BETWEEN x AND y 等效于 a < x OR a > y BETWEEN SYMMETRIC 和 BETWEEN 相似,不过 BETWEEN SYMMETRIC 不要求 AND 左边的参数小于或等于右边的参 数。如果左参数不是小于等于右参数,这两个参数会自动被交换,这样总是会应用一个非空范围。 当有一个输入为空时,普通的比较操作符会得到空(表示“未知”)。例如,7 = NULL 得到空,7 <> NULL 也 一样。如果这种行为不合适,可以使用 IS [ NOT ] DISTINCT FROM 谓词: 131 第5章 操作符 a IS DISTINCT FROM b a IS NOT DISTINCT FROM b 对于非空输入,IS DISTINCT FROM 和<> 操作符一样。不过,如果两个输入都为空,它会返回假。而如果只有一 个输入为空,它会返回真。类似地,IS NOT DISTINCT FROM 对于非空输入的行为与 = 相同,但是当两个输入都为 空时它返回真,并且当只有一个输入为空时返回假。因此,这些谓词实际上把空值当作一种普通数据值而不是“unknown”。 要检查一个值是否为空,使用下面的谓词: expression IS NULL expression IS NOT NULL 或者等效,但并不标准的谓词: expression ISNULL expression NOTNULL 不要写 expression = NULL,因为 NULL 是不等于 NULL 的(控制代表一个未知的值,因此我们无法知道两个未 知的数值是否相等)。 提示: 有些应用可能要求表达式 expression = NULL 在 expression 得出空值时返回真。我们强烈建议这样的应用 修改成遵循 SQL 标准。但是,如果这样修改不可能完成,那么我们可以使用配置变量 transform_null_equals 。如果 打开它,KingbaseES 将把 x = NULL 子句转换成 x IS NULL。 如果 expression 是行值,那么当行表达式本身为非空值或者行的所有域为非空时 IS NULL 为真。由于这种行 为,IS NULL 和 IS NOT NULL 并不总是为行值表达式返回反转的结果,特别是,一个同时包含 NULL 和非空值的 域将会对两种测试都返回假。在某些情况下,写成 row IS DISTINCT FROM NULL 或者 row IS NOT DISTINCT FROM NULL 会更好,它们只会检查整个行值是否为空而不需要在行的域上做额外的测试。 布尔值也可以使用下列谓词进行测试: boolean_expression IS TRUE boolean_expression IS NOT TRUE boolean_expression IS FALSE boolean_expression IS NOT FALSE boolean_expression IS UNKNOWN boolean_expression IS NOT UNKNOWN 这些谓词将总是返回真或假,从来不返回空值,即使操作数是空也如此。空值输入被当做逻辑值“未知”。请注 意实际上 IS UNKNOWN 和 IS NOT UNKNOWN 分别与 IS NULL 和 IS NOT NULL 相同,只是输入表达式必须是布尔类 型。 132 第5章 操作符 排序规则操作符 5.5 collate 操作符确定表达式的排序规则。 此操作符使您能够覆盖数据库使用标准排序规则派生规则为表达式派生的排序规则。 collate 是后缀一元操作符。它与其他一元操作符具有相同的优先级,但在对所有前缀一元操作符求值后进行求 值。您可以将此操作符应用于 CHAR、VARCHAR、VARCHAR2、TEXT。 collate 的操作符是一个参数,参数以 collation_name 来代指。您可以为其指定命名排序规则。 以下描述了 collate 操作符: 操作符:COLLATE collation_name 目的:确定表达式的排序规则 例子: CREATE TABLE students (student_id int ,first_name varchar(20) ,last_name varchar(25) CONSTRAINT stu_last_name_nn NOT NULL ,email varchar(25) CONSTRAINT stu_email_nn NOT NULL ,phone_number varchar(20) ,entrance_date Date DEFAULT SYSDATE CONSTRAINT stu_entrance_data_NN NOT NULL ,major_id varchar(10) CONSTRAINT stu_major_nn NOT NULL ,score int CONSTRAINT stu_sco_nn NOT NULL ,monitor_id int ,class_id int ); Select last_name from students ORDER BY last_name COLLATE "C"; 5.6 连接操作符 连接操作符操作字符类数据、clob 数据和 raw 数据。 操作符:|| 目的:连接字符串、CLOB 数据和 raw 数据。 示例: 133 第5章 操作符 CREATE TABLE students (student_id int ,first_name varchar(20) ,last_name varchar(25) CONSTRAINT stu_last_name_nn NOT NULL ,email varchar(25) CONSTRAINT stu_email_nn NOT NULL ,phone_number varchar(20) ,entrance_date Date DEFAULT SYSDATE CONSTRAINT stu_entrance_data_NN NOT NULL ,major_id varchar(10) CONSTRAINT stu_major_nn NOT NULL ,score int CONSTRAINT stu_sco_nn NOT NULL ,monitor_id int ,class_id int ); SELECT 'Name is' || last_name from students Order by last_name; 连接两个字符串的结果是另一个字符串。如果两个字符串都是 CHAR 类型,则结果只有 CHAR 类型。如果任一 字符串是数据类型 VARCHAR2,则结果是数据类型 VARCHAR2。无论类型是字符串或者 CLOB,在字符串末尾都 是通过空格来间隔,并且串联保存。 尽管 KingbaseES 将零长度字符串视为空值,但将零长度字符串与另一个操作数连接总是会产生另一个操作数, 因此 null 只能来自两个空字符串的连接。 5.7 位串操作符 KingbaseES 提供操作类型为 bit 和 bit varying 值的操作符。除了常用的比较操作符之外,还可以使用下表 所示的操作符。&、| 和 # 的位串操作数必须等长。在移位的时候,保留原始的位串的的长度,如例子所示。 134 第5章 操作符 表 5.7.1: 位串操作符 5.8 操作符 描述 例子 结果 || 连接 B'10001' || B'011' 10001011 & 按位与 B'10001' & B'01101' 00001 | 按位或 B'10001' | B'01101' 11101 # 按位异或 B'10001' # B'01101' 11100 ~ 按位求反 ~ B'10001' 01110 << 按位左移 B'10001' << 3 01000 >> 按位右移 B'10001' >> 2 00100 文本匹配操作符 KingbaseES 提供了 LIKE 操作符进行文本匹配。特别的,还可以使用 ~~、~~* 等操作符。操作符 ~~ 等效于 LIKE,而 ~~* 对应 ILIKE。还有 !~~ 和!~~* 操作符分别代表 NOT LIKE 和 NOT ILIKE。这些操作符都是 KingbaseES 特有的。 LIKE 操作符的语法如下: string LIKE pattern [ESCAPE escape-character] string NOT LIKE pattern [ESCAPE escape-character] 如果该 “string“匹配了提供的 “pattern“,那么 LIKE 表达式返回真(和预期的一样,如果 LIKE 返回真,那么 NOT LIKE 表达式返回假,反之亦然。一个等效的表达式是 NOT (string LIKE pattern )。 如果 “pattern“不包含百分号或者下划线,那么该模式只代表它本身的串;这时候 LIKE 的行为就象等号操作 符。在 “pattern“里的下划线(_)代表(匹配)任何单个字符;而一个百分号(%)匹配任何零或更多个字符的序 列。 一些例子: 'abc' LIKE 'abc' true 'abc' LIKE 'a%' true 'abc' LIKE '_b_' true 'abc' LIKE 'c' false LIKE 匹配文本总是覆盖整个串。因此,要匹配在串内任何位置的序列,必须以百分号开头和结尾。 要匹配文本的下划线或者百分号,而不是匹配其它字符,在 “pattern“里相应的字符必须前导转义字符。缺省的 转义字符是反斜线,但是你可以用 ESCAPE 子句指定一个不同的转义字符。要匹配转义字符本身,写两个转义字符。 135 第5章 操作符 注意: 如果关掉了参数 standard_conforming_strings ,在字符串常量中写的任何反斜线都需要被双写。 请注意反斜线在串文本里已经有特殊含义了,所以如果包含反斜线的字符,需要在 SQL 语句里写两个反斜线。 因此,匹配单个反斜线的字符实际上要在语句里写四个反斜线。可以通过用 ESCAPE 选择一个不同的转义字符来避 免这样;这样反斜线就不再是 LIKE 的特殊字符了。但仍然是字符文本分析器的特殊字符,所以你还是需要两个反斜 线。我们也可以通过写 ESCAPE ''的方式不选择转义字符,这样可以有效地禁用转义机制。 关键字 ILIKE 可以用于替换 LIKE,它匹配文本时,字符大小写无关。这个不属于 SQL 标准而是一个 KingbaseES 扩展。 在仅需要从字符串的开始部分搜索的情况,还有前缀操作符 ^@ 和相应的 starts_with 函数可以使用。 5.9 层次查询操作符 两个操作符 PRIOR 和 CONNECT_BY_ROOT 仅在层次查询中有效。 • PRIOR 在层次查询中,CONNECT BY condition 必须由 PRIOR 操作符限定一个表达式。如果 CONNECT BY condition 是复合的,那么只有一个条件需要 PRIOR 操作符,尽管您可以有多个 PRIOR 条件。PRIOR 计算层次 查询中当前行的父行的紧随其后的表达式。PRIOR 在使用相等操作符比较列值时最常使用。(PRIOR 关键字 可以在操作符的任一侧。)PRIOR 使 KingbaseES 使用列中父行的值。等号 (=) 以外的操作符理论上可以在 CONNECT BY 子句中使用。但是,这些其他操作符创建的条件可能会导致通过可能的组合的无限循环。在这 种情况下,KingbaseES 在运行时检测到循环并返回错误。 • CONNECT_BY_ROOT CONNECT_BY_ROOT 是一元操作符,仅在层次查询中有效。当您使用此操作符限定列时,KingbaseES 使 用根行中的数据返回列值。此操作符扩展了层次查询的 CONNECT BY[PRIOR ] 的功能。您不能在 START WITH 条件或 CONNECT BY 条件中指定此操作符。 5.10 集合操作符 集合操作符将两个组件查询的结果组合成一个结果。包含集合操作符的查询称为复合查询。 下表为集合操作符相关内容: 136 第5章 操作符 表 5.10.1: 集合操作符 5.11 操作符 返回的结果集 UNION 任一查询选择的所有不同行 UNION ALL 任一查询选择的所有行,包括所有重复项 INTERSECT 由两个查询都选择的行,重复的行出现一次 INTERSECT ALL 由两个查询都选择有行,重复的行出现一次 MINUS 由第一个查询而不是第二个查询选择的所有不同的行 MINUS ALL 第一个查询而不是第二个查询选择的所有行,包括重复的行 EXCEPT 由第一个查询而不是第二个查询选择的所有不同的行 EXCEPT ALL 由第一个查询而不是第二个查询选择的所有不同的行,包括重复的行 自定义操作符 与内置操作符一样,用户定义的操作符将一组操作数作为输入并返回结果。您可以使用CREATE OPERATOR 语句创建它们,并且它们由用户定义的名称标识。定义新操作符后,您可以像使用任何其他内置操作符一样在 SQL 语句中使用它。例如,您可以在 SELECT 语句的目标列表、子句的条件 WHERE 或 ORDER BY 子句和 GROUP BY 子句中使用用户定义的操作符。 137 第6章 表达式 6 第 章 表达式 本章介绍如何将值、运算符和函数组合成表达式。 本章包括以下部分: • SQL 表达式简介 • 简单表达式 • 复合表达式 • CASE 表达式 • 列表达式 • 日期时间表达式 • 函数表达式 • 占位符表达式 • 标量子查询表达式 • 类型构造表达式 • 表达式列表 6.1 SQL 表达式简介 一个表达式可以包含一个或者多个值,操作符,以及返回标量值的 SQL 函数。表达式通常需要推测和假设其包 含的成员的数据类型。 这个简单的表达式计算结果为 4 并且具有数据类型 int(与其组件相同的数据类型): 2*2 以下表达式是一个使用函数和运算符的更复杂表达式的示例。在当前日期增加 7 天,从总和中删除时间部分,并 将结果转换为 CHAR 数据类型: 138 第6章 表达式 TO_CHAR (TRUNC (SYSDATE + 7)) 您可以在以下位置使用表达式: • SELECT 语句的目标列表 • WHERE 子句和 HAVING 子句中的条件中 • CONNECT BY,START WITH 和 ORDER BY 子句 • INSERT 语句中的 VALUES 子句 • UPDATE 语句中的 SET 子句 例如,您可以在 UPDATE 的 SET 子句中使用’Smith’ : SET last_name = 'Smith'; 下面的语句中使用了表达式 INITCAP(last_name) 代替了上面的’Smith’: SET last_name = INITCAP(last_name); 表达式有多种形式,如以下列表所示: • simple_expression • compound_expression • case_expression • datetime_expression • function_expression • scalar_subquery_expression • type_constructor_expression • variable_expression 6.2 简单表达式 简单表达式包括列,伪列,常量,序列和 null。 简单表达式: { [ query_name. | [schema.] { table. | view. | materialized view. } | t_alias. ] { column | ROWID } | ROWNUM 139 第6章 表达式 | string | number | sequence. { CURRVAL | NEXTVAL } | NULL } ROWID 只能用表指定,不能用视图或物化视图指定。NCHAR 和 NVARCHAR2 不是有效的伪列数据类型。 一些有效的简单表达式是: employees.last_name 'this is a text string' 10 140 第6章 6.3 表达式 复合表达式 复合表达式指定其他表达式的组合。 复合表达式: { (expr) | { + | - | PRIOR } expr | expr { * | / | + | - | || } expr | expr COLLATE collation_name } 可以使用任何内置函数作为表达式 ( Function Expressions )。但是,不是所有的函数联合使用都是合理的。例 如,该 LENGTH 函数在聚合函数中不合适。 PRIOR 运算符用于 CONNECT BY 层次查询的子句中。 COLLATE 运算符确定表达式的排序规则。此运算符覆盖数据库使用标准排序规则派生规则为表达式派生的排序 规则。 一些有效的复合表达式是: 141 第6章 表达式 ('ZhangSan'||'LiSi') LENGTH('WangWu') * 57 SQRT(144) + 72 my_func(TO_CHAR(sysdate,'DD-MM-YY')) name COLLATE BINARY_CI 6.4 CASE 表达式 CASE 表达式允许您在 SQL 语句中使用 IF ... THEN ... ELSE 逻辑,而无需调用过程。语法是: case_expression: case_expression ::= CASE ( 'simple_case_expression' | 'searched_case_expression' ) ( 'else_clause' )? END simple_case_expression: simple_case_expression::= expr ( WHEN 'comparison_expr' THEN 'return_expr' )+ searched_case_expression: searched_case_expression ::= ( WHEN 'condition' THEN 'return_expr' )+ else_clause: 142 第6章 else_clause ::= 表达式 ELSE 'else_expr' 在一个一般 CASE 表达式中,KingbaseES 数据库依次搜索每一个 WHEN...THEN 对,当 expr 等于 comparison_expr 时则返回 return_expr。如果所有 WHEN... THEN 对都不满足此条件,并且存在 ELSE 子句,则返回 else_expr,否则,返回 null。 在搜索 CASE 表达式中,KingbaseES 从左到右搜索,直到找到一个 condition 为真的匹配项,然后返回 return_expr。如果没有 condition 为真,并且存在 ELSE 子句,则返回 else_expr。否则,返回 null。 KingbaseES 数据库使用最小化计算原则。对于一般 CASE 表达式,数据库仅在将每个 comparison_expr 与 expr 进行比较之前计算其值,而不是将 expr 与所有 comparison_expr 进行比较。因此,如果前一个 comparison_expr 等 于 expr,KingbaseES 将不会再计算后续 comparison_expr 的值。对于搜索 CASE 表达式,数据库依次评估每个条 件表达式 condition 以确定它是否为真,如果前一个表达式为真,则不再计算后续条件。 对于一般 CASE 表达式,expr 和所有 comparison_expr 值必须具有相同的数据类型(CHAR、VARCHAR、 NUMBER、BINARY_FLOAT 或 BINARY_DOUBLE)或都为数值类型。如果所有表达式都是数值类型,则 KingbaseES 将确定具有最高数值精度的参数,隐式的将其余参数转换为该数据类型,并返回该数据类型。 对于一般 CASE 表达式和搜索 CASE 表达式,所有 return_exprs 必须具有相同的数据类型(CHAR、VARCHAR、NUMBER、BINARY_FLOAT 或 BINARY_DOUBLE),或者都为数值类型。如果所有返回表达式都是数 值类型,则 KingbaseES 确定具有最高数值精度的参数,将其余参数隐式转换为该数据类型,并返回该数据类型。 CASE 如果比较的参数具有字符数据类型(CHAR、VARCHAR),则一般 CASE 表达式执行的比较是排序规 则敏感的,排序规则系统确定要使用的排序规则。 • 一般 CASE 表达式示例 对于示例 oe.customers 表, 表 中 的 每 个 客 户, 以 下 语 句 将 信 用 额 度 列 为 “Low”(如 果 等 于 100 美 元)、“High”(如果等于 5000 美元)和“Medium”(如果等于其他任何值)。 select cust_last_name,CASE credit_limit WHEN 100 THEN 'Low' when 5000 then 'high' ELSE 'Medium' END As credit From customer ORDER BY cust_last_name, credit; +----------------+--------+ | CUST_LAST_NAME | CREDIT | +================+========+ | Adjani | Medium | +----------------+--------+ | Adjani | Medium | +----------------+--------+ | Alexander | Medium | +----------------+--------+ | Alexander | Medium | +----------------+--------+ 143 第6章 | Altman | High 表达式 | +----------------+--------+ | Altman | Medium | +----------------+--------+ • 搜索 CASE 表达式示例 下面的语句找出样本表 oe.employees 中雇员的平均工资,使用 $2000 作为可能的最低工资: SELECT AVG(CASE WHEN e.salary > 2000 THEN e.salary ELSE 2000 END) "Average Salary" FROM employees e; +----------------+ | Average Salary | +================+ | 6461.68224 | +----------------+ 6.5 列表达式 列表达式(column_expression)在表达式可以是简单表达式、复合表达式、函数表达式或表达式列表,但它只 能包含以下表达式形式: • 表的列 • 常量(字符串或数字) • 确定性函数——SQL 内置函数或用户定义函数 本章中描述的其他表达形式均无效。 您可以将列表达式用于以下目的: • 创建基于函数的索引。 • 显式或隐式定义虚拟列。 列表达式的组合组件必须是确定性的。也就是说,同一组输入值必须返回同一组输出值。 6.6 日期时间表达式 一个日期时间表达式(datetime_expresion)产生一种类型的时间值。 日期时间表达式: 144 第6章 表达式 初始 expr 值是除标量子查询表达式外的任何表达式,其计算结果为数据类型 TIMESTAMP、TIMESTAMP WITH TIME ZONE 或 TIMESTAMP WITH LOCAL TIME ZONE。不支持 DATE 数据类型。如果这 expr 本 身就是 a datetime_expression,那么它必须用括号括起来。 日期时间表达式可以和时间间隔表达式进行组合生成新的日期时间表达式。 如果您指定 AT LOCAL,则 KingbaseES 会使用当前会话时区。 设置 AT TIME ZONE 的解释如下: • 字符串’[+|-]hh: mi’ 将时区指定为与 UTC 的偏移量。对于 hh,指定小时数。对于 mi,指定分钟数。 • time_zone_name:KingbaseES 返回对应于 有 效 时 区 区 域 名 称 的 列 表, 请 查 询 视 图 time_zone_name 指 定 时 区 的 日 期 时 间 表 达 式 值。 有 关 sys_timezone_names, 关 于 时 区 名 称 的 缩 写, 请 查 询 视 图 sys_timezone_abbrevs。 • expr:如果 expr 返回具有有效时区格式的字符串,则 KingbaseES 返回该时区的输入。否则,KingbaseES 返 回错误。 以下示例将一个时区的日期时间值转换为另一个时区: SELECT timezone('America/New_York', CAST(TO_DATE('1999-12-01 11:00:00','YYYY-MM-DD HH:MI:SS') AS TIMESTAMP)) AT TIME ZONE 'America/Los_Angeles' FROM DUAL; +--------------------------+ | timezone | +==========================+ | 1999-12-01 08:00:00 | +--------------------------+ 145 第6章 6.7 表达式 函数表达式 您可以使用任何内置 SQL 函数或用户定义的函数作为表达式。一些有效的内置函数表达式是: LENGTH('BLAKE') ROUND(1234.567*43) SYSDATE 用户定义的函数表达式可以调用: • KingbaseES 内置的包中的函数 • 用户定义的包或类型中的函数 • 用户定义的函数或运算符 一些有效的用户定义函数表达式是: circle_area(radius) payroll.tax_rate(empno) hr.employees.comm_pct@remote(dependents,empno) DBMS_LOB.getlength(column_name) My_function(a_column) 在用作表达式的用户定义函数中,支持位置、命名和混合表示法。例如,以下所有符号都是正确的: call my_function(arg1 => 3, arg2 => 4) ... call my_function(3, 4) ... call my_function(3, arg2 => 4) ... 6.8 占位符表达式 占位符表达式在 SQL 语句中提供一个位置,第三方语言在绑定变量时将为该位置提供一个值。您可以使用可选 的指示变量指定占位符表达式。这种形式的表达式只能出现在嵌入式 SQL 语句或在 KingbaseES 调用接口 (DCI) 程 序中处理的 SQL 语句中。 placeholder_expression : 146 第6章 表达式 :host_variable [ [ INDICATOR ] :indicator_variable ] 一些有效的占位符表达式是: :employee_name INDICATOR :employee_name_indicator_var :department_location 6.9 标量子查询表达式 标量子查询表达式是从一行中准确返回一个列值的子查询。标量子查询表达式的值是子查询的目标列表项的值。 如果子查询返回 0 行,则标量子查询表达式的值为 NULL。如果子查询返回多于一行,则 KingbaseES 返回错误。 您可以在大多数需要表达式 ( expr) 的语法中使用标量子查询表达式。在所有情况下,一个标量子查询必须包含 在它自己的括号中,即使它的句法位置已经将它定位在括号内(例如,当标量子查询用作内置函数的参数时)。 标量子查询在以下位置不是有效表达式: • 作为列的默认值 • 作为聚簇的哈希表达式 • 在 DML 语句中的 RETURNING 子句 • 用于函数索引 • 在 CHECK 约束中 • 在 GROUP BY 子句 • 在与查询无关的语句中 147 第6章 6.10 表达式 类型构造表达式 类型构造函数表达式指定对构造函数方法的调用, 类型构造函数的参数是任何表达式, 可以在调用函数的任何地方 调用类型构造函数。 type_constructor_expression : [ NEW ] [ schema. ]type_name ([ expr [, expr ]... ]) 该 NEW 关键字适用于对象类型的构造函数,但不适用于集合类型。它指示 KingbaseES 通过调用适当的构造函 数来构造一个新对象。关键字的使用 NEW 是可选的,但最好指定它。 如果 type_name 是对象类型,则表达式必须是有序列表,其中第一个参数是类型匹配对象类型的第一个属性的 值,第二个参数是类型匹配对象类型的第二个属性的值, 以此类推。构造函数的参数总数必须与对象类型的属性总数 匹配。 如果 type_name 是可变数组或嵌套表类型,则表达式列表可以包含零个或多个参数。零参数意味着构造一个空 集合。否则,每个参数对应一个元素值,其类型是集合类型的元素类型。 类型构造函数调用的限制:类型构造表达式只能在 PL/SQL 中使用。 表达式示例: 此示例使用 cust_address_typ 示例 oe 模式中的类型来显示在调用构造函数方法中使用表达式(PL/SQL 以斜体 显示): CREATE TYPE address_book_t AS TABLE OF cust_address_typ; DECLARE myaddr cust_address_typ := cust_address_typ('500 KingbaseES Parkway', 94065, 'Redwood Shores', 'CA', 'USA'); alladdr address_book_t := address_book_t(); BEGIN INSERT INTO customers VALUES (666999, 'Joe', 'Smith', myaddr, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); 148 第6章 表达式 END; 子查询示例: 此示例使用 warehouse_typ 示例模式中的类型 oe 来说明在调用构造函数方法时使用子查询。 CREATE TABLE warehouse_tab OF warehouse_typ; INSERT INTO warehouse_tab VALUES (warehouse_typ(101, 'new_wh', 201)); CREATE TYPE facility_typ AS OBJECT ( facility_id NUMBER, warehouse_ref REF warehouse_typ); CREATE TABLE buildings (b_id NUMBER, building facility_typ); INSERT INTO buildings VALUES (10, facility_typ(102, (SELECT REF(w) FROM warehouse_tab w WHERE warehouse_name = 'new_wh'))); SELECT b.b_id, b.building.facility_id "FAC_ID", DEREF(b.building.warehouse_ref) "WH" FROM buildings b; +------+------------------------------------------------------+ | B_ID | FAC_ID WH(WAREHOUSE_ID, WAREHOUSE_NAME, LOCATION_ID) | +======+======================================================+ | 10 | 102 WAREHOUSE_TYP(101, 'new_wh', 201) | +------+------------------------------------------------------+ 6.11 表达式列表 表达式列表是其他表达式的组合。 表达式列表: { expr [, expr ]... | ( [expr [, expr ]] ...) } 149 第6章 表达式 表达式列表可以出现在查询和子查询的比较和成员条件以及 GROUP BY 子句中。比较或成员条件中的表达式列 表有时称为行值构造函数或行构造函数。 比较和成员条件出现在 WHERE 子句的条件中。它们可以包含一个或多个逗号分隔的表达式或一组或多组表达 式,其中每组包含一个或多个逗号分隔的表达式。在后一种情况下(多组表达式): • 每个集合都由括号包围 • 每个集合必须包含相同数量的表达式 • 每个集合中的表达式数量必须与比较条件中运算符之前或 IN 成员条件中关键字之前的表达式数量相匹配。 以逗号分隔的表达式列表最多可以包含 1000 个表达式。以逗号分隔的表达式集合列表可以包含任意数量的集 合,但每个集合最多可以包含 1000 个表达式。 以下是条件中的一些有效表达式列表: (10, 20, 40) ('SCOTT', 'BLAKE', 'TAYLOR') ( ('Guy', 'Himuro', 'GHIMURO'),('Karen', 'Colmenares', 'KCOLMENA') ) 在第三个示例中,每个集合中的表达式数必须等于条件第一部分中的表达式数。例如: SELECT * FROM employees WHERE ( first_name, last_name, email ) IN (('Guy', 'Himuro', 'GHIMURO'),('Karen', 'Colmenares', 'KCOLMENA')); 在一个简单的 GROUP BY 子句中,您可以使用表达式列表的大写形式或小写形式: SELECT department_id, MIN(salary) min, MAX(salary) max FROM employees GROUP BY department_id, salary ORDER BY department_id, min, max; SELECT department_id, MIN(salary) min, MAX(salary) max FROM employees GROUP BY (department_id, salary) ORDER BY department_id, min, max; 在 ROLLUP、CUBE 和 GROUPING SETS 子句的 GROUP BY 子句中,您可以将单个表达式与同一表达式列 表中的表达式集组合在一起。以下示例在一条 SQL 语句中显示了几个有效的分组集表达式列表: 150 第6章 表达式 SELECT prod_category, prod_subcategory, country_id, cust_city, count(*) FROM products, sales, customers WHERE sales.prod_id = products.prod_id AND sales.cust_id = customers.cust_id AND sales.time_id = '01-oct-00' AND customers.cust_year_of_birth BETWEEN 1960 AND 1970 GROUP BY GROUPING SETS ( ( prod_category, prod_subcategory, country_id, cust_city ), ( prod_category, prod_subcategory, country_id ), ( prod_category, prod_subcategory ), country_id ) ORDER BY prod_category, prod_subcategory, country_id, cust_city; 151 第 7 章 条件表达式 7 第 章 条件表达式 条件表达式指定一个或多个表达式和逻辑(布尔)运算符的组合,并返回 TRUE、FALSE 或 UNKNOWN。 本章包含以下部分: • SQL 条件简介 • 比较条件 • 浮点条件 • 逻辑条件 • 模式匹配条件 • 空条件 • SQL/JSON 条件 • 复合条件 • BETWEEN 条件 • EXISTS 条件 • IN 条件 7.1 SQL 条件简介 条件可以有多种形式,如以下语法所示。 条件: { comparison_condition | floating_point_condition | logical_condition | pattern_matching_condition | null_condition 152 第 7 章 条件表达式 | JSON_condition | BETWEEN_condition | compound_condition | exists_condition | in_condition } 以下部分描述了各种形式的条件。condition 无论何时出现在 SQL 语句中,您都必须使用适当的条件语法。 您可以在这些语句的 WHERE 子句中使用条件: • DELETE • SELECT • UPDATE 您可以在 SELECT 语句的以下任何子句中使用条件: • WHERE • START WITH • CONNECT BY 153 第 7 章 条件表达式 • HAVING 条件可以说是逻辑数据类型,尽管 KingbaseES 数据库不显式支持这种数据类型。 以下简单条件总是计算为 TRUE: 1 = 1 以下更复杂的条件将 salary 值与 commission_pct 值相加(用 0 代替 null)并确定总和是否大于数字常量 25000: NVL(salary, 0) + NVL(salary + (salary*commission_pct, 0) > 25000) 逻辑条件可以将多个条件组合成一个条件。例如,您可以使用 AND 条件来组合两个条件: (1 = 1) AND (5 < 7) 以下是一些有效条件: name = 'SMITH' employees.department_id = departments.department_id hire_date > '01-JAN-08' job_id IN ('SA_MAN', 'SA_REP') salary BETWEEN 5000 AND 10000 Commission_pct IS NULL AND salary = 2100 • 条件优先级 优先级是 KingbaseES 数据库在同一表达式中计算不同条件的顺序。在计算包含多个条件的表达式时, KingbaseES 先计算优先级较高的条件,然后计算优先级低的条件。对于相同优先级的条件,KingbaseES 按照从左到右的顺序进行条件计算,但以下情况除外: • 对于使用 AND 连接的多个条件,不能保证从左到右进行计算 • 对于使用 OR 连接的多个条件,不能保证从左到右进行计算 以下列出了 SQL 条件从高到低的优先级。同一行中列出的条件具有相同的优先级。如表所示,KingbaseES 会优 先进行操作符运算。 表 7.1.1: SQL 条件优先级 条件类型 目的 =, !=, <, >,<=, >=, 比较 IS [NOT] NULL, 比较 LIKE, [NOT] BETWEEN 比较 [NOT] IN, EXISTS, IS OF type 比较 见续表 154 第 7 章 条件表达式 表 7.1.1 – 续表 7.2 条件类型 目的 NOT 逻辑否定 AND 连词 OR 或者 比较条件 比较条件将一个表达式与另一个表达式进行比较。这种比较的结果可以是 TRUE、FALSE 或 UNKNOWN。 比较条件不支持大对象 (LOB)。但是,您可以使用 PL/SQL 程序来比较 CLOB 数据。 在比较数字表达式时,KingbaseES 会使用数字优先级来确定该条件是否会比较数字、BINARY_FLOAT 或 BINARY_DOUBLE 值。 在比较字符表达式时,KingbaseES 会使用数据类型比较规则中描述的规则。这些规则定义了表达式的字符集如 何在比较之前对齐、使用二进制或语言比较(排序)、使用空白填充的比较语义,以及对排序键施加的限制所产生的 限制。 如果两个非标量类型的对象具有相同的命名类型,并且它们的元素之间存在一对一的对应关系,则它们具有可比 性。此外,用户定义对象类型的嵌套表,即使它们的元素具有可比性,也必须在它们上定义 MAP 方法,以便在相等 条件或 IN 条件下使用。 以下列出了比较条件: • 条件类型:=,作用:相等检验。 示例: SELECT * FROM employees WHERE salary = 2500 ORDER BY employee_id; • 条件类型:!= ^= <>,作用:不等检验。 示例: SELECT * FROM employees WHERE salary != 2500 ORDER BY employee_id; • 条件类型:>< ,作用:大于和小于比较。 示例: SELECT * FROM employees WHERE salary > 2500 ORDER BY employee_id; SELECT * FROM employees WHERE salary < 2500 ORDER BY employee_id; 155 第 7 章 条件表达式 • 条件类型:>=<=,作用:大于或等于和小于或等于比较。 示例: SELECT * FROM employees WHERE salary >= 2500 ORDER BY employee_id; SELECT * FROM employees WHERE salary <= 2500 ORDER BY employee_id; • op ANY,op SOME ,作用:”op” 必须是 =、!=、^=、<>、>、<、<= 或 >= 之一。op ANY 使用操作符 op 将左侧的值与右侧列表中的每个值或查询返回的每个值进行比较,如果这些比较中的任何一个返回 TRUE, 则 op ANY 返回 TRUE。如果所有这些比较都返回 FALSE,或者右侧的子查询没有返回任何行,则 op ANY 返回 FALSE。否则,返回值为 null。op ANY 和 op SOME 是同义词。 示例: SELECT * FROM employees WHERE salary = ANY (SELECT salary FROM employees WHERE Department_id = 30) ORDER BY employee_id; • op ALL ,作用说明:”op” 必须是 =、!=、^=、<>、>、<、<= 或 >= 之一。op ALL 使用操作符 op 将 左侧的值与右侧列表中的每个值或子查询返回的每个值进行比较,如果这些比较中的任何一个返回 FALSE,则 op ANY 返回 FALSE。如果所有这些比较都返回 TRUE,或者右侧的子查询没有返回任何行,则 op ALL 返回 TRUE。否则,返回值为 null。 示例: SELECT * FROM employees WHERE salary >= ALL (1400, 3000) ORDER BY employee_id; • 简单比较条件 简单比较条件指定与表达式或子查询结果的比较。 简单比较条件: simple_comparison_condition { expr { = | != | ^= | | < | >= | } ( expression_list | subquery ) } 156 第 7 章 条件表达式 表达式列表: expression_list { expr [, expr ]... | ( [expr [, expr ]] ...) } 157 第 7 章 条件表达式 如果使用此比较条件的下端形式表示运算符左侧的单个表达式,则可以使用 expression_list 的上端或下端形 式。如果使用此条件的下端形式表示运算符左侧的多个表达式,则必须使用 expression_list 的下端形式。在任 何一种情况下,expression_list 中的表达式都必须在维数和数据类型上与运算符左侧的表达式相匹配。如果指 定了子查询,则子查询返回的值必须在维数和数据类型上与运算符左侧的表达式相匹配。 • 组比较条件 组比较条件指定与列表或子查询中的任何或所有成员进行比较。 组比较条件: group_comparison_condition { expr { = | != | ^= | | < | >= | ANY | SOME | ALL } ({ expression_list | subquery }) | ( expr [, expr ]... ) { = | != | ^= | ANY | SOME | ALL } ({ expression_list [, expression_list ]... | subquery } ) } 158 第 7 章 条件表达式 表达式列表: expression_list { expr [, expr ]... | ( [expr [, expr ]] ...) } 如果使用此条件的上端形式(在运算符的左侧有单个表达式),则必须使用 expression_list 的上端形式。如果 159 第 7 章 条件表达式 使用此条件的下端形式(在运算符的左侧有多个表达式),则必须使用 expression_list 的下端形式,并且每个 expression_list 中的表达式必须在维数和数据类型上与运算符左侧的表达式相匹配。如果指定了子查询,则子 查询返回的值必须在维数和数据类型上匹配。 7.3 浮点条件 浮点条件可让您确定表达式是无限的还是运算的未定义结果(不是数字或 NaN)。 浮点条件: expr IS [ NOT ] { NAN | INFINITE } 在这两种形式的浮点条件中,expr 必须解析为数值数据类型或任何可以隐式转换为数值数据类型的数据类型。 浮点条件说明: • 条件类型:IS [NOT] NAN , 说明:当 NOT 未指定时,如果 expr 是特殊值 NAN,则返回 TRUE。当指定 NOT 时,如果 expr 不是特殊值 NAN,则返回 TRUE。 示例: SELECT COUNT(*) FROM employees WHERE commission_pct IS NOT NAN; • 条件类型:IS [NOT] INFINITE , 说明:当 NOT 未指定时,如果 expr 是特殊值 +INF 或-INF,则返回 TRUE。当 NOT 指定时,如果 expr 不是 +INF 也不是-INF,则返回 TRUE。 示例: SELECT last_name FROM employees WHERE salary IS NOT INFINITE; 7.4 逻辑条件 逻辑条件将两个组件条件的结果组合起来,以生成基于它们的单个结果,或反转单个条件的结果。以下列出了逻 辑条件。 • 条件类型:NOT , 说明:如果后面的条件为 TRUE,则返回 FALSE。如果是 FALSE 则返回 TRUE。如果是 UNKNOWN,那么它仍然存在 UNKNOWN。 示例: 160 第 7 章 条件表达式 SELECT * FROM employees WHERE NOT (job_id is NULL) ORDER BY employee_id; SELECT * from employees WHERE NOT (salary BETWEEN 1000 AND 2000) ORDER BY employee_id; • 条件类型:AND , 说明:如果两个组件条件都是 TRUE 则返回 TRUE。如果其中一个是 FALSE 则返回 FALSE。 否则返回 UNKNOWN。 示例: SELECT * FROM employees WHERE job_id = 'PU_CLERK' AND department_id = 30 ORDER BY employee_id; • 条件类型:OR , 说明:如果任一组件条件为 TRUE 则返回 TRUE。如果两者都是 FALSE 则返回 FALSE。否则 返回 UNKNOWN。 示例: SELECT * FROM employees WHERE job_id = 'PU_CLERK' OR department_id = 10 ORDER BY employee_id; 下表显示了将 NOT 条件应用于表达式的结果。 表 7.4.1: NOT 真值表 -- 真 假 未知 NOT FALSE TRUE UNKNOWN 下表显示了将 AND 条件组合到两个表达式的结果。 表 7.4.2: AND 真值表 AND 真 假 未知 真 TRUE FALSE UNKNOWN 假 FALSE FALSE FALSE 未知 UNKNOWN FALSE UNKNOWN 例如,在 WHERE 以下 SELECT 语句的子句中,AND 逻辑条件用于确保仅返回 2004 年之前雇佣且工资超过 2500 的人员: SELECT * FROM employees WHERE hire_fate < TO_DATE('01-JAN-2004', 'DD-MON-YYYY') AND salary > 2500 ORDER BY employee_id; 下表显示了应用于 OR 两个表达式的结果。 161 第 7 章 条件表达式 表 7.4.3: OR 真值表 OR 真 假 未知 真 TRUE TRUE TRUE 假 TRUE FALSE UNKNOWN 未知 TRUE UNKNOWN UNKNOWN 例如,以下查询返回佣金率为 40% 或工资大于 20,000 的员工: SELECT employes_id from employees WHERE commission_pct = .4 OR salary > 20000 ORDER BY employee_id; 7.5 模式匹配条件 模式匹配表达式比较字符函数。 • LIKE Condition LIKE 指定了一个模式匹配的计算。相等运算符 (=) 是将一个字符值与另一个字符值完全匹配,而 LIKE 条件 是通过在第一个值中搜索与指定的第二个值匹配的模式,将一个字符值的一部分与另一个字符值匹配。LIKE 使 用输入字符定义的字符集计算字符串。 like_condition: char1 [NOT] LIKE char2 ESCAPE esc_char 在这种语法中: – char1 是一个字符表达式,例如一个字符列,称为搜索值。 – char2 是一个字符表达式,通常是文字,称为模式。 – esc_char 是一个字符表达式,通常是文字,称为转义字符。 如果未指定 esc_char,则没有默认转义字符。如果 char1 、char2 或 esc_char 中的任何一个为空,则结果未 知。否则,转义字符(如果指定)必须是长度为 1 的字符串。 所有字符表达式(char1、char2 和 esc_char)都可以是任何数据类型 CHAR、VARCHAR 或 NCHAR、 NVARCHAR2。如果它们不同,则 KingbaseES 将它们全部转换为 char1 的数据类型。 模式可以包含特殊的模式匹配字符: – 模式中的下划线 (_) 与值中的一个字符(而不是多字节字符集中的一个字节)完全匹配。 – 模式中的百分号 (%) 可以匹配值中的零个或多个字符(与多字节字符集中的字节相反)。模式“%”不能 匹配空值。可以使用标识转义字符的转义子句在模式中包含实际字符% 或 _。如果转义字符在模式中的字 162 第 7 章 条件表达式 符% 或 _ 之前,则 KingbaseES 会直接解释这个字符,而不是作为一个特殊的模式匹配字符。你也可以通 过重复它来搜索转义字符本身。例如,如果 @ 是转义字符,则可以使用 @@ 来搜索 @。 只有与 ASCII 匹配的下划线 (_) 和百分号 (%) 字符被识别为模式匹配字符。它们出现在 East Aslan character 和 Unicode 中的全角变体被视为普通字符。 以下描述了这些 LIKE 条件: – 条件类型:x [NOT] LIKE y [ESCAPE ’z’],描述:x 是否匹配模式 y。在 y 内,字符% 匹配任何零个或多 个字符的字符串,但 null 除外。字符 _ 匹配任何单个字符。ESCAPE 除百分号 (%) 和下划线 (_) 外,可 以跟随任何字符。如果前面有转义字符,则通配符被视为普通字符。 例子:SELECT last_name FROM employees WHERE last_name LIKE ’%A_B%’ ESCAPE ’\’ ORDER BY last_name; 为了处理这些 LIKE 条件,KingbaseES 将模式划分为子模式,每个子模式由一个或两个字符组成。两个字 符的子模式以转义字符开头,另一个字符是%、_ 或转义字符。 设 P1 , P2 , ..., Pn 是这些子模式。如果有办法将搜索值划分为子字符串 S1、S2、...、Sn ,则类似条件为 真,这样对于 1 和 n 之间的所有 i: ∗ 如果 Pi 是 _,则 Si 是单个字符。 ∗ 如果 Pi 是%,那么 Si 是任何字符串。 ∗ 如果 Pi 是以转义字符开头的两个字符,则 Si 是 Pi 的第二个字符。 ∗ 否则,Pi = Si。 使用 LIKE 条件,您可以将值与模式而不是常数进行比较。模式必须出现在 LIKE 关键字之后。 例如,您可以使用以下查询来查找姓名以 R 开头的所有员工的工资: SELECT salary FROM employees WHERE last_name LIKE 'R%' ORDER BY salary; 以下查询使用 = 运算符而不是 LIKE 条件来查找名称为“R%”的所有员工的薪水: SELECT salary FROM employees WHERE last_name = 'R%' ORDER BY salary; 以下查询查找名称为“SM%”的所有员工的工资。KingbaseES 将’SM%’ 解释为文本文字,而不是模式,因为 它位于 LIKE 关键字之前: SELECT salary FROM employees WHERE 'SM%' LIKE last_name ORDER BY salary; – 比较规则和大小写 字符串比较规则会影响模式匹配的结果。KingbaseES 在使用上述算法对子模式 Pi 和子串 Si 进行比较时, 会基于从 char1 和 char2 推导出的排序规则。如果该排序规则是大小敏感的,则模式匹配也是大小写敏感 的。 – 索引列上的模式匹配 163 第 7 章 条件表达式 当您使用 LIKE 对索引列进行模式匹配时,如果模式中的前导字符不是% 或 _,KingbaseES 可以使用索 引来提高查询的性能。在这种情况下,KingbaseES 可以通过这个前导字符扫描索引。如果模式中的第一个 字符是% 或 _ ,则索引无法提高性能,因为 KingbaseES 无法扫描索引。 LIKE 条件:一般示例 此条件适用于以 last_name 开头的所有值 Ma: last_name LIKE 'Ma%' 所有这些 last_name 值都使条件为真: Mallin、Markle、Marlow、Marvins、Marvis、Matos 大小写很重要,因此以 MA、ma 和 mA 条件开头的 last_name 值使条件为假。 考虑这种情况: last_name LIKE 'SMITH_' last_name 对于这些值,此条件为真: SMITHE,SMITHY,SMITHS 这个条件对于 SMITH 是假的,因为特殊的下划线字符 (_) 必须与 last_name 值的一个字符匹配。 ESCAPE 子句示例 以下示例搜索 A_B 名称中包含该模式的员工: SELECT last_name FROM employees WHERE last_name LIKE '%A\\_B%' ESCAPE '\\' ORDER BY last_ name; 该 ESCAPE 子句将反斜杠 (\) 标识为转义字符。在该模式中,转义字符位于下划线 (_) 之前。这导 致 KingbaseES 按字面意思解释下划线,而不是作为特殊的模式匹配字符。 没有% 示例的模式 如果一个模式不包含该% 字符,那么只有当两个操作数的长度相同时,该条件才能成立。考虑该表的 定义和插入其中的值: CREATE TABLE ducks (f CHAR(6), v VARCHAR2(6)); INSERT INTO ducks VALUES ('DUCK', 'DUCK'); SELECT '*'||f||'*' "char", '*'||v||'*' "varchar" FROM ducks; +--------------+----------+ | char | varchar | +==============+==========+ | \*DUCK\ \ \* | \*DUCK\* | +--------------+----------+ 164 第 7 章 条件表达式 因为 KingbaseES 对空白值进行了 CHAR 填充,所以 f 的值被空白填充为 6 个字节。v 不是空白填充 的,长度为 4。 • REGEXP_LIKE 条件 REGEXP_LIKE 类似于 LIKE 条件,只是 REGEXP_LIKE 执行正则表达式匹配,而不是由 LIKE 执行的简 单模式匹配。此条件使用由输入字符集定义的字符来计算字符串。 regexp_like_condition: REGEXP_LIKE(source_char, pattern [, match_param ] ) – source_char 是用作搜索值的字符表达式。它通常是一个字符列,可以是任何数据类型 CHAR、VARCHAR2、NCHAR、NVARCHAR2、CLOB 或 NCLOB。 – pattern 是正则表达式。它通常是文本文字,可以是任何数据类型 CHAR、VARCHAR2、NCHAR 或 NVARCHAR2。它最多可以包含 512 个字节。如果 pattern 的数据类型与 source_char 的数据类型不同, KingbaseES 将转换 pattern 为 source_char 的数据类型。 – match_param 是数据类型 VARCHAR2 或者 CHAR 的字符表达式,允许您更改条件的默认匹配行为。 match_param 的值可以包含以下一个或多个字符: ∗ ’i’ 指定不区分大小写的匹配,即使确定的条件排序规则是区分大小写的。 ∗ ’c’ 指定区分大小写和区分重音的匹配,即使确定的条件排序规则不区分大小写或不区分重音。 ∗ ’n’ 允许句点 (.),它是匹配任何字符的通配符,来匹配换行符。如果省略此参数,则句点与换行符不 匹配。 ∗ ’m’ 将源字符串视为多行。KingbaseES 将 ^ 和 $ 分别解释为源字符串中任何位置的任何行的开始和 结束,而不仅仅是整个源字符串的开始或结束。如果省略此参数,则 KingbaseES 将源字符串视为单 行。 ∗ ’x’ 忽略空白字符。默认情况下,空白字符匹配自己。 如果 match_param 的值包含多个相互矛盾的字符,则 KingbaseES 使用最后一个字符。例如,如果您指 定’ic’,则 KingbaseES 使用区分大小写和区分重音的匹配。如果该值包含上述字符以外的字符,则 KingbaseES 将返回错误。 如果省略 match_param,则: ∗ 默认大小写和重音敏感度由确定的 REGEXP_LIKE 条件排序规则确定。 ∗ 句点 (.) 与换行符不匹配。 165 第 7 章 条件表达式 ∗ 源字符串被视为单行。 LIKE 与条件类似,条件对 REGEXP_LIKE 排序规则敏感。 例子:以下查询返回名字为 Steven 或 Stephen 的员工的名字和姓氏(其中 first_name 开头 Ste 和结尾 en 是 v 或者 ph): SELECT first_name,last_name FROM employees WHERE REGEXP_LIKE (first_name, '^Ste(v|ph)en$') ORDER BY first_name,last_name; +------------+-----------+ | FIRST_NAME | LAST_NAME | +============+===========+ | ·King | Steven | +------------+-----------+ | Steven | Markle | +------------+-----------+ | ·stiles | Stephen | +------------+-----------+ 以下查询返回姓氏中有双元音的员工的姓氏(其中 last_name 包含两个相邻的 a, e, i, o, or u,无论大小写): SELECT last_name FROM employees WHERE REGEXP_LIKE (last_name, '([aeiou])\\1', 'i') ORDER BY last_name; +-----------+ | 姓 | +===========+ | De Haan | +-----------+ | Greenberg | +-----------+ | Khoo | +-----------+ | Gee | +-----------+ | Greene | +-----------+ | Lee | +-----------+ | Bloom | +-----------+ | Feene | +-----------+ 166 第 7 章 条件表达式 7.6 空条件 NULL 条件测试空值。这是您应该用来测试空值的唯一条件。 null_condition: expr IS [ NOT ] NULL 下面列出了 null 条件: 条件类型:IS [NOT] NULL,作用:测试空值。 例子: SELECT last_name FROM employees WHERE commission_pct IS NULL ORDER BY last_name; 7.7 SQL/JSON 条件 SQL/JSON 条件允许您测试 JavaScript Object Notation (JSON) 数据,如下所示: • IS JSON Condition 可让您测试表达式是否在语法上是正确的 JSON 数据 • JSON_EQUAL 测试两个 JSON 值是否相同 IS JSON Condition(Oracle 模式) 功能: Oracle 模式下 IS JSON 条件表达式用于测试输入文本是否具有良好的 JSON 语法结构,若符合良好的 JSON 语法结构则返回 true,否则返回 false。 用法: expr IS [NOT] JSON [ { VALUE | SCALAR | ARRAY | OBJECT } ] [STRICT | LAX][{WITH | WITHOUT} UNIQUE KEYS ] 167 第 7 章 条件表达式 其中 expr 可以是列名、字符串常量、字符串表达式和函数名,数据类型必须是字符类型变量(包括 character varying(n),varchar(n),character(n),char(n), character varying(n byte),varchar(n byte),character(n byte),char(n byte),bpchar(n),bpchar(n byte),text,clob,blob)且大小写不敏感; 如果 expr 是空值,无论是 is json 还是 is not json 都返回空值。若不是字符串值,返回类型错误。 LAX|STRICT 该参数指定对输入格式检查的严格程度,指定 STRICT 参数时,进入 strict 模式,对输入格式进行严格 检查,指定 lax 参数或者没有指定时,进入 LAX 模式,对输入文本的格式进行松散检查。 VALUE | SCALAR | ARRAY | OBJECT 判断输入字符串是否为 JSON 数据默认采用 LAX 规则进行处理。 VALUE: 判断输入表达式是否是 json 数据的任意类型,此为默认选项。 ARRAY: 判断输入表达式是否是 json 数据的 array 类型。 OBJECT:判断输入文本是否是 json 数据的 object 类型。 SCALAR:判断输入文本是否是 json 数据的标量类型(包含字符串,数字,true,false,null) WITH UNIQUE KEYS 如果此参数被指定,只有 expr 中的键名唯一时才会被认为是良好的 json 结构。 IS JSON Condition(PG 模式) 功能: Oracle 模式下 IS JSON 条件表达式用于测试输入文本是否具有良好的 JSON 语法结构,若符合良好的 JSON 语法结构则返回 true,否则返回 false。 用法: expr IS [ NOT ] JSON [ { VALUE | SCALAR | ARRAY | OBJECT } ] [ { WITH | WITHOUT } UNIQUE [ KEYS ] ] 168 第 7 章 条件表达式 其中 IS JSON VALUE 判断输入文本是否为 json 结构的任意类型,解析规则遵循严格的 JSON 语法标准,此为默认选项; IS JSON SCALAR 判断输入文本是否为标量类型(字符串,数字或者 bool 类型); IS JSON ARRAY 判断输入是否为数组类型; IS JSON OBJECT 判断输入是否为对象类型; [{WITH | WITHOUT} UNIQUE KEYS ] 指定是否对键名的唯一性进行检查。 示例: 例子:测试 STRICT 或 LAX JSON 语法 以下语句创建表 t: CREATE TABLE t (col1 VARCHAR2(100)); 以下语句将值插入到 col1 表的列中 t: INSERT INTO t VALUES ('["LIT192","CS141","HIS160"]'); INSERT INTO t VALUES ('{"Name":"John"}'); INSERT INTO t VALUES ('{"Grade Values":{ A:4.0,B:3.0,C:2.0}}'); INSERT INTO t VALUES ('{ "isEnrolled" :true }' ); INSERT INTO t VALUES ('{"isMatriculated":False }'); INSERT INTO t VALUES (NULL); INSERT INTO t VALUES ('This is not well-formed JSON data'); 以下语句查询表 t 并返回 col1 格式正确的 JSON 数据的值。由于未指定 STRICT 或 LAX 关键字,因此本示例 使用默认 LAX 设置。因此,此查询返回使用 strict 或 lax JSON 语法的值。 SELECT col1 FROM T WHERE col1 IS JSON; +--------------------------------------------+ | COL1 | +============================================+ | [“LIT192”、“CS141”、“HIS160”] | +--------------------------------------------+ 169 第 7 章 条件表达式 | {“NAME”:“John”} | +--------------------------------------------+ | {“Grade Values”:{A:4.0,B:3.0,C:2.0}} | +--------------------------------------------+ | {“isEnrolled”:trye} | +--------------------------------------------+ | {“isMatriculated”:False} | +--------------------------------------------+ 以下语句查询表 t 并返回 col1 格式正确的 JSON 数据的值。此示例指定 STRICT 设置。因此,此查询仅返回使 用严格 JSON 语法的值。 SELECT col1 FROM T WHERE col1 IS JSON STRICT; +-------------------------------+ | COL1 | +===============================+ | [“LIT192”、“CS141”、“HIS160”] | +-------------------------------+ | {“Name”:“John”} | +-------------------------------+ | {“isEnrolled”:true} | +-------------------------------+ 以下语句查询表 t 并返回 col1 使用宽松 JSON 语法的 col1 值,但省略使用严格 JSON 语法的值。因此,此查询 仅返回包含宽松 JSON 语法中允许的异常的值。 SELECT col1 FROM T WHERE col1 IS NOT JSON STRICT AND col1 IS JSON LAX; +--------------------------------------------+ | COL1 | +============================================+ | {“Grade Values”:{A:4.0,B:3.0,C:2.0}} | +--------------------------------------------+ | {“isMatriculated”:False} | +--------------------------------------------+ 测试唯一键示例: 以下语句创建表 t: CREATE TABLE t (col1 VARCHAR2(100)); 以下语句将值插入到 col1 表的列中 t: 170 第 7 章 条件表达式 INSERT INTO t VALUES ('{a:100, b:200, c:300}'); INSERT INTO t VALUES ('{a:100, a:200, b:300}'); INSERT INTO t VALUES ('{a:100, b : {a:100, c:300}}'); 以下语句查询表 t 并返回 col1 具有每个对象内唯一键名的格式良好的 JSON 数据的值: SELECT col1 FROM t WHERE col1 IS JSON WITH UNIQUE KEYS; +-----------------------------+ | COL1 | +=============================+ | {a:100, b:200, c:300} | +-----------------------------+ | {a:100, b : {a:100, c:300}} | +-----------------------------+ 返回第二行,因为虽然键名 a 出现了两次,但它位于两个不同的对象中。 以下语句查询表 t 并返回 col1 格式正确的 JSON 数据的值,无论每个对象中是否存在唯一键名: SELECT col1 FROM t WHERE col1 IS JSON WITHOUT UNIQUE KEYS; +-----------------------------+ | COL1 | +=============================+ | {a:100, b:200, c:300} | +-----------------------------+ | {a:100, a:200, b:300} | +-----------------------------+ | {a:100, b : {a:100, c:300}} | +-----------------------------+ 使用 IS JSON 作为检查约束示例: 下面的语句将创建表 j_purchaseorder,它将在 po_document 列中存储 JSON 数据。该语句使用 ISJSON 条件 作为检查约束,以确保只有格式良好的 JSON 存储在列 po_document 中。 CREATE TABLE j_purchaseorder (id RAW NOT NULL, date_loaded TIMESTAMP(6) WITH TIME ZONE, po_document CLOB CONSTRAINT ensure_json CHECK (po_document IS JSON)); JSON_EQUAL 用法: JSON_EQUAL(expr, expr [{ TRUE | FALSE | ERROR } ON ERROR]) 功能: 171 第 7 章 条件表达式 JSON_EQUAL 表达式比较两个 JSON 值,如果相等,返回 TRUE,如果不相等,返回 FALSE。输入值必须是 有效 JSON 值。 JSON_EQUAL 表达式在比较过程中忽略无关紧要的空白和对象成员顺序。例如,如果两个 JSON 对象具有相 同的成员,无论其顺序如何变化,均视为相等。 JSON_EQUAL 表达式支持 ERROR ON ERROR,FALSE ON ERROR 和 TRUE ON ERROR. 默认是 FALSE ON ERROR。一个典型的错误实例是输入表达式不是有效的 JSON 值。 例子: 下面的语句返回 TRUE: JSON_EQUAL('{}', '{ }'); JSON_EQUAL('{a:1, b:2}', '{b:2 , a:1 }'); 下面的语句返回 FALSE: JSON_EQUAL('{a:"1"}', '{a:1 }'); 下面的语句返回错误: JSON_EQUAL('[1]', '[}' ERROR ON ERROR); 7.8 复合条件 复合条件指定其他条件的组合。 复合条件: { (condition) | NOT condition | condition { AND | OR } condition } 172 第 7 章 条件表达式 7.9 BETWEEN 条件 BETWEEN 条件确定一个表达式的值是否在由其他两个表达式定义的区间内。 between_condition: expr1 [ NOT ] BETWEEN expr2 AND expr3 所有三个表达式都必须是数字、字符或日期时间表达式。在 SQL 中,expr1 可能会多次评估。如果 BETWEEN 表达式出现在 PL/SQL 中,expr1 则保证只计算一次。如果表达式不是所有相同的数据类型,则 KingbaseES 数据库 会将表达式隐式转换为通用数据类型。如果它不能这样做,那么它会返回一个错误。 以下两个表达式等价: expr1 NOT BETWEEN expr2 AND expr3 NOT(expr1 BETWEEN expr2 AND expr3) 下面这两个表达式是等价的: expr1 BETWEEN expr2 AND expr3 expr2 <= expr1 AND expr1 <= expr3 如果 expr3 < expr2,则区间为空。如果 expr1 是 NULL,那么结果是 NULL。如果 expr1 不为 NULL,则该值 为 FALSE,指定关键字 NOT 时则为 TRUE。 布尔运算符 AND 可能会产生意想不到的结果。具体来说,在表达式 x AND y 中,条件 x 为 NULL 不足以确定 该表达式的值。仍然需要计算第二个操作数 y。当第二个操作数为 FALSE 时结果为 FALSE,否则为 NULL。 以下为 BETWEEN 条件简介: 条件类型:[NOT] BETWEEN x AND y,简介:[NOT](expr2 小于等于 expr1 AND expr1 小于等于 expr3 )。 例子: SELECT * FROM employees WHERE salary BETWEEN 2000 AND 3000 ORDER BY employee_id; 173 第 7 章 条件表达式 7.10 EXISTS 条件 EXISTS 条件用于测试子查询中是否存在行。 EXISTS (subquery) 以下介绍了这种 EXISTS 情况: 条件类型:EXISTS,如果子查询至少返回一行,则为 TRUE。 例子: SELECT department_id FROM departments d WHERE EXISTS (SELECT * FROM employees e WHERE d.department_id = e. department_id) ORDER BY department_id; 7.11 IN 条件 in_condition 是一个成员条件。它用于测试给定值是否在指定的表达式列表或子查询中。 in_condition: { expr [ NOT ] IN [(]{ expression_list | subquery }[)] | [(] expr [, expr ]... [)] [ NOT ] IN [(]{ expression_list [, expression_list ]... | subquery } [)] } 表达式列表: 174 第 7 章 条件表达式 { expr [, expr ]... | [(] [expr [, expr ]] ...[)] } **注意 **MySQL 模式下 IN 条件中的括号不能省略。 如果使用 in_condition 条件的上方形式(在运算符的左边有一个单个表达式),则必须使用 expression_list 的 上方形式。如果使用此条件的下方形式(在运算符的左侧有多个表达式),则必须使用 expression_list 的下方形式, 并且每个 expression_list 中的表达式必须在维数和数据类型上与运算符左侧的表达式相匹配。 KingbaseES 数据库并不总是按照它们出现在 IN 列表中的顺序来计算 expression_list 中的表达式。但是,子查 询的选择列表中的表达式将按其指定的顺序进行计算。 以下列出了 IN 条件的形式: • 条件类型:IN,Equal-to-any-member,相当于 =。 示例: SELECT * FROM employees WHERE job_id IN ('PU_CLERK','SH_CLERK') ORDER BY employee_id; SELECT * FROM employees WHERE salary IN (SELECT salary FROM employees WHERE department_id = 30) ORDER BY employee_id; • 条件类型:NOT IN,叙述:相当于!= ALL。如果集合中的任何成员为 NULL,则计算为 FALSE。 示例: SELECT * FROM employees WHERE salary NOT IN (SELECT salary FROM employees WHERE department_id = 30) ORDER BY employee_id; SELECT * FROM employees WHERE job_id NOT IN ('PU_CLERK', 'SH_CLERK') ORDER BY employee_id; 如果 NOT IN 操作后列表中的任何项目计算结果为 null,则所有行计算结果为 FALSE 或 UNKNOWN,并且 不返回任何行。例如,以下语句为每一行返回字符串’TRUE ’: SELECT "TRUE" FROM employees WHERE department_id NOT IN (10, 20); 175 第 7 章 条件表达式 然而,以下语句不返回任何行: SELECT "TRUE" FROM employees WHERE department_id NOT IN (10, 20, NULL); 前面的示例不返回任何行,因为 WHERE 子句条件的计算结果为: department_id!= 10 AND department_id!= 20 AND department_id!= null 因为第三个条件 department_id 与 null 比较,所以结果为 UNKNOWN,因此整个表达式的结果为 FALSE(对 于 department_id 等于 10 或 20 的行)。这种行为很容易被忽略,尤其是当 NOT IN 操作符引用子查询时。 此外,如果某个 NOT IN 条件引用了一个根本不返回任何行的子查询,则将返回所有行,如下例所示: SELECT "TRUE" FROM employees WHERE department_id NOT IN (SELECT 0 FROM DUAL WHERE 1 = 2); 对于字符参数,IN 条件是排序规则敏感的。 176 第 8 章 函数 8 第 章 函数 函数类似于运算符,因为它们操作数据项并返回结果。函数在参数格式上与运算符不同。这种格式使它们能够对 零个、一个、两个或多个参数进行操作。 函数(参数,参数,...)没有任何参数的函数类似于伪列。但是,伪列通常为结果集中的每一行返回不同的值, 而没有任何参数的函数通常为每一行返回相同的值。 注意: KingbaseES 函数最大支持 8192 个参数,当参数个数超过 512 个时,将不再支持函数重载。 本章包含以下部分: • 关于 SQL 函数 • 数学函数 • 字符串函数 • 大对象函数 • 二进制串函数 • 模式匹配函数 • 数据类型格式化函数 • 时间日期函数 • 枚举支持函数 • SET 支持函数 • 几何函数 • 网络地址函数 • XML 函数 • JSON 函数 • 序列操作函数 177 第 8 章 函数 • 数组函数 • 范围函数 • 聚集函数 • 窗口函数 • 集合返回函数 • 系统信息函数 • 系统管理函数 • ABBREV • ABS • ACOS • ACOSH • ADDDATE(MySQL 模式) • ADDTIME(MySQL 模式) • ADD_MONTHS • AGE • APPENDCHILDXML • ARRAY_AGG • ARRAY_APPEND • ARRAY_CAT • ARRAY_DIMS • ARRAY_FILL • ARRAY_LENGTH • ARRAY_LOWER • ARRAY_NDIMS • ARRAY_POSITION • ARRAY_POSITIONS • ARRAY_PREPEND • ARRAY_REMOVE • ARRAY_REPLACE • ARRAY_TO_JSON • ARRAY_TO_STRING 178 第 8 章 函数 • ARRAY_TO_TSVECTOR • ARRAY_UPPER • ASIN • ASINH • ATAN • ATAN2 • ATANH • AVG • BFILENAME • BIT_AND • BIT_LENGTH • BIT_OR • BITAND • BITTONUMERIC • BLOB_EXPORT • BLOB_IMPORT • BOOL_AND • BOOL_OR • BOUND_BOX • BOX • BTRIM • CARDINALITY • CAST • CBRT • CEIL • CEILING • CENTER • CHAR_LENGTH • CHARACTER_LENGTH • CHARINDEX • CHARTOROWID 179 第 8 章 函数 • CHR • CIRCLE • CLOB_EXPORT • CLOB_IMPORT • CLOCK_TIMESTAMP • COALESCE • COL_DESCRIPTION • CONCAT • CONCAT_WS • CONNECTIONS • CONTAINS • CONVERT • CONVERT(MySQL 模式) • CONVERT_FROM • CONVERT_TO • CONVERT_TZ(MySQL 模式) • CORR • COS • COSH • COT • COUNT • COVAR_POP • COVAR_SAMP • CUME_DIST • CURDATE(MySQL 模式) • CURRENT_DATABASE • CURRENT_DATE • CURRENT_QUERY • CURRENT_SCHEMA • CURRENT_SCHEMAS • CURRENT_SETTING 180 第 8 章 函数 • CURRENT_TIME • CURRENT_TIME(MySQL 模式) • CURRENT_TIMESTAMP • CURRENT_TIMESTAMP(MySQL 模式) • CURRVAL • CURSOR_TO_XML • CURTIME(MySQL 模式) • DATEDIFF(MySQL 模式) • DAY(MySQL 模式) • DAYNAME(MySQL 模式) • DAYOFMONTH(MySQL 模式) • DAYOFWEEK(MySQL 模式) • DAYOFYEAR(MySQL 模式) • DATE_PART • DATE_SUB(MySQL 模式) • DATE_TRUNC • DAYS_BETWEEN • DECODE • DECODING • DEGREES • DELETEXML • DENSE_RANK • DIAMETER • DIV • EMPTY_BLOB • EMPTY_CLOB • EMPTY_NCLOB • ENCODE • ENUM_FIRST • ENUM_LAST • ENUM_RANGE 181 第 8 章 函数 • EVERY • EXISTSNODE • EXP • EXPORT_SET • EXTRACT • EXTRACT(MySQL 模式) • EXTRACTVALUE • FAMILY • FIND_IN_SET • FIRST • FIRST_VALUE • FLOOR • FORMAT • FORMAT_PICO_TIME(MySQL 模式) • FORMAT_TYPE • FROM_BASE64(MySQL 模式) • FROM_DAYS(MySQL 模式) • FROM_UNIXTIME(MySQL 模式) • GENERATE_SERIES • GENERATE_SUBSCRIPTS • GET_BIT • GET_BYTE • GET_CURRENT_TS_CONFIG • GET_DISK_INFO • GET_FORMAT(MySQL 模式) • GET_LICENSE_VALIDDAYS • GETUSERNAME • GREATEST • GROUP_CONCAT • GROUPING • GROUPING_ID 182 第 8 章 函数 • HAS_ANY_COLUMN_PRIVILEGE • HAS_COLUMN_PRIVILEGE • HAS_DATABASE_PRIVILEGE • HAS_FOREIGN_DATA_WRAPPER_PRIVILEGE • HAS_FUNCTION_PRIVILEGE • HAS_LANGUAGE_PRIVILEGE • HAS_SCHEMA_PRIVILEGE • HAS_SEQUENCE_PRIVILEGE • HAS_SERVER_PRIVILEGE • HAS_TABLE_PRIVILEGE • HAS_TABLESPACE_PRIVILEGE • HAS_TYPE_PRIVILEGE • HEIGHT • HEXTORAW • HOUR(MySQL 模式) • HOST • HOSTMASK • IF • IFNULL • INET_CLIENT_ADDR • INET_CLIENT_PORT • INET_MERGE • INET_SAME_FAMILY • INET_SERVER_ADDR • INET_SERVER_PORT • INITCAP • INSERTCHILDXML • INSERTCHILDXMLAFTER • INSERTCHILDXMLBEFORE • INSERTXMLAFTER • INSERTXMLBEFORE 183 第 8 章 函数 • INSTR • INSTRB • ISEMPTY • ISFINITE • ISNULL • ISNULL(MySQL 模式) • ISOPEN • JSON • JSON_AGG • JSON_ARRAY • JSON_ARRAY_ELEMENTS • JSON_ARRAY_ELEMENTS_TEXT • JSON_ARRAY_LENGTH • JSON_ARRAYAGG • JSON_BUILD_ARRAY • JSON_BUILD_OBJECT • JSON_EACH • JSON_EACH_TEXT • JSON_EQUAL • JSON_EXISTS • JSON_EXTRACT_PATH • JSON_EXTRACT_PATH_TEXT • JSON_OBJECT • JSON_OBJECT_AGG • JSON_OBJECT_KEYS • JSON_OBJECTAGG • JSON_POPULATE_RECORD • JSON_QUERY • JSON_SCALAR • JSON_SERIALIZE • JSON_STRIP_NULLS 184 第 8 章 函数 • JSON_TABLE • JSON_TO_RECORD • JSON_TO_RECORDSET • JSON_TYPEOF • JSON_VALUE • JSONB_AGG • JSONB_ARRAY_ELEMENTS • JSONB_ARRAY_ELEMENTS_TEXT • JSONB_ARRAY_LENGTH • JSONB_BUILD_ARRAY • JSONB_BUILD_OBJECT • JSONB_EACH • JSONB_EACH_TEXT • JSONB_EXTRACT_PATH • JSONB_EXTRACT_PATH_TEXT • JSONB_INSERT • JSONB_OBJECT • JSONB_OBJECT_AGG • JSONB_OBJECT_KEYS • JSONB_PATH_EXISTS • JSONB_PATH_MATCH • JSONB_PATH_QUERY • JSONB_PATH_QUERY_ARRAY • JSONB_PATH_QUERY_FIRST • JSONB_POPULATE_RECORD • JSONB_POPULATE_RECORDSET • JSONB_PRETTY • JSONB_SET • JSONB_STRIP_NULLS • JSONB_TO_RECORD • JSONB_TO_RECORDSET 185 第 8 章 函数 • JSONB_TYPEOF • JUSTIFY_DAYS • JUSTIFY_HOURS • JUSTIFY_INTERVAL • LAG • LAST • LAST_DAY • LAST_VALUE • LASTVAL • LCASE • LEAD • LEAST • LEFT • LENGTH • LENGTHB • LISTAGG • LN • LNNVL • LOCALTIME • LOCALTIME(MySQL 模式) • LOCALTIMESTAMP • LOCALTIMESTAMP(MySQL 模式) • LOCATE(MySQL 模式) • LOG • LOG10 • LOWER • LOWER_INC • LOWER_INF • LPAD • LSEG • LTRIM 186 第 8 章 函数 • MAKEDATE(MySQL 模式) • MAKETIME(MySQL 模式) • MAKE_DATE • MAKE_INTERVAL • MAKE_SET • MAKE_TIME • MAKE_TIMESTAMP • MAKE_TIMESTAMPTZ • MAX • MD5 • MICROSECOND(MySQL 模式) • MID • MIN • MINUTE(MySQL 模式) • MOD • MODE • MONTH(MySQL 模式) • MONTH(Oracle 模式) • MONTHNAME(MySQL 模式) • MONTHS_BETWEEN • NANVL • NEW_TIME • NEXT_DAY • NEXTVAL • NLSSORT • NOW • NTH_VALUE • NTILE • NULLIF • NUMTODSINTERVAL • NUMTOYMINTERVAL 187 第 8 章 函数 • NVL • NVL2 • OCTET_LENGTH • ORA_HASH • OVERLAY • PERCENT_RANK • PERCENTILE_CONT • PERCENTILE_DISC • PERIOD_ADD(MySQL 模式) • PERIOD_DIFF(MySQL 模式) • PI • POSITION • POWER • QUARTER(MySQL 模式) • QUERY_TO_XML • QUOTE_IDENT • QUOTE_LITERAL • QUOTE_NULLABLE • RADIANS • RADIUS • RAND • RANDOM • RANGE_MERGE • RANK • RATIO_TO_REPORT • RAWTOHEX • RAWTONHEX • REGEXP_LIKE • REGEXP_MATCH • REGEXP_MATCHES • REGEXP_REPLACE 188 第 8 章 函数 • REGEXP_REPLACE(Oracle 模式) • REGEXP_SPLIT_TO_ARRAY • REGEXP_SPLIT_TO_TABLE • REMAINDER • REPEAT • REPLACE • REVERSE • RIGHT • ROUND • ROW_COUNT(MySQL 模式) • ROW_NUMBER • ROW_TO_JSON • ROWIDTOCHAR • RPAD • RTRIM • SCALE • SCORE • SECOND(MySQL 模式) • SEC_TO_TIME(MySQL 模式) • SESSION_ID • SESSION_USER • SESSIONTIMEZONE • SETSEED • SETVAL • SETWEIGHT • SHA224 • SHA256 • SHA384 • SHA512 • SIGN • SIN 189 第 8 章 函数 • SINH • SPLIT_PART • SQRT • STATEMENT_TIMESTAMP • STDDEV • STDDEV(MySQL 模式) • STDDEV_POP • STDDEV_SAMP • STR_TO_DATE • STR_VALID • STRING_AGG • STRING_TO_ARRAY • STRIP • STRPOS • SUBSTR • SUBSTRB • SUBSTRING • SUBSTRING_INDEX(MySQL 模式) • SUBTIME(MySQL 模式) • SUM • SUPPRESS_REDUNDANT_UPDATES_TRIGGER • SYS_BACKEND_PID • SYS_CANCEL_BACKEND • SYS_COLUMN_SIZE • SYS_CONTEXT • SYS_DATABASE_SIZE • SYS_EVENT_TRIGGER_DDL_COMMANDS • SYS_EVENT_TRIGGER_DROPPED_OBJECTS • SYS_EVENT_TRIGGER_TABLE_REWRITE_OID • SYS_EVENT_TRIGGER_TABLE_REWRITE_REASON • SYS_FUNCTION_IS_VISIBLE 190 第 8 章 函数 • SYS_GET_CONSTRAINTDEF • SYS_GET_EXPR • SYS_GET_FUNCTION_ARGUMENTS • SYS_GET_FUNCTION_IDENTITY_ARGUMENTS • SYS_GET_FUNCTION_RESULT • SYS_GET_FUNCTIONDEF • SYS_GET_INDEXDEF • SYS_GET_KEYWORDS • SYS_GET_OBJECT_ADDRESS • SYS_GET_RULEDEF • SYS_GET_SERIAL_SEQUENCE • SYS_GET_STATISTICSOBJDEF • SYS_GET_TRIGGERDEF • SYS_GET_USERBYID • SYS_GET_VIEWDEF • SYS_GUID • SYS_HAS_ROLE • SYS_IDENTIFY_OBJECT • SYS_IDENTIFY_OBJECT_AS_ADDRESS • SYS_INDEXES_SIZE • SYS_KINGBASE_START_TIME • SYS_LS_DIR • SYS_LS_LOGDIR • SYS_LS_TMPDIR • SYS_LS_WALDIR • SYS_READ_BINARY_FILE • SYS_READ_FILE • SYS_RELATION_FILENODE • SYS_RELATION_FILEPATH • SYS_RELATION_SIZE • SYS_RELOAD_CONF 191 第 8 章 函数 • SYS_SIZE_BYTES • SYS_SIZE_PRETTY • SYS_SLEEP • SYS_SLEEP_FOR • SYS_SLEEP_UNTIL • SYS_STAT_FILE • SYS_TABLE_IS_VISIBLE • SYS_TABLE_SIZE • SYS_TABLESPACE_DATABASES • SYS_TABLESPACE_LOCATION • SYS_TABLESPACE_SIZE • SYS_TERMINATE_BACKEND • SYS_TOTAL_RELATION_SIZE • SYSDATE • TABLE_TO_XML • TAN • TANH • TIME(MySQL 模式) • TIMEDIFF(MySQL 模式) • TIMESTAMP(MySQL 模式) • TIMESTAMPADD(MySQL 模式) • TIMESTAMPDIFF(MySQL 模式) • TIME_FORMAT • TIME_TO_SEC(MySQL 模式) • TIMEOFDAY • TIMESUB • TO_ASCII • TO_BASE64(MySQL 模式) • TO_BINARY_DOUBLE • TO_BLOB • TO_CHAR 192 第 8 章 函数 • TO_DATE • TO_DATETIME • TO_DAYS(MySQL 模式) • TO_DSINTERVAL • TO_HEX • TO_JSON • TO_JSONB • TO_MULTI_BYTE • TO_NUMBER • TO_SECONDS(MySQL 模式) • TO_SINGLE_BYTE • TO_TIMESTAMP • TO_TIMESTAMP_TZ • TO_YMINTERVAL • TRANSACTION_TIMESTAMP • TRANSLATE • TRIM • TRUNC • UCASE • UNICODE • UNIX_TIMESTAMP(MySQL 模式) • UNNEST • UPDATEXML • UPPER • USER • USERENV • UTC_DATE(MySQL 模式) • UTC_TIME(MySQL 模式) • UTC_TIMESTAMP(MySQL 模式) • VALUE • VAR_POP 193 第 8 章 函数 • VAR_SAMP • VARIANCE • VARIANCE(MySQL 模式) • VERSION • WEEK(MySQL 模式) • WEEKDAY(MySQL 模式) • WEEKOFYEAR(MySQL 模式) • WM_CONCAT • XML_IS_WELL_FORMED • XML_IS_WELL_FORMED_CONTENT • XML_IS_WELL_FORMED_DOCUMENT • XMLAGG • XMLCOMMENT • XMLCONCAT • XMLELEMENT • XMLEXISTS • XMLFOREST • XMLPARSE • XMLPI • XMLROOT • XMLSEQUENCE • XMLSERIALIZE • XMLTABLE • XPATH • XPATH_EXISTS • YEAR • YEARWEEK(MySQL 模式) • 用户自定义函数 194 第 8 章 函数 8.1 关于 SQL 函数 SQL 函数内置于 KingbaseES 数据库中,可用于各种适当的 SQL 语句。不要将 SQL 函数与用 PL/SQL 编写的 用户定义函数混淆。 如果调用 SQL 函数的参数的数据类型与 SQL 函数预期的数据类型不同,那么 KingbaseES 会在执行 SQL 函数 之前尝试将参数转换为预期的数据类型。 8.1.1 SQL 函数中的空值 大多数标量函数在给定 null 参数时返回 null。您可以使用该 NVL 函数在发生 null 时返回一个值。例如,如果为 空,则表达式 NVL(commission_pct,0) 返回 0,如果 commission_pct 不为空,则返回的值 commission_pct。 有关聚集函数如何处理空值的信息,请参阅聚集函数 。 8.1.2 SQL 函数的语法 在 SQL 函数的语法图中,参数由它们的数据类型表示。当参数 function 出现在 SQL 语法中时,将其替换为本 节中描述的函数之一。函数按其参数和返回值的数据类型分组。 将 SQL 函数应用于 LOB 列时,KingbaseES 数据库会在 SQL 和 PL/SQL 处理期间创建临时 LOB。您应该确保 临时表空间配额足以为您的应用程序存储这些临时 LOB。 SQL 函数可能对排序规则敏感,这意味着它执行的字符值比较或匹配由排序规则控制。函数使用的特定排序规 则由函数参数的排序规则确定。 如果 SQL 函数的结果具有字符数据类型,则排序规则派生规则定义排序规则以与结果关联。 以下内容对 KingbaseES 数据库中的函数按照其用途进行分类,然后对每个函数的用法、功能、使用示例进行说 明。 8.2 数学函数 下列表显示 KingbaseES 了可用的数学函数。这些函数中有许多都有多种不同的形式,区别是参数不同,在这些 数字函数的参数中,dp 表示 double precision。除非特别指明,任何特定形式的函数都返回和它的参数相同的数 据类型。处理 double precision 数据的函数大多数是在宿主系统的 C 库基础上实现的。因此,边界情况下的准确 度和行为是根据宿主系统而变化的。 ABS BITAND BITTONUMERIC CBRT 195 第 8 章 函数 CEIL CEILING CORR COUNT COVAR_POP COVAR_SAMP CUME_DIST DEGREES DIV EXP FLOOR LN LOG LOG10 MOD NANVL PI POWER RADIANS RATIO_TO_REPORT REMAINDER ROUND ROW_COUNT(MySQL 模式) ROW_NUMBER SCALE SCORE SIGN SQRT TRUNC 用于产生随机数的函数。 RAND 196 第 8 章 函数 RANDOM SETSEED 下列表显示了可用的三角函数。所有三角函数都有类型为 double precision 的参数和返回类型。每一种三角函 数都有两个变体,一个以弧度度量角,另一个以角度度量角。 ACOS ASIN ATAN ATAN2 COS COT SIN TAN 下列表显示可用的双曲函数。所有这些函数的参数和返回值的类型都是 double precision。 SINH COSH TANH ASINH ACOSH ATANH 8.3 字符串函数 本节描述了用于检查和操作字符串值的函数。在这个环境中的串包括所有类型 character、character varying 和 text 的值。除非另外说明,所有下面列出的函数都可以处理这些类型,不过需要注意的是,在使用 character 类型的时候,它有自动填充空白的潜在影响。有些函数还可以处理位串类型。 SQL 定义了一些字符串函数,它们使用关键字,而不是逗号来分隔参数。详情请见下表,KingbaseES 也提供了 这些函数使用正常函数调用语法的版本。 注意: 由于存在从那些数据类型到 text 的隐式强制措施,在 KingbaseES V8R3 之前,这些函数也可以接受多种非 字符串数据类型。这些强制措施在目前版本中已经删除,因为它们常常导致令人惊讶的行为。不过,字符串串接操作 符(||)仍然接受非字符串输入,只要至少一个输入是一种字符串类型,如下表所示。对于其他情况,如果你需要复 197 第 8 章 函数 制之前的行为,可以为 text 插入一个显式强制措施。对于 || 操作符,支持两个字符之间输入若干空格或者换行的 字符,效果和不加空格或换行一致。 BIT_LENGTH BTRIM CHAR_LENGTH CHARACTER_LENGTH CHARINDEX CHARTOROWID CHR COALESCE CONCAT CONCAT_WS CONTAINS CONVERT CONVERT_FROM CONVERT_TO DECODE DECODING QUOTE_IDENT QUOTE_LITERAL QUOTE_NULLABLE ENCODE FORMAT FROM_BASE64(MySQL 模式) GREATEST GROUP_CONCAT GROUPING GROUPING_ID HEXTORAW IF 198 第 8 章 函数 IFNULL ISNULL ISNULL(MySQL 模式) INITCAP LNNVL INSTR INSTRB LCASE LEAST LEFT LENGTH LENGTHB LOWER LTRIM MID NLSSORT NULLIF NVL NVL2 OCTET_LENGTH ORA_HASH OVERLAY POSITION RAWTOHEX RAWTONHEX REPEAT REPLACE REVERSE RIGHT ROWIDTOCHAR RPAD 199 第 8 章 函数 RTRIM SETWEIGHT SPLIT_PART STRIP STRPOS SUBSTR SUBSTRB SUBSTRING SUBSTRING_INDEX(MySQL 模式) SYS_GUID TO_BASE64(MySQL 模式) TRANSLATE TRIM TRUNC UCASE UNICODE UPPER WM_CONCAT 8.4 大对象函数 本节描述那些检查和操作类型为大对象类型的值的函数。 BFILENAME BLOB_EXPORT BLOB_IMPORT CLOB_EXPORT CLOB_IMPORT EMPTY_BLOB EMPTY_CLOB EMPTY_NCLOB TO_BLOB 200 第 8 章 函数 8.5 二进制串函数 本节描述那些检查和操作类型为 bytea 的值的函数。 SQL 定义了一些使用关键字而不是逗号来分割参数的串函数。详情请见下表。KingbaseES 也提供了这些函数使 用常规函数调用语法的版本。 注意: 本页中显示的示例结果假设服务器参数 bytea_output 被设置为 escape(传统 KingbaseES 格式)。 BTRIM DECODING ENCODE FROM_BASE64(MySQL 模式) GET_BIT GET_BYTE LENGTH MD5 OCTET_LENGTH OVERLAY POSITION SHA224 SHA256 SHA384 SHA512 SUBSTRING TRIM 8.6 模式匹配函数 本节描述了 KingbaseES 支持 POSIX 正则表达式模式匹配的函数。 REGEXP_COUNT REGEXP_INSTR REGEXP_LIKE 201 第 8 章 函数 REGEXP_REPLACE REGEXP_REPLACE(Oracle 模式) REGEXP_MATCH REGEXP_MATCHES REGEXP_SPLIT_TO_TABLE REGEXP_SPLIT_TO_ARRAY 8.7 数据类型格式化函数 KingbaseES 格式化函数提供一套强大的工具用于把各种数据类型(日期/时间、整数、浮点、数字)转换成格式 化的字符串以及反过来从格式化的字符串转换成指定的数据类型。下表列出了这些函数。这些函数都遵循一个公共的 调用规范:第一个参数是待格式化的值,而第二个是一个定义输出或输入格式的模板。 CAST CONVERT(MySQL 模式) FORMAT FORMAT_PICO_TIME(MySQL 模式) NUMTODSINTERVAL NUMTOYMINTERVAL ROWIDTOCHAR TO_ASCII TO_BINARY_DOUBLE TO_BLOB TO_CHAR TO_DATE TO_DATETIME TO_DSINTERVAL TO_HEX TO_JSON TO_JSONB TO_MULTI_BYTE TO_NUMBER 202 第 8 章 函数 TO_SINGLE_BYTE TO_TIMESTAMP TO_TIMESTAMP_TZ TO_YMINTERVAL 表 8.7.1: 数据类型格式化函数 函数 返回类型 描述 例子 to_char( timestamp , text ) text 把时间戳转成字符串 to_char(current_timestamp, ’HH12:MI:SS’) to_char( interval , text ) 把间隔转成字符串 text to_char(interval ’15h? 2m? 12s’,HH24:MI:SS’) to_char( int , text ) text 把整数转成字符串 to_char(125, ’999’) to_char( double precision , text 把实数或双精度转成 to_char(125.8::real, ’999D9’) 字符串 text ) to_char( numeric , text ) text 把数字转成字符串 to_char(-125.8, ’999D99S’) to_date( text , text ) date 把字符串转成日期 to_date(’05? Dec? 2000’, ’DD? Mon? YYYY’) to_number( text , text ) numeric 把字符串转成数字 to_number(’12,454.8-’,’99G999D9S’) to_timestamp( text , text ) timestamp 把字符串转成时间戳 to_timestamp(’05?Dec?2000’,D?Mon? with time YYYY’) zone to_timestamp_tz(expr1 text ) timestamp 把字符串转换成 with WITH TEMSTAMP time TI to_timestamp_tz(’2010-10-10 10:10:10’) zone IME ZONE 类型 to_timestamp_tz(expr1 text , timestamp 把字符串按照 expr2 to_timestamp_tz(’97/2/16 8:14:30’, expr2 text ) with 的格式转换成 TIEM- ’FMYYYY/ FMDD STAMP WITH TIME FMHH:FMMI:FMSS’) time zone FMMM/ ZONE 类型 注意: 还有一个单一参数的 to_timestamp 函数。 提示: to_timestamp 和 to_date 存在的目的是为了处理无法用简单造型转换的输入格式。对于大部分标准的日 203 第 8 章 函数 期/时间格式,简单地把源字符串造型成所需的数据类型是可以的,并且简单很多。类似地,对于标准的数字表示形 式,to_number 也是没有必要的。 在一个 to_char 输出模板串中,一些特定的模式可以被识别并且被替换成基于给定值的被恰当地格式化的数 据。任何不属于模板模式的文本都简单地照字面拷贝。同样,在一个输入模板串里(对其他函数),模板模式标识 由输入数据串提供的值。如果在模板字符串中有不是模板模式的字符,输入数据字符串中的对应字符会被简单地跳过 (不管它们是否等于模板字符串字符)。 下表展示了可以用于格式化日期和时间值的模版。 表 8.7.2: 用于日期/时间格式化的模板模式 模式 描述 HH 一天中的小时(01-12) HH12 一天中的小时(01-12) HH24 一天中的小时(00-23) MI 分钟(00-59)minute (00-59) SS 秒(00-59) MS 毫秒(000-999) US 微秒(000000-999999) SSSS 午夜后的秒(0-86399) AM, am, PM or pm 正午指示器(不带句号) A.M., a.m., P.M. or p.m. 正午指示器(带句号) Y,YYY 带逗号的年(4 位或者更多位) YYYY 年(4 位或者更多位) YYY 年的后三位 YY 年的后两位 Y 年的最后一位 IYYY ISO 8601 周编号方式的年(4 位或更多位) IYY ISO 8601 周编号方式的年的最后 3 位 IY ISO 8601 周编号方式的年的最后 2 位 见续表 204 第 8 章 函数 表 8.7.2 – 续表 模式 描述 I ISO 8601 周编号方式的年的最后一位 BC, bc, AD 或者 ad 纪元指示器(不带句号) B.C., b.c., A.D. 或者 a.d. 纪元指示器(带句号) MONTH 全大写形式的月名(空格补齐到 9 字符) Month 全首字母大写形式的月名(空格补齐到 9 字符) month 全小写形式的月名(空格补齐到 9 字符) MON 简写的大写形式的月名(英文 3 字符,本地化长度可变) Mon 简写的首字母大写形式的月名(英文 3 字符,本地化长度可变) mon 简写的小写形式的月名(英文 3 字符,本地化长度可变) MM 月编号(01-12) DAY 全大写形式的日名(空格补齐到 9 字符) Day 全首字母大写形式的日名(空格补齐到 9 字符) day 全小写形式的日名(空格补齐到 9 字符) DY 简写的大写形式的日名(英语 3 字符,本地化长度可变) Dy 简写的首字母大写形式的日名(英语 3 字符,本地化长度可变) dy 简写的小写形式的日名(英语 3 字符,本地化长度可变) DDD 一年中的日(001-366) IDDD ISO 8601 周编号方式的年中的日(001-371,年的第 1 日时第一个 ISO 周 的周一) DD 月中的日(01-31) D 周中的日,周日(1)到周六(7) ID 周中的 ISO 8601 日,周一(1)到周日(7) W 月中的周(1 -5)(第一周从该月的第一天开始) WW 年中的周数(1- 53)(第一周从该年的第一天开始) 见续表 205 第 8 章 函数 表 8.7.2 – 续表 模式 描述 IW ISO 8601 周编号方式的年中的周数(01 - 53 ;新的一年的第一个周四在第 一周) CC 世纪(2 位数)(21 世纪开始于 2001-01-01) J 儒略日(从午夜 UTC 的公元前 4714 年 11 月 24 日开始的整数日数) Q 季度(to_date 和 to_timestamp 会忽略) RM 大写形式的罗马计数法的月(I-XII;I 是一月) rm 小写形式的罗马计数法的月(i-xii;i 是一月) TZ 大写形式的时区缩写(仅在 to_char 中支持) tz 小写形式的时区缩写(仅在 to_char 中支持) TZH 时区的小时 TZM 时区的分钟 OF 从 UTC 开始的时区偏移(仅在 to_char 中支持) 修饰语可以被应用于模板模式来修改它们的行为。例如,FMMonth 就是带着 FM 修饰语的 Month 模式。 表 8.7.3: 用于日期/时间格式化的模板模式修饰语 修饰语 描述 例子 FM prefix 填充模式(抑制前导零和填充的空格) FMMonth TH suffix 大写形式的序数后缀 DDTH, e.g., 12TH th suffix 小写形式的序数后缀 DDth, e.g., 12th FX prefix 固定的格式化全局选项(见使用须知) FX?Month?DD?Day TM prefix 翻译模式(基于 lc_time 打印本地化的日 TMMonth 和月名) SP suffix 拼写模式(未实现) DDSP 日期/时间格式化的使用须知: • FM 抑制前导的零或尾随的空白,否则会把它们增加到输入从而把一个模式的输出变成固定宽度。在 KingbaseES 中,FM 只修改下一个声明,而在 Oracle 中,FM 影响所有随后的声明,并且重复的 FM 修饰语将触发 填充模式开和关。 206 第 8 章 函数 • TM 不包括结尾空白。to_timestamp 和 to_date 会忽略 TM 修饰语。 • 除非使用了 FX 选项,否则 to_timestamp 和 to_date 跳过输入字符串开头的多个空格以及日期和时间值。例 如,to_timestamp('?2000????JUN', 'YYYY MON') 和 to_timestamp('2000 - JUN', 'YYYY-MON') 运行, 但 to_timestamp('2000????JUN', 'FXYYYY MON') 返回一个错误,因为 to_timestamp 只需要一个空格。FX 必须指定为模板中的第一项。 • 分隔符 (空格或非字母/非数字字符) 任 何 单 个 分 隔 符 或 被 跳 过, 除 非 使 用 在模板字符串 to_timestamp FX 和 to_date 匹配输入字符串中的 选 项。 例 如,to_timestamp('2000JUN', 'YYYY///MON') 和 to_timestamp('2000/JUN', 'YYYY MON') 运行,但 to_timestamp('2000//JUN', 'YYYY/MON') 返回一 个错误,因为输入字符串中的分隔符数量超过模板中的分隔符数量。 如果指定了 FX,模板字符串中的分隔符将与输入字符串中的一个字符匹配。但是请注意,输入字符串 字 符 不 需 要 与 模 板 字 符 串 的 分 隔 符 相 同。 例 如, to_timestamp('2000/JUN', 'FXYYYY MON') 运 行, 但 to_timestamp('2000/JUN', 'FXYYYY??MON') 返回一个错误,因为模板字符串中的第二个空格使用了输入字 符串中的字母 J。 • 一个 TZH 模板模式可以匹配一个有符号的数字。如果没有 FX 选项,负号可能是不明确的,并且可以被解释 为分隔符。这种歧义的解决方法如下: 如果模板字符串中 TZH 之前的分隔符数量小于输入字符串中负号之前的 分隔符数量,则负号被解释为 TZH。否则,负号被认为是值之间的分隔符。例如, to_timestamp('2000 -10', 'YYYY TZH') 匹配-10 到 TZH,但 to_timestamp('2000 -10', 'YYYY??TZH') 匹配 10 到 TZH。 • 在 to_char 模板里可以有普通文本,并且它们会被照字面输出。你可以把一个子串放到双引号里强迫它被解释 成一个文本,即使它里面包含模板模式也如此。例如,在 '"Hello Year" YYYY'中,YYYY 将被年份数据代替, 但是 Year 中单独的 Y 不会。在 to_date、to_number 以及 to_timestamp 中,文本和双引号字符串会导致跳 过该字符串中所包含的字符数量,例如"XX" 会跳过两个输入字符(不管它们是不是 XX)。 提示: KingbaseES V9 之前的版本, 可以使用非字母或非数字字符跳过输入字符串中的任意文本。例 如,to_timestamp('2000y6m1d', 'yyyy-MM-DD') 曾被使用。 现 在 您 只 能 使 用 字 母 字 符 来 实 现 此 目 的。 例 如,to_timestamp('2000y6m1d', 'yyyytMMtDDt') 和 to_timestamp('2000y6m1d', 'yyyy"y"MM"m"DD"d"') 忽略 y、m、和 d。 • 如果你想在输出里有双引号,那么你必须在它们前面放反斜线,例如 '\"YYYY Month\"'。不然,在双引号字符 串外面的反斜线就不是特殊的。在双引号字符串内,反斜线会导致下一个字符被取其字面形式,不管它是什么 字符(但是这没有特殊效果,除非下一个字符是一个双引号或者另一个反斜线)。 • 在 to_timestamp 和 to_date 中,如果年份格式声明少于四位(如 YYY)并且提供的年份少于四位,年份将被 调整为最接近于 2020 年,例如 95 会变成 1995。 • 在 to_timestamp 和 to_date 中,在处理超过 4 位数的年份时,YYYY 转换具有限制。你必须在 YYYY 后 面 使 用 一 些 非 数 字 字 符 或 者 模 板, 否 则 年 份 总 是 被 解 释 为 4 位 数 字。 例 如 (对 于 20000 年): to_date('200001131', 'YYYYMMDD') 将会被解释成一个 4 位数字的年份,而不是在年份后使用一个非数 字分隔符,像 to_date('20000-1131', 'YYYY-MMDD') 或 to_date('20000Nov31', 'YYYYMonDD')。 • 在 to_timestamp 和 to_date 中,CC(世纪)字段会被接受,但是如果有 YYY、YYYY 或者 Y,YYY 字段则会 忽略它。如果 CC 与 YY 或 Y 一起使用,则结果被计算为指定世纪中的那一年。如果指定了世纪但是没有指定 207 第 8 章 函数 年,则会假定为该世纪的第一年。 • 在 to_timestamp 和 to_date 中,工作日名称或编号(DAY、D 以及相关的字段类型)会被接受,但会为了计 算结果的目的而忽略。季度(Q)字段也是一样。 • 在 to_timestamp 和 to_date 中,一个 ISO 8601 周编号的日期(与一个格里高利日期相区别)可以用两种方 法之一被指定为 to_timestamp 和 to_date: – 年、周编号和工作日:例如 to_date('2006-42-4', 'IYYY-IW-ID') 返回日期 2006-10-19。如果你忽略 工作日,它被假定为 1(周一)。 – 年和一年中的日:例如 to_date('2006-291', 'IYYY-IDDD') 也返回 2006-10-19。 尝试使用一个混合了 ISO 8601 周编号和格里高利日期的域来输入一个日期是无意义的,并且将导致一个错误。 在一个 ISO 周编号的年的环境下,一个“月”或“月中的日”的概念没有意义。在一个格里高利年的环境下,ISO 周 没有意义。用户应当避免混合格里高利和 ISO 日期声明。 警告: 虽然 to_date 将会拒绝混合使用格里高利和 ISO 周编号日期的域,to_char 却不会,因为 YYYY-MM-DD (IYYY-IDDD) 这种输出格式也会有用。但是避免写类似 IYYY-MM-DD 的内容,那会得到在起始年附 近异常的结果(详见EXTRACT , DATE_PART )。 • 在 to_timestamp 中,毫秒(MS)和微秒(US)域都被用作小数点后的秒位。例如 to_timestamp('12.3', 'SS.MS') 不是 3 毫秒, 而是 300,因为该转换把它看做 12 + 0.3 秒。这意味着对于格式 SS.MS 而言,输入 值 12.3、12.30 和 12.300 指定了相同数目的毫秒。要得到三毫秒,你必须使用 12.003,转换会把它看做 12 + 0.003 = 12.003 秒。 下面是一个更复杂的例子 �to_timestamp('15:12:02.020.001230', 'HH24:MI:SS.MS.US') 是 15 小时、12 分 钟和 2 秒 + 20 毫秒 + 1230 微秒 = 2.021230 秒。 • to_char(..., 'ID') 的一周中日的编号匹配 extract(isodow from ...) 函数,但是 to_char(..., 'D') 不匹配 extract(dow from ...) 的日编号。 • to_char(interval) 格式化 HH 和 HH12 为显示在一个 12 小时的时钟上,即零小时和 36 小时输出为 12,而 HH24 会输出完整的小时值,对于间隔它可以超过 23. 下表展示了可以用于格式化数字值的模版模式。 208 第 8 章 函数 表 8.7.4: 用于数字格式化的模板模式 模式 描述 9 数位(如果无意义可以被删除) 0 数位(即便没有意义也不会被删除) . (period) 小数点 , (comma) 分组(千)分隔符 PR 尖括号内的负值 S 带符号的数字(使用区域) L 货币符号(使用区域) D 小数点(使用区域) G 分组分隔符(使用区域) MI 在指定位置的负号(如果数字 < 0) PL 在指定位置的正号(如果数字 > 0) SG 在指定位置的正/负号 RN 罗马数字(输入在 1 和 3999 之间) TH or th 序数后缀 V 移动指定位数(参阅注解) EEEE 科学记数的指数 数字格式化的用法须知: • 0 指定一个总是被打印的数位,即便它包含前导/拖尾的零。9 也指定一个数位,但是如果它是前导零则会被 空格替换,而如果是拖尾零并且指定了填充模式则它会被删除(对于 to_number() 来说,这两种模式字符等 效)。 • 模式字符 S、L、D 以及 G 表示当前 locale 定义的负号、货币符号、小数点以及数字分隔符字符(见 lc_monetary 和 lc_numeric )。不管 locale 是什么,模式字符句号和逗号就表示小数点和数字分隔符。 • 对于 to_char() 的模式中的一个负号,如果没有明确的规定,将为该负号保留一列,并且它将被锚接到(出现 在左边)那个数字。如果 S 正好出现在某个 9 的左边,它也将被锚接到那个数字。 • 使用 SG、PL 或 MI 格式化的符号并不挂在数字上面;例如,to_char(-12, 'MI9999') 生成'-??12',而 to_char(-12, 'S9999') 生成 '??-12'。(Oracle 里的实现不允许在 9 前面使用 MI,而是要求 9 在 MI 前 面。) 209 第 8 章 函数 • TH 不会转换小于零的数值,也不会转换小数。 • PL、SG 和 TH 是 KingbaseES 扩展。 • 在 to_number 中,如果没有使用 L 或 TH 之类的非数据模板模式,相应数量的输入字符会被跳过,不管它们是 否匹配模板模式,除非它们是数据字符(也就是数位、负号、小数点或者逗号)。例如,TH 会跳过两个非数据 字符。 • 带有 to_char 的 V 会把输入值乘上 10^n,其中 “n“是跟在 V 后面的位数。带有 to_number 的 V 以类似的方 式做除法。to_char 和 to_number 不支持使用结合小数点的 V(例如,不允许 99.9V99)。 • EEEE(科学记数法)不能和任何其他格式化模式或修饰语(数字和小数点模式除外)组合在一起使用,并且必 须位于格式化字符串的最后(例如 9.99EEEE 是一个合法的模式)。 某些修饰语可以被应用到任何模板来改变其行为。例如,FM99.99 是带有 FM 修饰语的 99.99 模式。下表展示 了用于数字格式化模式修饰语。 表 8.7.5: 用于数字格式化的模板模式修饰语 修饰语 描述 例子 FM prefix 填充模式(抑制拖尾零和填充的空白) FM99.99 TH suffix 大写序数后缀 999TH th suffix 小写序数后缀 999th 下表展示了一些使用 to_char 函数的例子。 表 8.7.6: to_char 例子 表达式 结果 to_char(current_timestamp, 'Day,?DD??HH12:MI:SS') 'Tuesday??,?06??05:39:18' to_char(current_timestamp, 'FMDay,?FMDD??HH12:MI:SS') 'Tuesday,?6??05:39:18' to_char(-0.1, '99.99') '??-.10' to_char(-0.1, 'FM9.99') '-.1' to_char(-0.1, 'FM90.99') '-0.1' to_char(0.1, '0.9') '?0.1' to_char(12, '9990999.9') '????0012.0' to_char(12, 'FM9990999.9') '0012.' to_char(485, '999') '?485' 见续表 210 第 8 章 函数 表 8.7.6 – 续表 表达式 结果 to_char(-485, '999') '-485' to_char(485, '9?9?9') '?4?8?5' to_char(1485, '9,999') '?1,485' to_char(1485, '9G999') '?1?485' to_char(148.5, '999.999') '?148.500' to_char(148.5, 'FM999.999') '148.5' to_char(148.5, 'FM999.990') '148.500' to_char(148.5, '999D999') '?148,500' to_char(3148.5, '9G999D999') '?3?148,500' to_char(-485, '999S') '485-' to_char(-485, '999MI') '485-' to_char(485, '999MI') '485?' to_char(485, 'FM999MI') '485' to_char(485, 'PL999') '+485' to_char(485, 'SG999') '+485' to_char(-485, 'SG999') '-485' to_char(-485, '9SG99') '4-85' to_char(-485, '999PR') '<485>' to_char(485, 'L999') 'DM?485' to_char(485, 'RN') '????????CDLXXXV' to_char(485, 'FMRN') 'CDLXXXV' to_char(5.2, 'FMRN') 'V' to_char(482, '999th') '?482nd' to_char(485, '"Good?number:"999') 'Good?number:?485' 见续表 211 第 8 章 函数 表 8.7.6 – 续表 表达式 结果 to_char(485.8, '"Pre:"999"?Post:"?.999') 'Pre:?485?Post:?.800' to_char(12, '99V999') '?12000' to_char(12.4, '99V999') '?12400' to_char(12.45, '99V9') '?125' to_char(0.0004859, '9.99EEEE') ' 4.86e-04' 8.8 时间日期函数 下表展示了可用于处理日期/时间值的函数,其细节在随后的小节中描述。并演示了基本算术操作符(+、* 等) 的行为。而与格式化相关的函数,可以参考数据类型格式化函数 。 所有下文描述的接受 time 或 timestamp 输入的函数和操作符实际上都有两种变体:一种接收 time with time zone 或 timestamp with time zone,另外一种接受 time without time zone 或者 timestamp without time zone。为了简化,这些变种没有被独立地展示。此外,+ 和 * 操作符都是可交换的操作符对(例如,date + integer 和 integer + date);我们只显示其中一个。 注意: 参数为 interval 类型的函数,也支持 yminterval 或 dsinterval 类型的参数。 ADDDATE(MySQL 模式) ADDTIME(MySQL 模式) ADD_MONTHS AGE CONVERT_TZ(MySQL 模式) CLOCK_TIMESTAMP CURDATE(MySQL 模式) CURRENT_DATE CURRENT_TIME CURRENT_TIME(MySQL 模式) CURRENT_TIMESTAMP CURRENT_TIMESTAMP(MySQL 模式) 212 第 8 章 函数 CURTIME(MySQL 模式) DATEDIFF(MySQL 模式) DAY(MySQL 模式) DAYNAME(MySQL 模式) DAYOFMONTH(MySQL 模式) DAYOFWEEK(MySQL 模式) DAYOFYEAR(MySQL 模式) DATE_PART DATE_SUB(MySQL 模式) DATE_TRUNC DAYS_BETWEEN EXTRACT EXTRACT(MySQL 模式) FORMAT_PICO_TIME(MySQL 模式) FROM_DAYS(MySQL 模式) FROM_UNIXTIME(MySQL 模式) GET_FORMAT(MySQL 模式) HOUR(MySQL 模式) ISFINITE JUSTIFY_DAYS JUSTIFY_HOURS JUSTIFY_INTERVAL LAST_DAY LOCALTIME LOCALTIME(MySQL 模式) LOCALTIMESTAMP LOCALTIMESTAMP(MySQL 模式) LOCATE(MySQL 模式) MAKEDATE(MySQL 模式) MAKETIME(MySQL 模式) MAKE_DATE 213 第 8 章 函数 MAKE_INTERVAL MAKE_TIME MAKE_TIMESTAMP MAKE_TIMESTAMPTZ MICROSECOND(MySQL 模式) MINUTE(MySQL 模式) MONTH(MySQL 模式) MONTH(Oracle 模式) MONTHNAME(MySQL 模式) MONTHS_BETWEEN NEW_TIME NEXT_DAY NOW PERIOD_ADD(MySQL 模式) PERIOD_DIFF(MySQL 模式) QUARTER(MySQL 模式) ROUND SECOND(MySQL 模式) SEC_TO_TIME(MySQL 模式) SESSIONTIMEZONE STATEMENT_TIMESTAMP STR_VALID STR_TO_DATE SUBTIME(MySQL 模式) SYSDATE TIME(MySQL 模式) TIMEDIFF(MySQL 模式) TIMESTAMP(MySQL 模式) TIMESTAMPADD(MySQL 模式) TIMESTAMPDIFF(MySQL 模式) TIME_FORMAT 214 第 8 章 函数 TIME_TO_SEC(MySQL 模式) TIMEOFDAY TIMESUB TO_DAYS(MySQL 模式) TO_SECONDS(MySQL 模式) TO_TIMESTAMP TRUNC UNIX_TIMESTAMP(MySQL 模式) UTC_DATE(MySQL 模式) UTC_TIME(MySQL 模式) UTC_TIMESTAMP(MySQL 模式) WEEK(MySQL 模式) WEEKDAY(MySQL 模式) WEEKOFYEAR(MySQL 模式) YEAR YEARWEEK(MySQL 模式) 8.9 枚举支持函数 对于枚举类型有一些函数允许更清洁的编码,而不需要为一个枚举类型硬写特定的值。它们被列在下表中。 ENUM_FIRST ENUM_LAST ENUM_RANGE 8.10 SET 支持函数 下表展示了可以用于 SET 类型的函数。 EXPORT_SET FIND_IN_SET MAKE_SET(bits,oid) 215 第 8 章 函数 8.11 几何函数 几何类型 point、box、lseg、line、path、polygon 和 circle 有一大堆本地支持函数,如下列表所示。 BOUND_BOX BOX CENTER CIRCLE DIAMETER HEIGHT ISOPEN LENGTH LSEG RADIUS 8.12 网络地址函数 下表展示了所有可以用于 cidr 和 inet 类型的函数。函数 abbrev、host 主要是为了提供可选的显示格式用 的。 ABBREV FAMILY HOST HOSTMASK INET_CLIENT_ADDR INET_CLIENT_PORT INET_MERGE INET_SAME_FAMILY INET_SERVER_ADDR INET_SERVER_PORT 216 第 8 章 函数 8.13 XML 函数 本节中描述的函数以及类函数的表达式都在类型 xml 的值上操作。 用于在值和类型 xml 之间转换的类函数的表达式 xmlparse 和 xmlserialize 不在这里重复介绍。 APPENDCHILDXML CURSOR_TO_XML DELETEXML EXISTSNODE EXTRACT EXTRACTVALUE INSERTCHILDXML INSERTCHILDXMLAFTER INSERTCHILDXMLBEFORE INSERTXMLAFTER INSERTXMLBEFORE QUERY_TO_XML TABLE_TO_XML UPDATEXML XMLCOMMENT XMLCONCAT XMLELEMENT XMLEXISTS XMLFOREST XMLPI XMLROOT XMLSEQUENCE XMLSERIALIZE XMLTABLE XML_IS_WELL_FORMED XML_IS_WELL_FORMED_CONTENT XML_IS_WELL_FORMED_DOCUMENT 217 第 8 章 函数 XPATH XPATH_EXISTS XMLAGG XMLCOMMENT XMLCONCAT XMLELEMENT XMLEXISTS XMLFOREST XMLPARSE XMLPI XMLROOT XMLSEQUENCE XMLSERIALIZE XMLTABLE XPATH XPATH_EXISTS 8.14 JSON 函数 本节描述用于处理和创建 JSON 数据的函数。 ARRAY_TO_JSON JSON JSON_AGG JSON_ARRAY JSON_ARRAY_ELEMENTS JSON_ARRAY_ELEMENTS_TEXT JSON_ARRAY_LENGTH JSON_ARRAYAGG JSON_BUILD_ARRAY JSON_BUILD_OBJECT JSON_EACH 218 第 8 章 函数 JSON_EACH_TEXT JSON_EQUAL JSON_EXISTS JSON_EXTRACT_PATH JSON_EXTRACT_PATH_TEXT JSON_OBJECT JSON_OBJECT_AGG JSON_OBJECT_KEYS JSON_OBJECTAGG JSON_POPULATE_RECORD JSON_QUERY JSON_SCALAR JSON_SERIALIZE JSON_STRIP_NULLS JSON_TABLE JSON_TO_RECORD JSON_TO_RECORDSET JSON_TYPEOF JSON_VALUE JSONB_AGG JSONB_ARRAY_ELEMENTS JSONB_ARRAY_ELEMENTS_TEXT JSONB_ARRAY_LENGTH JSONB_BUILD_ARRAY JSONB_BUILD_OBJECT JSONB_EACH JSONB_EACH_TEXT JSONB_EXTRACT_PATH JSONB_EXTRACT_PATH_TEXT JSONB_INSERT JSONB_OBJECT 219 第 8 章 函数 JSONB_OBJECT_AGG JSONB_OBJECT_KEYS JSONB_PATH_EXISTS JSONB_PATH_MATCH JSONB_PATH_QUERY JSONB_PATH_QUERY_ARRAY JSONB_PATH_QUERY_FIRST JSONB_POPULATE_RECORD JSONB_POPULATE_RECORDSET JSONB_PRETTY JSONB_SET JSONB_STRIP_NULLS JSONB_TO_RECORD JSONB_TO_RECORDSET JSONB_TYPEOF ROW_TO_JSON TO_JSON TO_JSONB 8.15 序列操作函数 本节描述用于操作 序列对象的函数,序列对象也被称为序列生成器或者就是序列。序列对象通常用于为表的行 生成唯一的标识符。下表中列出的这些序列函数,可以为我们从序列对象中获取连续的序列值提供了简单的、多用户 安全的方法。 CURRVAL LASTVAL NEXTVAL SETVAL 220 第 8 章 函数 8.16 数组函数 下表展示了可以用于数组类型的函数。 ARRAY_APPEND ARRAY_CAT ARRAY_DIMS ARRAY_FILL ARRAY_LENGTH ARRAY_LOWER ARRAY_NDIMS ARRAY_POSITION ARRAY_POSITIONS ARRAY_PREPEND ARRAY_REMOVE ARRAY_REPLACE ARRAY_TO_JSON ARRAY_TO_STRING ARRAY_TO_TSVECTOR ARRAY_UPPER CARDINALITY STRING_TO_ARRAY UNNEST 8.17 范围函数 下表显示可用于范围类型的函数。 ISEMPTY LOWER_INC LOWER_INF RANGE_MERGE 221 第 8 章 函数 8.18 聚集函数 聚集函数从一个输入值的集合计算出一个单一值。在 SELECT 语句中支持聚集函数嵌套调用,SELECT 列表中 仅支持一层聚集函数嵌套,查询语句中必须包含 GROUP BY 子句。 ARRAY_AGG AVG BIT_AND BIT_OR BOOL_AND BOOL_OR CORR COUNT COVAR_POP COVAR_SAMP CUME_DIST EVERY FIRST GROUP_CONCAT JSON_AGG JSON_ARRAYAGG JSON_OBJECT_AGG JSON_OBJECTAGG JSONB_AGG JSONB_OBJECT_AGG LAST LISTAGG MAX MIN RANK STDDEV STDDEV(MySQL 模式) 222 第 8 章 函数 STDDEV_POP STDDEV_SAMP STRING_AGG SUM VAR_POP VAR_SAMP VARIANCE VARIANCE(MySQL 模式) WM_CONCAT XMLAGG 8.19 窗口函数 窗口函数提供在与当前查询行相关的行集合上执行计算的能力。 下表列出了内建的窗口函数。注意必须使用窗口函数的语法调用这些函数;一个 OVER 子句是必需的。 在这些函数之外,任何内建的或者用户定义的通用或者统计性聚集(即非有序集和假想集聚集)都可以被用作一 个窗口函数,内建聚集的列表请见聚集函数 。仅当聚集函数调用后面跟着一个 OVER 子句时,聚集函数才会像窗口函 数那样工作,否则它们会按非窗口聚集的方式运行并且为整个集合返回一个单一行。 “DISTINCT“表示在基于窗口帧执行聚集计算时,忽略参数值重复的行。 用法: function_name ( [[DISTINCT] expression [, expression ... ]]) [ FILTER ( WHERE filter_clause ) ] OVER window_ name 223 第 8 章 函数 function_name ( [[DISTINCT] expression [, expression ... ]]) [ FILTER ( WHERE filter_clause ) ] OVER ( window_definition ) 示例 select a, b, c, count(distinct c) over (partition by a) v from tab where a < 3; a | b | c | v ---+---+---+--1 | 1 | 1 | 5 1 | 1 | 1 | 5 1 | 1 | 2 | 5 1 | 2 | 2 | 5 1 | 2 | 3 | 5 1 | 2 | 3 | 5 1 | | 4 | 5 1 | | 4 | 5 1 | | 5 | 5 1 | | 5 | 5 2 | 3 | 1 | 5 2 | 3 | 1 | 5 2 | 3 | 2 | 5 2 | 4 | 2 | 5 2 | 4 | 3 | 5 2 | 4 | 3 | 5 2 | | 4 | 5 2 | | 4 | 5 2 | | 5 | 5 2 | | 5 | 5 (20 rows) CUME_DIST DENSE_RANK 224 第 8 章 函数 FIRST FIRST_VALUE LAG LAST LAST_VALUE LEAD LISTAGG MIN MODE NTH_VALUE NTILE PERCENT_RANK PERCENTILE_CONT PERCENTILE_DISC RANK RATIO_TO_REPORT ROW_NUMBER SUM TO_MULTI_BYTE TO_SINGLE_BYTE 8.20 集合返回函数 本节描述那些可能返回多于一行的函数。目前这个类中被使用最广泛的是级数生成函数。其他更特殊的集合返回 函数在本手册的其他地方描述。 GENERATE_SERIES GENERATE_SUBSCRIPTS VALUE 225 第 8 章 函数 8.21 系统信息函数 下表展示了多个可以抽取会话和系统信息的函数。 除了本节列出的函数,还有一些与统计系统相关的函数也提供系统信息。 COL_DESCRIPTION CONNECTIONS CURRENT_DATABASE CURRENT_QUERY CURRENT_SCHEMA CURRENT_SCHEMAS FORMAT_TYPE GETUSERNAME GET_CURRENT_TS_CONFIG GET_LICENSE_VALIDDAYS HAS_ANY_COLUMN_PRIVILEGE HAS_COLUMN_PRIVILEGE HAS_DATABASE_PRIVILEGE HAS_FOREIGN_DATA_WRAPPER_PRIVILEGE HAS_FUNCTION_PRIVILEGE HAS_LANGUAGE_PRIVILEGE HAS_SCHEMA_PRIVILEGE HAS_SEQUENCE_PRIVILEGE HAS_SERVER_PRIVILEGE HAS_TABLE_PRIVILEGE HAS_TABLESPACE_PRIVILEGE HAS_TYPE_PRIVILEGE INET_CLIENT_ADDR INET_CLIENT_PORT INET_SERVER_ADDR INET_SERVER_PORT SESSION_ID 226 第 8 章 函数 SESSION_USER SYS_BACKEND_PID SYS_CONTEXT SYS_FUNCTION_IS_VISIBLE SYS_GET_CONSTRAINTDEF SYS_GET_EXPR SYS_GET_FUNCTION_ARGUMENTS SYS_GET_FUNCTION_IDENTITY_ARGUMENTS SYS_GET_FUNCTION_RESULT SYS_GET_FUNCTIONDEF SYS_GET_INDEXDEF SYS_GET_KEYWORDS SYS_GET_OBJECT_ADDRESS SYS_GET_RULEDEF SYS_GET_SERIAL_SEQUENCE SYS_GET_STATISTICSOBJDEF SYS_GET_TRIGGERDEF SYS_GET_USERBYID SYS_GET_VIEWDEF SYS_HAS_ROLE SYS_IDENTIFY_OBJECT SYS_IDENTIFY_OBJECT_AS_ADDRESS SYS_KINGBASE_START_TIME SYS_TABLE_IS_VISIBLE SYS_TABLESPACE_DATABASES SYS_TABLESPACE_LOCATION TRANSACTION_TIMESTAMP USER USERENV VERSION 227 第 8 章 函数 8.22 系统管理函数 这一节描述的函数被用来控制和监视一个 KingbaseES 安装。包括配置设定函数、服务器信号函数、备份控制函 数、恢复控制函数、数据库对象管理函数、索引维护函数、通用文件访问函数等。参见下表: CURRENT_SETTING GET_DISK_INFO SYS_CANCEL_BACKEND SYS_COLUMN_SIZE SYS_DATABASE_SIZE SYS_INDEXES_SIZE SYS_LS_DIR SYS_LS_LOGDIR SYS_LS_TMPDIR SYS_LS_WALDIR SYS_READ_BINARY_FILE SYS_READ_FILE SYS_RELATION_FILENODE SYS_RELATION_FILEPATH SYS_RELATION_SIZE SYS_RELOAD_CONF SYS_SIZE_BYTES SYS_SIZE_PRETTY SYS_SLEEP SYS_SLEEP_FOR SYS_SLEEP_UNTIL SYS_STAT_FILE SYS_TABLE_SIZE SYS_TABLESPACE_SIZE SYS_TERMINATE_BACKEND SYS_TOTAL_RELATION_SIZE 228 第 8 章 函数 8.23 触发器函数 KingbaseES 提供内建的触发器函数,来影响触发行为: SUPPRESS_REDUNDANT_UPDATES_TRIGGER 8.24 事件触发器函数 KingbaseES 提供了一些助手函数来从事件触发器检索信息: SYS_EVENT_TRIGGER_DDL_COMMANDS SYS_EVENT_TRIGGER_DROPPED_OBJECTS SYS_EVENT_TRIGGER_TABLE_REWRITE_OID SYS_EVENT_TRIGGER_TABLE_REWRITE_REASON 8.25 ABBREV 用法: abbrev({inet | cidr}) 功能: 缩写显示格式文本 例子: abbrev(inet ’10.1.0.0/16’) abbrev(cidr ’10.1.0.0/16’) 8.26 ABS 用法: 229 第 8 章 函数 abs (n) 功能: ABS 返回 n 的绝对值。 此函数将任何数值数据类型或任何可以隐式转换为数值数据类型的非数值数据类型作为参数。该函数返回与参数 的数值数据类型相同的数据类型。 例子: 以下示例返回 -10 的绝对值: SELECT abs(-10); 8.27 ACOS 用法: acos(n) 功能: ACOS 返回 n 的反余弦。参数 n 必须在 -1 到 1 的范围内,并且函数返回一个在 0 到 pi 范围内的值,以弧度表 示。 此函数将任何数值数据类型或任何可以隐式转换为数值数据类型的非数值数据类型作为参数。如果参数是 BINARY_FLOAT,则函数返回 BINARY_DOUBLE。否则,函数返回与参数相同的数值数据类型。 例子: 以下示例返回 0.5 的反余弦: SELECT acos('0.5'); 8.28 ACOSH 用法: 230 第 8 章 函数 acosh(n) 功能: ACOS 返回 n 的反双曲余弦。 例子: 以下示例返回 3 的反双曲余弦: SELECT acosh(float8 '3'); 8.29 ADDDATE(MySQL 模式) 用法: adddate(date,float4) returns date adddate(date,interval) return datetime adddate(datetime,float4) return datetime adddate(datetime,interval) return datetime adddate(timestamp,float4) return timestamp adddate(timestamp,interval) return timestamp adddate(time,float4) return datetime adddate(time,interval) return datetime 功能: 参数为 date 和 float4 时,返回结果为 date 表示的日期加上 round(float4) 天数的日期; 参数为 date 和 interval 时,计算 date 表示的日期加上 interval 之后的结果; 参数为 datetime 和 float4 时,返回结果为当前 datetime 值加上 round(float4) 天数的 datetime 类型值; 参数为 datetime 和 interval 时,计算当前 datetime 值加上 interval 之后的结果; 参数为 timestamp 和 float4 时,返回结果为当前 timestamp 表示的时间戳加上 round(float4) 天数的 timestamp 类型值; 参数为 timestamp 和 interval 时,计算 timestamp 表示的时间戳加上 interval 之后的结果; 参数为 time 和 float4 时,计算当前日期下的时间加上 round(float4) 天数的 datetime 类型值; 参数为 time 和 interval 时,计算当前日期下的时间加上 interval 后的 datetime 类型值。 例子: 231 第 8 章 函数 test=# select adddate(date'2022-10-24', 520); adddate -----------2024-03-27 (1 row) test=# select adddate(date'2022-10-24', interval '5' month); adddate --------------------2023-03-24 00:00:00 (1 row) test=# select adddate(datetime'2022-10-24 21:30:00', 520); adddate --------------------2024-03-27 21:30:00 (1 row) test=# select adddate(datetime'2022-10-24 21:30:00', interval '5' hour); adddate --------------------2022-10-25 02:30:00 (1 row) test=# select adddate(timestamp'2022-10-24 21:30:00', 520); adddate --------------------2024-03-27 21:30:00 (1 row) test=# select adddate(timestamp'2022-10-24 21:30:00', interval '5' minute); adddate --------------------2022-10-24 21:35:00 (1 row) test=# select adddate(time'21:30:00', 520); adddate --------------------2024-12-02 21:30:00 (1 row) test=# select adddate(time'21:30:00', interval '5' second); adddate --------------------- 232 第 8 章 函数 2023-07-01 21:30:05 (1 row) 8.30 ADDTIME(MySQL 模式) 用法: addtime(n1,n2) 功能: 将日期时间 n1 与时间 n2 相加。 参数和返回值说明: 函数返回值由参数类型决定,详见下表: 表 8.30.1: ADDTIME-PARAMETER 参数 n1 参数 n2 返回值 date time timestamp interval timestamp time interval time interval interval time time time interval interval 参数范围及返回结果说明如下: 233 第 8 章 函数 表 8.30.2: ADDTIME-PARAMETER-RANGE 参数 类型 值域 输出结果 n1 date 4713 BC 至 5874897 AD 正常输出 timestamp 4713 BC 至 294276 AD time -838:59:59 到 838:59:59 interval -178000000 年至 178000000 年 返回空 NULL n2 空值 无 报错 time -838:59:59 到 838:59:59 正常输出 interval -178000000 年至 178000000 年 报错 NULL 空值 无 其他类型 注意: 当参数 n1 为 date 日期类型时,若未指定时间部分,时间值默认为“00:00:00”。 例子: SELECT ADDTIME(date'2020-01-01',time'12:00:00') "ADDTIME"; ADDTIME --------------------2020-01-01 12:00:00 SELECT ADDTIME(timestamp'2020-01-01 12:00:00',interval'1 02:00:00') "ADDTIME"; ADDTIME --------------------2020-01-02 14:00:00 SELECT ADDTIME(time'12:00:00',time'02:00:00') "ADDTIME"; ADDTIME --------------------- 234 第 8 章 函数 14:00:00 SELECT ADDTIME(interval'1 01:00:00',interval'1 02:00:00') "ADDTIME"; ADDTIME -----------51:00:00 8.31 ADD_MONTHS 用法: add_months(expr1,expr2) 功能: 返回 expr1 加上 expr2 个月的日期时间值。 a. expr1 数据类型是日期/时间类型 (DATE、TIMESTAMP 和 TIMESTAMPTZ) 或可以转换为日期/时间类型的 数据类型。输入日期/时间格式串时自动转成 TIMESTAMP。 b. expr2 数据类型为 INT 型。 输入 TIMESTAMP 和 TIMESTAMPTZ 时返回 TIMESTAMP。输入 DATE 时返回 DATE。 例子: select add_months(date'2012-1-20',-1) AS RESULT; select add_months(timestamp'2012-1-31 10:00:00',-20) select add_months('20120101',12) AS RESULT; AS RESULT; 8.32 AGE 用法: 235 第 8 章 函数 age(timestamp, timestamp) age(timestamp) 功能: 减去参数生成一个年、月不包含日的格式化结果。当只有一个参数时减去 current_date (午夜时间)。 例子: SELECT age(timestamptz '2013-07-01 12:00:00', timestamptz '2011-03-01 12:00:00'); 8.33 APPENDCHILDXML 用法: appendchildxml(xml_instance xml, xpath text , value_expr xml) appendchildxml(xml_instance xml, xpath text , value_expr xml,namespace _text) 功能: 函数 appendchildxml 将 “value_expr“提供的值作为 “xpath“节点的子节点追加到 “xml_instance“中。成功则返 回追加后的 “xml_instance“数据,失败则返回 ERROR。此函数使用前需要创建 kdb_utils_function 扩展。 例子: SELECT appendchildxml('', '/test/value', XMLPARSE(CONTENT 'newnode')); 8.34 ARRAY_AGG 用法: 236 第 8 章 函数 array_agg(expression) 功能: 当参数为非数组类型时,array_agg 将输入值 (包括空值) 连接到一个数组,返回参数类型的数组。当参数为数 组类型时,array_agg 将输入数组串接到一个更高维度的数组中,并返回一个与参数数据类型相同的数组。输入数组 必须具有相同维度,并且不能为空或者 NULL。 例子: SELECT array_agg(array[i, nullif(i, 3), i+1]) from generate_series(1,4) g(i); 8.35 ARRAY_APPEND 用法: array_append(anyarray, anyelement) 功能: 向数组 anyarray 末端追加元素 anyelement。 例子: SELECT array_append( ARRAY[1,2], 3); 8.36 ARRAY_CAT 用法: array_append(anyarray1, anyarray2) 237 第 8 章 函数 功能: 连接两个数组。 例子: SELECT array_cat( ARRAY[1,2], ARRAY[3,4]); 8.37 ARRAY_DIMS 用法: array_dims(anyarray) 功能: 返回数组维度的文本表示。 例子: SELECT array_dims( ARRAY[[1,2,3], [4,5,6]]); 8.38 ARRAY_FILL 用法: array_fill(anyelement, int[], int[]) 功能: 返回一个用指定值和指定维度初始化后的数组。 例子: SELECT array_fill( 7, ARRAY[3], ARRAY[2]); 238 第 8 章 函数 8.39 ARRAY_LENGTH 用法: array_length(anyarray,int) 功能: 返回数组指定维度的长度。 例子: SELECT array_length( array[1,2,3,4], 1); 8.40 ARRAY_LOWER 用法: array_lower(anyarray, int) 功能: 返回数组指定维度下界。 例子: SELECT array_lower( array[1,2,3,4], 1); 8.41 ARRAY_NDIMS 用法: array_ndims(anyarray) 239 第 8 章 函数 功能: 返回数组维度数。 例子: SELECT array_ndims( ARRAY[[1,2,3], [4,5,6]]); 8.42 ARRAY_POSITION 用法: array_position(anyarray, anyelement[, int]) 功能: 返回数组中 anyelement 第一次出现的下标,如果函数第三个参数指定,那么从第三个参数指定的下标开始查 找。 例子: SELECT array_position( ARRAY['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'], 'mon'); 8.43 ARRAY_POSITIONS 用法: array_positions(anyarray, anyelement) 功能: 240 第 8 章 函数 返回数组 anyarray 中出现 anyelement 的下标组成的数组。 例子: SELECT array_positions( ARRAY['A', 'A', 'B', 'A'], 'A'); 8.44 ARRAY_PREPEND 用法: array_prepend(anyelement, anyarray) 功能: 向数组头部插入元素。 例子: SELECT array_prepend( 1, ARRAY[2,3]); 8.45 ARRAY_REMOVE 用法: array_remove(anyarray, anyelement) 功能: 从数组 anyarray 中移除值为 anyelement 的元素。 例子: SELECT array_remove( ARRAY[1,2,3,2], 2); 241 第 8 章 函数 8.46 ARRAY_REPLACE 用法: array_replace(anyarray, anyelement1, anyelement2) 功能: 将数组 anyarray 中值为 anyelement1 的元素替换为 anyelement1。 例子: SELECT array_replace( ARRAY[1,2,5,4], 5, 3); 8.47 ARRAY_TO_JSON 用法: array_to_json(anyarray [, pretty_bool]) 功能: 把数组 anyarray 作为 json 数组返回,一个多维数组会成为一个数组的 json 数组。如果 pretty_bool 设为真, 将会在数组维度之间增加换行符。 例子: SELECT array_to_json('{{1,5},{99,100}}'::int[],true); 8.48 ARRAY_TO_STRING 用法: 242 第 8 章 函数 array_to_string(anyarray, text [, text]) 功能: 使用指定的分隔符和可选的空字符串连接数组元素。 例子: SELECT array_to_string( ARRAY[1, 2, 3, NULL, 5],',', '*'); 8.49 ARRAY_TO_TSVECTOR 用法: array_to_tsvector(text[]) 功能: 文本搜索函数之一,把词位数组转化成 tsvector。 例子: SELECT array_to_tsvector('{fat,cat,rat}'::text[]); 8.50 ARRAY_UPPER 用法: array_upper(anyarray, int) 功能: 243 第 8 章 函数 返回数组指定维度上界。 例子: SELECT array_upper( ARRAY[1,8,3,7], 1); 8.51 ASIN 用法: asin(n) 功能: ASIN 返回 n 的反正弦。参数 n 必须在 -1 到 1 的范围内,函数返回的值在-pi /2 到 pi /2 的范围内,以弧度表 示。 此函数将任何数值数据类型或任何可以隐式转换为数值数据类型的非数值数据类型作为参数。如果参数是 BINARY_FLOAT,则函数返回 BINARY_DOUBLE。否则,函数返回与参数相同的数值数据类型。 例子: 以下示例返回 0.5 的反正弦: SELECT ASIN(0.5); 8.52 ASINH 用法: asinh(n) 功能: ASINH 返回 n 的反双曲正弦。 例子: 244 第 8 章 函数 以下示例返回 0.5 的反正弦: SELECT asinh(2); 8.53 ATAN 用法: atan(n) 功能: ATAN 返回 n 的反正切。参数 n 可以在无界范围内,并返回 - pi /2 到 pi /2 范围内的值,以弧度表示。 此函数将任何数值数据类型或任何可以隐式转换为数值数据类型的非数值数据类型作为参数。如果参数是 BINARY_FLOAT,则函数返回 BINARY_DOUBLE。否则,函数返回与参数相同的数值数据类型。 例子: 以下示例返回 0.5 的反正切: SELECT ATAN(0.5) ; 8.54 ATAN2 用法: atan2(n1, n2) 功能: ATAN2 返回 n1 和 n2 的反正切。参数 n1 可以在无界范围内,并返回-pi 到 pi 范围内的值,具体取决于 n1 和 n2 的符号,以弧度表示。 此函数将任何数值数据类型或任何可以隐式转换为数值数据类型的非数值数据类型作为参数。如果任何参数是 BINARY_FLOATor BINARY_DOUBLE,则函数返回 BINARY_DOUBLE。否则函数返回 NUMBER。 245 第 8 章 函数 例子: 以下示例返回 1 和 2 的反正切: SELECT atan2(1,2); 8.55 ATANH 用法: atanh(n) 功能: ATANh 返回 n 的反双曲正切。 例子: 以下示例返回 0.2 的反双曲正切: SELECT atanh(0.2); 8.56 AVG 用法: avg(expression) 功能: AVG 返回 expr 的平均值。 此函数将任何数值数据类型或任何可以隐式转换为数值数据类型的非数值数据类型作为参数。该函数返回与参数 的数值数据类型相同的数据类型。 例子: 以下示例计算 students 表中所有学生的平均成绩(score): 246 第 8 章 函数 SELECT avg(score) from students; 8.57 BFILENAME 用法: bfilename('directory','filename') 功能: 利用 bfilename 函数来向BFILE 类型 插入值。当向 BFILE 字段插入空串或 NULL 时,会直接返回 0。 注意: 仅支持 Oracle 模式下使用此函数。 参数说明: directory:是文件在服务器文件系统上实际所在目录名的别名。 filename:是服务器文件系统上的文件名。 例子: 利用 bfilename 函数向 bfile 字段插入数据: CREATE DIRECTORY dir as '/tmp/bfile'; CREATE DIRECTORY dir1 as '/tmp/bfile'; CREATE TABLE test_bfile(id int, column_bfile bfile); CREATE TABLE test_bfile1(id int, column_bfile bfile default NULL); INSERT INTO test_bfile VALUES(1, bfilename('','myfile.sql')); INSERT INTO test_bfile VALUES(2, bfilename('dir','')); INSERT INTO test_bfile VALUES(3, bfilename('dir','myfile.sql')); INSERT INTO test_bfile VALUES(4, bfilename('dir1','myfile1.sql')); INSERT INTO test_bfile VALUES(5, NULL); INSERT INTO test_bfile VALUES(6, ''); SELECT * FROM test_bfile; id|column_bfile | --+--------------------------------+ 247 第 8 章 函数 1|bfilename(NULL, 'myfile.sql') | 2|bfilename('dir', NULL) | 3|bfilename('dir', 'myfile.sql') | 4|bfilename('dir1', 'myfile1.sql')| 5| | 6| | 8.58 BIT_AND 用法: bit_and(expression) 功能: 聚集函数,计算所有非空值按位与。如果没有非空值传入,返回空值。 例子: CREATE TABLE tinyint_fun(a tinyint); INSERT INTO tinyint_fun values('55'); INSERT INTO tinyint_fun values('100'); SELECT bit_and(a) from tinyint_fun; 8.59 BIT_LENGTH 用法: bit_length(string) 功能: 返回 string 中的位数。 例子: 248 第 8 章 函数 SELECT bit_length('jose'); 8.60 BIT_OR 用法: bit_or(expression) 功能: 聚集函数,对输入的非空值按位或运算,如果没有输入非空值,则返回空值。 例子: CREATE TABLE tinyint_fun(a tinyint); INSERT INTO tinyint_fun values('55'); INSERT INTO tinyint_fun values('100'); SELECT bit_or(a) from tinyint_fun; 8.61 BITAND 用法: bitand(expr1, expr2) 功能: 该 BITAND 函数将其输入和输出视为位向量;输出是 AND 输入的按位。expr1 和的类型 expr2 是 NUMBER, 结果是类型 NUMBER。如果任一参数 BITAND 为 NULL,则结果为 NULL。参数必须在 -(2 (n-1) ) .. ((2 (n-1) )-1) 范围内。如果参数超出此范围,则结果未定义。 结果分几个步骤计算。首先,每个参数 A 都被替换为 value SIGN(A)*FLOOR(ABS(A))。这种转换具有将每个 参数截断为零的效果。接下来,每个参数 A(现在必须是整数值)被转换为 n 位二进制补码二进制整数值。使用按位 运算组合这两个位值 AND。最后,将得到的 n 位二进制补码值转换回 NUMBER。 249 第 8 章 函数 注意: • BITAND 定义的当前实现 n= 128。 • PL/SQL 支持重载,BITAND 其中输入和结果的类型都为 all BINARY_INTEGER,并且 n= 32。‘ 例子: 以下示例 AND 对数字 6(二进制 1,1,0)和 3(二进制 0,1,1)执行操作: SELECT BITAND(6,3); 8.62 BITTONUMERIC 用法: bittonumeric(expr) 功能: 此函数将 0 和 1 组成的位串转为 numeric 类型数值。expr 可以是 01 组成的常量串 (’0110’),也可以是 bit(n),varbit(n) 类型的表达式,其中 n 最大支持 64,超过会报错,即返回值范围为 64 位整数的取值范围。 例子: select bittonumeric('0110'); --6 create table tb(a varbit(10)); insert into tb values('1110110'); select bittonumeric(a) from tb; --118 8.63 BLOB_EXPORT 用法: blob_export(blob ,string ) 250 第 8 章 函数 功能: 将 blob 大对象的内容导出到磁盘文件。 例子: 将 test_blob 表的 lob 列导入到 blob_out.data 文件中。 SELECT blob_export(lob, 'blob_out.data') FROM test_blob; 8.64 BLOB_IMPORT 用法: blob_import(string ) 功能: 将指定文件 blob 大对象的形式导入到数据库。 例子: 将 blob_out.data 文件导入到 test_blob 表的 lob 列中。 INSERT INTO test_blob VALUES (2, blob_import('./blob.data')); 8.65 BOOL_AND 用法: bool_and(expression) 功能: 聚集函数,求逻辑与,如果所有输入值为真则结果为真,否则为假。 例子: 对表 table 的列 boolcol 所有值求逻辑与。 251 第 8 章 函数 SELECT bool_and(boolcol) FROM table; 8.66 BOOL_OR 用法: bool_or(expression) 功能: 聚集函数,求逻辑或,如果有输入值为真则结果为真,否则为假。 例子: 对表 table 的列 boolcol 所有值求逻辑或。 SELECT bool_or(boolcol) FROM table; 8.67 BOUND_BOX 用法: bound_box(box, box) 功能: 几何函数,方框到外包框。 例子: 对表 table 的列 boolcol 所有值求逻辑或。 SELECT bound_box(box '((0,0),(1,1))', box '((3,3),(4,4))'); 252 第 8 章 函数 8.68 BOX 用法: box(circle) box(point) box(point, point) box(polygon) 功能: 几何函数,根据参数不同。 • circle 圆到方框 • point 点到空方框 • point,point 点到方框 • polygon 多边形到方框 例子: SELECT box(circle '((0,0),2.0)'); SELECT box(point '(0,0)'); SELECT box(point '(0,0)', point '(1,1)'); SELECT box(polygon '((0,0),(1,1),(2,0))'); 8.69 BTRIM 用法: btrim(string text [,characters text]) btrim(string bytea, bytes bytea) 253 第 8 章 函数 功能: • 字符串函数,从 string 的开头或结尾删除最长的只包含 characters (默认是一个空格)的串。 • 二进制串函数,从 string 的开头或结尾删除值出现在 bytes 中字节组成的最长串。 例子: 处理二进制串: SELECT btrim('\000trim\001'::bytea, '\000\001'::bytea); 处理字符串: SELECT btrim('xyxtrimyyx', 'xyz'); 8.70 CARDINALITY 用法: cardinality(anyarray) 功能: 数组函数,返回数组中元素总数,如果数组为空则返回 0。 例子: SELECT cardinality( ARRAY[[1,2], [3,4]]); 8.71 CAST 用法: 254 第 8 章 函数 cast(expression AS target_type) 功能: 用于转换数据类型。其中表达式 expression 可以是常量、列、表达式;目标数据类型即想转换的数据类型。 例子: SELECT CAST ('2023-02-21' AS DATE); 8.72 CBRT 用法: cbrt(dp) 功能: 数学函数,返回 dp 的立方根。 例子: 求 27 的立方根: SELECT cbrt(27.0); 8.73 CEIL 用法: ceil(n) 功能: 255 第 8 章 函数 数学函数,CEIL 返回大于或等于 n 的最小整数。该数字 n 始终可以写为整数 k 和正分数的差 f,使得 0 <= f< 1 和 n= k- f。CEIL 的值是整数 k。因此,当且仅当的值恰好是一个整数时,它的值 CEIL 就是它本身。此函数将任 何数值数据类型或任何可以隐式转换为数值数据类型的非数值数据类型作为参数。该函数返回与参数的数值数据类型 相同的数据类型。 例子: SELECT ceil(-42.8); 8.74 CEILING 用法: ceiling({dp|numeric}) ceiling() 功能: • 数学函数,CEIL 返回大于或等于 dp 的最小整数。ceil 函数的别名。 • json 函数,返回大于或等于 SQL/JSON 数字的最接近整数。 例子: SELECT ceiling(-95.3); SELECT jsonb_path_query('[0, 1, -2, -3.4, 5.6]', '$[*].ceiling()'); 8.75 CENTER 用法: center(object) 256 第 8 章 函数 功能: 几何函数,返回图形 object 的中心点。 例子: SELECT center(box '((0,0),(1,2))'); 8.76 CHAR_LENGTH 用法: char_length(string) 功能: 字符串函数,返回字符串 string 的字符数。 例子: SELECT char_length('hello'); 8.77 CHARACTER_LENGTH 用法: character_length(string) 功能: 字符串函数,返回字符串 string 的字符数, 同 char_length 。 例子: SELECT character_length('hello'); 257 第 8 章 函数 8.78 CHARINDEX 用法: charindex(sub_str varchar, src_str varchar[, start_location int default 1]) 功能: 字符串函数,返回 sub_str 在 src_str 中第一次出现的位置,从 start_location 位置开始查找, start_location 小于等于 0 或者为空时默认为 1。不存在则返回 0。 例子: SELECT charindex('bar', 'foobarbar', 5); 8.79 CHARTOROWID 用法: chartorowid(string) 功能: 将一个字符串类型转换为 ROWID 类型,若属于合法的 rowid 类型则将其转换为一个 rowid 类型返回。 例子: # select chartorowid('AAAAAAAAAAPiAAAAAAAAAAB'); chartorowid ------------------------AAAAAAAAAAPiAAAAAAAAAAB (1 row) 258 第 8 章 函数 8.80 CHR 用法: chr(int) 功能: 字符串函数,返回给定代码的字符。对于 UTF8 该参数被视作一个 Unicode 代码点。对于其他多字节编码该参 数必须指定一个 ASCII 字符。NULL (0) 字符不被允许,因为文本数据类型不能存储这种字节。 例子: SELECT chr(65); 8.81 CIRCLE 用法: circle(box) circle(point ,double precision) circle(polygon) 功能: 几何类型转换函数,将输入图形转换到圆形。 例子: 方框到圆: SELECT circle(box '((0,0),(1,1))'); 中心和半径到圆: 259 第 8 章 函数 SELECT circle(point'(0,0)', 2.0); 多边形到圆: SELECT circle(polygon '((0,0),(1,1),(2,0))'); 8.82 CLOB_EXPORT 用法: clob_export(clob, string, encode) 功能: 将 clob 大对象的内容导出到文件。string 指定导出的文件路径,encode 指定编码格式,可以为空。 例子: SELECT clob_export (lob, 'clob_asc_out.data','sqlascii') FROM test_clob; 8.83 CLOB_IMPORT 用法: clob_import(string, encode) 功能: 将 clob 大对象的内容从文件导入到数据库。string 指定导出的文件路径,encode 指定编码格式,可以为空。 例子: SELECT clob_import ('clob_asc_out.data','sqlascii') FROM dual; 260 第 8 章 函数 8.84 CLOCK_TIMESTAMP 用法: clock_timestamp() 功能: 日期/时间函数,返回当前日期和时间(在语句执行期间变化)。 例子: SELECT clock_timestamp(); 8.85 COALESCE 用法: COALESCE(value [, ...]) 功能: COALESCE 函数返回它的第一个非空参数的值。当且仅当所有参数都为空时才会返回空。它常用于在为显示目的 检索数据时用缺省值替换空值。 如 果 description 不 为 空, 这 将 会 返 回 它 的 值, 否 则 如 果 short_description 非空则返回 short_description 的值,如果前两个都为空则返回 (none)。和 CASE 表达式一样,COALESCE 将不会计算无 助于判断结果的参数;也就是说,在第一个非空参数右边的参数不会被计算。这个 SQL 标准函数提供了类似于 NVL 和 IFNULL 的能力,它们被用在某些其他数据库系统中。 例子: 以下示例使用示例 oe.product_information 表来组织产品清仓销售。它为所有标价的产品提供 10% 的折扣。如 果没有标价,则销售价格为最低价格。如果没有最低价格,则销售价格为“5”: 261 第 8 章 函数 SELECT product_id, list_price, min_price, COALESCE(0.9*list_price, min_price, 5) "Sale" FROM product_ information WHERE supplier_id = 102050 ORDER BY product_id; 8.86 COL_DESCRIPTION 用法: col_description(table_oid, column_number) 功能: col_description 为一个表列返回注释,该表列由所在表的 OID 和它的列号指定(obj_description 不能被用 在表列,因为表列没有自己的 OID)。 例子: CREATE TABLE comment_test ( id int, positive_col int CHECK (positive_col > 0), indexed_col int, CONSTRAINT comment_test_pk PRIMARY KEY (id)); COMMENT ON COLUMN comment_test.id IS 'Column ''id'' on comment_test'; SELECT col_description('comment_test'::regclass, 1) as comment; 8.87 CONCAT 用法: concat(str ”any” [, str ”any” [, ...] ]) 功能: 262 第 8 章 函数 字符串函数,串接所有参数的文本表示。NULL 参数被忽略. 例子: 此示例使用嵌套连接三个字符串: SELECT concat('abcde',2, NULL, 22); 8.88 CONCAT_WS 用法: concat_ws(sep text,str ” any” [,str ” any” [, ...]]) 功能: 字符串函数,将除了第一个参数 seq 外的其他参数用分隔符串接在一起。第一个参数被用作分隔符字符串。 NULL 参数被忽略。 例子: 此示例使用分隔符连接三个字符串: SELECT concat_ws(',','abcde', 2,NULL, 22); 8.89 CONNECTIONS 用法: connections() 功能: 返回数据库服务器当前的用户连接数。 263 第 8 章 函数 例子: SELECT connections(); 8.90 CONTAINS 用法: contains(expr1 text,expr2 text [,label Numeric]) 功能: 在 SELECT 语句中使用 CONTAINS 函数来指定文本查询的查询表达式,不限定使用位置。CONTAINS 返回 bool 变量,表示 expr1 是否包含 expr2。label 标识符表示是否计算相关性分数,利用 score 函数可以获得分数。 参数说明: a. expr1:指定要搜索的文本列或字符串。索引非必须。 b. expr2:查询条件文本列或字符串,用于在 expr1 中查找匹配值。支持 and(&)、or(|)、<->、and not。其 中“<->”连接的词,按“and”进行匹配查找。。 c. Label:(可选)指定标识 CONTAINS 操作生成的分数的标签,Numeric 类型。如果没有标签,contains 可以 用于单独计算,但无法和 Score 联动。不同 contains 函数中 label 必须不同,否则报错;但对 contains 函数中 参数完全相同的情况,label 可以相同。 返回值说明: 对于选定的每一行,CONTAINS 运算符返回 bool 变量,表示 expr1 是否包含 expr2。(如果 Contains 包含 label 参数,则会计算 expr1 与 expr2 的相关程度评分供带有对应 label 的 score 函数调用)。 例子: SELECT CONTAINS('test of contains','contain'); contains ---------t (1 row) 另请参阅: SCORE 264 第 8 章 函数 8.91 CONVERT 用法: convert(string bytea,src_encoding name,dest_encoding name) 功能: 字符串函数,将字符串转换为 dest_encoding。原始编码由 src_encoding 指定。string 在这个编码中必须可用。 转换可以使用 CREATECONVERSION 定义。也有一些预定义的转换。 例子: 用 Latin-1 encoding (ISO 8859-1) 表示的 text_in_utf8 SELECT convert('text_in_utf8','UTF8','LATIN1'); 8.92 CONVERT(MySQL 模式) 用法: convert(expr,type) 功能: 同 CAST(expr AS type) 表达式,将输入的 expr 转化为固定的 type 类型。 例子: SELECT convert('2023-02-18', DATETIME); 8.93 CONVERT_FROM 用法: convert_from(string bytea, src_encoding name) 265 第 8 章 函数 功能: 字符串函数,将字符串转换为数据库编码。原始编码由 src_encoding 指定。string 在这个编码中必须可用。 例子: 用当前数据库编码表示的 text_in_utf8 SELECT convert_from(’text_in_utf8’,’UTF8’); 8.94 CONVERT_TO 用法: convert_to(string text,dest_encoding name) 功能: 字符串函数,将字符串 string 转换为 dest_encoding 指定的编码格式。 例子: 用 UTF8 编码表达的 sometext SELECT convert_to(’some text’, ’UTF8’); 8.95 CONVERT_TZ(MySQL 模式) 用法: convert_tz(dt,from_tz,to_tz) 功能: 将日期时间 dt 从 from_tz 表示的时区转换成 to_tz 表示的时区的日期时间。 参数说明: dt:date、timestamp 或者 time 等时间日期类型。 266 第 8 章 函数 from_tz 和 to_tz:时区表示值,可以为以下几种格式: 1. 时区全名,例如:Asia/Shanghai、US/Hawaii 等; 2. 时区简写,例如:EDT、GMT 等; 3. 时间偏移量,范围为 [-14:00,+14:00],例如:+00:00,+8:00,-1:00。 返回值: timestamp 类型的日期时间值。 例子: SELECT CONVERT_TZ(date'2000-01-01','+0:00','+1:00') "CONVERT_TZ"; CONVERT_TZ -------------------2000-01-01 01:00:00 SELECT CONVERT_TZ(20200101,'+0:00','+1:00') "CONVERT_TZ"; CONVERT_TZ -------------------2020-01-01 01:00:00 SELECT CONVERT_TZ(timestamp'2000-01-01 12:00:00','GMT','MET') "CONVERT_TZ"; CONVERT_TZ -------------------2000-01-01 13:00:00 SELECT CONVERT_TZ(timestamp'2000-01-01 12:00:00','Africa/Tripoli','Africa/Abidjan') "CONVERT_TZ"; CONVERT_TZ -------------------2000-01-01 10:00:00 8.96 CORR 用法: corr(y,x) 267 第 8 章 函数 功能: CORR 返回一组数字对的相关系数。您可以将其用作聚合或分析函数。 此函数将任何数值数据类型或任何可以隐式转换为数值数据类型的非数值数据类型作为参数。 例子: CREATE TABLE aggtest ( a int2, b float4 ); SELECT corr(b, a) FROM aggtest; 8.97 COS 用法: cos(n) 功能: 三角函数,COS 返回 n 的余弦(以弧度表示的角度)。 此函数将任何数值数据类型或任何可以隐式转换为数值数据类型的非数值数据类型作为参数。 例子: 以下示例返回 180 度的余弦: SELECT COS(180 * 3.14159265359/180) ; 8.98 COSH 用法: cosh(n) 268 第 8 章 函数 功能: 三角函数,COSH 返回 n 的双曲余弦。 此函数将任何数值数据类型或任何可以隐式转换为数值数据类型的非数值数据类型作为参数。 例子: 以下示例返回零的双曲余弦: SELECT COSH(0) ; 8.99 COT 用法: cot(n) 功能: 三角函数,COSH 返回 n 的余切。n 以弧度表示。 例子: SELECT cot(1::tinyint); 8.100 COUNT 用法: count(expr) 功能: 269 第 8 章 函数 count 返回查询返回的行数。您可以将其用作聚合或分析函数。 如果指定 expr,则返回不为空 COUNT 的行数。您可以计算 expr 所有行,也可以只计算 expr 的不同值。 如果您指定星号 (*),则此函数返回所有行,包括重复行和空行。COUNT 从不返回 null。 例子: • 聚合示例 以下示例 COUNT 用作聚合函数: SELECT count(*) "Total" FROM students; • 分析示例 下面的示例为 employees 表中的每个员工计算在低于员工工资 50 到高于员工工资 150 范围内获得工资的员工的 移动计数。 SELECT last_name, salary, COUNT(*) OVER (ORDER BY salary RANGE BETWEEN 50 PRECEDING AND 150 FOLLOWING) AS mov_count FROM employees ORDER BY salary, last_name; 8.101 COVAR_POP 用法: covar_pop(Y, X) 功能: covar_pop 返回一组数字对的总体协方差。您可以将其用作聚集或分析函数。 此函数将任何数值数据类型或任何可以隐式转换为数值数据类型的非数值数据类型作为参数。 例子: CREATE TABLE aggtest ( a int2, b float4 ); SELECT covar_pop(b, a) FROM aggtest; 270 第 8 章 函数 8.102 COVAR_SAMP 用法: covar_samp(Y, X) 功能: COVAR_SAMP 返回一组数字对的样本协方差。您可以将其用作聚合或分析函数。 此函数将任何数值数据类型或任何可以隐式转换为数值数据类型的非数值数据类型作为参数。KingbaseES 确定 具有最高数值优先级的参数,将其余参数隐式转换为该数据类型,并返回该数据类型。 (SUM(expr1 * expr2) - SUM(expr1) * SUM(expr2) / n) / (n-1) 其中 n 是 ( expr1, expr2) 对的数量,其中既不为空 expr1 也不 expr2 为空。 该函数返回一个类型的值 NUMBER。如果函数应用于空集,则返回 null。 例子: CREATE TABLE aggtest ( a int2, b float4 ); SELECT covar_samp(b, a) FROM aggtest; 8.103 CUME_DIST 用法: cume_dist() cume_dist(args) 功能: 271 第 8 章 函数 CUME_DIST 计算一组值中某个值的累积分布。返回值的范围 CUME_DIST 是 >0 到 <=1。领带值始终评估 为相同的累积分布值。 此函数将任何数值数据类型或任何可以隐式转换为数值数据类型的非数值数据类型作为参数。KingbaseES 数据 库确定具有最高数值优先级的参数,将剩余参数隐式转换为该数据类型,进行计算并返回 NUMBER。 • 作为聚合函数,对于由函数的参数和相应的排序规范标识 CUME_DIST 的假设行,计算行在聚合组中的行之 间的相对位置。KingbaseES 进行此计算,就好像假设行被插入到要聚合的行组中一样。该函数的参数标识每个 聚合组中的单个假设行。因此,它们必须全部计算为每个聚合组中的常量表达式。常量参数表达式和聚合子句 中的表达式按位置匹配。因此,参数的数量必须相同,并且它们的类型必须兼容。 • 作为分析函数,CUME_DIST 计算一组值中指定值的相对位置。对于 row r,假设升序排列,CUME_DISTofr 是值小于或等于行数 r 除以正在评估的行数的值(整个查询结果集或分区)。 例子: • 聚合示例 下面的例子计算了一个假设雇员在样本表中的雇员中的累积分布,该雇员的薪水为 $15,500,佣金率为 5% oe.employees: SELECT CUME_DIST(15500, .05) WITHIN GROUP (ORDER BY salary, commission_pct) "Cume-Dist of 15500" FROM employees; • 分析示例 以下示例计算采购部门中每个员工的工资百分比。例如,40% 的文员工资低于或等于冰室。 SELECT job_id, last_name, salary, CUME_DIST() OVER (PARTITION BY job_id ORDER BY salary) AS cume_dist FROM employees WHERE job_id LIKE 'PU%' ORDER BY job_id, last_name, salary, cume_dist; 8.104 CURDATE(MySQL 模式) 用法: curDate() 功能: 返回当前数据库的日期。 例子: SELECT curDate(); curdate ------------ 272 第 8 章 函数 2022-10-28 (1 row) 8.105 CURRENT_DATABASE 用法: current_database() 功能: 会话信息函数,返回当前数据库名。 例子: SELECT current_database(); 8.106 CURRENT_DATE 用法: current_date() 功能: current_date 以数据类型的公历中的值返回会话时区中的当前日期 DATE。 例子: SELECT current_date(); 8.107 CURRENT_QUERY 用法: 273 第 8 章 函数 current_query() 功能: 当前正在执行的查询的文本,和客户端提交的一样(可能包含多于一个语句)。 例子: SELECT current_query(); 8.108 CURRENT_SCHEMA 用法: current_schema() 功能: 返回当前模式名。 例子: SELECT current_schema(); 8.109 CURRENT_SCHEMAS 用法: current_schemas(boolean) 功能: 274 第 8 章 函数 返回搜索路径中的模式名,boolean 参数指定是否包含隐含模式。 例子: SELECT current_schemas(true); 8.110 CURRENT_SETTING 用法: current_setting(setting_name [, missing_ok]) 功能: 配置设定函数,获得设置的当前值。current_setting 得到 “setting_name“设置的当前值。它对应于 SQL 命令 SHOW。如果没有名为 “setting_name“的设置,除非提供 missing_ok 并且其值为 true,current_setting 会抛出错 误。 例子: SELECT current_setting('datestyle'); 8.111 CURRENT_TIME 用法: current_time(precision) 功能: 根据 precision 指定的精度参数,返回带有时区的时间。 例子: 275 第 8 章 函数 SELECT current_time(8); 8.112 CURRENT_TIME(MySQL 模式) 用法: current_time([n]) 功能: 获取当前服务器的时间。 注意: 此函数不可创建函数索引。 参数说明: n:表示时间秒值小数点后面的位数,int 整数类型,范围为 [0,6],默认值为 0。 返回值: time 时间类型 例子: SELECT CURRENT_TIME() "CURRENT_TIME"; CURRENT_TIME ------------------17:16:24 SELECT CURRENT_TIME(1) "CURRENT_TIME"; CURRENT_TIME ------------------17:16:33.4 276 第 8 章 函数 8.113 CURRENT_TIMESTAMP 用法: current_timestamp(precision) 功能: CURRENT_TIMESTAMP 以数据类型的值返回会话时区中的当前日期和时间 TIMESTAMP WITH TIME ZONE。时区偏移反映了 SQL 会话的当前本地时间。如果省略 precision,则默认值为 6。此函数与返回值的区别 在于 LOCALTIMESTAMP 返回值。CURRENT_TIMESTAMPTIMESTAMP WITH TIME ZONELOCALTIMESTAMPTIMESTAMP 在可选参数中,precision 指定返回的时间值的小数秒精度。 例子: SELECT current_timestamp(8); 8.114 CURRENT_TIMESTAMP(MySQL 模式) 用法: current_timestamp([n]) 功能: 获取当前服务器的日期时间。 注意: 此函数不可创建函数索引。 参数说明: n:表示时间秒值小数点后面的位数,int 类型整数,范围为 [0,6],默认值为 0。 返回值: timestamp 类型 277 第 8 章 函数 例子: SELECT CURRENT_TIMESTAMP() "CURRENT_TIMESTAMP"; CURRENT_TIMESTAMP ------------------------2022-05-21 13:36:21 SELECT CURRENT_TIMESTAMP(1) "CURRENT_TIMESTAMP"; CURRENT_TIMESTAMP ------------------------2022-05-21 13:36:21.4 8.115 CURRVAL 用法: currval(regclass) 功能: 序列操作函数,返回最近一次用 nextval 获取的指定序列的值。 例子: CREATE TEMP SEQUENCE testseq; SELECT nextval('testseq'); SELECT currval('testseq'); SELECT nextval('testseq'); SELECT currval('testseq'); 8.116 CURSOR_TO_XML 用法: cursor_to_xml(cursor refcursor, count int, nulls boolean,tableforest boolean, targetns text) 278 第 8 章 函数 功能: XML 操作函数,把关系表的内容映射成 XML 值。它们可以被看成是 XML 导出功能。 例子: CREATE TABLE xmltbl (a int, b text); INSERT INTO xmltbl VALUES (1, 'one'), (2, 'two'), (-1, null); DECLARE xc CURSOR WITH HOLD FOR SELECT * FROM xmltbl ORDER BY 1, 2; SELECT cursor_to_xml('xc'::refcursor, 5, false, true, ''); 8.117 CURTIME(MySQL 模式) 用法: curtime() 功能: 返回当前数据库的系统时间。 例子: select curtime(); curtime ---------15:46:33 (1 row) 8.118 DATEDIFF(MySQL 模式) 用法: datediff(n1,n2) 279 第 8 章 函数 功能: 计算两个日期之间的间隔天数。 参数说明: n1:date、timestamp 或者 time 等时间日期类型,或者是可隐式转换成日期类型的字符类型和数值类型。 n2:date、timestamp 或者 time 时间日期类型,或者是可隐式转换成日期类型的字符类型和数值类型。 注意: 当参数为 time 类型时,该参数以当前系统日期时间为值,并被隐式转化为 timestamp 类型再进行计算。 返回值: int 类型 例子: SELECT DATEDIFF(DATE'2022-01-02',TIME'10:00:00') "DATEDIFF"; DATEDIFF -----------96 SELECT DATEDIFF(DATE'2022-01-02',TIMESTAMP'2022-01-01 10:00:00') "DATEDIFF"; DATEDIFF --------------------1 8.119 DAY(MySQL 模式) 用法: day(n) 功能: 返回给定日期的月份的日期值,参数为 NULL 时返回空。 参数说明: 280 第 8 章 函数 n:date、timestamp 或者 time 等时间日期类型。当参数为 time 类型时,该参数以当前系统日期时间为值,并 被隐式转化为 timestamp 类型再进行计算。 返回值: integer 类型,值域为 1 至 31。 例子: SELECT DAY(TIME'2:00:00') "DAY"; DAY ------5 SELECT DAY(DATE'20220131') "DAY"; DAY ------31 SELECT DAY(TIMESTAMP'20220101 101000') "DAY"; DAY ------1 8.120 DAYNAME(MySQL 模式) 用法: dayname(n) 功能: 返回给定日期的星期名称,参数为 NULL 时返回空。 参数说明: n:date、timestamp、time 等时间日期类型。当参数为 time 类型时,该参数以当前系统日期时间为值,并被隐 式转化为 timestamp 类型再进行计算。 返回值: 281 第 8 章 函数 text 类型 例子: SELECT DAYNAME(DATE'2022-01-02') "DAYNAME"; DAYNAME ----------Sunday SELECT DAYNAME(TIMESTAMP'2022-01-05 1:00:00') "DAYNAME"; DAYNAME -----------Wednesday 8.121 DAYOFMONTH(MySQL 模式) 用法: dayofmonth(n) 功能: 返回给定日期的月份的日期值,与 DAY() 函数为同义词。参数为 NULL 时返回空。 参数说明: n:date、timestamp、time 等时间日期类型。当参数为 time 类型时,该参数以当前系统日期时间为值,并被隐 式转化为 timestamp 类型再进行计算。 返回值: integer 类型,值域为 1~31。 例子: SELECT DAYOFMONTH(DATE'2022-01-02') "DAYOFMONTH"; DAYOFMONTH ----------2 282 第 8 章 函数 SELECT DAYOFMONTH(TIMESTAMP’2022-01-05 1:00:00’) "DAYOFMONTH"; DAYOFMONTH -----------5 8.122 DAYOFWEEK(MySQL 模式) 用法: dayofweek(n) 功能: 返回给定日期的星期索引,参数为 NULL 时返回空。 参数说明: n:date、timestamp、time 等时间日期类型。当参数为 time 类型时,该参数以当前系统日期时间为值,并被隐 式转化为 timestamp 类型再进行计算。 返回值: integer 类型,值域为 1 至 7。 例子: SELECT DAYOFWEEK(DATE'2022-01-02') "DAYOFWEEK"; DAYOFWEEK ----------1 SELECT DAYOFWEEK(TIMESTAMP’2022-01-05 1:00:00’) "DAYOFWEEK"; DAYOFMONTH -----------4 283 第 8 章 函数 8.123 DAYOFYEAR(MySQL 模式) 用法: dayofyear(n) 功能: 返回给定日期所在当前年份中的第几天,参数为 NULL 时返回空。 参数说明: n:date、timestamp、time 等时间日期类型。当参数为 time 类型时,该参数以当前系统日期时间为值,并被隐 式转化为 timestamp 类型再进行计算。 返回值: integer 类型, 值域为 1 至 366。 例子: SELECT DAYOFYEAR(DATE'2022-01-02') "DAYOFYEAR"; DAYOFYEAR ----------2 SELECT DAYOFYEAR(TIMESTAMP’2022-01-05 1:00:00’) "DAYOFYEAR"; DAYOFYEAR -----------5 8.124 DATE_PART 用法: date_part(text,timestamp) date_part(text, interval) 284 第 8 章 函数 功能: 获取子域,date_part 函数等价于 SQL 标准函数 extract。 例子: SELECT date_part('hour', timestamp '2001-02-16 20:38:40'); SELECT date_part('month', interval '2 years 3 months'); 8.125 DATE_SUB(MySQL 模式) 用法: date_sub(n,interval) 功能: 将时间值从日期值中减去。 参数说明: n:date、timestamp 或者 time 等时间日期类型。 interval:interval 类型。 返回值: timestamp 类型 例子: SELECT DATE_SUB(DATE'2000-01-01',INTERVAL '1' DAY) "DATE_SUB"; DATE_SUB --------------------1999-12-31 00:00:00 SELECT DATE_SUB(TIMESTAMP'2000-01-01 12:00:00',INTERVAL '1' HOUR) "DATE_SUB"; 285 第 8 章 函数 DATE_SUB --------------------2000-01-01 11:00:00 8.126 DATE_TRUNC 用法: date_trunc(field, source [, time_zone ]) 功能: date_trunc 函数在概念上和用于数字的 trunc 函数类似。“source“是类型 timestamp、timestamp with time zone 或 interval 的值表达式(类型 date 和 time 的值都分别被自动转换成 timestamp 或者 interval)。 “field“ 选择对输入值选用什么样的精度进行截断。返回值的类型类似于 timestamp、timestamp with time zone, 或 interval,并且所有小于选定的精度的域都设置为零(或者一,对于日期和月份)。 “field“的有效值是 � 286 第 8 章 函数 microseconds milliseconds second minute hour day week month quarter year decade century millennium 当输入值的类型 timestamp with time zone 时,对特定时区进行截断;例如,将其截断为 day 将生成该区域 的午夜值。默认情况下,截断是当前 TimeZone 设置,但可选 “time_zone“提供参数来指定不同的时区。时区名称可 以用 时区中描述的任何一种方式指定。 在处理时间戳时,如果 timestamp without time zone 或 interval 输入,则无法指定时区。这些都是表面的 价值。 例子: SELECT date_trunc('hour', TIMESTAMP '2001-02-16 20:38:40'); SELECT date_trunc('year', TIMESTAMP '2001-02-16 20:38:40'); SELECT date_trunc('day', TIMESTAMP WITH TIME ZONE '2001-02-16 20:38:40+00'); SELECT date_trunc('hour', INTERVAL '3 days 02:47:33'); 8.127 DAYS_BETWEEN 用法: days_between(date1,date2) 287 第 8 章 函数 功能: 返回 date1 和 date2 两个日期之间的天数。 例子: SELECT days_between('2020-01-01','2021-01-01'); 8.128 DECODE 用法: decode(expr,search,result,[search,result, ...] default) 功能: DECODE 逐个将 expr 与每个搜索值 (search) 进行比较。如果 expr 等于搜索值 (search),则 KingbaseES 数据库 返回相应的结果 (result)。如果找不到匹配项,则将返回默认值 (default)。如果省略默认值,则返回空值 (NULL)。 参数可以是任何类型。如果 expr 和 search 是字符数据,那么 KingbaseES 使用非添加的比较语义对它们进行比 较。返回的字符串是 VARCHAR 数据类型,与第一个结果参数在同一个字符集中。 如果第一个搜索结果对是数字,则 KingbaseES 将比较所有搜索结果表达式和第一个用于确定具有最高数字优先 级的参数的表达式,隐式将其余参数转换为该数据类型,并返回该数据类型。search、result 和 default 可以从表达式 派生。 KingbaseES 数据库使用短路评估。数据库只在将每个 search 与 expr 进行比较之前对其求值,而不是在将所有 search 与 expr 进行比较之前对其求值。因此,如果前一个 search 等于 expr,KingbaseES 不再计算其它 search、 result。KingbaseES 自动将 expr 和每个 search 转换为比较前的第一个 search。 KingbaseES 自动转换返回值与第一个结果相同的数据类型。如果第一个结果具有数据类型 CHAR 或者如果第一 个结果为空,则 KingbaseES 将返回值转换为数据类型 VARCHAR。 在 DECODE 函数中,KingbaseES 认为两个空值相等。DECODE 函数中的最大参数个数 (包括 expr、search、 result 和 default) 为 255 个。 例子: 288 第 8 章 函数 SELECT decode(NULL,1,3,NULL,4); 8.129 DECODING 用法: decoding(string text,format text) 功能: 从 string 中的文本表达解码二进制数据。format 的选项和 encode 中的一样。 例子: SELECT decoding('MTIzAAE=','base64'); 8.130 DEGREES 用法: degrees(dp) 功能: 数学函数,把弧度转化为角度。 例子: SELECT degrees(0.5); 8.131 DELETEXML 用法: 289 第 8 章 函数 deletexml(xml_instance xml, xpath text) deletexml(xml_instance xml, xpath text, namespace _text) 功能: 函数 deletexml 会删除 “xml_instance“实例中与 “xpath“表达式匹配的节点。 每次删除指定的一层节点,若一层含有多个节点,则该层所有节点都将被删除。若删除节点后父节点值为空,则 父节点只显示结尾部分,否则显示完整父节点及父节点的其他值。 此函数使用前需要创建 kdb_utils_function 扩展。 例子: 删除一层多个节点 SELECT deletexml('oldnodeoldnode','/test/value'); 删除的节点值为空 SELECT deletexml('', '//b'); 删除指定节点后父节点值为空 SELECT deletexml('11','/test/value/t'); 删除指定节点后,指定节点的父节点值不为空 SELECT deletexml('121212', '/test/value/t'); 8.132 DENSE_RANK 用法: dense_rank() 功能: 290 第 8 章 函数 通用窗口函数,返回不带间隙的当前行排名。 例子: SELECT dense_rank(x) WITHIN GROUP (ORDER BY x) FROM (VALUES (1),(1),(2),(2),(3),(3)) v(x) GROUP BY (x) ORDER BY 1; 8.133 DIAMETER 用法: diameter(circle) 功能: 几何函数,返回圆的直径。 例子: SELECT diameter(circle '((0,0),2.0)'); 8.134 DIV 用法: div(y numeric, x numeric) 功能: 数学函数,返回 y 除以 x 的整数商。 例子: SELECT div(9,4); 291 第 8 章 函数 8.135 EMPTY_BLOB 用法: empty_blob() 功能: 二进制函数,大对象函数,产生并返回一个新的 blob 对象。 例子: SELECT empty_blob(); 8.136 EMPTY_CLOB 用法: empty_clob() 功能: 大对象函数,产生并返回一个新的 clob 对象。 例子: SELECT empty_clob(); 8.137 EMPTY_NCLOB 用法: empty_nclob() 292 第 8 章 函数 功能: 大对象函数,产生并返回一个新的 nclob 对象。 例子: SELECT empty_nclob(); 8.138 ENCODE 用法: encode(data bytea,format text) 功能: 字符串函数,将二进制数据 data 编码成一个文本表达。format 支持的格式有:base64 、hex、escape。escape 将零字节和高位组字节转换为八进制序列(nnn)和双写的反斜线 例子: SELECT encode(’123000001’,’base64’); 8.139 ENUM_FIRST 用法: enum_first(anyenum) 功能: 枚举函数,返回输入枚举类型的第一个值。 例子: 293 第 8 章 函数 SELECT enum_first(null::rainbow); 8.140 ENUM_LAST 用法: enum_last(anyenum) 功能: 枚举函数,返回输入枚举类型的最后一个值。 例子: SELECT enum_last(null::rainbow); 8.141 ENUM_RANGE 用法: enum_range(anyenum) enum_range(anyenum, anyenum) 功能: 枚举函数,输入一个枚举参数时,将输入枚举类型的所有值作为一个有序的数组返回。输入两个参数时,以一个 数组返回在给定两个枚举值之间的范围。值必须来自相同的枚举类型。如果第一个参数为空,其结果将从枚举类型的 第一个值开始。如果第二参数为空,其结果将以枚举类型的最后一个值结束。 例子: .. code: SELECT enum_range(null::rainbow); SELECT enum_range('orange'::rainbow,'green'::rainbow); 294 第 8 章 函数 8.142 EVERY 用法: every(expression) 功能: 等价于BOOL_AND 。 例子: SELECT every(boolcol) FROM table; 8.143 EXISTSNODE 用法: existsnode(text PASSING [BY { REF | VALUE }] xml [BY { REF | VALUE }]) existsnode(xml_instance xml, xpath text) 功能: XML 函数 existsnode 会遍历 “xml“实例,判断指定节点是否存在于实例中。若存在则返回 1,不存在则返回 0。 此函数使用前需要创建 kdb_utils_function 扩展。 例子: SELECT existsnode('//town[text() = ''Toronto'']' PASSING BY REF 'Bidford-on-AvonCwmbranBristol'); SELECT existsnode('//town[text() = ''Cwmbran'']' PASSING BY REF 'Bidford-on-AvonCwmbranBristol'); SELECT existsnode('d', '/a/b'); 295 第 8 章 函数 8.144 EXP 用法: exp({dp|numeric}) 功能: 数学函数,返回输入参数的指数。 例子: SELECT exp(1.0); 8.145 EXPORT_SET 用法: EXPORT_SET(bits,on,off,separator,number_of_bits) 功能: 返回一个字符串。其中对于 bits 值中的每个位,可以得到一个 on 字符串,而对于每个清零位,可以得到一个 off 字符串。从右到左检查 bits 中的比特位(从低位到高位)。字符串从左到右添加到结果中,由指定的 separator 分隔 符分隔,默认为逗号。检查的位数由 number_of_bits 给出,如果大于 64,则 number_of_bits 将被静默剪裁为 64. 它被视为无符号整数,因此值-1 与 64 实际上相同。 例子: SELECT EXPORT_SET(6,'1','0',',',5); EXPORT_SET ------------ 296 第 8 章 函数 0,1,1,0,0 (1 row) 8.146 EXTRACT 用法: EXTRACT(field FROM source) extract(xml_instance xml, xpath text) 功能: • 时间函数 extract 函数从日期/时间值中抽取子域,例如年或者小时等。“source“必须是一个类型 timestamp、time 或 interval 的值表达式(类型为 date 的表达式将被造型为 timestamp,并且因此也可以被同样使用)。“field“是一 个标识符或者字符串,它指定从源值中抽取的域。extract 函数返回类型为 double precision 的值。 下列值是有效的域名字 � century 世纪 SELECT EXTRACT(CENTURY FROM TIMESTAMP '2000-12-16 12:21:13'); 结果:20 SELECT EXTRACT(CENTURY FROM TIMESTAMP '2001-02-16 20:38:40'); 结果:21 第一个世纪从 0001-01-01 00:00:00 AD 开始,尽管那时候人们还不知道这是第一个世纪。这个定义适 用于所有使用格里高利历法的国家。其中没有 0 世纪,我们直接从公元前 1 世纪到公元 1 世纪。 day 对于 timestamp 值,是(月份)里的日域(1-31);对于 interval 值,是日数 SELECT EXTRACT(DAY FROM TIMESTAMP '2001-02-16 20:38:40'); 结果:16 SELECT EXTRACT(DAY FROM INTERVAL '40 days 1 minute'); 结果:40 decade 年份域除以 10 297 第 8 章 函数 SELECT EXTRACT(DECADE FROM TIMESTAMP '2001-02-16 20:38:40'); 结果:200 dow 一周中的日,从周日(0)到周六(6) SELECT EXTRACT(DOW FROM TIMESTAMP '2001-02-16 20:38:40'); 结果:5 请注意,extract 的一周中的日和 to_char(..., 'D') 函数不同。 doy 一年的第几天(1 -365/366) SELECT EXTRACT(DOY FROM TIMESTAMP '2001-02-16 20:38:40'); 结果:47 epoch 对于 timestamp with time zone 值,是自 1970-01-01 00:00:00 UTC 以来的秒数(结果可能 是负数);对于 date and timestamp 值,是自本地时间 1970-01-01 00:00:00 以来的描述;对于 interval 值,它是时间间隔的总秒数。 SELECT EXTRACT(EPOCH FROM TIMESTAMP WITH TIME ZONE '2001-02-16 20:38:40.12-08'); 结果:982384720.12 SELECT EXTRACT(EPOCH FROM INTERVAL '5 days 3 hours'); 结果:442800 不能用 to_timestamp 把一个 epoch 值转换回成时间戳: SELECT to_timestamp(982384720.12); Result: 2001-02-17 04:38:40.12+00 hour 小时域(0 - 23) SELECT EXTRACT(HOUR FROM TIMESTAMP '2001-02-16 20:38:40'); 结果:20 isodow 一周中的日,从周一(1)到周日(7) SELECT EXTRACT(ISODOW FROM TIMESTAMP '2001-02-18 20:38:40'); 结果:7 除了周日,这和 dow 相同。这符合 ISO 8601 中一周中的日的编号。 isoyear 日期所落在的 ISO 8601 周编号的年(不适用于间隔) SELECT EXTRACT(ISOYEAR FROM DATE '2006-01-01'); 结果:2005 298 第 8 章 函数 SELECT EXTRACT(ISOYEAR FROM DATE '2006-01-02'); 结果:2006 每一个 ISO 8601 周编号的年都开始于包含 1 月 4 日的那一周的周一,在早的 1 月或迟的 12 月中 ISO 年可能和格里高利年不同。更多信息见 week 域。 这个域不能用于 KingbaseES V9 之前的版本。 microseconds 秒域,包括小数部分,乘以 1,000,000。请注意它包括全部的秒 SELECT EXTRACT(MICROSECONDS FROM TIME '17:12:28.5'); 结果:28500000 millennium 千年 SELECT EXTRACT(MILLENNIUM FROM TIMESTAMP '2001-02-16 20:38:40'); 结果:3 19xx 的年份在第二个千年里。第三个千年从 2001 年 1 月 1 日开始。 milliseconds 秒域,包括小数部分,乘以 1000。请注意它包括完整的秒。 SELECT EXTRACT(MILLISECONDS FROM TIME '17:12:28.5'); 结果:28500 minute 分钟域(0 - 59) SELECT EXTRACT(MINUTE FROM TIMESTAMP '2001-02-16 20:38:40'); 结果:38 month 对于 timestamp 值,它是一年里的月份数(1 - 12);对于 interval 值,它是月的数目,然后对 12 取模(0 - 11) SELECT EXTRACT(MONTH FROM TIMESTAMP '2001-02-16 20:38:40'); 结果:2 SELECT EXTRACT(MONTH FROM INTERVAL '2 years 3 months'); 结果:3 SELECT EXTRACT(MONTH FROM INTERVAL '2 years 13 months'); 结果:1 quarter 该天所在的该年的季度(1 - 4) SELECT EXTRACT(QUARTER FROM TIMESTAMP '2001-02-16 20:38:40'); 结果:1 second 秒域,包括小数部分(0 - 59 [1]_ ) 299 第 8 章 函数 SELECT EXTRACT(SECOND FROM TIMESTAMP '2001-02-16 20:38:40'); 结果:40 SELECT EXTRACT(SECOND FROM TIME '17:12:28.5'); 结果:28.5 timezone 与 UTC 的时区偏移,以秒记。正数对应 UTC 东边的时区,负数对应 UTC 西边的时区(从技 术上来看,KingbaseES 不使用 UTC,因为其中不处理闰秒)。 timezone_hour 时区偏移的小时部分。 timezone_minute 时区偏移的分钟部分。 week 该天在所在的 ISO 8601 周编号的年份里是第几周。根据定义,一年的第一周包含该年的 1 月 4 日 并且 ISO 周从星期一开始。换句话说,一年的第一个星期四在第一周。 在 ISO 周编号系统中,早的 1 月的日期可能位于前一年的第五十二或者第五十三周,而迟的 12 月的 日期可能位于下一年的第一周。例如,2005-01-01 位于 2004 年的第五十三周,并且 2006-01-01 位 于 2005 年的第五十二周,而 2012-12-31 位于 2013 年的第一周。我们推荐把 isoyear 域和 week 一起使用来得到一致的结果。 SELECT EXTRACT(WEEK FROM TIMESTAMP '2001-02-16 20:38:40'); 结果:7 year 年份域。要记住这里没有 0 AD,所以从 AD 年里抽取 BC 年应该小心处理。 SELECT EXTRACT(YEAR FROM TIMESTAMP '2001-02-16 20:38:40'); 结果:2001 注意: 当输入值为 +/-Infinity 时,extract 对于单调增的域(epoch、julian、year、isoyear、decade、century 以及 millennium)返回 +/-Infinity。对于其他域返回 NULL。KingbaseES V8R2 之前的版本对所有输入无穷的情况 都返回零。 extract 函数主要的用途是做计算性处理。对于用于显示的日期/时间值格式化,参阅数据类型格式化函数 。 • XML 函数 extract 会返回 xpath 指定的节点的 xml 数据。此函数使用前需要创建 kdb_utils_function 扩展。 例子: • 处理时间时 请参考功能说明里的例子。 • 处理 XML 时 300 第 8 章 函数 SELECT extract(xml('< 行>1'), '/行/ID'); SELECT extract(xml('< 行>1'), '/行'); SELECT extract(xml('< 行 属性 =" 测试属性">1'), '/行'); SELECT extract(xml('< 行 属性 =" 测试属性">1'), '/行/@ 属性'); 8.147 EXTRACT(MySQL 模式) 用法: extract( unit from source ) 功能: 返回给定日期时间的指定部分。 参数说明: unit:存在有效域内的 text 类型,值域为: microsecond second minute hour day week month quarter year second_microsecond minute_microsecond minute_second hour_microsecond hour_second hour_minute day_microsecond day_second day_minute 301 第 8 章 函数 day_hour year_month source:date、timestamp、time 等日期时间类型。 注意: 1. 当参数 unit 不在有效域内,为 null 或空值时,函数会报错; 2. 当参数 source 为 null,函数返回 null。 返回值: double 类型 例子: SELECT EXTRACT(day from date'2022-01-02'); extract ----------2 SELECT EXTRACT(day from timestamp'2022-01-05 1:00:00'); extract ----------5 SELECT EXTRACT(day from time'2:00:00'); extract ----------6 SELECT EXTRACT(day from date'20220101'); extract ----------1 8.148 EXTRACTVALUE 用法: 302 第 8 章 函数 extractvalue(xml_instance xml, xpath text) extractvalue(xml_instance xml, xpath text, namespace _text) 功能: 函数 extractvalue 会返回 “xpath“指定的节点的值。如果节点的值是另一个节点,则不可获取,若指定节点路 径存在多个相同节点,则会报错,也可通过数组形式,如:’/a/b[1]’ 指定返回具体节点。 此函数使用前需要创建:ref:kdb_utils_function 扩展。 例子: SELECT extractvalue('b','/a/b'); SELECT extractvalue('test', '//mydefns:b/text()',ARRAY[ARRAY[ 'mydefns', 'http://example.com']]); SELECT extractvalue('b1b2','/a/b[2]'); 8.149 FAMILY 用法: family(inet) 功能: 返回 inet 指定的网络地址族类型,返回 4 为 IPV4,6 为 IPV6。day 例子: SELECT family('::1'); 8.150 FIND_IN_SET 用法: 303 第 8 章 函数 FIND_IN_SET(str,strlist) FIND_IN_SET(str,oid) 功能: FIND_IN_SET(str,strlist) 返回第二个参数中第一个参数的索引(位置)。如果字符串 str 在由 N 个子字符串组 成的 strlist 中,则返回 1~N 范围内的值。strlist 是由以’,’分隔的子字符串组成。如果 str 不在 strlist 中或 strlist 是空字符串,则返回 0。 FIND_IN_SET(str,oid) 返回 str 在 sys_set 中对应的位置索引值。如果字符串 str 在 sys_set 中,则返回 1~64 范围内的值(sys_set 按照 setdisplayorder 从小到大排序后的位置索引值)。如果 str 不在系统表 sys_set 中,则返 回 0。oid 为 settypid,具体见 sys_set 。 例子: select FIND_IN_SET('b','a,b,c,d'); FIND_IN_SET ------------2 (1 row) SELECT FIND_IN_SET('O',16393); FIND_IN_SET ------------2 (1 row) 8.151 FIRST 用法: aggregate_function KEEP ( DENSE_RANK FIRST ORDER BY expr [ DESC | ASC ] [ NULLS { FIRST | LAST } ] [ , … ] ) [ OVER ( [ query_partition_clause ] ) ] [ FILTER ( WHERE filter_clause ) ] 304 第 8 章 函数 aggregate_function::= MIN | MAX | SUM | AVG | COUNT | VARIANCE | STDDEV query_partition_clause::= PARTITION BY expr [ , … ] 或 PARTITION BY ( expr [ , … ] ) 305 第 8 章 函数 功能: FIRST 既是聚集函数,也是分析函数。FIRST 函数首先对输入行按指定排序规则排序,然后返回排名为 FIRST 的一组行,最后在返回行的数值上执行聚集计算。如果只有唯一的排名为 FIRST 的返回行,那么聚集操作只在非聚 集的唯一行上执行。 FIRST 函数总是用于聚集函数后,与聚集函数联合使用。当指定 OVER 子句时,FIRST 函数为分析函数;当省 略 OVER 子句时,FIRST 函数为聚集函数。 aggregate_function 函数可以是 MIN、MAX、SUM、AVG、COUNT、VARIANCE 和 STDDEV 这些函数之 一。aggregate_function 在排名为 FIRST 的行中的数值上执行操作。aggregate_function 仅支持 ALL 关键字修 饰,而不支持 DISTINCT 和 UNIQUE 关键字修饰。 定 义 KEEP 关 键 字 是 为 了 使 语 义 清 晰, 它 限 定 了 aggregate_function 的 输 入 行 范 围, 表 示 只 有 aggregate_function 的 FIRST 的值才会被返回。DENSE_RANK FIRST 表示将只在那些 DENSE_RANK 排名 为最小值(FIRST)的行上进行聚集操作。 ORDER BY 子句用法与 SELECT 语句中的 ORDER BY 子句相同。 query_partition_clause 是 OVER 子 句 唯 一 有 效 的 部 分。 如 果 包 含 了 OVER 子 句, 但 省 略 了 query_partition_clause,则 FIRST 函数被视为分析函数,但分析定义的窗口是全表。 另请参阅: 更多信息请参阅聚集函数 、窗口函数 和LAST 函数 例子: 以下示例创建了一张雇员表。 CREATE TABLE employees ( employee_id numeric(6) , first_name varchar(20) , last_name varchar(25) , email varchar(25) , phone_number varchar(20) , hire_date date , job_id varchar2(10) , salary numeric(8,2) , commission_pct numeric(2,2) , manager_id numeric(6) , department_id numeric(4) ) ; 以下是聚集函数的示例,对 employees 表按部门分组,在分组内按提成比例排序,返回最高和最低薪水。 SELECT department_id, MIN(salary) KEEP (DENSE_RANK FIRST ORDER BY commission_pct) "Worst", MAX(salary) KEEP (DENSE_RANK LAST ORDER BY commission_pct) "Best" FROM employees 306 第 8 章 函数 GROUP BY department_id ORDER BY department_id; 以下是分析函数的示例,对 employees 表按部门分区,在分区窗口内按提成比例排序,返回每个雇员名字、部门 ID、薪水和最高、最低薪水值。 SELECT last_name, department_id, salary, MIN(salary) KEEP (DENSE_RANK FIRST ORDER BY commission_pct) OVER (PARTITION BY department_id) "Worst", MAX(salary) KEEP (DENSE_RANK LAST ORDER BY commission_pct) OVER (PARTITION BY department_id) "Best" FROM employees ORDER BY department_id, salary, last_name; 8.152 FIRST_VALUE 用法: first_value(value any) 功能: 返回在窗口帧中第一行上计算的 value 。只考虑“窗口帧”内的行,它默认情况下包含从分区的开始行直到当前 行的最后一个同等行。 例子: CREATE TEMP TABLE datetimes( id int, f_time time, f_timetz timetz, f_interval interval, f_timestamptz timestamptz, f_timestamp timestamp ); INSERT INTO datetimes VALUES (1, '11:00', '11:00 BST', '1 year', '2000-10-19 10:23:54+01', '2000-10-19 10:23:54'), (2, '12:00', '12:00 BST', '2 years', '2001-10-19 10:23:54+01', '2001-10-19 10:23:54'), (3, '13:00', '13:00 BST', '3 years', '2001-10-19 10:23:54+01', '2001-10-19 10:23:54'), 307 第 8 章 函数 (4, '14:00', '14:00 BST', '4 years', '2002-10-19 10:23:54+01', '2002-10-19 10:23:54'), (5, '15:00', '15:00 BST', '5 years', '2003-10-19 10:23:54+01', '2003-10-19 10:23:54'), (6, '15:00', '15:00 BST', '5 years', '2004-10-19 10:23:54+01', '2004-10-19 10:23:54'), (7, '17:00', '17:00 BST', '7 years', '2005-10-19 10:23:54+01', '2005-10-19 10:23:54'), (8, '18:00', '18:00 BST', '8 years', '2006-10-19 10:23:54+01', '2006-10-19 10:23:54'), (9, '19:00', '19:00 BST', '9 years', '2007-10-19 10:23:54+01', '2007-10-19 10:23:54'), (10, '20:00', '20:00 BST', '10 years', '2008-10-19 10:23:54+01', '2008-10-19 10:23:54'); SELECT id, f_time, first_value(id) OVER w FROM datetimes WINDOW w AS (ORDER BY f_time RANGE BETWEEN '70 min'::interval preceding AND '2 hours'::interval following); 8.153 FLOOR 用法: floor(n) 功能: FLOOR 返回等于或小于 n 的最大整数。该数字 n 始终可以写为整数 k 和正分数之和 f,使得 0 <= f< 1 和 n= k+ f。的值 FLOOR 是整数 k。因此,当且仅当的值恰好是一个整数 n 时,它的值 FLOOR 就是它本身。此函数将任 何数值数据类型或任何可以隐式转换为数值数据类型的非数值数据类型作为参数。该函数返回与参数的数值数据类型 相同的数据类型。 例子: 以下示例返回等于或小于 42.3 的最大整数 SELECT FLOOR(42.3); 8.154 FORMAT 用法: format(formatstr text [, formatarg "any" [, ...] ]) 308 第 8 章 函数 功能: 函数 format 根据一个格式字符串产生格式化的输出,其形式类似于 C 函数 sprintf。“formatstr“是一个格式 字符串,它指定了结果应该如何被格式化。格式字符串中的文本被直接复制到结果中,除了使用格式说明符的地方。 格式说明符在字符串中扮演着占位符的角色,它定义后续的函数参数如何被格式化及插入到结果中。每一个 “formatarg“参数会被根据其数据类型的常规输出规则转换为文本,并接着根据格式说明符被格式化和插入到结果字符串 中。格式说明符由一个% 字符开始并且有这样的形式 %[position][flags][width]type 其中的各组件域是: position(可选) 一个形式为 n$ 的字符串,其中 “n“是要打印的参数的索引。索引 1 表示 “formatstr“之后的第一个参数。如果 “position“被忽略,默认会使用序列中的下一个参数。 flags(可选) 控制格式说明符的输出如何被格式化的附加选项。当前唯一支持的标志是一个负号 (-),它将导致格式说明符的输出会被左对齐(left-justified)。除非 “width“域也被指定,否者这 个域不会产生任何效果。 width(可选) 指定用于显示格式说明符输出的最小字符数。输出将被在左部或右部(取决于-标志)用 空格填充以保证充满该宽度。太小的宽度设置不会导致输出被截断,但是会被简单地忽略。宽度可 以使用下列形式之一指定:一个正整数;一个星号(*)表示使用下一个函数参数作为宽度;或者一 个形式为 *n$ 的字符串表示使用第 “n“个函数参数作为宽度。 如果宽度来自于一个函数参数,则参数在被格式说明符的值使用之前就被消耗掉了。如果宽度参数 是负值,结果会在长度为 abs(“width“) 的域中被左对齐(如果-标志被指定)。 type(必需) 格式转换的类型,用于产生格式说明符的输出。支持下面的类型: • s 将参数值格式化为一个简单字符串。一个控制被视为一个空字符串。 • I 将参数值视作 SQL 标识符,并在必要时用双写引号包围它。如果参数为空,将会是一个错误 (等效于 quote_ident)。 • L 将参数值引用为 SQL 文 字。 一 个 空 值 将 被 显 示 为 不 带 引 号 的 字 符 串 NULL(等 效 于 quote_nullable)。 除了以上所述的格式说明符之外,要输出一个文字形式的% 字符,可以使用特殊序列%%。 例子: 下面有一些基本的格式转换的例子: SELECT format('Hello %s', 'World'); 结果:Hello World 309 第 8 章 函数 SELECT format('Testing %s, %s, %s, %%', 'one', 'two', 'three'); 结果:Testing one, two, three, % SELECT format('INSERT INTO %I VALUES(%L)', 'Foo bar', E'O\'Reilly'); 结果:INSERT INTO "Foo bar" VALUES('O''Reilly') SELECT format('INSERT INTO %I VALUES(%L)', 'locations', 'C:\Program Files'); 结果:INSERT INTO locations VALUES(E'C:\\Program Files') 下面是使用 “width“域和-标志的例子: SELECT format('|%10s|', 'foo'); 结果:| foo| SELECT format('|%-10s|', 'foo'); 结果:|foo | SELECT format('|%*s|', 10, 'foo'); 结果:| foo| SELECT format('|%*s|', -10, 'foo'); 结果:|foo | SELECT format('|%-*s|', 10, 'foo'); 结果:|foo | SELECT format('|%-*s|', -10, 'foo'); 结果:|foo | 这些例子展示了 “position“域的例子: SELECT format('Testing %3$s, %2$s, %1$s', 'one', 'two', 'three'); 结果:Testing three, two, one SELECT format('|%*2$s|', 'foo', 10, 'bar'); 结果:| bar| SELECT format('|%1$*2$s|', 'foo', 10, 'bar'); 结果:| foo| 不同于标准的 C 函数 sprintf,KingbaseES 的 format 函数允许将带有或者不带有 “position“域的格式说明符 被混在同一个格式字符串中。一个不带有 “position“域的格式说明符总是使用最后一个被消耗的参数的下一个参数。 另外,format 函数不要求所有函数参数都被用在格式字符串中。例如: 310 第 8 章 函数 SELECT format('Testing %3$s, %2$s, %s', 'one', 'two', 'three'); 结果:Testing three, two, three 对于安全地构造动态 SQL 语句,%I 和%L 格式说明符特别有用。 8.155 FORMAT_PICO_TIME(MySQL 模式) 用法: format_pico_time(n) 功能: 将皮秒值转化为可读格式的文本字符串。 参数说明: n:bigint、numeric 等数值类型或 double precision 等浮点数类型。参数存在小数时,将其整数部分截取后再计 算输出。 返回值: text 类型,转化格式见下表: 表 8.155.1: FORMAT_PICO_TIME 参数值 结果单位 结果单位指示符 最多 10 3 - 1 皮秒 ps 最多 10 6 - 1 纳秒 ns 最多 10 9 - 1 微秒 us 最多 10 12 - 1 毫秒 ms 高达 60×10 12 - 1 秒 s 高达 3.6×10 15 - 1 分钟 min 高达 8.64×10 16 - 1 小时 h 8.64×10 16 及以上 天 d 311 第 8 章 函数 注意: 1. 参数 n 为 NULL 时,函数返回为空; 2. 参数 n 为空值‘’或空格‘’时,返回值为 0ps。 例子: SELECT FORMAT_PICO_TIME(1000000) "FORMAT_PICO_TIME"; FORMAT_PICO_TIME ----------------1.00 us SELECT FORMAT_PICO_TIME(10000.7) "FORMAT_PICO_TIME"; FORMAT_PICO_TIME ----------------10.00 ns SELECT FORMAT_PICO_TIME('a') "FORMAT_PICO_TIME"; FORMAT_PICO_TIME ----------------0 ps SELECT FORMAT_PICO_TIME('') "FORMAT_PICO_TIME"; FORMAT_PICO_TIME ----------------0 ps 8.156 FORMAT_TYPE 用法: format_type(type_oid, typemod) 功能: 312 第 8 章 函数 format_type 返回一个数据类型的 SQL 名称,它由它的类型 OID 标识并且可能是一个类型修饰符。如果不知道 相关的修饰符,则为类型修饰符传递 NULL。 例子: SELECT format_type('varchar'::regtype, 42); 8.157 FROM_BASE64(MySQL 模式) 用法: from_base64(string text) 功能: from_base64 函数接受一个经过 to_base64 函数编码的字符串,并将解码后的结果以二进制字符串的形式返回。 如果输入为 null 或非法的 base64 字符串,则结果为 null;将自动忽略参数中的换行、回车、制表符和空格。 from_base64 函数为 MySQL 兼容函数,仅支持在 MySQL 模式下使用。 例子: SELECT from_base64(to_base64('abc')); 8.158 FROM_DAYS(MySQL 模式) 用法: from_days(n) 功能: 将数值类型转换为日期类型。 参数说明: n:bigint、numeric 等数值类型或 double precision 等浮点数类型。参数存在小数时,将其四舍五入成整数后再 进行计算。 313 第 8 章 函数 返回值: date 类型 注意: 1. 参数 n 为负数、空值‘’或空格‘’时,函数返回为“0001-01-01 BC”; 2. 参数 n 为 NULL 时,函数返回空。 例子: SELECT FROM_DAYS(10000) "FROM_DAYS"; FROM_DAYS ----------0027-05-19 SELECT FROM_DAYS(10000.7) "FROM_DAYS"; FROM_DAYS -----------0027-05-20 8.159 FROM_UNIXTIME(MySQL 模式) 用法: from_unixtime(n [, 'format']) 功能: 将时间戳转化为以当前会话时区表示的日期时间值。若指定 format 参数,则时间戳转化为以当前会话时区表示 的日期时间后,根据 format 参数的格式化规则再将其格式化成字符串。 参数说明: n:bigint、numeric 等数值类型或 double precision 等浮点数类型。参数存在小数时,将其四舍五入成六位小数 后进行计算。 314 第 8 章 函数 format:text 类型,指定格式规则。具体见下表: 表 8.159.1: 格式化规则表 值 描述 %a 周缩写(Sun...Sat) %b 月缩写(Jan...Dec) %c 月份(0..12,不补零) %D 有英语后缀的一个月中第几天(0th,1st,2nd,3rd...) %d 一个月中第几天(00..31) %e 一个月中第几天(0..31) %f 微秒值(000000..999999) %H 24 小时制小时(00..23) %h 12 小时制小时(01..12) %I 12 小时制小时(01..12) %i 分钟值(00..59) %j 一年中的天(001..366) %k 24 小时制小时(0..23,不补零) %l 12 小时制小时(1..12,不补零) %M 月份名称(January..December) %m 月份(00..12) %p AM 或 PM %r 12 小时制的时间,带 AM 或 PM Hh: mm: ss 后跟 AM 或 PM %S 秒值(00..59) %s 秒值(00..59) %T 24 小时制时间(hh:mm:ss) %U 一年中的周数,周日作为一周的第一天,mode 为 0 %u 一年中的周数,周一作为一周的第一天,mode 为 1 见续表 315 第 8 章 函数 表 8.159.1 – 续表 值 描述 %V 一年中的周数,周日作为一周的第一天,mode 为 2,和%X 一起使用 %v 一年中的周数,周一作为一周的第一天,mode 为 3,和%x 一起使用 %W 星期名(Sunday..Saturday) %w 一周的第几天(0=Sunday..6=Saturday) %X 星期日是一周的第一天的一周的年份, 四位数字, 和%V 一起使用 %x 星期一是一周的第一天的一周的年份, 四位数字, 和%v 一起使用 %Y 年份值,四位数字(XXXX) %y 年份值,两位数字(XX) %% 字面值% 字符 %x 对于上面没有列出的任何值(x) 返回值: 函数返回值根据参数数量决定,未指定 format 参数时,返回 timestamp 类型;指定了 format 参数时,返回 text 类型。 注意: 1. 参数 n 为负数时,函数返回为空; 2. 参数 n 为 NULL 时,函数返回空; 3. 参数 n 为空值‘’或空格‘’时,返回值为“1970-01-01 00:00:00”,若指定了 format 参数,再根据 format 参 数进行格式化; 4. format 参数为不合法或不能匹配的字符串时,返回 format 参数值。 例子: SELECT FROM_UNIXTIME(0) "FROM_UNIXTIME"; FROM_UNIXTIME --------------------1970-01-01 08:00:00 SELECT FROM_UNIXTIME(100.123456) "FROM_UNIXTIME"; 316 第 8 章 函数 FROM_UNIXTIME --------------------------1970-01-01 08:01:40.123456 SELECT FROM_UNIXTIME(100) "FROM_UNIXTIME"; FROM_UNIXTIME --------------------1970-01-01 08:01:40 SELECT FROM_UNIXTIME(1,'%y-%m-%d %h:%i:%s') "FROM_UNIXTIME"; FROM_UNIXTIME -------------------70-01-01 08:00:01 SELECT FROM_UNIXTIME(1,'abc') "FROM_UNIXTIME"; FROM_UNIXTIME -------------------abc 8.160 GENERATE_SERIES 用法: generate_series(start, stop) generate_series(start, stop, step) generate_series(start, stop, step interval) 功能: 级数生成函数,产生一系列值,从 start 到 stop,默认步长为 1, 当指定 step 参数时,步长为 step 。当 “step“为正时,如果 “start“大于 “stop“则返回零行。相反,当 “step“为负时,如果 “start“小于 “stop“则返回零行。 对于 NULL 输入也会返回零行。“step“为零是一个错误。 317 第 8 章 函数 例子: SELECT * FROM generate_series(2,4); SELECT * FROM generate_series(5,1,-2); SELECT * FROM generate_series(4,3); SELECT generate_series(1.1, 4, 1.3); SELECT current_date + s.a AS dates FROM generate_series(0,14,7) AS s(a); SELECT * FROM generate_series('2008-03-01 00:00'::timestamp, '2008-03-04 12:00', '10 hours'); 8.161 GENERATE_SUBSCRIPTS 用法: generate_subscripts(array anyarray, dim int) generate_subscripts(array anyarray, dim int, reverse boolean) 功能: 下标生成函数,生成一个级数组成给定数组的下标。当 reverse 为真时,级数以逆序返回。 例子: -- 基本使用 SELECT generate_subscripts('{NULL,1,NULL,2}'::int[], 1) AS s; -- 表示一个数组,下标和被下标的值需要一个子查询 SELECT a AS array, s AS subscript, a[s] AS value FROM (SELECT generate_subscripts(a, 1) AS s, a FROM arrays) foo; -- 平面化一个 2D 数组 CREATE OR REPLACE FUNCTION unnest2(anyarray) RETURNS SETOF anyelement AS $$ select $1[i][j] from generate_subscripts($1,1) g1(i), generate_subscripts($1,2) g2(j); $$ LANGUAGE sql IMMUTABLE; CREATE FUNCTION SELECT * FROM unnest2(ARRAY[[1,2],[3,4]]); 318 第 8 章 函数 8.162 GET_BIT 用法: get_bit(string, offset) 功能: 二进制串函数,从二进制串中抽取 offset 指定的位。get_bit 在每一个字节中从右边起计数位;例如位 0 是第一 个字节的最低有效位,而位 15 是第二个字节的最高有效位。除了可以用于二进制串之外,也可以用于位串,当使用 于一个位串时,函数将串的第一(最左)位计数为位 0。 例子: 二进制串操作 SELECT get_bit('Th\000omas'::bytea, 45); 8.163 GET_BYTE 用法: get_byte(string, offset) 功能: 二进制串函数,从二进制串中抽取 offset 指定的字节。把一个二进制串中的一个字节计数为字节 0。除了可以用 于二进制串之外,也可以用于位串,当使用于一个位串时,函数将串的第一(最左)位计数为位 0。 例子: 二进制串操作 SELECT get_byte('Th\000omas'::bytea, 4); 319 第 8 章 函数 8.164 GET_CURRENT_TS_CONFIG 用法: get_current_ts_config() 功能: 获取默认文本搜索配置信息。 例子: SELECT get_current_ts_config(); 8.165 GET_DISK_INFO 用法: get_disk_info(file_path IN TEXT, dev OUT TEXT, mount_point OUT TEXT, size OUT TEXT, used OUT TEXT)) 功能: 指定文件系统路径,返回路径所在设备名,挂载点,单位字节的容量和已使用容量等磁盘使用信息。 例子: 获取 Oid 为 1663 的表空间对象磁盘占用信息 SELECT get_disk_info(sys_tablespace_location(1663)); 8.166 GET_FORMAT(MySQL 模式) 用法: 320 第 8 章 函数 get_format(date,'format') 功能: 返回指定的国家地区时间输出格式。 参数说明: date:DATE、DATETIME、TIME 三个固定值,不可输入其他值。 format:可指定为“EUR”、“USA”、“JIS”、“ISO”、“INTERNAL”五个固定的字符串。 返回值: 返回值为根据两个参数组合决定的格式字符串,如下表所示: 表 8.166.1: GET_FORMAT 函数调用 结果 GET_FORMAT(DATE,’USA’) ’%m.%d.%Y’ GET_FORMAT(DATE,’JIS’) ’%Y-%m-%d’ GET_FORMAT(DATE,’ISO’) ’%Y-%m-%d’ GET_FORMAT(DATE,’EUR’) ’%d.%m.%Y’ GET_FORMAT(DATE,’INTERNAL’) ’%Y%m%d’ GET_FORMAT(DATETIME,’USA’) ’%Y-%m-%d %H.%i.%s’ GET_FORMAT(DATETIME,’JIS’) ’%Y-%m-%d %H:%i:%s’ GET_FORMAT(DATETIME,’ISO’) ’%Y-%m-%d %H:%i:%s’ GET_FORMAT(DATETIME,’EUR’) ’%Y-%m-%d %H.%i.%s’ GET_FORMAT(DATETIME,’INTERNAL’) ’%Y%m%d%H%i%s’ GET_FORMAT(TIME,’USA’) ’%h:%i:%s %p’ GET_FORMAT(TIME,’JIS’) ’%H:%i:s%’ GET_FORMAT(TIME,’ISO’) ’%H:%i:%s’ GET_FORMAT(TIME,’EUR’) ’%H.%i.%s’ 见续表 321 第 8 章 函数 表 8.166.1 – 续表 函数调用 结果 GET_FORMAT(TIME,’INTERNAL’) ’%H%i%s’ 注意: 1. 参数 date 为非法值时,函数会报错; 2. 参数 format 为除了’EUR’、’USA’、’JIS’、’ISO’、’INTERNAL’ 以外的值时,函数返回空。 例子: SELECT GET_FORMAT('date','EUR') "GET_FORMAT"; GET_FORMAT ------------%d.%m.%Y 8.167 GET_LICENSE_VALIDDAYS 用法: get_license_validdays() 功能: 返回 license 剩余有效时间。 例子: SELECT get_license_validdays(); 8.168 GETUSERNAME 用法: 322 第 8 章 函数 getusername() 功能: 返回当前用户名。 例子: SELECT getusername(); 8.169 GREATEST 用法: GREATEST(value [, ...]) 功能: 函数从一个任意的数字表达式列表里选取最大的数值。表达式必须都可以转换成一个普通的数据类型,它将会是 结果类型。只要列表中有一个 NULL 值,则结果返回 NULL。 例子: SELECT greatest('abc','abb','aba','bbb'); 8.170 GROUP_CONCAT 用法: GROUP_CONCAT([DISTINCT] col [ORDER BY col ] [SEPARATOR str_val]) 323 第 8 章 函数 功能: 将指定表达式的结果集中的非空字符连接成一个字符串并返回。该函数被封装在 kdb_utils_function 扩展中,调 用此函数需要首先创建 kdb_utils_function 扩展。 参数说明: clo:任意数组或非数组类型的字段。 str_val:任意非空的可见字符或字符串,最大长度 1073741823。 返回值说明: 返回值类型:text。 当表达式结果类型为 bytea 时,返回的包含二进制字符串的串联值,数据类型为 text。暂不支持用户自定义设置 返回结果的最大长度。函数返回值长度最大支持 1073741823。当返回值完整长度大于设置的最大长度时,结果将被 截断。 例子: CREATE TABLE group_concat_test(a int, b int ,c int PRIMARY KEY); INSERT INTO group_concat_test VALUES(1,1,3); INSERT INTO group_concat_test VALUES(2,3,2); INSERT INTO group_concat_test VALUES(3,2,1); INSERT INTO group_concat_test VALUES(1,2,0); INSERT INTO group_concat_test VALUES(NULL,2,6); CREATE EXTENSION kdb_utils_function; SELECT group_concat(a) FROM group_concat_test; SELECT group_concat(distinct a) FROM group_concat_test; SELECT group_concat(b order by b desc) FROM group_concat_test; SELECT group_concat(b separator '--') FROM group_concat_test; SELECT group_concat(a order by b,c) FROM t1; 8.171 GROUPING 用法: grouping(args...) 功能: 324 第 8 章 函数 GROUPING 将超聚合行与常规分组行区分开来。GROUP BY 扩展,例如 ROLLUP 和 CUBE 生成超聚合行, 其中所有值的集合由 null 表示。使用该 GROUPING 函数,您可以将表示超聚合行中所有值的集合的空值与常规行 中的空值区分开来。 expr 函数中的必须 GROUPING 匹配 GROUP BY 子句中的表达式之一。expr 如果该行中的值是表示所有值的集 合的空值,则该函数返回值 1 。否则,它返回零。函数返回值的数据类型 GROUPING 为 KingbaseES NUMBER。 有关这些术语的讨论,请参阅SELECT group_by_clause。 例子: 在以下示例中,它使用示例表 hr.departments,hr.employees 如果 GROUPING 函数返回 1(表示超聚合行而不 是表中的常规行),则字符串“All Jobs”出现在“JOB”列中,而不是 null 否则会出现: SELECT DECODE(GROUPING(department_name), 1, 'ALL DEPARTMENTS', department_name) AS department, DECODE(GROUPING(job_id), 1, 'All Jobs', job_id) AS job, COUNT(*) "Total Empl", AVG(salary) * 12 "Average Sal " FROM employees e, departments d WHERE d.department_id = e.department_id GROUP BY ROLLUP (department_name, job_id) ORDER BY department, job; 8.172 GROUPING_ID 用法: grouping_id(args...) 功能: GROUPING_ID 返回对应于与行关联的 GROUPING 位向量的数字。GROUPING_ID 仅适用于包含 GROUP BY 扩展(例如 ROLLUP 或 CUBE)和 GROUPING 函数的 SELECT 语句。GROUPING_ID 在功能上等同于获取 多个 GROUPING 函数的结果并将它们连接成一个位向量(一串 1 和 0)。通过使用 GROUPING_ID,可以避免使 用多个 GROUPING 函数并使行过滤条件更易于表达。使用 GROUPING_ID 可以更轻松地进行行过滤,因为可以使 用 GROUPING_ID = n 的单个条件来识别所需的行。 expr 函数中的必须 GROUPING_ID 匹配 GROUP BY 子句中的表达式之一。最右边参数指派的位是最低有效 位,如果对应的表达式被包括在产生结果行的分组集合的分组条件中则每一位是 0,否则是 1。函数返回值的数据类 型 GROUPING 为 KingbaseES NUMBER。有关这些术语的讨论,请参阅:ref:SELECT group_by_clause。 例子: 在以下示例中,它使用表 items_sold,GROUPING_ID 函数返回 make 和 model 列是否包含在超聚合行中的位 的向量。make 为高位,model 为低位。 325 第 8 章 函数 SELECT make, model, GROUPING_ID(make,model), sum(sales) FROM items_sold GROUP BY ROLLUP(make,model); make | model | grouping_id | sum ------+-------+-------------+----| | 3 | 55 Foo | Tour | 0 | 20 Foo | GT | 0 | 10 Bar | Sport | 0 | 5 Bar | City | 0 | 15 Bar | | 0 | 5 Foo | | 1 | 30 Bar | | 1 | 25 (8 rows) 8.173 HAS_ANY_COLUMN_PRIVILEGE 用法: has_any_column_privilege(user, table, privilege) has_any_column_privilege(table, privilege) 功能: 检查 user 用户(未指定时使用当前用户)是否能以特定方式访问一个表的任意列。希望的访问权限类型必须是 下列值的某种组合:SELECT、INSERT、UPDATE 或 REFERENCES。注意在表级别上具有这些权限中的任意一种将会隐 式地把它授予给表上的每一列。 例子: CREATE TABLE tbl(); SELECT has_any_column_privilege('tbl', 'INSERT, UPDATE, REFERENCES'); 8.174 HAS_COLUMN_PRIVILEGE 用法: 326 第 8 章 函数 has_column_privilege(user, table, column, privilege) has_column_privilege(table,column, privilege) 功能: 检查 user 用 户 (未 指 定 时 使 用 当 前 用 户) 是 否 能 以 特 定 方 式 访 问 一 个 表 的 column 指 定 列。 has_column_privilege 检查一个用户是否能以特定方式访问一个列。它的参数可能性与 has_table_privilege 类 似,并且列还可以使用名字或者属性号来指定。希望的访问权限类型必须是下列值的某种组合:SELECT、INSERT、 UPDATE 或 REFERENCES。注意在表级别上具有这些权限中的任意一种将会隐式地把它授予给表上的每一列。 例子: SELECT has_column_privilege(9999,'nosuchcol','select'); SELECT has_column_privilege('mytable','f2','select'); 8.175 HAS_DATABASE_PRIVILEGE 用法: has_database_privilege(user, database, privilege) has_database_privilege(database, privilege) 功能: 检查 user 用户(未指定时使用当前用户)是否能以 privilege 指定方式访问 database 数据库。希望的访问权 限类型必须是以下值的某种组合:CREATE、CONNECT、TEMPORARY 或 TEMP(等价于 TEMPORARY)。 例子: SELECT has_database_privilege(current_database(), 'CONNECT'); 327 第 8 章 函数 8.176 HAS_FOREIGN_DATA_WRAPPER_PRIVILEGE 用法: has_foreign_data_wrapper_privilege(user, fdw, privilege) has_foreign_data_wrapper_privilege(fdw, privilege) 功能: 检查 “user“ 用户(未指定时使用当前用户)是否能以特定方式访问一个外部数据包装器。它的参数可能性类似 于 has_table_privilege。希望的访问权限类型必须是 USAGE。 例子: SELECT has_foreign_data_wrapper_privilege('foo', 'USAGE'); 8.177 HAS_FUNCTION_PRIVILEGE 用法: has_function_privilege(user, function, privilege) has_function_privilege(function, privilege) 功能: 检查 user 用 户 (未 指 定 时 使 用 当 前 用 户) 是 否 能 以 特 定 方 式 访 问 一 个 函 数。 其 参 数 可 能 性 类 似 has_table_privilege。在用一个文本串而不是 OID 指定一个函数时,允许的输入和 regprocedure 数据类型 一样(参阅对象标识符类型 )。希望的访问权限类型必须是 EXECUTE。 例子: SELECT has_function_privilege('joeuser', 'myfunc(int, text)', 'execute'); 328 第 8 章 函数 8.178 HAS_LANGUAGE_PRIVILEGE 用法: has_language_privilege(user, language, privilege) has_language_privilege(language, privilege) 功能: 检查 user 用户(未指定时使用当前用户)是否可以以某种特定的方式访问一个过程语言。希望的访问权限类型 必须是 USAGE。 例子: SELECT has_database_privilege(current_database(), 'CONNECT'); 8.179 HAS_SCHEMA_PRIVILEGE 用法: has_schema_privilege(user, schema, privilege) has_schema_privilege(schema, privilege) 功能: 检查 user 用户(未指定时使用当前用户)是否能以 privilege 指定方式访问 schema 。希望的访问权限类型必 须是 CREATE 或 USAGE。 例子: SELECT has_schema_privilege('public', 'USAGE'); 329 第 8 章 函数 8.180 HAS_SEQUENCE_PRIVILEGE 用法: has_sequence_privilege(user, sequence, privilege) has_sequence_privilege(sequence, privilege) 功能: 检查 user 用户(未指定时使用当前用户)是否能以某种特定方式访问一个序列。所希望测试的访问权限类型必 须是下列之一:USAGE、SELECT 或 UPDATE。 例子: CREATE SEQUENCE x_seq; SELECT has_sequence_privilege('x_seq', 'SELECT'); 8.181 HAS_SERVER_PRIVILEGE 用法: has_server_privilege(user, server, privilege) has_server_privilege(server, privilege) 功能: 检查 user 用户(未指定时使用当前用户)是否可以以某种特定的方式访问一个外部服务器。希望的访问权限类 型必须是 CREATE 或 USAGE。 例子: SELECT has_server_privilege('regress_test_role',(SELECT oid FROM sys_foreign_server WHERE srvname='s8'), 'USAGE'); 330 第 8 章 函数 8.182 HAS_TABLE_PRIVILEGE 用法: has_table_privilege(user, table, privilege) has_table_privilege(table,privilege) 功能: 检查 user 用户(未指定时使用当前用户)是否可以用某种特定的方式访问一个表。该用户可以通过名字 或者 OID (sys_authid.oid)来指定,也可以用 public 表示 PUBLIC 伪角色。如果省略该参数,则使用 current_user。该表可以通过名字或者 OID 指定(因此,实际上有六种 has_table_privilege 的变体,我们可 以通过它们的参数数目和类型来区分它们)。如果用名字指定,那么在必要时该名字可以是模式限定的。所希望的 权限类型是用一个文本串来指定的,它必须是下面的几个值之一:SELECT、INSERT、UPDATE、DELETE、TRUNCATE、 REFERENCES 或 TRIGGER。WITH GRANT OPTION 可以被选择增加到一个权限类型来测试是否该权限是使用转授选项得 到。另外,可以使用逗号分隔来列出多个权限类型,在这种情况下只要具有其中之一的权限则结果为真(权限字符串 的大小写并不重要,可以在权限名称之间出现额外的空白,但是在权限名内部不能有空白)。 例子: SELECT has_table_privilege('myschema.mytable', 'select'); SELECT has_table_privilege('joe', 'mytable', 'INSERT, SELECT WITH GRANT OPTION'); 8.183 HAS_TABLESPACE_PRIVILEGE 用法: has_tablespace_privilege(user, tablespace, privilege) has_tablespace_privilege(tablespace, privilege) 功能: 检查 user 用户(未指定时使用当前用户)是否可以以某种特定的方式访问一个表空间。其参数可能性类似 “has_table_privilege“。希望的访问权限类型必须是 CREATE。 331 第 8 章 函数 例子: CREATE TABLESPACE mytsp LOCATION '/path/to/mytsp'; SELECT has_tablespace_privilege('mytsp', 'CREATE'); 8.184 HAS_TYPE_PRIVILEGE 用法: has_type_privilege(user, type, privilege) has_type_privilege(type, privilege) 功能: 检查 user 用户(未指定时使用当前用户)是否能以特定的方式访问一种类型。其参数的可能性类同于 has_table_privilege。在用字符串而不是 OID 指定类型时,允许的输入和 regtype 数据类型相同(见对象标识 符类型 )。期望的访问特权类型必须等于 USAGE。 例子: SELECT has_type_privilege('int8', 'USAGE'); 8.185 HEIGHT 用法: height(box) 功能: 几何函数,返回方框的垂直尺寸 例子: 332 第 8 章 函数 SELECT height(box '((0,0),(1,1))'); 8.186 HEXTORAW 用法: hextoraw(varchar2) 功能: 把十六进制字符串转换为相应的字节串。注意 HEXTORAW 函数和 raw 数据类型都需要加载 kdb_raw 插件才 能使用。 参数说明: varchar2:十六进制字符串。 返回值: RAW 类型。 例子: SELECT hextoraw('abcd') FROM DUAL; hextoraw ---------ABCD 8.187 HOUR(MySQL 模式) 用法: hour(n) 功能: 333 第 8 章 函数 返回给定时间的小时部分。 参数说明: n:date、timestamp、time 等时间日期类型。 返回值: integer 类型, 值域为 0 至 838。 例子: SELECT HOUR(DATE'2022-01-02') "HOUR"; HOUR ----------0 SELECT HOUR(TIMESTAMP'2022-01-05 1:00:00') "HOUR"; HOUR -----------1 8.188 HOST 用法: host(inet) 功能: inet 函数,抽取 IP 地址为文本。 例子: SELECT host('192.168.1.5/24'); 8.189 HOSTMASK 用法: 334 第 8 章 函数 hostmask(inet) 功能: inet 函数,为网络地址构造主机掩码。 例子: SELECT hostmask('192.168.23.20/30'); 8.190 IF 用法: if(expr1 INT 兼容类型, expr2 任意类型, expr3 任意类型) 功能: 如果 expr1 不为 NULL 并且 expr1 不等于 0,返回 expr2 作为结果,否则返回 expr3。 参数说明: a. expr1 是 INTEGER 类型表达式或者是可以转换成 INTEGER 的类型。 b. expr2 数据类型可以是系统的数据类型中的某一个 (如:TEXT,INTEGER,FLOAT 等)。 c. expr3 数据类型可以是系统的数据类型中的某一个 (如:TEXT,INTEGER,FLOAT 等)。 返回值说明: 返回值的数据类型:返回类型取决于 expr2,expr3 的类型。 例子: SELECT IF(100, 'T', 'F') AS RESULT1, IF(1 - 1, 'T', 'F') AS RESULT2, IF('100', 'T', 'F') AS RESULT3, IF(NULL, 'T', 'F') AS RESULT4; 335 第 8 章 函数 8.191 IFNULL 用法: ifnull(expr1, expr2) 功能: 当 “expr1“不是 NULL,IFNULL 返回 “expr1“。否则它返回 “expr2“ 例子: SELECT ifnull(NULL,'exp2'); SELECT ifnull('exp1','exp2'); 8.192 INET_CLIENT_ADDR 用法: inet_client_addr() 功能: inet_client_addr 返回当前客户端的 IP 地址。如果连接是通过 Unix 域套接字进行的,返回 NULL。 例子: SELECT inet_client_addr(); 8.193 INET_CLIENT_PORT 用法: inet_client_port() 336 第 8 章 函数 功能: inet_client_port 返回当前客户端的端口号。如果连接是通过 Unix 域套接字进行的,返回 NULL。 例子: SELECT inet_client_port(); 8.194 INET_MERGE 用法: inet_merge(inet,inet) 功能: inet_merge 返回包括给定网络的最小网络。 例子: SELECT inet_merge('192.168.1.5/24', '192.168.2.5/24'); 8.195 INET_SAME_FAMILY 用法: inet_same_family(inet, inet) 功能: 判断连个地址是否同一个 IP 协议族。 例子: 337 第 8 章 函数 SELECT inet_same_family(('192.168.1.5/24', '::1')); 8.196 INET_SERVER_ADDR 用法: inet_server_addr() 功能: inet_server_addr 返回接受当前连接的服务器的 IP。如果连接是通过 Unix 域套接字进行的,返回 NULL。 例子: SELECT inet_server_addr(); 8.197 INET_SERVER_PORT 用法: inet_server_port() 功能: inet_server_port 返回接受当前连接的服务器的端口号。如果连接是通过 Unix 域套接字进行的,返回 NULL。 例子: SELECT inet_server_port(); 8.198 INITCAP 用法: 338 第 8 章 函数 initcap(string) 功能: INITCAP 返回 char,每个单词的第一个字母大写,所有其他字母小写。单词由空格或非字母数字字符分隔。 char 可以是任何数据类型 CHAR、VARCHAR、NCHAR 或 NVARCHAR。返回值与的数据类型相同 char。数 据库根据为基础字符集定义的二进制映射设置初始字符的大小写。 例子: 以下示例将字符串中的每个单词大写: SELECT initcap('hi THOMAS'); 8.199 INSERTCHILDXML 用法: insertchildxml(xml_instance xml, xpath text, child_expr text , value_expr xml) insertchildxml(xml_instance xml, xpath text , child_expr text ,value_expr xml, namespace _text) 功能: 函数 insertchildxml 将 “value_expr“提供的值作为 “xpath“指定节点的子节点插入到 “xml_instance“中。成功 则返回插入后的 “xml_instance“数据,失败则返回 ERROR。 此函数使用前需要创建 kdb_utils_function 扩展。 例子: SELECT insertchildxml('onethree', '//b', 'name', 'newnode'); SELECT insertchildxml('test', '//mydefns:b/text()', 'name', 'newnode', ARRAY[ARRAY['mydefns', 'http://example.com']]); 339 第 8 章 函数 8.200 INSERTCHILDXMLAFTER 用法: insertchildxmlafter(xml_instance xml, xpath text, child_expr text , value_expr xml) insertchildxmlafter(xml_instance xml, xpath text , child_expr text ,value_expr xml,namespace _text) 功能: 函数 insertchildxmlafter 将 “value_expr“提供的一个或多个集合元素作为 “xpath“指定的目标父元素的子元 素插入到 “child_expr“指定的现有集合元素之后。成功则返回插入后的 “xml_instance“数据,失败则返回 ERROR。 此函数使用前需要创建 kdb_utils_function 扩展。 例子: 在指定节点的所有“b”子节点之后插入: SELECT insertchildxmlafter('onetwofour', '/a', 'b', 'three'); 在指定节点的第一个“b”子节点之后插入: SELECT insertchildxmlafter('onetwofour', '/a', 'b[1]', 'three'); 在指定节点的第二个“b”子节点之后插入: SELECT insertchildxmlafter('onetwofour', '/a', 'b[2]', 'three'); 8.201 INSERTCHILDXMLBEFORE 用法: insertchildxmlbefore(xml_instance xml, xpath text, child_expr text , value_expr xml) insertchildxmlbefore(xml_instance xml, xpath text , child_expr text , value_expr xml,namespace _text) 340 第 8 章 函数 功能: 函数 insertchildxmlbefore 将 “value_expr“提供的一个或多个集合元素作为 “xpath“指定的目标父元素的子元 素插入到 “child_expr“指定的现有集合元素之前。成功则返回插入后的 “xml_instance“数据,失败则返回 ERROR。 此函数使用前需要创建 kdb_utils_function 扩展。 例子: 在指定节点的所有“b”子节点之前插入: SELECT insertchildxmlbefore('one23twofour', '/a', 'b', 'three'); 在指定节点的第一个“b”子节点之前插入: SELECT insertchildxmlbefore('onetwo', '/a', 'b[1]', 'three'); 在指定节点的第二个“b”子节点之前插入: SELECT insertchildxmlbefore('one23twofour', '/a', 'b[2]', 'three'); 8.202 INSERTXMLAFTER 用法: insertxmlafter(xml_instance xml, xpath text , value_expr xml) insertxmlafter(xml_instance xml, xpath text , value_expr xml,namespace _text) 功能: 函数 insertxmlafter 将 “value_expr“提供的值插入到 “xpath“指定的节点之后。成功则返回插入后的 “xml_instance“数据,失败则返回 ERROR。 341 第 8 章 函数 此函数使用前需要创建 kdb_utils_function 扩展。 例子: SELECT insertxmlafter('test', '//mydefns:b/text()', 'newnode', ARRAY[ARRAY['mydefns', 'http://example.com']]); 8.203 INSERTXMLBEFORE 用法: insertxmlbefore(xml_instance xml, xpath text , value_expr xml) insertxmlbefore(xml_instance xml, xpath text , value_expr xml,namespace _text) 功能: 函数 insertxmlbefore 将 “value_expr“提供的值插入到 “xpath“指定的节点之前。成功则返回插入后的 “xml_instance“数据,失败则返回 ERROR。 此函数使用前需要创建 kdb_utils_function 扩展。 例子: SELECT insertxmlbefore('b','/a/b','c'); SELECT insertxmlbefore('','/a/b','c'); SELECT insertxmlbefore('','/a/b',''); SELECT insertxmlbefore('test', '//mydefns:b/text()', 'newnode', ARRAY[ARRAY['mydefns', 'http://example.com']]); 8.204 INSTR 用法: instr(expr1 text, expr2 text,[expr3 int[,expr4 int]]) 342 第 8 章 函数 功能: 在父字符串 expr1 中的第 expr3 个位置(从 1 开始)以字符为单位开始查找第 expr4 次出现的子字符串的位置, 0 表示不包含子字符串 expr2。如果 expr3 为负,则从 expr1 的倒数第 expr3 个位置开始反向查找,位置依然是从字 符串开头算起。 例子: SELECT instr('bcaaaaabbc', 'a', -2); 8.205 INSTRB 用法: instrb(expr1 text,expr2 text,[expr3 int[,expr4 int]]) 功能: 在父字符串 expr1 中的第 expr3 个位置(从 1 开始)以字节为单位开始查找第 expr4 次出现的子字符串的位置, 0 表示不包含子字符串 expr2。如果 expr3 为负,则从 expr1 的倒数第 expr3 个位置开始反向查找,位置依然是从字 符串开头算起。 例子: SELECT instrb(’bcaaaaabbc’, ’a’, -2); 8.206 ISEMPTY 用法: 343 第 8 章 函数 isempty(anyrange) 功能: 判断范围 anyrange 是否为空。 例子: SELECT isempty(numrange(1.1,2.2)); 8.207 ISFINITE 用法: isfinite(date) isfinite(timestamp) isfinite(interval) 功能: 判断传入参数是否为有限值。 例子: SELECT isfinite(date '2001-02-16'); SELECT isfinite(timestamp '2001-02-16 21:28:30'); SELECT isfinite(interval '4 hours'); 8.208 ISNULL 用法: 344 第 8 章 函数 isnull(expr1, expr2) 功能: 等同于函数 NVL(expr1 任意类型, expr2 任意类型)。当 expr1 为 NULL 时,用 expr2 代替本表达式的值;否 则本函数的值保持 expr1 的原值。另外 expr1 及 expr2 数据类型可以是系统的数据类型中的某一个 (如:TEXT、 INTEGER、FLOAT 等),expr1 和 expr2 的数据类型应该一致。 如果 expr1 不为 NULL,数据类型同 expr1;如果 expr1 为 NULL,数据类型同 expr2。 在兼容性方面,ISNULL 相当于 MSSQL 2005 中的 ISNULL 函数、KingbaseES 中的 NVL 函数、ORACLE 中的 NVL 函数。 例子: SELECT ISNULL('2001-01-10', TO_DATE('05 Dec 2000', 'DD Mon YYYY')) AS RESULT1, ISNULL(NULL, TO_DATE('05 Dec 2000', 'DD Mon YYYY')) AS RESULT2, ISNULL(NULL, 123) AS RESULT3, ISNULL(789, 123) AS RESULT4, ISNULL(NULL, '123') AS RESULT5; 8.209 ISNULL(MySQL 模式) 用法: isnull(expr) 功能: 判断表达式 expr 为 NULL,则返回值 1,非空返回 0。 ISNULL() 函数只支持传入一个参数,参数的形式为: • 常量表达:数字类型,字符类型,日期/时间类型,布尔类型,几何类型,位串类型,JSON 数据类型。 • 变量和变量表达式。 • 列:用户自定义列,序列,生成列,隐含列,索引列。 • 函数:数学函数,日期/时间函数,字符串函数,强制转换函数,XML 函数,加密和压缩函数,锁定函数,信 息函数,空间分析函数,位函数,聚合函数等任意类型的表达式。 345 第 8 章 函数 • 特殊字符:空值,空字符,空字符串。 • ISNULL() 函数不支持传入类型为 DDL,DML,DQL,DCL 类型的 SQL 语句。 例子: select isnull(10); +------------+ | isnull(10) | +------------+ | 0 | +------------+ 1 row in set (0.00 sec) select isnull(null); +--------------+ | isnull(null) | +--------------+ | 1 | +--------------+ 1 row in set (0.00 sec) select isnull(2,3); ERROR 1582 (42000): Incorrect parameter count in the call to native function 'isnull' 8.210 ISOPEN 用法: isopen(path) 功能: 几何函数,判断参数是否一个开放路径。 例子: isopen(path '[(0,0),(1,1),(2,0)]') 346 第 8 章 函数 8.211 JSON 用法: json ( expression [ FORMAT JSON [ ENCODING UTF8 ] ] [ { WITH | WITHOUT } UNIQUE [ KEYS ] ] [ RETURNING json_data_type ] ) expression [ FORMAT JSON [ENCODING UTF8] ] 字符串 expression 提供了 JSON 的文本数据。可以是字符串类型:varchar、char、text、varchar2、nvarchar2、nvarchar、clob、nclob,或者 UTF8 编码的二进制类型(bytea、blob)。 { WITH | WITHOUT } UNIQUE [ KEYS ] 定义是否允许重复键。 RETURNING json_data_type 指定生成的 JSON 对象的返回类型的输出子句。只能返回 JSON 或者 JSONB 类型。 功能: JSON 函数,使用 JSON 数据类型构造函数来解析文档的 JSON 输入(标量、对象或者数组),返回一个 JSON 类型的实例。 例子: select json('{"aa":"bb","aa":"cc"}'); 结果: ----------------------{"aa":"bb","aa":"cc"} (1 row) 347 第 8 章 函数 select json('{"aa":"bb","aa":"cc"}' without unique returning jsonb); 结果: -------------{"aa": "cc"} (1 row) select json('{"aa":"bb","aa":"cc"}' with unique returning jsonb); 结果: ERROR: duplicate JSON object key value 8.212 JSON_AGG 用法: json_agg(expression) 功能: 聚集函数,将传入值包括空值聚集成一个 JSON 数组。 例子: SELECT json_agg(q) FROM ( SELECT $$a$$ || x AS b, y AS c, ARRAY[ROW(x.*,ARRAY[1,2,3]), ROW(y.*,ARRAY[4,5,6])] AS z FROM generate_series(1,2) x, generate_series(4,5) y) q; 8.213 JSON_ARRAY 8.213.1 用法 1 用法: JSON_ARRAY ( [ { value_expression [ FORMAT JSON ] } [, ...] ] 348 第 8 章 函数 [ { NULL | ABSENT } ON NULL ] [ RETURNING data_type [ FORMAT JSON [ ENCODING UTF8 ] ] ] ) value_expression [ FORMAT JSON ] 为构造 JSON 数据提供数据的输入子句。 { NULL | ABSENT } ON NULL 指定此函数在 value_expression 计算结果为 null 时的行为。 RETURNING data_type [ FORMAT JSON [ ENCODING UTF8 ]] 指定生成数据的类型。支持以下类型:json、jsonb、bytea 和字符串类型(text、char、varchar 和 nchar),还支持 VARCHAR2、BLOB、CLOB 类型。 功能: JSON 处理函数,函数通过 SQL 或者 JSON 数据构建一个 JSON 数组。 例子: SELECT JSON_ARRAY(f.code,f.title,f.did) AS films FROM films AS f WHERE f.did = 103; 结果: films ---------------------------------------------------["P_301", "Vertigo", 103] ["P_302", "Becket", 103] ["P_303", "48 Hrs", 103] (3 rows) 349 第 8 章 函数 8.213.2 用法 2 用法: JSON_ARRAY ( [ query_expression ] [ RETURNING data_type [ FORMAT JSON [ ENCODING UTF8 ] ] ] ) query_expression 提供用于构造 JSON 数组的的数据的 SQL 查询。查询只能返回包含要在数组中使用的一个列,不能是多 列。 RETURNING data_type [ FORMAT JSON [ ENCODING UTF8 ]] 指定生成数据的类型。支持以下类型:json、jsonb、bytea 和字符串类型(text、char、varchar 和 nchar),还支持 VARCHAR2、BLOB、CLOB 类型。 功能: JSON 处理函数,函数通过 SQL 或者 JSON 数据构建一个 JSON 数组。。 例子: SELECT JSON_ARRAY(SELECT f.title FROM films AS f where f.did = 103) AS film_titles; 结果: film_titles ---------------------------------------------------["Vertigo", "Becket", "48 Hrs"] (1 row) 8.213.3 用法 3 用法: 350 第 8 章 函数 json [ [ { value_expression [ FORMAT JSON ] } [, ...] ] [ { NULL | ABSENT } ON NULL ] [ RETURNING data_type [ FORMAT JSON [ ENCODING UTF8 ] ] ] ] value_expression [ FORMAT JSON ] 参数值表达式数据表列。 { NULL | ABSENT } ON NULL 指定函数在 value_expression 计算结果为 null 时的行为。 RETURNING data_type [ FORMAT JSON [ ENCODING UTF8 ]] 指定生成数据的类型。支持以下类型:json、jsonb、bytea 和字符串类型(text、char、varchar 和 nchar),还支持 VARCHAR2、BLOB、CLOB 类型。 功能: JSON 处理函数,通过 SQL 或者 JSON 数据构建一个 JSON 数组。 例子: 基础数据 create table t1(id int, name text); insert into t1 values(1,'aa'); insert into t1 values(2,'bb'); insert into t1 values(3,'cc'); insert into t1 values(4,'dd'); insert into t1 values(3,'cccc'); select json[id,name] from t1; 结果: 351 第 8 章 函数 json ------------[1, "aa"] [2, "bb"] [3, "cc"] [4, "dd"] [3, "cccc"] 8.214 JSON_ARRAY_ELEMENTS 用法: json_array_elements(json) 功能: JSON 处理函数,将传入值包括空值聚集成一个 JSON 数组。 例子: SELECT json_array_elements('[1,true,[1,[2,3]],null,{"f1":1,"f2":[7,8,9]},false,"stringy"]'); 8.215 JSON_ARRAY_ELEMENTS_TEXT 用法: json_array_elements_text(json) 功能: JSON 处理函数,把一个 JSON 数组扩展成 text 值集合。 例子: 352 第 8 章 函数 SELECT * FROM json_array_elements_text('["foo","bar"]'); 8.216 JSON_ARRAY_LENGTH 用法: json_array_length(json) 功能: JSON 处理函数,返回最外层 JSON 数组中的元素数量。 例子: SELECT json_array_length('[1,2,3,{"f1":1,"f2":[5,6]},4]'); 8.217 JSON_ARRAYAGG 用法: JSON_ARRAYAGG ( [ value_expression ] [ ORDER BY sort_expression ] [ { NULL | ABSENT } ON NULL ] [ RETURNING data_type [ FORMAT JSON [ ENCODING UTF8 ] ] ] ) 353 第 8 章 函数 value_expression value_expression 是一个表达式,它为 JSON 值提供其类型的输入。 ORDER BY sort_expression 输入数据的排序规则。详见SELECT 章节的GROUP BY 子句 。 { NULL | ABSENT } ON NULL 指定函数在 value_expression 计算结果为 null 时的行为。 RETURNING data_type [ FORMAT JSON [ ENCODING UTF8 ]] 指定生成数据的类型。支持以下类型:json、jsonb、bytea 和字符串类型(text、char、varchar 和 nchar),还支持 VARCHAR2、BLOB、CLOB 类型。 功能: JSON 处理函数,函数将提供的 JSON 数据聚合到 JSON 数组中。 例子: SELECT JSON_ARRAYAGG( f.title ORDER BY f.title ASC) AS film_titles FROM films AS f; 结果: film_titles ---------------------------------------------------["48 Hrs", "Absence of Malice", "Bananas", "Becket", "Bed Knobs and Broomsticks", "Das Boot", "Storia di una donna", "Taxi Driver", "The African Queen", "The King and I", "There's a Girl in my Soup", "The Third Man", "Une Femme est une Femme", "Vertigo", "War 354 第 8 章 函数 and Peace", "West Side Story", "Yojimbo"] (1 row) 8.218 JSON_BUILD_ARRAY 用法: json_build_array( VARIADIC "any") 功能: JSON 处理函数,将可变参数列表构造成一个可能包含不同数据类型的 JSON 数组。 例子: SELECT json_build_array(1,2,'3',4,5); 8.219 JSON_BUILD_OBJECT 用法: json_build_object( VARIADIC "any") 功能: JSON 处理函数,将可变参数列表构造成一个 JSON 对象,通过转换,该参数列表由交替出现的键和值构成。 例子: SELECT json_build_object('foo',1,'bar',2); 8.220 JSON_EACH 用法: 355 第 8 章 函数 json_each(json) 功能: JSON 处理函数,扩展最外层的 JSON 对象成为一组键值对。 例子: SELECT * FROM json_each('{"a":"foo", "b":"bar"}'); 8.221 JSON_EACH_TEXT 用法: json_each_text(json) 功能: JSON 处理函数,扩展最外层的 JSON 对象成为一组键值对,返回值为 text 类型。 例子: SELECT * FROM json_each_text('{"a":"foo", "b":"bar"}')`; 8.222 JSON_EQUAL 用法: json_equal( expr ,expr [{error|false|true} on error ]) 356 第 8 章 函数 expr 输入参数,可以是列名、字符串常量、复合表达式和函数表达式,数据类型必须是字符类型变量(character [(n [char |byte])], character varying[(n [char |byte])],text,clob,blob) {error|false|true} on error 发生错误时,默认返回 true 或者 false。 功能: JSON 处理函数,用于判断输入的两个文本值是否相等,前提是两个文本必须是有效的 JSON 值,否则返回 false,当都为有效 JSON 值且相等则返回 true,否则返回 false。 例子: SELECT json_equal('{"a":1}','{"a":1}') FROM dual; 结果: t SELECT json_equal('{"a":1}','{"a":2}') FROM dual; 结果: f SELECT json_equal('{"a":1}','{"a":1}' false on error) FROM dual; 结果: t 8.223 JSON_EXISTS 用法: json_exists( context_item, path_expression [ PASSING { value AS varname }[, ...]] [ RETURNING data_type ] 357 第 8 章 函数 [ { TRUE | FALSE | UNKNOWN | ERROR } ON ERROR ] ) context_item 输入表达式 path_expression 路径表达式 [ PASSING { value AS varname }[, ...]] 使用此子句将值传递给路径表达式 [ RETURNING data_type ] 此子句指定返回的数据类型 [ { TRUE | FALSE | UNKNOWN | ERROR } ON ERROR ] 当未找到匹配值时,使用此子句返回指定的值, 默认 FALSE 功能: 使用表达式 JSON_EXISTS 用于从一个输入的 json 文本中检索指定的 jsonpath 路径是否存在指定的 JSON 值, 如果存在返回 true,不存在返回 false。 例子: SELECT JSON_EXISTS(jsonb '{"key1": [1,2,3]}', 'strict $.key1[*] ?(@ > 2)'); ** 返回值:** json_exists ------------t (1 row) 358 第 8 章 函数 SELECT JSON_EXISTS(jsonb '{"a": [1,2,3]}', 'lax $.a[5]' ERROR ON ERROR); ** 返回值:** json_exists ------------f (1 row) SELECT JSON_EXISTS(jsonb '{"a": [1,2,3]}', 'strict $.a[5]'); ** 返回值:** json_exists ------------f (1 row) 8.224 JSON_EXTRACT_PATH 用法: json_extract_path(from_json json, VARIADIC path_elems text[]) 功能: JSON 处理函数,返回由 path_elems 指向的 JSON 值(等效于 #> 操作符)。 例子: SELECT json_extract_path('{"f2":{"f3":1},"f4":{"f5":99,"f6":"foo"}}','f4'); 8.225 JSON_EXTRACT_PATH_TEXT 用法: json_extract_path_text(from_json json, VARIADIC path_elems text[]) 功能: 359 第 8 章 函数 JSON 处理函数,以 text 类型返回由 path_elems 指向的 JSON 值(等效于 #> 操作符)。 例子: SELECT json_extract_path_text('{"f2":{"f3":1},"f4":{"f5":99,"f6":"foo"}}','f 4', 'f6'); 8.226 JSON_OBJECT 8.226.1 用法 1 用法: json_object(text[]) text 文本数组。 功能: JSON 处理函数,从文本数组中构造 JSON 对象。该函数必须可以使具有偶数个成员的一维数组 (成员被当做交 替出现的键值对),或者是一个二维数组(每一个内部数组刚好有两个元素,可以被看做键值对)。 例子: SELECT json_object('{a, 1, b, "def", c, 3.5}'); ** 返回值:** {"a": "1", "b": "def", "c": "3.5"} SELECT json_object('{{a,1},{b, "def"},{c, 3.5}}'); ** 返回值:** {"a": "1", "b": "def", "c": "3.5"} 8.226.2 用法 2 用法: json_object( keys text[], values text[]) 360 第 8 章 函数 keys json 属性 key 键数组。 values json 属性 value 值数组。 功能: JSON 处理函数,从文本数组中构造 JSON 对象。从两个独立的数组得到键/值对。在其他方面和一个参数的形 式相同。 例子: SELECT json_object('{a,b}', '{1,2}') FROM dual ; ** 返回值:** {"a" : "1", "b" : "2"} 8.226.3 用法 3 用法: json_object ( [ { key_expression { value | ':' } value_expression [ format json [ encoding utf8 ] ] }[, ...] ] [ { null | absent } on null ] [ returning data_type [ format json [ encoding utf8 ] ] ] [ { with | without } unique [ keys ] ] ) 361 第 8 章 函数 key_expression json 数据 key 表达式。 value | ':' json 数据参数 key 和 value 中间隔离符号。 value_expression json 数据 value 表达式。 format json 指定 format json 以声明由它产生的值表示 JSON 数据。 encoding utf8 声明 json 字符编码。 { null | absent } on null 指定函数在 expr 计算结果为 null 时的行为。 362 第 8 章 函数 returning data_type 函数返回对象格式,默认是 varchar2(4000) 类型,可以通过 RETURNING 子句执行返回类型。 可选(varchar2,clob,blob,json) { with | without } unique [ keys ] 保证生成的 JSON 对象具有唯一键。 功能: JSON 处理函数,从文本数组中构造 JSON 对象。通过函数表达式形式创建 JSON 对象。 例子: SELECT JSON_OBJECT('name' : first_name || ' ' || last_name,'email' : email,'phone' : phone_number,'hire_date ' : hire_date) FROM hr.employees WHERE employee_id = 140; ** 返回值:** {"name":"Joshua Patel","email":"JPATEL","phone":"650.121.1834","hire_date":"1998-04-06T00:00:00"} SELECT JSON_OBJECT('key1' VALUE NULL ABSENT ON NULL) FROM dual; ** 返回值:** {} SELECT JSON_OBJECT ('name' value '"Foo"' FORMAT JSON ) FROM DUAL; ** 返回值:** {"name":"Foo"} SELECT json_object('id' value 'aa', 'id' value 'bb' with unique keys) FROM dual; ** 返回值:** ERROR: duplicate JSON key "id" 8.227 JSON_OBJECT_AGG 用法: json_object_agg(name, value) 功能: 聚集函数,将 name 和 value 对聚合成 JSON 对象,值可以为空,名字不能为空。 例子: 363 第 8 章 函数 CREATE TEMP TABLE foo (serial_num int, name text, type text); INSERT INTO foo VALUES (847001,'t15','GE1043'); INSERT INTO foo VALUES (847002,'t16','GE1043'); INSERT INTO foo VALUES (847003,'sub-alpha','GESS90'); SELECT json_object_agg(name, type) FROM foo; 8.228 JSON_OBJECT_KEYS 用法: json_object_keys(json) 功能: JSON 函数,返回外层 JSON 对象中键的集合。 例子: SELECT json_object_keys('{"f1":"abc","f2":{"f3":"a", "f4":"b"}}'); 8.229 JSON_OBJECTAGG 8.229.1 用法 1 用法: json_objectagg( [ { key_expression { VALUE | ':' } value_expression } ] [ { NULL | ABSENT } ON NULL ] [ { WITH | WITHOUT } UNIQUE [ KEYS ] ] [ RETURNING data_type [ FORMAT JSON [ ENCODING UTF8 ] ] ] ) 364 第 8 章 函数 key_expression { VALUE | ':' } value_expression 输入的数据聚集为一个 JSON 对象。 { NULL | ABSENT } ON NULL 指定函数在 key_expression 计算结果为 null 时的行为。 { WITH | WITHOUT } UNIQUE [ KEYS ] 定义是否允许重复键。 RETURNING data_type [ FORMAT JSON [ ENCODING UTF8 ]] 指定生成数据的类型。支持以下类型:json、jsonb、bytea 和字符串类型(text、char、varchar 和 nchar),还支持 VARCHAR2、BLOB、CLOB 类型。 功能: 聚集函数,把键值对聚集成一个 JSON 对象。 例子: 基础数据 create table t1(id int, name text); insert into t1 values(1,'aa'); insert into t1 values(2,'bb'); insert into t1 values(3,'cc'); insert into t1 values(4,'dd'); insert into t1 values(3,'cccc'); select json_objectagg(id : name) from t1; 结果: { "1" : "aa", "2" : "bb", "3" : "cc", "4" : "dd", "3" : "cccc" } 365 第 8 章 函数 select json_objectagg(id value name) from t1; 结果: { "1" : "aa", "2" : "bb", "3" : "cc", "4" : "dd", "3" : "cccc" } select json_objectagg(id value name with unique keys returning jsonb) from t1; 结果: ERROR: duplicate JSON object key value 8.229.2 用法 2 用法: json_objectarray( [ { key_expression { VALUE | ':' } value_expression } ] [ { NULL | ABSENT } ON NULL ] [ RETURNING data_type [ FORMAT JSON [ ENCODING UTF8 ] ] ] [ { WITH | WITHOUT } UNIQUE [ KEYS ] ] ) key_expression { VALUE | ':' } value_expression 输入的数据聚集为一个 JSON 对象。 { NULL | ABSENT } ON NULL 指定函数在 key_expression 计算结果为 null 时的行为。 { WITH | WITHOUT } UNIQUE [ KEYS ] 366 第 8 章 函数 定义是否允许重复键。 RETURNING data_type [ FORMAT JSON [ ENCODING UTF8 ]] 指定生成数据的类型。支持以下类型:json、jsonb、bytea 和字符串类型(text、char、varchar 和 nchar),还支持 VARCHAR2、BLOB、CLOB 类型。 功能: 聚集函数,把键值对聚集成一个 JSON 对象。 例子: 基础数据 create table t1(id int, name text); insert into t1 values(1,'aa'); insert into t1 values(2,'bb'); insert into t1 values(3,'cc'); insert into t1 values(4,'dd'); insert into t1 values(3,'cccc'); select json_objectagg(id : name) from t1; 结果: { "1" : "aa", "2" : "bb", "3" : "cc", "4" : "dd", "3" : "cccc" } select json_objectagg(id value name) from t1; 结果: { "1" : "aa", "2" : "bb", "3" : "cc", "4" : "dd", "3" : "cccc" } select json_objectagg(id value name returning jsonb with unique keys ) from t1; 结果: ERROR: duplicate JSON object key value 8.230 JSON_POPULATE_RECORD 用法: json_populate_record(base anyelement,from_json json) 功能: JSON 函数,扩展 from_json 中的对象成一个行,它的列匹配由 base 定义的记录类型。 例子: 367 第 8 章 函数 SELECT * FROM json_populate_record(null::myrowtype,'{"a":1, "b": ["2", "a b"],"c": {"d":4, "e": "ab c"}}'); 8.231 JSON_QUERY 用法: json_query ( expression [FORMAT JSON [ENCODING UTF8]],JSON_basic_path_expression [ PASSING { value AS varname } [, ...]] [ RETURNING data_type [ FORMAT JSON [ ENCODING UTF8 ] ] [ { WITHOUT | WITH { CONDITIONAL | [UNCONDITIONAL] } } [ ARRAY ] WRAPPER ] [ { KEEP | OMIT } QUOTES [ ON SCALAR STRING ] ] [{ERROR|NULL|EMPTY|EMPTY ARRAY|EMPTY OBJECT|DEFAULT expression } ON EMPTY ] [{ERROR|NULL|EMPTY|EMPTY ARRAY|EMPTY OBJECT|DEFAULT expression } ON ERROR ] ) 368 第 8 章 函数 369 第 8 章 函数 expression 输入的 json 文本,完整的支持可以为字符常量、函数、或者列名(数据类型为 clob,blob 或者 varchar2),V9C7 版本只支持输入类型为 JSONB 类型,其他类型后续补充; FORMAT JSON 是在 expression 为字符串类型时将 expression 格式化成 json 格式。 ENCODING UTF8 指定输入为二进制类型时的字符集。 json_basic_path_expression 用于指定 json 文件所要查询的路径。 PASSING { value AS varname } [, ...] 将 varname 变量的值替换成 value 进行查询,需要注意 a.varname 为非限定标识符(不带双引号)时会自动转换为小写,为限定标识符(带双引号)时原样存储 不进行大小写转换。b.varname 的数据类型应与检索值相同。 RETURNING data_type 指定返回值的数据类型。支持以下类型:json、jsonb、bytea 和字符串类型(text、char、varchar 和 nchar),还支持 VARCHAR2、BLOB、CLOB 类型。 { WITHOUT | WITH { CONDITIONAL | [UNCONDITIONAL] } } [ ARRAY ] WRAPPER 控制 JSON_QUERY 函数返回值是否用方括号“[]”包围。 a.WITHOUT WRAPPER:默认选项,返回值不用‘[]’包围。b.WITH WRAPPER: 返回值用‘[]’包 围,等价于 WITH ARRAY WRAPPER。c.WITH UNCONDITIONAL WRAPPER: 等价于 WITH WRAPPER. d.WITH CONDITIONAL WRAPPER: • 如果匹配到多个值或单个标量值,与 WITH WRAPPER 相同; • 如果匹配到单个对象或者数组,与 WITHOUT WRAPPER 相同。 { KEEP | OMIT } QUOTES [ ON SCALAR STRING ] Quotes 子句指定当返回值为标量字符串时是否保留双引号(“”). a. 指定 KEEP 时保留,此为默认选项;b. 指定 OMIT 时不保留。c.QUOTES 子句不能与 WITH WRAPPER 子句共用。d.ON SCALAR STRING 关键字只为语法清晰,添加与否对结果无影响。 {ERROR|NULL|EMPTY|EMPTY ARRAY|EMPTY OBJECT|DEFAULT expression } ON ERROR 指定错误发生时的返回值。 a.NULL ON ERROR - 返回 NULL, 此为默认选项 b.ERROR ON ERROR - 报错 c.EMPTY ON ERROR - 等价于 EMPTY ARRAY ON ERROR. d.EMPTY ARRAY ON ERROR - 返回空数组 ([]) e.EMPTY OBJECT ON ERROR - 返回空对象 ({}) {ERROR|NULL|EMPTY|EMPTY ARRAY|EMPTY OBJECT|DEFAULT expression } ON EMPTY 370 第 8 章 函数 指定没有结果相匹配时的返回值。 a.NULL ON EMPTY - 返回 NULL, 此为默认选项 b.ERROR ON EMPTY - 报错 c.EMPTY ON EMPTY - 等价于 EMPTY ARRAY ON ERROR. d.EMPTY ARRAY ON EMPTY - 返回空数组 ([]) e.EMPTY OBJECT ON EMPTY - 返回空对象 ({}) 功能: JSON 函数,用于从一个输入的 json 文本中根据指定的 jsonpath 路径检索所需的值(可以为标量值,也可以为 对象或者数组)。 例子: SELECT JSON_query(jsonb '{"a": 1, "b": 2}', '$.* ? (@ > $"xy")' PASSING 1 AS XY); json_query -----------2 (1 row) SELECT JSON_QUERY(jsonb '"aaa"', '$' RETURNING text KEEP QUOTES); json_query -----------"aaa" (1 row) SELECT JSON_query(jsonb '{"a":"b","c":"d"}', '$.ab' returning varchar empty on empty); json_query -----------[] (1 row) select json_query(jsonb '["aaa",123]', '$[*]' returning varchar(2) error on error); ERROR: JSON path expression in JSON_QUERY should return singleton item without wrapper 8.232 JSON_SCALAR 用法: json_scalar ( expression [ RETURNING json_data_type ] ) 371 第 8 章 函数 expression 用于构造 JSON 标量值的数据。 [ RETURNING json_data_type ] 函数返回值,可以返回 json 类型或 jsonb 类型,默认是 jsob 类型。 功能: JSON 函数,使用 JSON_SCALAR 函数从 SQL 数据生成 JSON 标量值。 例子: SELECT json_scalar(true ); 结果: ------------true (1 row) SELECT json_scalar(1 returning json); 结果: ------------1 \gdesc 结果: -------------+-----json_scalar | json 8.233 JSON_SERIALIZE 用法: json_serialize ( expression [ FORMAT JSON [ ENCODING UTF8 ] ] [ RETURNING data_type [ FORMAT JSON [ ENCODING UTF8 ] ] ] ) 372 第 8 章 函数 expression [ FORMAT JSON [ ENCODING UTF8 ] ] 转需要换为字符或二进制字符串的 json 值。 [ RETURNING data_type [ FORMAT JSON [ ENCODING UTF8 ] ] ] json 数据转换后的数据类型(text, char, bytea)等,默认是 text 类型。 功能: JSON 函数,表达式用于把 JSON 类型的数据转换为字符串或二进制字符串。返回值可以是任意字符串类型或二 进制字符串类型。 例子: select json_serialize('{"a":{"a":"c"}}' returning varchar(10) ); 结果: ---------------{"a":{"a": select json_serialize('{"a":{"a":"c"}}' returning bytea format json encoding utf8 ); 结果: ---------------------------------\x7b2261223a7b2261223a2263227d7d explain(verbose,costs off) select json_serialize( '1' returning text) as json_type ; 结果: ---------------------------------------------------Result Output: JSON_SERIALIZE('1'::json RETURNING text) (2 rows) 373 第 8 章 函数 8.234 JSON_STRIP_NULLS 用法: json_strip_nulls(from_json json) 功能: JSON 函数,返回 from_json,其中所有具有空值的对象域都被过滤掉,其他空值不动。 例子: SELECT json_strip_nulls('[{"f1":1,"f2":null},2,null,3]'); 8.235 JSON_TABLE 用法: json_table ( context_item, path_expression [ AS json_path_name ] [ PASSING { value AS varname } [, ...] ] COLUMNS ( json_table_column [, ...] ) [ PLAN ( json_table_plan ) | PLAN DEFAULT ( { INNER | OUTER } [ , { CROSS | UNION } ] | { CROSS | UNION } [ , { INNER | OUTER } ] ) ] [{ERROR | EMPTY} ON ERROR] ) 374 第 8 章 函数 context_item 查询的输入数据。 path_expression [ AS json_path_name ] [ PASSING { value AS varname } [, ...] ] 定义查询的 JSON 路径表达式和一个可选的 PASSING 子句,它可以为 path_expression 提供数据值。输 入数据评估的结果称为行模式。行模式用作构造视图中行值的来源。 COLUMNS( json_table_column [, ...] ) 定义构造视图模式的 COLUMNS 子句。在此子句中,必须指定要使用 SQL/ JSON 项填充的所有列。 json_table_column 说明请见【子句分项】。 [ PLAN ( json_table_plan ) | PLAN DEFAULT ( { INNER | OUTER } [ , { CROSS | UNION } ] | { CROSS | UNION } [ , { INNER | OUTER } ] ) ] 定义如何将 NESTD PATH 子句返回的数据连接到构造的视图。json_table_plan 说明请见【子句分 项】。 [{ERROR | EMPTY} ON ERROR] 指定发生错误时函数返回的值。默认为 EMPTY ON ERROR。 子句分项: json_table_column 定义构造视图模式的 COLUMNS 子句。子句包含以下五种类型: 375 第 8 章 函数 类型 1: name type [ PATH json_path_specification ] [ { WITHOUT | WITH { CONDITIONAL | [UNCONDITIONAL] } } [ ARRAY ] WRAPPER ] (注:此处实际只能支持 WITHOUT [ARRAY] WRAPPER) [ { KEEP | OMIT } QUOTES [ ON SCALAR STRING ] ] (注:此处实际不支持此子句) [ { ERROR | NULL | DEFAULT expression } ON EMPTY ] [ { ERROR | NULL | DEFAULT expression } ON ERROR ] 说明:与 JSON_QUERY 函数相同的方式评估 JSON 数据,找到一个或多个指定的 JSON 值, 并返回包含这些 JSON 值的字符串列。 类型 2: name type FORMAT json_representation [ PATH json_path_specification ] [ { WITHOUT | WITH { CONDITIONAL | [UNCONDITIONAL] } } [ ARRAY ] WRAPPER ] [ { KEEP | OMIT } QUOTES [ ON SCALAR STRING ] ] [ { ERROR | NULL | EMPTY { ARRAY | OBJECT } | DEFAULT expression } ON EMPTY ] [ { ERROR | NULL | EMPTY { ARRAY | OBJECT } | DEFAULT expression } ON ERROR ] 说明:与 JSON_VALUE 函数相同的方式评估 JSON 数据,即它找到指定的标量 JSON 值,并 将这些 JSON 值的列作为 SQL 值返回。 类型 3: name type EXISTS [ PATH json_path_specification ] [ { ERROR | TRUE | FALSE | UNKNOWN } ON ERROR ] | NESTED PATH json_path_specification [ AS path_name ] COLUMNS ( json_table_column [, ...] ) 说明:与 JSON_EXISTS 条件相同的方式评估 JSON 数据,即确定是否存在指定的 JSON 值。 它返回‘true’或‘false’的 VARCHAR2 列,或值为 1 或 0 的 NUMBER 列。 类型 4: name FOR ORDINALITY 说明:返回一列生成的数据类型为 NUMBER 的行号。每个表只能有一个序数列。行编号从 1 开始。 类型 5: NESTED PATH json_path_specification [ AS json_path_name ] COLUMNS ( json_table_column [, ...] ) 说明:将嵌套 JSON 对象或 JSON 数组中的 JSON 值与来自父对象或数据中的 JSON 值一起 376 第 8 章 函数 展平为单行中的各个列。可以递归地使用此子句将来自多层嵌套对象或数组的数据投影到单行 中。 PLAN ( json_table_plan ) 定义如何将 NESTD PATH 子句返回的数据连接到构造的视图。 完整子句格式: PLAN( json_path_name [ { OUTER | INNER } json_table_plan_primary ] | json_table_plan_primary { UNION json_table_plan_primary } [...] | json_table_plan_primary { CROSS json_table_plan_primary } [...] ) 说明:通过设置子句的 INNER,OUTER,UNION 和 CROSS,定义子句中的数据如何连接到视图中。 • INNER JOIN,以便在连接 NESTED PATH 返回的数据后,如果父行没有任何子行,则从输出中省 略父行。 • LEFT OUTER JOIN,这样即使父行在连接 NESTED PATH 返回的数据后没有任何子行,也始终 包含在输出中,如果缺少相应的值,则将 NULL 值插入到子列中。 • UNION,为每个兄弟列生成的每个值生成一行。其他兄弟的列设置为空。 • CROSS,为兄弟列中的每个值的组合生成一行。 功能: JSON 函数,查询 JSON 数据并将结果显示为关系视图,可以作为常规 SQL 表访问。只能在 SELECT 语句的 FROM 子句中使用 json_table。 例子: SELECT t.* from json_table('{"a":{"b":"c"}}'::jsonb, '$.a' columns(b text format json path '$.b '))t; 结果: b ----"c" (1 row) SELECT t.* from json_table('{"a":{"b":"c"}}'::jsonb, '$.a' columns(b text exists path '$.b'))t; 结果: b -----true (1 row) select t.* from json_table(' [ {"a": 1, "b": [], "c": []}, 377 第 8 章 函数 {"a": 2, "b": [1, 2, 3], "c": [10, null, 20]} ]'::jsonb , '$[*]' columns( a int path 'lax $.a', nested path 'strict $.b[*]' as pb columns ( b int path '$' ), nested path 'strict $.c[*]' as pc columns ( c int path '$' ) ) ) t; 结果: a | b | c ---+---+---1 | | 2 | 1 | 2 | 2 | 2 | 3 | 2 | | 10 2 | | 2 | | 20 (7 rows) select t.* from json_table('[ {"a": 1, "b": [], "c": []}, {"a": 2, "b": [1, 2, 3], "c": [10, null, 20]} ]'::jsonb , '$[*]' columns( id for ordinality, id2 for ordinality, a int path 'lax $.a', nested path 'strict $.b[*]' as pb columns ( b int path '$' ), nested path 'strict $.c[*]' as pc columns ( c int path '$' ) ) ) t; 结果: id | id2 | a | b | c ----+-----+---+---+---1 | 1 | 1 | | 2 | 2 | 2 | 1 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 3 | 2 | 2 | 2 | | 10 2 | 2 | 2 | | 2 | 2 | 2 | | 20 (7 rows) SELECT * 378 第 8 章 函数 FROM (VALUES ('1'), ('"err"')) vals(js) LEFT OUTER JOIN JSON_TABLE(vals.js::jsonb, '$' COLUMNS (a int PATH '$' NULL ON ERROR) ERROR ON ERROR) jt ON true; 结果: js | a -------+--1 | 1 "err" | (2 rows) 基础数据 1: CREATE TEMP TABLE jsonb_table_test (js jsonb); INSERT INTO jsonb_table_test VALUES ( '[ {"a": 1, "b": [], "c": []}, {"a": 2, "b": [1, 2, 3], "c": [10, null, 20]} ]' ); 基础数据 1-例子 1: select jt.* from jsonb_table_test jtt, json_table ( jtt.js,'strict $[*]' as p columns ( n for ordinality, a int path 'lax $.a' default -1 on empty, nested path 'strict $.b[*]' as pb columns ( b int path '$' ), nested path 'strict $.c[*]' as pc columns ( c int path '$' ) ) plan (p outer (pb union pc)) ) jt; 结果: n | a | b | c ---+---+---+---1 | 1 | | 2 | 2 | 1 | 2 | 2 | 2 | 2 | 2 | 3 | 2 | 2 | | 10 379 第 8 章 函数 2 | 2 | | 2 | 2 | | 20 (7 rows) 基础数据 1-例子 2: select jt.* from jsonb_table_test jtt, json_table ( jtt.js,'strict $[*]' as p columns ( n for ordinality, a int path 'lax $.a' default -1 on empty, nested path 'strict $.b[*]' as pb columns ( b int path '$' ), nested path 'strict $.c[*]' as pc columns ( c int path '$' ) ) plan (p inner (pb union pc)) ) jt; 结果: n | a | b | c ---+---+---+---2 | 2 | 1 | 2 | 2 | 2 | 2 | 2 | 3 | 2 | 2 | | 10 2 | 2 | | 2 | 2 | | 20 (6 rows) 基础数据 1-例子 3: select jt.* from jsonb_table_test jtt, json_table ( jtt.js,'strict $[*]' as p columns ( n for ordinality, a int path 'lax $.a' default -1 on empty, nested path 'strict $.b[*]' as pb columns ( b int path '$' ), nested path 'strict $.c[*]' as pc columns ( c int path '$' ) ) plan (p inner (pb cross pc)) ) jt; 380 第 8 章 函数 结果: n | a | b | c ---+---+---+---2 | 2 | 1 | 10 2 | 2 | 1 | 2 | 2 | 1 | 20 2 | 2 | 2 | 10 2 | 2 | 2 | 2 | 2 | 2 | 20 2 | 2 | 3 | 10 2 | 2 | 3 | 2 | 2 | 3 | 20 (9 rows) 基础数据 2: CREATE TEMP TABLE jsonb_table_test (js jsonb); INSERT INTO jsonb_table_test VALUES ( '[ {"a": 1, "b": [], "c": []}, {"a": 2, "b": [1, 2, 3], "c": [10, null, 20]}, {"a": 3, "b": [1, 2], "c": []}, {"x": "4", "b": [1, 2], "c": 123} ]' ); 基础数据 2-例子 1: select jt.* from jsonb_table_test jtt, json_table ( jtt.js,'strict $[*]' as p columns ( n for ordinality, a int path 'lax $.a' default -1 on empty, nested path 'strict $.b[*]' as pb columns ( b int path '$' ), nested path 'strict $.c[*]' as pc columns ( c int path '$' ) ) plan default (outer, union) ) jt; 结果: n | a | b | c ---+----+---+---1 | 1 | | 381 第 8 章 函数 2 | 2 | 1 | 2 | 2 | 2 | 2 | 2 | 3 | 2 | 2 | | 10 2 | 2 | | 2 | 2 | | 20 3 | 3 | 1 | 3 | 3 | 2 | 4 | -1 | 1 | 4 | -1 | 2 | (11 rows) 基础数据 2-例子 2: select jt.* from jsonb_table_test jtt, json_table ( jtt.js,'strict $[*]' as p columns ( n for ordinality, a int path 'lax $.a' default -1 on empty, nested path 'strict $.b[*]' as pb columns ( b int path '$' ), nested path 'strict $.c[*]' as pc columns ( c int path '$' ) ) plan (p outer (pb union pc)) ) jt; 结果: n | a | b | c ---+----+---+---1 | 1 | | 2 | 2 | 1 | 2 | 2 | 2 | 2 | 2 | 3 | 2 | 2 | | 10 2 | 2 | | 2 | 2 | | 20 3 | 3 | 1 | 3 | 3 | 2 | 4 | -1 | 1 | 4 | -1 | 2 | (11 rows) 基础数据 3: CREATE TABLE my_films ( js jsonb ); 382 第 8 章 函数 INSERT INTO my_films VALUES ( '{ "favorites": [ { "kind": "comedy", "films": [ { "title": "Bananas", "director": "Woody Allen" }, { "title": "The Dinner Game", "director": "Francis Veber" } ] }, { "kind": "horror", "films": [ { "title": "Psycho", "director": "Alfred Hitchcock" } ] }, { "kind": "thriller", "films": [ { "title": "Vertigo", "director": "Alfred Hitchcock" } ] }, { "kind": "drama", "films": [ { "title": "Yojimbo", "director": "Akira Kurosawa" } ] } ] }'); 383 第 8 章 函数 基础数据 3-例子 1: SELECT jt.* FROM my_films, JSON_TABLE ( js, '$.favorites[*]' COLUMNS ( id FOR ORDINALITY, kind text PATH '$.kind', NESTED PATH '$.films[*]' COLUMNS ( title text PATH '$.title', director text PATH '$.director'))) AS jt; 结果: id | kind | title | director ----+----------+------------------+------------------1 | comedy | Bananas | Woody Allen 1 | comedy | The Dinner Game | Francis Veber 2 | horror | Psycho | Alfred Hitchcock 3 | thriller | Vertigo | Alfred Hitchcock 4 | drama | Akira Kurosawa | Yojimbo (5 rows) 基础数据 3-例子 2: SELECT director1 AS director, title1, kind1, title2, kind2 FROM my_films, JSON_TABLE ( js, '$.favorites' AS favs COLUMNS ( NESTED PATH '$[*]' AS films1 COLUMNS ( kind1 text PATH '$.kind', NESTED PATH '$.films[*]' AS film1 COLUMNS ( title1 text PATH '$.title', director1 text PATH '$.director') ), NESTED PATH '$[*]' AS films2 COLUMNS ( kind2 text PATH '$.kind', NESTED PATH '$.films[*]' AS film2 COLUMNS ( title2 text PATH '$.title', director2 text PATH '$.director' ) ) ) PLAN (favs OUTER ((films1 INNER film1) CROSS (films2 INNER film2))) ) AS jt WHERE kind1 > kind2 AND director1 = director2; 384 第 8 章 函数 结果: director | title1 | kind1 | title2 | kind2 ------------------+---------+----------+--------+-------Alfred Hitchcock | Vertigo | thriller | Psycho | horror (1 row) 8.236 JSON_TO_RECORD 用法: json_to_record(json) 功能: JSON 函数,从一个 JSON 对象构建一个任意的记录,正如所有返回 record 的函数一样,调用者必须用一个 AS 子句显式的定义记录的结构。 例子: SELECT * FROM json_to_record('{"a":1,"b":[1,2,3],"c":[1,2,3],"e":"bar","r": {"a": 123, "b": "a b c"}}') as x(aint,b text, c int[], d text, r myrowtype); 8.237 JSON_TO_RECORDSET 用法: json_to_recordset(json) 功能: JSON 函数,从一个 JSON 对象数组构建一个任意的记录集合,正如所有返回 record 的函数一样,调用者必须 用一个 AS 子句显式的定义记录的结构。 例子: 385 第 8 章 函数 SELECT * FROM json_to_recordset ('[{"a":1,"b":"foo"},{"a":"2","c":"bar"}]')as x(a int, b text); 8.238 JSON_TYPEOF 用法: json_typeof(json) 功能: JSON 函数,把最外层的 JSON 对象类型作为一个文本串返回。可能类型是:object 、array 、string 、 number 、boolean 以及 null 。 例子: SELECT json_typeof('-123.4'); 8.239 JSON_VALUE 用法: json_value( expression [ format json [ encoding utf8 ] ], json_basic_path_expression [returning json_value_return_type] [{ null|error|default literal} on error] [{ null|error|default literal} on empty] ) 386 第 8 章 函数 expression 输入的 json 文本,完整的支持可以为字符常量、函数、或者列名(数据类型为 clob,blob 或者 varchar2),V9C7 版本只支持输入类型为 JSONB 类型,其他类型后续补充; format json 是在 expression 为字符串类型时将 expression 格式化成 json 格式。 encoding utf8 指定输入为二进制类型时的字符集。 json_basic_path_expression 用于指定 json 文件所要查询的路径。 returning json_value_return_type 指 定 返 回 值 的 数 据 类 型。 若 没 有 使 用 此 子 句, 返 回 数 据 类 型 为 text。 支 出 返 回 类 型: CHAR,VARCHAR,NCHAR,TEXT,NUMERIC,INT2,INT4,INT8,FLOAT4,FLOAT8,DATE,TIME,TIMESTAMP,TIMETZ, { null|error|default literal} on error 指定错误发生时的返回值。 { null|error|default literal} on empty 指定没有结果相匹配时的返回值。 功能: 387 第 8 章 函数 JSON 函数,从一段给定的 json 文本中获取所需要的值,返回为标量值或者用户自定义的 object 或者 collection 类型。 例子: select json_value(jsonb '{"a": 1, "b": 2}','$.b' ); 结果: 2 select json_value(jsonb '{"a": 1, "b": 2}','$.* ? (@> 1)'); 结果: 2 select json_value(jsonb '{"a": 1, "b": 2}','$.* ? (@ > 1)' RETURNING int); 结果: 2 select json_value(jsonb '{"a": 1, "b": {"c":2,"c":3}}','$.b.c' error on error); 结果: 3 select json_value(jsonb '{"a": 1, "b": {"c":2,"c":3}}','$.b.d' default 'error' on empty); 结果: error 8.240 JSONB_AGG 用法: jsonb_agg(expression) 功能: 聚集函数,将传入值包括空值聚集成一个 JSON 数组。 例子: SELECT jsonb_agg(q) FROM ( SELECT $$a$$ || x AS b, y AS c, ARRAY[ROW(x.*,ARRAY[1,2,3]), 388 第 8 章 函数 ROW(y.*,ARRAY[4,5,6])] AS z FROM generate_series(1,2) x, generate_series(4,5) y) q; 8.241 JSONB_ARRAY_ELEMENTS 用法: jsonb_array_elements(jsonb) 功能: JSON 处理函数,将传入值包括空值聚集成一个 JSON 数组。 例子: SELECT jsonb_array_elements('[1,true,[1,[2,3]],null,{"f1":1,"f2":[7,8,9]},false,"stringy"]'); 8.242 JSONB_ARRAY_ELEMENTS_TEXT 用法: jsonb_array_elements_text(jsonb) 功能: JSON 处理函数,把一个 JSON 数组扩展成 text 值集合。 例子: SELECT * FROM jsonb_array_elements_text('["foo","bar"]'); 389 第 8 章 函数 8.243 JSONB_ARRAY_LENGTH 用法: jsonb_array_length(jsonb) 功能: JSON 处理函数,返回最外层 JSON 数组中的元素数量。 例子: SELECT jsonb_array_length('[1,2,3,{"f1":1,"f2":[5,6]},4]'); 8.244 JSONB_BUILD_ARRAY 用法: jsonb_build_array( VARIADIC "any") 功能: JSON 处理函数,将可变参数列表构造成一个可能包含不同数据类型的 JSON 数组。 例子: SELECT jsonb_build_array(1,2,'3',4,5); 8.245 JSONB_BUILD_OBJECT 用法: jsonb_build_object( VARIADIC "any") 390 第 8 章 函数 功能: JSON 处理函数,将可变参数列表构造成一个 JSON 对象,通过转换,该参数列表由交替出现的键和值构成。 例子: SELECT jsonb_build_object('foo',1,'bar',2); 8.246 JSONB_EACH 用法: jsonb_each(jsonb) 功能: JSON 处理函数,扩展最外层的 JSON 对象成为一组键值对。 例子: SELECT * FROM jsonb_each('{"a":"foo", "b":"bar"}'); 8.247 JSONB_EACH_TEXT 用法: jsonb_each_text(jsonb) 功能: JSON 处理函数,扩展最外层的 JSON 对象成为一组键值对,返回值为 text 类型。 例子: 391 第 8 章 函数 SELECT * FROM jsonb_each_text('{"a":"foo", "b":"bar"}'); 8.248 JSONB_EXTRACT_PATH 用法: jsonb_extract_path(from_json jsonb, VARIADIC path_elems text[]) 功能: JSON 处理函数,返回由 path_elems 指向的 JSON 值(等效于 #> 操作符)。 例子: SELECT jsonb_extract_path('{"f2":{"f3":1},"f4":{"f5":99,"f6":"foo"}}','f4'); 8.249 JSONB_EXTRACT_PATH_TEXT 用法: jsonb_extract_path(from_json jsonb, VARIADIC path_elems text[]) 功能: JSON 处理函数,以 text 类型返回由 path_elems 指向的 JSON 值(等效于 #> 操作符)。 例子: SELECT jsonb_extract_path_text('{"f2":{"f3":1},"f4":{"f5":99,"f6":"foo"}}','f 4', 'f6'); 8.250 JSONB_INSERT 用法: 392 第 8 章 函数 jsonb_insert(target jsonb, path text[], new_value jsonb [, insert_after boolean]) 功能: JSON 处理函数,返回被插入了 new_value 的 target 。如果 path 指定的 target 节在一个 JSONB 数组中, new_value 将被插入到目标之前(insert_after 默认为 false)或者之后(insert_after 为 true)。如果 path 指定 的 target 节在一个 JSONB 对象内,则只有当 target 不存在时才插入 new_value。对于面向路径的操作符来说, 出现在 path 中的负整数表示从 JSONB 数组的末尾开始计数。 例子: SELECT jsonb_insert('{"a": [0,1,2]}', '{a,1}', '"new_value"'); SELECT jsonb_insert('{"a":[0,1,2]}','{a, 1}','"new_value"', true); 8.251 JSONB_OBJECT 8.251.1 用法 1 用法: jsonb_object(text[]) text 文本数组。 功能: JSON 处理函数,从文本数组中构造 JSON 对象。该函数必须可以使具有偶数个成员的一维数组 (成员被当做交 替出现的键值对),或者是一个二维数组(每一个内部数组刚好有两个元素,可以被看做键值对)。 例子: SELECT jsonb_object('{a, 1, b, "def", c, 3.5}'); ** 返回值:** 393 第 8 章 函数 {"a": "1", "b": "def", "c": "3.5"} SELECT jsonb_object('{{a,1},{b, "def"},{c, 3.5}}'); ** 返回值:** {"a": "1", "b": "def", "c": "3.5"} 8.251.2 用法 2 用法: jsonb_object( keys text[], values text[]) keys json 属性 key 键数组。 values json 属性 value 值数组。 功能: JSON 处理函数,从文本数组中构造 JSON 对象。从两个独立的数组得到键/值对。在其他方面和一个参数的形 式相同。 例子: SELECT jsonb_object('{a,b}', '{1,2}') FROM dual ; ** 返回值:** {"a" : "1", "b" : "2"} 8.252 JSONB_OBJECT_AGG 用法: jsonb_object_agg(name, value) 394 第 8 章 函数 功能: 聚集函数,将 name 和 value 对聚合成 JSON 对象,值可以为空,名字不能为空。 例子: CREATE TEMP TABLE foo (serial_num int, name text, type text); INSERT INTO foo VALUES (847001,'t15','GE1043'); INSERT INTO foo VALUES (847002,'t16','GE1043'); INSERT INTO foo VALUES (847003,'sub-alpha','GESS90'); SELECT jsonb_object_agg(name, type) FROM foo; 8.253 JSONB_OBJECT_KEYS 用法: jsonb_object_keys(jsonb) 功能: JSON 函数,返回外层 JSON 对象中键的集合。 例子: SELECT jsonb_object_keys('{"f1":"abc","f2":{"f3":"a", "f4":"b"}}'); 8.254 JSONB_PATH_EXISTS 用法: jsonb_path_exists(target jsonb, path jsonpath[, vars jsonb [, silent bool]]) 功能: 395 第 8 章 函数 JSON 函数,检查 JSON 路径是否返回指定 JSON 值的任何项。 例子: SELECT jsonb_path_exists('{"a":[1,2,3,4,5]}', '$.a[*] ?(@ >= $min && @ <= $max)', '{"min":2,"max":4}'); 8.255 JSONB_PATH_MATCH 用法: jsonb_path_match(target jsonb, path jsonpath [, vars jsonb [, silent bool]]) 功能: JSON 函数,返回指定 JSON 值的 JSON 路径谓词检查的结果。只考虑结果的第一项。如果结果不是布尔值, 则返回 NULL。 例子: SELECT jsonb_path_match('{"a":[1,2,3,4,5]}', 'exists($.a[*] ? (@ >= $min && @ <= $max))', '{"min":2,"max":4} '); 8.256 JSONB_PATH_QUERY 用法: jsonb_path_query(targetjsonb, path jsonpath [, vars jsonb [, silent bool]]) 功能: JSON 函数,获取指定 JSON 值的 JSON 路径返回的所有项。 例子: 396 第 8 章 函数 SELECT * FROM jsonb_path_query('{"a":[1,2,3,4,5]}', '$.a[*] ? (@ >= $min && @ <= $max)', '{"min":2,"max":4} '); 8.257 JSONB_PATH_QUERY_ARRAY 用法: jsonb_path_query_array(target jsonb, path jsonpath[, vars jsonb [, silent bool]]) 功能: JSON 函数,获取指定 JSON 值的 JSON 路径返回的所有项,并将结果包装到数组中。 例子: SELECT * FROM jsonb_path_query_array('{"a":[1,2,3,4,5]}', '$.a[*] ? (@ >= $min && @ <= $max)', '{"min":2, "max":4}'); 8.258 JSONB_PATH_QUERY_FIRST 用法: jsonb_path_query_first(targetjsonb, path jsonpath [, vars jsonb [, silent bool]]) 功能: JSON 函数,获取指定 JSON 值的 JSON 路径返回的第一个 JSON 项。在没有结果时返回 NULL。 例子: 397 第 8 章 函数 SELECT * FROM jsonb_path_query_first('{"a":[1,2,3,4,5]}', '$.a[*] ? (@ >= $min && @ <= $max)', '{"min":2, "max":4}'); 8.259 JSONB_POPULATE_RECORD 用法: jsonb_populate_record(base anyelement,from_json jsonb) 功能: JSON 函数,扩展 from_json 中的对象成一个行,它的列匹配由 base 定义的记录类型。 例子: SELECT * FROM jsonb_populate_record(null::myrowtype,'{"a":1, "b": ["2", "a b"],"c": {"d":4, "e": "ab c"}}'); 8.260 JSONB_POPULATE_RECORDSET 用法: jsonb_populate_recordset(base anyelement,from_json jsonb) 功能: JSON 函数,扩展 from_json 中最外层的对象数组成一个集合,它的列匹配由 base 定义的记录类型。 例子: SELECT json_populate_recordset(row(1,2), '[]'); 8.261 JSONB_PRETTY 用法: 398 第 8 章 函数 jsonb_pretty(from_json jsonb) 功能: JSON 函数,把 from_json 处理成一段带缩进的 JSON 文本。 例子: SELECT jsonb_pretty('[{"f1":1,"f2":null},2,null,3]'); 8.262 JSONB_SET 用法: jsonb_set(target jsonb, path text[],new_value jsonb[, create_missing boolean]) 功能: JSON 函数,返回 target 其中由 path 指定的节用 new_value 替换,如果指定的项不存在并且 create_missing 为真(默认为真)则加上 new_value 。正如面向路径的操作符一样,出现在 path 中的负整数表示从 JSON 数组的末 尾开始数 例子: SELECT jsonb_set('[{"f1":1,"f2":null},2,null,3]', '{0,f1}', '[2,3,4]', false); 8.263 JSONB_STRIP_NULLS 用法: jsonb_strip_nulls(from_json jsonb) 399 第 8 章 函数 功能: JSON 函数,返回 from_json,其中所有具有空值的对象域都被过滤掉,其他空值不动。 例子: SELECT jsonb_strip_nulls('[{"f1":1,"f2":null},2,null,3]'); 8.264 JSONB_TO_RECORD 用法: jsonb_to_record(jsonb) 功能: JSON 函数,从一个 JSON 对象构建一个任意的记录,正如所有返回 record 的函数一样,调用者必须用一个 AS 子句显式的定义记录的结构。 例子: SELECT * FROM jsonb_to_record('{"a":1,"b":[1,2,3],"c":[1,2,3],"e":"bar","r": {"a": 123, "b": "a b c"}}') as x(aint,b text, c int[], d text, r myrowtype); 8.265 JSONB_TO_RECORDSET 用法: jsonb_to_recordset(json) 功能: 400 第 8 章 函数 JSON 函数,从一个 JSON 对象数组构建一个任意的记录集合,正如所有返回 record 的函数一样,调用者必须 用一个 AS 子句显式的定义记录的结构。 例子: SELECT * FROM jsonb_to_recordset ('[{"a":1,"b":"foo"},{"a":"2","c":"bar"}]')as x(a int, b text); 8.266 JSONB_TYPEOF 用法: jsonb_typeof(json) 功能: JSON 函数,把最外层的 JSON 对象类型作为一个文本串返回。可能类型是:object 、array 、string 、 number 、boolean 以及 null 。 例子: SELECT jsonb_typeof('-123.4'); 8.267 JUSTIFY_DAYS 用法: justify_days(interval) 功能: 时间函数,调整间隔,使 30 天时间段表示为月。 例子: SELECT justify_days(interval '35 days'); 401 第 8 章 函数 8.268 JUSTIFY_HOURS 用法: justify_hours(interval) 功能: 时间函数,调整间隔,使 24 小时时间段表示为日。 例子: SELECT justify_hours(interval '27 hours'); 8.269 JUSTIFY_INTERVAL 用法: justify_interval(interval) 功能: 时间函数,使用 justify_days 和 justify_hours 调整间隔,并进行额外的符号调整。 例子: SELECT justify_interval(interval '1 month -1 hour') as "1 month -1 hour"; 8.270 LAG 用法: lag(value anyelement[, offset integer [,default anyelement ]]) 402 第 8 章 函数 功能: 返回 value,它在分区内当前行的之前 offset 个位置的行上计算;如果没有这样的行,返回 default 替代(必须和 value 类型相同)。offset 和 default 都是根据当前行计算的结果。如果忽略它们,则 offset 默认是 1,default 默认是 空值。 例子: CREATE TABLE test(id integer); INSERT INTO test values(1); INSERT INTO test values(3); INSERT INTO test values(6); SELECT id, lag(id, 1, 0) from test; 8.271 LAST 用法: aggregate_function KEEP ( DENSE_RANK LAST ORDER BY expr [ DESC | ASC ] [ NULLS { FIRST | LAST } ] [ , … ] ) [ OVER ( [ query_partition_clause ] ) ] [ FILTER ( WHERE filter_clause ) ] 403 第 8 章 函数 功能: LAST 既是聚集函数,也是分析函数。LAST 函数首先对输入行按指定排序规则排序,然后返回排名为 LAST 的一 组行,最后在返回行的数值上执行聚集计算。如果只有唯一的排名为 LAST 的返回行,那么聚集操作只在非聚集的唯 一行上执行。 LAST 函数总是用于聚集函数后,与聚集函数联合使用。当指定 OVER 子句时,LAST 函数为分析函数;当省略 OVER 子句时,LAST 函数为聚集函数。 aggregate_function 函数可以是 MIN、MAX、SUM、AVG、COUNT、VARIANCE 和 STDDEV 这些函数之 一。aggregate_function 在排名为 LAST 的行中的数值上执行操作。aggregate_function 仅支持 ALL 关键字修 饰,而不支持 DISTINCT 和 UNIQUE 关键字修饰。 定 义 KEEP 关 键 字 是 为 了 使 语 义 清 晰, 它 限 定 了 aggregate_function 的 输 入 行 范 围, 表 示 只 有 aggregate_function 的 LAST 的值才会被返回。DENSE_RANK LAST 表示将只在那些 DENSE_RANK 排名为 最大值(LAST)的行上进行聚集操作。 ORDER BY 子句用法与 SELECT 语句中的 ORDER BY 子句相同。 404 第 8 章 函数 query_partition_clause 是 OVER 子 句 唯 一 有 效 的 部 分。 如 果 包 含 了 OVER 子 句, 但 省 略 了 query_partition_clause,则 LAST 函数被视为分析函数,但分析定义的窗口是全表。 另请参阅: 更多信息请参阅聚集函数 、窗口函数 和FIRST 函数,使用示例请参阅FIRST 函数 8.272 LAST_DAY 用法: last_day(date date1) 功能: 计算日期所在月份的最后一天。 参数说明: date1:日期,date 类型。 返回值: 函数返回值类型为 date。 例子: SELECT last_day('2013-7-15 12:12:11'); last_day --------------------2013-07-31 12:12:11 (1 row) 8.273 LAST_VALUE 用法: last_value(value any) 405 第 8 章 函数 功能: LAST_VALUE 函数返回在窗口帧中的最后一行上计算的 value 值。类型与 any 一致。 参数说明: value:窗户帧的名子,通常为投影列列名。 例子: select * from t1; a --1 2 (3 rows) select nvl2(a, 4, 5) from t1; nvl2 -----4 4 5 (3 rows) 8.274 LASTVAL 用法: lastval() 功能: LASTVAL 返回最近一次使用的 nextval 获取的任何序列的值。 返回值: 最近一次使用的 nextval 获取的任何序列的值。 例子: select nextval('seq'); nextval 406 第 8 章 函数 --------1 (1 row) select lastval(); lastval --------1 (1 row) 8.275 LCASE 用法: lcase(string) 功能: 函数返回将指定字符串转为小写后的字符串。 例子: SELECT LCASE('AAFcdEF') "Change" FROM DUAL; +-----------------+ | Change | +=================+ | aafcdef | +-----------------+ 8.276 LEAD 用法: lead(value any, offset integer [, default any]) over ([partition by partition_expression] [order by sort_ expression [ASC|DESC]]) 407 第 8 章 函数 功能: LEAD 返回 value, 它在分区内当前行的之后 offset 个位置的行上计算结果,如果没有这样的行,返回 default 值 替代 (必须与 value 类型相同)。 offset 和 default 都是根据当前行计算的结果。如果忽略它们,则 offset 默认值是 1,default 默认值是 NULL。 参数说明: value:用于计算的表达式。 offset: 当前行的偏移量。 default: 如果没有 offset 的行。则返回 default 值。 返回值: value 或者是 default。 例子: SELECT lead(ten) OVER (PARTITION BY four ORDER BY ten), ten, four FROM tenk1 WHERE unique2 < 10; lead | ten | four ------+-----+-----0 | 0 | 0 4 | 0 | 0 | 4 | 0 1 | 1 | 1 7 | 1 | 1 9 | 7 | 1 | 9 | 1 | 0 | 2 3 | 1 | 3 | 3 | 3 (10 rows) 408 第 8 章 函数 8.277 LEAST 用法: least(value[,...]) 功能: least 函数从一个任意的数字表达式列表中选取最小的值,这些表达式必须都可以转换成一个普通的数据。这个 类型也将会是结果的数据类型。只要列表中有一个 NULL 值,则结果返回 NULL。 参数说明: value:用于获取最小值的表达式。通常为常量表达式。 返回值: value[,...] 的最小值。 例子: select least(3,5,9,2,1) from dual; least ------1 (1 row) select least(NULL,NULL,NULL,NULL,NULL) from dual; least ------(1 row) 8.278 LEFT 用法: left(str text, n int) 409 第 8 章 函数 功能: 返回字符串中的前 n 个字符。当 n 为负时,将返回除了最后 |n | 个字符之外的所有字符。 例子: select left('abcde',2); +-----------+ | left | +===========+ | ab | +-----------+ 8.279 LENGTH 用法: length(string) 功能: 函数返回的 LENGTH 长度 char。LENGTH 使用输入字符集定义的字符计算长度。LENGTHB 使用字节而不是 字符。LENGTHC 使用 Unicode 完整字符。LENGTH2 使用 UCS2 代码点。LENGTH4 使用 UCS4 代码点。 char 可以是任何数据类型 CHAR, VARCHAR, NCHAR, NVARCHAR, CLOB, 或 NCLOB. 例外是 LENGTHC,LENGTH2 和 LENGTH4, 不允许 char 是 CLOBor NCLOB。返回值是数据类型 NUMBER。如果 char 具有 data type CHAR,则长度包括所有尾随空格。如果 char 为 null,则此函数返回 null。 对 LENGTHB 的限制:该 LENGTHB 函数仅支持单字节 LOB。它不能与 CLOB 多 NCLOB 字节字符集中的 数据一起使用。 例子: 以下示例使用 LENGTH 使用单字节数据库字符集的函数: SELECT LENGTH('CANDIDE') "Length in characters" FROM DUAL; +----------------------+ | Length in characters | +======================+ | 7 | +----------------------+ 410 第 8 章 函数 下一个示例假定一个双字节数据库字符集。 SELECT LENGTHB ('CANDIDE') "Length in bytes" FROM DUAL; +-----------------+ | Length in bytes | +=================+ | 14 | +-----------------+ 8.280 LENGTHB 用法: lengthb(string text ) 功能: 函数返回指定 bytea 或 bit 类型数据的字节数,仅支持单字节 LOB。它不能与 CLOB 多 NCLOB 字节字符集中 的数据一起使用。 例子: SELECT LENGTHB('1001'::bit) bit_lengthb, lengthb('100111111110000000000000000000000000001111'::bytea) bytea_ lengthb; FROM DUAL; +--------------------+---------------------+ | bit_lengthb | bytea_lengthb | +====================+=====================+ | 1 | 42 | +--------------------|---------------------| 8.281 LISTAGG 用法: listagg (measure_expr[,’delimiter’]) WITHIN GROUP (order_by_clause) [OVER query_partition_clause] 411 第 8 章 函数 功能: 对于指定的度量值,LISTAGG 函数在 ORDER BY 子句中指定的每个组中对数据进行排序,然后连接度量值列 的值。可作为单个集合聚集函数、分组聚集函数、分析函数在不同应用场景中使用。 参数说明: measure_expr:用于聚集的表达工。通常为列表达式。 delimiter: 聚集表达式中间的分隔符。 返回值: 多行聚集后的带 delimiter 的值。 例子: select *, listagg(user_name,',') within group (order by user_name) over (partition by phone_num) from account; user_name | phone_num | amount | listagg -----------+-------------+--------+-----------------Lily | 13642160022 | 5000 | Lily,Lucy Lucy | 13642160022 | 3000 | Lily,Lucy | 13642160022 | 5050 | Lily,Lucy Addy | 15950558535 | 6800 | Addy,Alice,Aline Alice | 15950558535 | 12000 | Addy,Alice,Aline Aline | 15950558535 | 8500 | Addy,Alice,Aline Tom | 18622685434 | 10000 | Tom,Toney Toney | 18622685434 | 9000 | Tom,Toney (8 rows) 8.282 LN 用法: ln({dp|numeric}) 412 第 8 章 函数 功能: LN 返回 n 的自然对数,其中 n 大于 0。 此函数将任何数值数据类型或任何可以隐式转换为数值数据类型的非数值数据类型作为参数。如果参数是 BINARY_FLOAT,则函数返回 BINARY_DOUBLE。否则,函数返回与参数相同的数值数据类型。 例子: 以下示例返回 95 的自然对数: SELECT LN(95) "Natural log of 95" FROM DUAL; +-------------------+ | Natural log of 95 | +===================+ | 4.55387689 | +-------------------+ 8.283 LNNVL 用法: lnnvl(condition) 功能: 如果 condition 是 FALSE 或者是 UNKNOWN,LNNVL 返回 TRUE。如果 condition 是 TRUE,LNNVL 返回 FALSE。注意 LNNVL 函数需要加载 kdb_utils_function 插件才能使用。 参数说明: condition:用于判断 true 和 false 的布尔表达式。 返回值: 返回非 condition 的值。 例子: 413 第 8 章 函数 select lnnvl(true); lnnvl ------f (1 row) select lnnvl(false); lnnvl ------t (1 row) 8.284 LOCALTIME 用法: localtime 功能: 获取当前时间。 返回值: 函数返回值类型为 time。 例子: SELECT localtime; localtime ----------------19:23:02.220375 (1 row) 8.285 LOCALTIME(MySQL 模式) 用法: 414 第 8 章 函数 localtime([n]) 功能: 获取当前服务器的日期时间。 注意: 此函数不可创建函数索引。 参数说明: n:表示时间秒值小数点后面的位数,int 整数类型,范围为 [0,6],默认值为 0。 返回值: timestamp 时间类型 例子: SELECT LOCALTIME() "LOCALTIME"; LOCALTIME --------------------2022-10-10 13:36:21 SELECT LOCALTIME(1) "LOCALTIME"; LOCALTIME ----------------------2022-10-10 13:36:21.4 8.286 LOCALTIMESTAMP 用法: localtimestamp() 415 第 8 章 函数 功能: 获取当前时间戳。 返回值: 函数返回值类型为 timestamp。 例子: SELECT localtimestamp; localtimestamp ---------------------------2022-06-28 19:27:31.656652 (1 row) 8.287 LOCALTIMESTAMP(MySQL 模式) 用法: localtimestamp([n]) 功能: 获取当前服务器的日期时间。 注意: 此函数不可创建函数索引。 参数说明: n:表示时间秒值小数点后面的位数,int 整数类型,范围为 [0,6], 默认值为 0。 返回值: timestamp 时间类型 例子: SELECT LOCALTIMESTAMP() "LOCALTIMESTAMP"; LOCALTIMESTAMP 416 第 8 章 函数 --------------------2022-10-10 14:00:00 SELECT LOCALTIMESTAMP(1) "LOCALTIMESTAMP"; LOCALTIMESTAMP ----------------------2022-10-10 14:00:00.5 8.288 LOCATE(MySQL 模式) 用法: locate(substr, str) locate(substr, str, pos) 功能: 返回子字符串 substr 在字符串 str 中第一次出现的位置,位置计数的起始值为 1。若有 pos 参数,则返回从位置 pos 之后第一次出现的位置,位置计数的起始值为 1。 参数说明: substr:匹配的子字符串。 str:被匹配的字符串。 pos:被匹配的字符串的起始位置。 返回值: 函数返回值类型为 int。 例子: SELECT locate('bc', 'abc,ABC,bcd,BCD'); locate -------------2 (1 row) SELECT locate('bc', 'abc,ABC,bcd,BCD', 5); locate -------------6 (1 row) 417 第 8 章 函数 8.289 LOG 用法: log({dp|numeric}) log(n2 numeric, n1 numeric) 功能: LOG 返回以 n2 为底 n1 的对数。底数 n2 可以是除 0 或 1 以外的任何正数,n1 也可以是任何正数。 此函数将任何数值数据类型或任何可以隐式转换为数值数据类型的非数值数据类型作为参数。如果任何参数是 BINARY_FLOATor BINARY_DOUBLE,则函数返回 BINARY_DOUBLE。否则函数返回 NUMBER。 例子: 以下示例返回 100 的对数: SELECT LOG(10,100) "Log base 10 of 100" FROM DUAL; +--------------------+ | Log base 10 of 100 | +====================+ | 2 | +--------------------+ 8.290 LOG10 用法: log10({numeric|double}) 418 第 8 章 函数 功能: 返回对 numeric 和 double 值进行取以 10 为底的对数值。 例子: 以下示例返回 100 的以 10 为底的对数: select log10(100); log10 ------2 (1 行记录) 8.291 LOWER 用法: lower(string) 功能: LOWER 返回 char,所有字母小写。char 可以是任何数据类型 CHAR, VARCHAR, NCHAR, NVARCHAR, CLOB, 或 NCLOB. 返回值与的数据类型相同 char。数据库根据为基础字符集定义的二进制映射设置字符的大小写。 例子: 以下示例以小写形式返回字符串: SELECT LOWER('MR. SCOTT MCMILLAN') "Lowercase" FROM DUAL; +--------------------+ | Lowercase | +====================+ | mr. scott mcmillan | +--------------------+ 8.292 LOWER_INC 用法: 419 第 8 章 函数 lower_inc(anyrange) 功能: 函数测试一个范围值的下界。 例子: SELECT LOWER_INC( NUMRANGE(1.1, 2.2) ) “Result" FROM DUAL; +-----------------+ | “Result | +=================+ | t | +-----------------+ 8.293 LOWER_INF 用法: lower_inf(anyrange) 功能: 函数测试一个范围值的下界是否无限。 例子: SELECT LOWER_INF( '(,)'::DATERANGE ) "Result" FROM DUAL; +-----------------+ | Result | +=================+ | t | +-----------------+ 420 第 8 章 函数 8.294 LPAD 用法: lpad(string text,length int [, fill text]) 功能: LPAD 返回 expr1,n 用 expr2。此函数对于格式化查询的输出很有用。 两者 expr1 和 expr2 都可以是数据类型 CHAR、VARCHAR、NCHAR、NVARCHAR、CLOB 或 NCLOB 中任 何一种。如果 expr1 是字符数据类型,则返回字符串是 VARCHAR 类型。如果 expr1 是国家字符数据类型,则返回 的字符串是数据类型 NVARCHAR,如果是 expr1 是数据类型 LOB,则返回 LOB。返回的字符串与 expr1 的字符集 相同。参数 n 必须是 NUMBER 整数或可以隐式转换为 NUMBER 整数的值。 如果不指定 expr2,则默认为一个空白。如果 expr1 长于 n,则此函数返回 expr1 适合的部分 n。 参数 n 是显示在终端屏幕上的返回值的总长度。在大多数字符集中,这也是返回值中的字符数。但是,在某些多 字节字符集中,字符串的显示长度可能与字符串中的字符数不同。 例子: 下面的示例用星号 (*) 和句点 (.) 字符向左填充字符串: SELECT LPAD('Page 1',15,'*.') "LPAD example" FROM DUAL; +-----------------+ | LPAD example | +=================+ | *.*.*.*.*Page 1 | +-----------------+ 8.295 LSEG 用法: lseg(box) lseg(point, point) 421 第 8 章 函数 功能: 测绘点到点的线段。 参数说明: box:用于测量方框对角线线段的方框,类型为 box。 point: 用于点到点的线段。 返回值: 返回 lseg 类型的线段。 例子: SELECT lseg(box'((0,0),(0,1))') from dual; lseg --------------[(0,1),(0,0)] (1 row) SELECT lseg(point'(-1,0)', point'(1,0)') from dual; lseg ---------------[(-1,0),(1,0)] (1 row) 8.296 LTRIM 用法: ltrim(string text [, characters text]) 功能: LTRIM 从字符串包含的所有字符的左端删除 set。如果不指定 set,则默认为一个空白。KingbaseES 数据库 char 从其第一个字符开始扫描并删除所有出现的字符,set 直到到达一个不在的字符 set,然后返回结果。 422 第 8 章 函数 两者 char 和 set 都可以是任何数据类型 CHAR、VARCHAR、NCHAR、NVARCHAR、CLOB 或 NCLOB。如 果 char 是字符数据类型,则返回 VARCHAR,N 如果 char 是国家字符数据类型,则返回的字符串数据类型 VARCHAR,如果是 char 数据类型是 LOB,则返回 LOB。 例子: 以下示例从字符串中删除所有最左侧出现的小于号 ( <)、大于号 ( >) 和等号 ( ):= SELECT LTRIM('<=====>BROWNING<=====>', '<>=') "LTRIM Example" FROM DUAL; +-----------------+ | LTRIM Example | +=================+ | BROWNING<=====> | +-----------------+ 8.297 MAKEDATE(MySQL 模式) 用法: makedate(year,dayofyear) 功能: 返回指定年份 y 第 n 天的日期值。当有多个参数任一为 NULL 时返回空,若只有一个入参且为 NULL 则报错。 参数说明: year:年份值,可以是 integer、numeric 等数值类型,或者 real、double precision 等浮点数类型。若参数存在小 数时,将其四舍五入成整数后再进行计算。 dayofyear:一年中的天数值,可以是 integer、numeric 等数值类型,或者 real、double precision 等浮点数类型。 若参数存在小数时,将其四舍五入成整数后再进行计算。 注意: 若 year 属于 0 到 99 之间,系统会自动补位。其若小于 70,则系统以 2000 年后(即 20yy)计算,其余情况 以 1900 年后即(19yy)计算。 返回值: date 类型日期值。 例子: 423 第 8 章 函数 SELECT MAKEDATE(2000.7,1) "MAKEDATE"; MAKEDATE -------------2001-01-01 SELECT MAKEDATE(2000,1.7) "MAKEDATE"; MAKEDATE -------------2000-01-02 SELECT MAKEDATE(12,1) "MAKEDATE"; MAKEDATE -------------2012-01-01 SELECT MAKEDATE(78,1) "MAKEDATE"; MAKEDATE -------------1978-01-01 8.298 MAKETIME(MySQL 模式) 用法: maketime(hour,minute,second) 功能: 返回由参数指定组成的时间值。 参数说明: hour:小时值,可以是 integer、numeric 等数值类型,或者 real、double precision 等浮点数类型。若参数存在小 数时,将其四舍五入成整数后再进行计算。 minute:分钟值,可以是 integer、numeric 等数值类型,或者 real、double precision 等浮点数类型。若参数存 在小数时,将其四舍五入成整数后再进行计算。 424 第 8 章 函数 second:秒值,或者 real、double precision 等浮点数类型。若参数超出 6 位的小数部分时,将其四舍五入为 6 位 小数后再进行计算。 返回值: time 类型时间值。 注意: 1. 参数为非数字字符串时,则函数默认该参数值为 0 并返回结果; 2. 任意参数为 NULL 时,函数返回为空。 例子: SELECT MAKETIME(12,1,1) "MAKETIME"; MAKETIME -------------12:01:01 SELECT MAKETIME(12.1,1,1) "MAKETIME"; MAKETIME -------------12:01:01 SELECT MAKETIME('',1,1) "MAKETIME"; MAKEDATE -------------00:01:01 8.299 MAKE_DATE 用法: make_date(year int, month int, day int) 功能: 425 第 8 章 函数 从年,月,日域创建日期。 参数说明: year:年,int 类型。 month:月,int 类型。 day:日,int 类型。 返回值: 函数返回值类型为 date。 例子: SELECT make_date(2013, 7, 15); make_date -----------2013-07-15 (1 row) 8.300 MAKE_INTERVAL 用法: make_interval(years int default 0, months int default 0, weeks int default 0, days int default 0, hours int default 0, mins int default 0, secs double default 0.0) 功能: 从年,月,周,日,时,分,秒域创建时间间隔。 参数说明: years:年,int 类型,默认值 0。 months:月,int 类型,默认值 0。 weeks:周,int 类型,默认值 0。 days:日,int 类型,默认值 0。 hours:时,int 类型,默认值 0。 426 第 8 章 函数 mins:分,int 类型,默认值 0。 secs:秒,double 类型,默认值 0.0。 返回值: 函数返回值类型为 interval。 例子: SELECT make_interval(years := 3, months := 7); make_interval ---------------3 years 7 mons (1 row) 8.301 MAKE_SET(bits,oid) 用法: MAKE_SET(bits,oid) 功能: 返回一个设定 SET 值(一个由’,’分隔子字符串的字符串),该值由设置位 bits 中的相应位的字符串组成 (系 统表 sys_set 按照 setdisplayorder 从小到大排序后,setlable 对应的 bit 位为 1,2,4,8,…2^63)。oid 为 SET 类型的 oid,具体见 sys_set 中 settypid。 例子: select MAKE_SET(6,16393); MAKE_SET ---------O,Y (1 row) 8.302 MAKE_TIME 用法: 427 第 8 章 函数 make_time(hour int, min int, sec double) 功能: 从时,分,秒域创建时间。 参数说明: hour:时,int 类型,范围 [0, 23]。 min:分,int 类型,范围 [0, 59]。 sec:秒,double 类型,范围 [0, 60]。 返回值: 函数返回值类型为 time。 例子: SELECT make_time(23, 59, 5.9); make_time ----------------23:59:05.900000 (1 row) 8.303 MAKE_TIMESTAMP 用法: make_timestamp(year int, month int, day int, hour int, min int, sec double) 功能: 从年,月,日,时,分,秒域创建时间戳。 参数说明: year:年,int 类型,范围 >= 1。 month:月,int 类型,范围 [1, 12]。 day:日,int 类型,范围 [1, 31]。 428 第 8 章 函数 hour:时,int 类型,范围 [0, 23]。 min:分,int 类型,范围 [0, 59]。 sec:秒,double 类型,范围 [0, 60]。 返回值: 函数返回值类型为 timestamp。 例子: SELECT make_timestamp(2014,12,28,6,30,45.887); make_timestamp ---------------------------2014-12-28 06:30:45.887000 (1 row) 8.304 MAKE_TIMESTAMPTZ 用法: make_timestamptz(year int, month int, day int, hour int, min int, sec double[, timezone text]) 功能: 从年,月,日,时,分,秒,时区域创建时间戳。 参数说明: year:年,int 类型,范围 >= 1。 month:月,int 类型,范围 [1, 12]。 day:日,int 类型,范围 [1, 31]。 hour:时,int 类型,范围 [0, 23]。 min:分,int 类型,范围 [0, 59]。 sec:秒,double 类型,范围 [0, 60]。 timezone:时区,text 类型。 429 第 8 章 函数 返回值: 函数返回值类型为 timestamp。 例子: select make_timestamptz(1973, 07, 15, 08, 15, 55.33, '+8'); make_timestamptz ------------------------------1973-07-15 08:15:55.330000+08 (1 row) 8.305 MAX 用法: max(expression) 功能: MAX 返回的最大值 expression。您可以将其用作聚合或分析函数。 例子: • 聚合示例 以下示例确定 hr.employees 表中的最高薪水: SELECT MAX(salary) "Maximum" FROM employees; +---------+ | Maximum | +=========+ | 24000 | +---------+ • 分析示例 以下示例为每位员工计算向与该员工相同的经理报告的员工的最高薪水。 SELECT manager_id, last_name, salary, MAX(salary) OVER (PARTITION BY manager_id) AS mgr_max FROM employees ORDER BY manager_id, last_name, salary; +------------+-----------+--------+---------+ 430 第 8 章 函数 | MANAGER_ID | LAST_NAME | SALARY | MGR_MAX | +============+===========+========+=========+ | 100 | Cambrault | 11000 | 17000 | +------------+-----------+--------+---------+ | 100 | De Haan | 17000 | 17000 | +------------+-----------+--------+---------+ | 100 | Errazuriz | 12000 | 17000 | +------------+-----------+--------+---------+ | 100 | Fripp | 8200 | 17000 | +------------+-----------+--------+---------+ | 100 | Hartstein | 13000 | 17000 | +------------+-----------+--------+---------+ | 100 | Kaufling | 7900 | 17000 | +------------+-----------+--------+---------+ | 100 | Kochhar | 17000 | 17000 | +------------+-----------+--------+---------+ | . . . | | | | +------------+-----------+--------+---------+ 如果将此查询用谓词括在父查询中,则可以确定每个部门中薪水最高的员工: SELECT manager_id, last_name, salary FROM (SELECT manager_id, last_name, salary, MAX(salary) OVER (PARTITION BY manager_id) AS rmax_sal FROM employees) WHERE salary = rmax_sal ORDER BY manager_id, last_name, salary; +------------+-----------+--------+ | MANAGER_ID | LAST_NAME | SALARY | +============+===========+========+ | 100 | De Haan | 17000 | +------------+-----------+--------+ | 100 | Kochhar | 17000 | +------------+-----------+--------+ | 101 | Greenberg | 12008 | +------------+-----------+--------+ | 101 | Higgins | 12008 | +------------+-----------+--------+ | 102 | Hunold | 9000 | +------------+-----------+--------+ | 103 | Ernst | 6000 | +------------+-----------+--------+ | 108 | Faviet | 9000 | +------------+-----------+--------+ | 114 | Khoo | 3100 | +------------+-----------+--------+ | 120 | Nayer | 3200 | +------------+-----------+--------+ 431 第 8 章 函数 | 120 | Taylor | 3200 | +------------+-----------+--------+ | 121 | Sarchand | 4200 | +------------+-----------+--------+ | 122 | Chung | 3800 | +------------+-----------+--------+ | 123 | Bell | 4000 | +------------+-----------+--------+ | 124 | Rajs | 3500 | +------------+-----------+--------+ | 145 | Tucker | 10000 | +------------+-----------+--------+ | 146 | King | 10000 | +------------+-----------+--------+ | 147 | Vishney | 10500 | +------------+-----------+--------+ | 148 | Ozer | 11500 | +------------+-----------+--------+ | 149 | Abel | 11000 | +------------+-----------+--------+ | 201 | Fay | 6000 | +------------+-----------+--------+ | 205 | Gietz | 8300 | +------------+-----------+--------+ | | King | 24000 | +------------+-----------+--------+ 22 rows selected. 8.306 MD5 用法: md5(string) 功能: MD5 用于计算给定参数的 MD5 哈希值,结果以十六进制输出。 例子: 432 第 8 章 函数 以下示例返回计算给定参数的 MD5 哈希值: SELECT md5('Th\000omas '::bytea); md5 ---------------------------------91d24a7b16bedaecc378bae28391865e (1 row) 8.307 MICROSECOND(MySQL 模式) 用法: microsecond(n) 功能: 返回指定时间的微秒值。 参数说明: n:date、timestamp、time 等时间日期类型。 返回值: integer 类型,值域为 0 至 999999。 例子: SELECT MICROSECOND(DATE'2022-01-02') "MICROSECOND"; MICROSECOND -------------0 SELECT MICROSECOND(TIMESTAMP'2022-01-05 1:00:00.122') "MICROSECOND"; MICROSECOND -------------122000 SELECT MICROSECOND(TIME'2:00:00.43') "MICROSECOND"; MICROSECOND 433 第 8 章 函数 -------------430000 8.308 MID 用法: mid(str, pos) mid(str, pos, count) 功能: 返回从位置 pos 开始的一个子字符串。若 count 参数给定,返回从位置 pos 开始长度为 count 的一个子字符串。 例子: SELECT mid('hello world!', 2.8); mid -------------llo world! (1 row) SELECT mid('hello world!', 2.8, 5); mid ---------llo w (1 row) 8.309 MIN 用法: min(expression) 功能: MIN 返回 expr 的最小值。您可以将其用作聚合或分析函数。 例子: 434 第 8 章 函数 • 聚合示例 以下语句返回表 hr.employees 中最早的雇用日期: SELECT MIN(hire_date) "Earliest" FROM employees; +-----------+ | Earliest | +===========+ | 13-JAN-01 | +-----------+ • 分析示例 下面的示例为每位员工确定在与员工相同日期或之前受雇的员工。然后,它确定向与该员工相同的经理报告的员 工子集,并返回该子集中的最低工资。 SELECT manager_id, last_name, hire_date, salary,MIN(salary) OVER(PARTITION BY manager_id ORDER BY hire_date RANGE UNBOUNDED PRECEDING) AS p_cmin FROM employees ORDER BY manager_id, last_name, hire_date, salary; +------------+-----------+-----------+--------+--------+ | MANAGER_ID | LAST_NAME | HIRE_DATE | SALARY | P_CMIN | +============+===========+===========+========+========+ | 100 | Cambrault | 15-OCT-07 | 11000 | 6500 | +------------+-----------+-----------+--------+--------+ | 100 | De Haan | 13-JAN-01 | 17000 | 17000 | +------------+-----------+-----------+--------+--------+ | 100 | Errazuriz | 10-MAR-05 | 12000 | 7900 | +------------+-----------+-----------+--------+--------+ | 100 | Fripp | 10-APR-05 | 8200 | 7900 | +------------+-----------+-----------+--------+--------+ | 100 | Hartstein | 17-FEB-04 | 13000 | 7900 | +------------+-----------+-----------+--------+--------+ | 100 | Kaufling | 01-MAY-03 | 7900 | 7900 | +------------+-----------+-----------+--------+--------+ | 100 | Kochhar | 21-SEP-05 | 17000 | 7900 | +------------+-----------+-----------+--------+--------+ | 100 | Mourgos | 16-NOV-07 | 5800 | 5800 | +------------+-----------+-----------+--------+--------+ | 100 | Partners | 05-JAN-05 | 13500 | 7900 | +------------+-----------+-----------+--------+--------+ | 100 | Raphaely | 07-DEC-02 | 11000 | 11000 | +------------+-----------+-----------+--------+--------+ | 100 | Russell | 01-OCT-04 | 14000 | 7900 | +------------+-----------+-----------+--------+--------+ | . . . | | | | | +------------+-----------+-----------+--------+--------+ 435 第 8 章 函数 8.310 MINUTE(MySQL 模式) 用法: minute(n) 功能: 返回指定时间的分钟值。 参数说明: n:date、timestamp、time 等时间日期类型。 返回值: integer 类型,值域为 0 至 59。 例子: SELECT MINUTE(DATE'2022-01-02') "MINUTE"; MINUTE -------------0 SELECT MINUTE(TIMESTAMP'2022-01-05 1:11:00') "MINUTE"; MINUTE -------------11 SELECT MINUTE(TIME'2:12:00') "MINUTE"; MINUTE -------------12 8.311 MOD 用法: 436 第 8 章 函数 mod(y,x) 功能: MOD 返回 n2 除以 n1 的余数。n1 如果为 0,则返回 n2。 此函数将任何数值数据类型或任何可以隐式转换为数值数据类型的非数值数据类型作为参数。KingbaseES 确定 具有最高数值优先级的参数,将其余参数隐式转换为该数据类型,并返回该数据类型。 n1 如果和的乘积 n2 为负,则此函数的行为与经典数学模函数不同。经典模数可以使用 MOD 具有以下公式的函 数表示: n2 - n1 * FLOOR(n2/n1) MOD 下表说明了函数和经典模数之间的区别: n2 n1 MOD(n2,n1) Classical Modulus 11 4 3 3 11 -4 3 -1 -11 4 -3 1 -11 -4 -3 -3 也可以参阅:FLOOR ,类似于 MOD,但 ROUND 在其公式中使用而不是 FLOOR。 例子: 以下示例返回 11 除以 4 的余数: SELECT MOD(11,4) "Modulus" FROM DUAL; +---------+ | Modulus | +=========+ | 3 | +---------+ 437 第 8 章 函数 8.312 MODE 用法: mode() WITHIN GROUP (ORDER BY expr [ DESC | ASC | USING operator ] ) [ FILTER ( WHERE filter_clause ) ] OVER ( [ query_partition_clause ] ) query_partition_clause: PARTITION BY expr [ , … ] 或 PARTITION BY ( expr [ , … ] ) 功能: 窗口函数 MODE 返回最频繁的输入值(如果有多个频度相同的值就选第一个),并且在计算中忽略 NULL 值。 规则: 1、不支持在函数内使用 DISTINCT 关键字和 ORDER BY 子句。 2、WITHIN GROUP 中的 ORDER BY 子句: • ASC、DESC 和 USING operator 分别用于指定按升序、降序和用户自定义规则排序,默认为 ASC 升序。 • 允许使用 NULLS FIRST 和 NULLS LAST,但由于函数忽略 NULL 值,不会有任何实际效果。 438 第 8 章 函数 • 排序表达式可以由常量、列或者函数表达式组成,不能使用输出列中的名称或编号,不能包含聚集函数和分析 函数。 • ORDER BY 子句最大支持的排序表达式个数在理论上没有限制。 3、OVER 子句 • query_partition_clause 是 OVER 子 句 唯 一 有 效 的 部 分。 如 果 包 含 了 OVER 子 句, 但 省 略 了 query_partition_clause,则定义的窗口是全表。 • 分区表达式可以由常量、来自 FROM 子句的表、视图或物化视图中的列,或者函数表达式组成,但分区表达式 中不能包含聚集函数和分析函数。 4、不支持 KEEP 函数。 5、支持用于视图,支持 dump/restore 工具。 例子: SELECT depname, empno, salary, mode() WITHIN GROUP (ORDER BY salary) OVER (PARTITION BY depname) FROM empsalary ORDER BY depname, salary; 8.313 MONTH(MySQL 模式) 用法: month(n) 功能: 返回指日期的月份值。 参数说明: n:date、timestamp、time 等时间日期类型。当参数为 time 类型时,该参数以当前系统日期时间为值,并被隐 式转化为 timestamp 类型再进行计算。 返回值: integer 类型,值域为 1~12。 例子: 439 第 8 章 函数 SELECT MONTH(DATE'2022-01-02') "MONTH"; MONTH -------------1 SELECT MONTH(TIMESTAMP'2022-01-05 1:11:00') "MONTH"; MONTH -------------1 SELECT MONTH(TIME'2:12:00') "MONTH";---返回当前系统日期的月份值 MONTH -------------6 8.314 MONTH(Oracle 模式) 用法: month(datetime date) 功能: 从日期时间域获取月份。 参数说明: datetime:日期时间,date 类型。 返回值: 函数返回值类型为 int。 例子: select month('2013-7-15 14:10:30'); month ------- 440 第 8 章 函数 7 (1 row) 8.315 MONTHNAME(MySQL 模式) 用法: monthname(n) 功能: 返回指日期的月份名称。 参数说明: n:date、timestamp、time 等时间日期类型。当参数为 time 类型时,该参数以当前系统日期时间为值,并被隐 式转化为 timestamp 类型再进行计算。 返回值: text 类型 例子: SELECT MONTHNAME(DATE'2022-01-02') "MONTHNAME"; MONTHNAME -------------January SELECT MONTHNAME(TIMESTAMP'2022-01-05 1:11:00') "MONTHNAME"; MONTHNAME -------------January SELECT MONTHNAME(TIME'2:12:00') "MONTHNAME";---返回当前系统日期的月份 MONTHNAME -------------June 441 第 8 章 函数 8.316 MONTHS_BETWEEN 用法: months_between(date date1, date date2) 功能: 计算日期 1 与日期 2 的月份差。 参数说明: date1:日期 1,date 类型。 date2:日期 2,date 类型。 返回值: 函数返回值类型为 double。 例子: SELECT months_between ('2007-02-28 111111', '2007-04-30 112121'); months_between ---------------------2.0647438769414577 (1 row) 8.317 NANVL 用法: nanvl(numeric n1, numeric n2) 功能: 如果 n1 是 NaN,则返回 n2;如果 n1 不是 NaN,则返回 n1。 参数说明: n1: numeric 类型数字或可以隐式转换成数字的表达式,可为 NULL。 442 第 8 章 函数 n2: numeric 类型数字或可以隐式转换成数字的表达式,可为 NULL。 返回值: n1 或 n2 的值。如果 n1 或 n2 不可转换为 numeric 类型,则返回错误信息。 例子: select nanvl(1, 45.4); --第一个参数不是 NaN,所以返回第一个参数值 1 nanvl ------1 (1 row) select nanvl('1.23', 45.4); --第一个参数可以转换成数字 1.23 并且不是 NaN,所以返回第一个参数转换成的数字值 1. 23 nanvl ------1.23 (1 row) select nanvl('NaN',2.2); --第一个参数是 NaN,所以返回第二个参数值 2.2 nanvl ------2.2 (1 row) 8.318 NEW_TIME 用法: new_time(str timestamp, zonename1 text, zonename2 text) 功能: 将时间戳在 zonename1 的时区下转换到在 zonename2 时区的时间戳。 参数说明: str: 关于 timestamp 的字符串。 zonename1: 关于时区 1 的字符串缩写。 zonename2: 关于时区 2 的字符串缩写。 例子: 443 第 8 章 函数 SELECT new_time('2022-10-24 21:30:00', 'GMT', 'PRC'); 8.319 NEXT_DAY 用法: next_day(date1 date, weekday text) 功能: 获取下一个周几。 参数说明: date1: 输入日期,date 类型。 weekday: 周几,text。 返回值: 函数返回值类型为 date。 例子: SELECT next_day ('2003-08-01 111211', 'TUESDAY'); next_day --------------------2003-08-05 11:12:11 (1 row) 8.320 NEXTVAL 用法: nextval(regclass) 功能: 444 第 8 章 函数 NEXTVAL 递增序列并返回新值。 参数说明: regclass:已经创建的序列名。 返回值: 返回 regclass 序列的递增新值。 例子: create sequence seq start with 1; select nextval('seq'); nextval --------1 (1 row) 8.321 NLSSORT 用法: nlssort(expr,nls_param) 功能: NLSSORT 返回字符值的排序规则键 char 和显式或隐式指定的排序规则。排序规则键是一串字节,用于 char 根 据指定的排序规则进行排序。排序规则键的属性是,当根据它们的二进制顺序比较时,为给定排序规则生成的两个这 样的键的相互排序与根据给定排序规则比较时源字符值的相互排序相同。 char 和’ nlsparam’ 都可以是任何数据类型 CHAR、VARCHAR、NCHAR 或 NVARCHAR。 ’nlsparam’ 的值必须具有以下形式 'NLS_SORT = collation' 其中 collation 是语言排序规则的名称或 BINARY. NLSSORT 使用指定的排序规则生成排序规则键。如果省略’ nlsparam’,则此函数使用参数的派生排序规则 char。如果您指定 BINARY,则此函数返回 char 值本身转换为 RAW 并可能被截断,如下所述。 如果您指定’ lsparam’,那么您可以将后缀附加到语言排序规则名称 _ai 以请求不区分重音的排序规则或 _ci 请 求不区分大小写的排序规则。不建议在查询子句中使用不区分重音或不区分大小写的排序规则,ORDER BY 因为它 会导致不确定的排序顺序。 445 第 8 章 函数 返回的排序规则键是 RAW 数据类型。char 由给定排序规则的给定值产生的排序规则键的长度可能超过 RAW 返 回值的最大长度 NLSSORT。在这种情况下,NLSSORT 的行为取决于初始化参数的值 MAX_STRING_SIZE。如果 MAX_STRING_SIZE = EXTENDED,则返回值的最大长度为 32767 字节。如果归类键超过此限制,则函数将失败 并出现错误“ORA-12742:无法创建归类键”。如果短输入字符串包含高比例的 Unicode 字符且分解率非常高,则也 可能会报告此错误。 如果 MAX_STRING_SIZE = STANDARD,则返回值的最大长度为 2000 字节。如果要返回的值超过限制,则 NLSSORT 计算最大前缀或初始子字符串的排序规则键,char 以便计算结果不超过最大长度。例如 FRENCH,对于 单语排序规则,前缀长度通常为 1000 个字符。例如 GENERIC_M,对于多语言排序规则,前缀通常为 500 个字符。 例如,对于 Unicode 归类算法 (UCA) 归类,UCA0610_DUCET 前缀通常为 285 个字符。确切的长度可能会更低或 更高,具体取决于排序规则和 char. 当行为 MAX_STRING_SIZE = STANDARD 暗示两个字符值的排序规则键(NLSSORT 结果)被比较以找到 语言顺序时,如果它们在前缀上没有差异,即使它们可能在某些进一步的字符位置不同,则它们被认为是相等的。 因为该 NLSSORT 函数被隐式用于查找比较条件的语言排序,所以 BETWEEN 条件、IN 条件、ORDER BY、 GROUP BY 和 COUNT(DISTINCT),这些操作可能返回仅对长字符值近似的结果。如果您想保证这些操作的结果 是准确的,那么将您的数据库迁移到使用 MAX_STRING_SIZE = EXTENDED。 此函数不直接支持 CLOB 数据。但是,CLOBs 可以通过隐式数据转换作为参数传入。 例子: 此函数可用于指定基于语言排序序列而不是字符串的二进制值的排序和比较操作。下面的示例创建一个包含两个 值的测试表,并显示函数如何对返回的值进行排序 NLSSORT: CREATE TABLE test (name VARCHAR(15)); INSERT INTO test VALUES ('Gaardiner'); INSERT INTO test VALUES ('Gaberd'); INSERT INTO test VALUES ('Gaasten'); SELECT * FROM test ORDER BY name; +-----------+ | NAME | +===========+ | Gaardiner | +-----------+ | Gaasten | +-----------+ | Gaberd | +-----------+ SELECT * FROM test ORDER BY NLSSORT(name, 'NLS_SORT = XDanish'); 446 第 8 章 函数 +-----------+ | NAME | +===========+ | Gaberd | +-----------+ | Gaardiner | +-----------+ | Gaasten | +-----------+ 以下示例显示了如何 NLSSORT 在比较操作中使用该函数: SELECT * FROM test WHERE name > 'Gaberd' ORDER BY name; no rows selected SELECT * FROM test WHERE NLSSORT(name, 'NLS_SORT = XDanish') > NLSSORT('Gaberd', 'NLS_SORT = XDanish') ORDER BY name; +-----------+ | NAME | +===========+ | Gaardiner | +-----------+ | Gaasten | +-----------+ 如果您经常 NLSSORT 在具有相同语言排序序列的比较操作中使用,则考虑这种更有效的替代方案:将 NLS_COMP 参数(对于数据库或当前会话)LINGUISTIC 设置为,NLS_SORT 并将会话的参数设置为所需的排 序序列。默认情况下,KingbaseES 数据库将使用该排序顺序进行当前会话期间的所有排序和比较操作: ALTER SESSION SET NLS_COMP = 'LINGUISTIC'; ALTER SESSION SET NLS_SORT = 'XDanish'; SELECT * FROM test WHERE name > 'Gaberd' ORDER BY name; +-----------+ | NAME | +===========+ | Gaardiner | +-----------+ | Gaasten | +-----------+ 447 第 8 章 函数 8.322 NOW 用法: now() 功能: 获取当前时间。 返回值: 函数返回值类型为 timestamp。 例子: SELECT now(); now ------------------------------2022-06-28 19:33:29.581229+08 (1 row) 8.323 NTH_VALUE 用法: nth_value(value any, nth integer) over ([partition by partition_expression] [order by sort_expression [ASC| DESC]]) 功能: 448 第 8 章 函数 NTH_VALUE 返回在窗口帧中的第 nth 行 (行从 1 计数) 上计算的 value, 类型与 any 一致。如果没有这样的行 则返回空值。本函数为通用窗口函数。 参数说明: value:窗户帧的名子,通常为投影列列名。 nth:第几行。 例子: SELECT nth_value(ten, four + 1) OVER (PARTITION BY four), ten, four FROM (SELECT * FROM tenk1 WHERE unique2 < 10 ORDER BY four, ten)s; nth_value | ten | four -----------+-----+-----0 | 0 | 0 0 | 0 | 0 0 | 4 | 0 1 | 1 | 1 1 | 1 | 1 1 | 7 | 1 1 | 9 | 1 | 0 | 2 | 1 | 3 | 3 | 3 (10 rows) 8.324 NTILE 用法: ntile(num_buckets integer) 功能: NTILE 从 1 到 num_backet 参数值的整数范围,尽可能等分分区。 参数说明: num_backet:要等分分区的个数。 返回值: 记录 449 第 8 章 函数 例子: SELECT ntile(3) OVER (ORDER BY ten, four), ten, four FROM tenk1 WHERE unique2 < 10; ntile | ten | four -------+-----+-----1 | 0 | 0 1 | 0 | 0 1 | 0 | 2 1 | 1 | 1 2 | 1 | 1 2 | 1 | 3 2 | 3 | 3 3 | 4 | 0 3 | 7 | 1 3 | 9 | 1 (10 rows) 8.325 NULLIF 用法: nullif(expr1, expr2) 功能: NULLIF 比较 expr1 和 expr2。如果它们相等,则函数返回 null。如果它们不相等,则函数返回 expr1。expr1 不 能指定文字‘NULL’。 参数说明: expr1:用于判断其值是否与 expr2 相等的表达式,通常为列表达式。 expr2:用于判断 expr1 值是否与其相等的表达式,通常为常量表达式。 返回值: expr1 的值,或者是 NULL。 例子: select * from t1; a --- 450 第 8 章 函数 1 2 (2 rows) select nullif(a, 1) from t1; nullif -------2 (2 rows) 8.326 NUMTODSINTERVAL 用法: 功能: 将输入的数字与 UNIT 转换为关于日期和时间的 dsinterval。 格式串见上述图片。 例子: select numtodsinterval(27 , 'hour') from dual; numtodsinterval ----------------------1 day 03:00:00.000000 (1 行记录) 8.327 NUMTOYMINTERVAL 用法: 功能: 将输入的数字与 UNIT 转换为关于 YEAR 和 MONTH 的 yminterval。 451 第 8 章 函数 格式串见上述图片。 例子: # select numtoyminterval(27 , 'month') from dual; numtoyminterval ----------------2 years 3 mons (1 行记录) 8.328 NVL 用法: nvl(expr1, expr2) 功能: 如果表达式 expr1 不为空,返回表达式 expr1; 如果 expr1 为空,返回表达式 expr2。 参数说明: expr1:用于判断其值是否为 NULL 的表达式,通常为列表达式。 expr2:用于 expr1 为 NULL 时 NVL 的返回值表达式,通常为常量表达式。 返回值: expr1 的值,或者是 expr2。 例子: select * from t1; a --1 2 (3 rows) select nvl(a, 4) from t1; nvl ----1 452 第 8 章 函数 2 4 (3 rows) 8.329 NVL2 用法: nvl2(expr1,expr2,expr3) 功能: NVL2 允许根据指定表达式是否为空来确定查询返回的值。如果表达式 expr1 不为空,返回表达式 expr2, 如果 expr1 为空,返回表达式 expr3。 参数说明: expr1:用于判断其值是否为 NULL 的表达式,通常为列表达式。 expr2:用于 expr1 不为 NULL 时 NVL2 的返回值表达式,通常为常量表达式。 expr3:用于 expr1 为 NULL 时 NVL2 的返回值表达式,通常为常量表达式。 返回值: expr2 的值,或者是 expr3。 例子: select * from t1; a --1 2 (3 rows) select nvl2(a, 4, 5) from t1; nvl2 -----4 4 453 第 8 章 函数 5 (3 rows) 8.330 OCTET_LENGTH 用法: octet_length(string) 功能: 函数返回以字节计的数据字符表达的长度, 字符串尾部空格字符也会被计算在内。 例子: SELECT OCTET_LENGTH( 'abc '::text ) "LENGTH" FROM DUAL; +-----------+ | LENGTH | +===========+ | 5 | +-----------+ 8.331 ORA_HASH 用法: ORA_HASH(expr [, max_bucket[,seed_value]]) 功能: ORA_HASH 是一个计算给定表达式的哈希值的函数。 454 第 8 章 函数 • expr 参数为需要计算哈希值的数据;expr 表示的数据长度没有限制,通常解析为列名。expr 不能是如下几种类 型:货币类型、几何类型、位串类型、文本搜索类型、XML 类型、JSON 类型(支持 JSONB 类型)和组合类 型,其他类型均可支持。 • 可选的 max_bucket 参数确定哈希函数返回的最大桶值。您可以指定 0 到 9223372036854775807 之间的任何 值。默认值为 9223372036854775807。 • 可选的 seed_value 参数使 KingbaseES 能够为同一组数据生成许多不同的结果。您可以指定 0 到 9223372036854775807 之间的任何值。默认为 8816678312871386365. 例子: SELECT ORA_HASH('KingbaseES', 99, 5); ora_hash ---------33 (1 row) 8.332 OVERLAY 用法: overlay(string placing string from int [for int]) 功能: 将用字符串 expr1 中指定起始位 (from 后的数值)开始后的 (指定长度,for 后的数值) 字符串,用给定的字符串 expr2 替换。 • 如果有 for 关键字,则将 expr1 从 from 后的数位开始,到 for 后的数为止,替换成 expr2。 • 如果没有 for 关键字,则将 expr1 从 from 后的数位开始,共 expr2 字符串长度的子字符串,替换成 expr2。 例子: SELECT OVERLAY('1234567890' PLACING 'hom' FROM 2 FOR 4); +-----------+ | overlay | +===========+ | 1hom67890 | +-----------+ 455 第 8 章 函数 SELECT OVERLAY('Txxxxas' PLACING 'hometown' FROM 2 ); +-----------+ | overlay | +===========+ | Thometown | +-----------+ 8.333 PERCENT_RANK 用法: • 聚合语法 percent_rank_aggregate: • 分析语法 percent_rank_analytic: 功能: PERCENT_RANK 类似于 CUME_DIST(累积分布)函数。返回值的范围 PERCENT_RANK 是 0 到 1,包 括 0 到 1。任何集合中的第一行的 aPERCENT_RANK 为 0。返回值为 NUMBER。 • 作为聚合函数,对于由函数的参数和相应的排序规范标识 PERCENT_RANK 的假设行,计算行的秩减 1 除以 聚合组中的行数。这个计算就像假设的行被插入到 KingbaseES 数据库要聚合的行组中一样。 456 第 8 章 函数 • 该函数的参数标识每个聚合组中的单个假设行。因此,它们必须全部计算为每个聚合组中的常量表达式。常量 参数表达式和 ORDER BY 聚合子句中的表达式按位置匹配。因此,参数的数量必须相同,并且它们的类型必 须兼容。 • 作为一个分析函数,对于 row r,PERCENT_RANK 计算排名为 r 负 1,除以 1 小于被评估的行数(整个查询 结果集或分区)。 例子: • 聚合示例 以下示例计算样本表中假设员工的百分比排名,hr.employees 工资为 15,500 美元,佣金为 5%: SELECT PERCENT_RANK(15000, .05) WITHIN GROUP (ORDER BY salary, commission_pct) "Percent-Rank" FROM employees; +--------------+ | Percent-Rank | +==============+ | .971962617 | +--------------+ • 分析示例 以下示例为每位员工计算部门内员工薪水的百分比排名: SELECT department_id, last_name, salary, PERCENT_RANK() OVER (PARTITION BY department_id ORDER BY salary DESC) AS pr FROM employees ORDER BY pr, salary, last_name; +---------------+-----------+------------+-------+------------+ | DEPARTMENT_ID | LAST_NAME | SALARY | PR | | +===============+===========+============+=======+============+ | | 10 | Whalen | 4400 | 0 | +---------------+-----------+------------+-------+------------+ | | 40 | Mavris | 6500 | 0 | +---------------+-----------+------------+-------+------------+ | | Grant | 7000 | 0 | | +---------------+-----------+------------+-------+------------+ | | 80 | Vishney | 10500 | .181818182 | +---------------+-----------+------------+-------+------------+ | | 80 | Zlotkey | 10500 | .181818182 | +---------------+-----------+------------+-------+------------+ | | 30 | Khoo | 3100 | .2 | +---------------+-----------+------------+-------+------------+ | | 50 | Markle | 2200 | .954545455 | +---------------+-----------+------------+-------+------------+ | | 50 | Philtanker | 2200 | .954545455 | +---------------+-----------+------------+-------+------------+ 457 第 8 章 函数 | | 50 | Olson | 2100 | 1 | +---------------+-----------+------------+-------+------------+ | . . . | | | | | +---------------+-----------+------------+-------+------------+ 8.334 PERCENTILE_CONT 用法: percentile_cont({fraction | fractions}) WITHIN GROUP (ORDER BY expr [ DESC | ASC | USING operator ] ) [ FILTER ( WHERE filter_clause ) ] OVER ( [ query_partition_clause ] ) query_partition_clause: PARTITION BY expr [ , … ] 或 PARTITION BY ( expr [ , … ] ) 458 第 8 章 函数 直接参数与 percentile_cont 有序集聚集函数相同,支持以下两种形式: • 用于计算连续百分率,返回一个对应于排序中指定分数的值,如有必要就在相邻的输入项之间插值。 • 用于计算多重连续百分率,返回一个匹配 fractions 参数形状的结果数组,其中每一个非空元素都用对应于那个 百分率的值替换。 功能: 窗口函数 PERCENTILE_CONT 是一个基于连续分布模型的逆分布函数。它接收一个百分率值和一个排序定 义,返回一个对应于排序中指定分数的值,如有必要就在相邻的输入项之间插值,并且在计算中忽略 NULL 值。 规则: 参考:ref:MODE 。 8.335 PERCENTILE_DISC 用法: percentile_disc({fraction | fractions}) WITHIN GROUP (ORDER BY expr [ DESC | ASC | USING operator ] ) [ FILTER ( WHERE filter_clause ) ] OVER ( [ query_partition_clause ] ) query_partition_clause: PARTITION BY expr [ , … ] 或 PARTITION BY ( expr [ , … ] ) 459 第 8 章 函数 直接参数与 percentile_disc 有序集聚集函数相同,支持以下两种形式: • 用于计算离散百分率,返回第一个在排序中位置等于或者超过指定分数的输入值。 • 用于计算多重离散百分率,返回一个匹配 fractions 参数形状的结果数组,其中每一个非空元素都用对应于那个 百分率的输入值替换。 功能: 窗口函数 PERCENTILE_DISC 是一个基于离散分布模型的逆分布函数。它接受一个百分率值和一个排序定 义,返回输入集合中的一个元素,并且在计算中忽略 NULL 值。 规则: 参考:ref:MODE 。 例子: SELECT depname, empno, salary, percentile_disc(0.5) WITHIN GROUP (ORDER BY salary) OVER (PARTITION BY depname) median FROM empsalary ORDER BY depname, salary; 8.336 PERIOD_ADD(MySQL 模式) 用法: period_add(p,n) 功能: 将指定月份 n 加到指定格式为 YYMM 或 YYYYMM 的日期 p 上。 460 第 8 章 函数 参数说明: p:可以表示为 YYMM 或 YYYYMM 格式的 bigint、numeric 等数值类型、double precision 等浮点数类型。参 数存在小数时,将其四舍五入转为 bigint 类型后再计算输出。若参数不能转换为 YYMM 或 YYYYMM 格式,函数 运行会报错。 n: bigint、numeric 等数值类型、double precision 等浮点数类型。参数存在小数时,将其四舍五入转为 bigint 类 型后再计算输出。 注意: 若参数 p 为 YYMM 格式,YY 属于 0 到 99 之间,系统会自动补位。其若小于 70,则系统以 2000 年后(即 20YY)计算,其余情况以 1900 年后即(19YY)计算。 返回值: bigint 类型,格式为“YYYYMM”。 注意: 1. 任意参数为 NULL 时,函数返回为空; 2. 参数为空值或其他不合法格式时,返回报错。 例子: SELECT PERIOD_ADD(202002,1) "PERIOD_ADD"; PERIOD_ADD -------------202003 SELECT PERIOD_ADD(202002,-1) "PERIOD_ADD"; PERIOD_ADD -------------202001 SELECT PERIOD_ADD(202002,NULL) "PERIOD_ADD"; PERIOD_ADD -------------- 461 第 8 章 函数 8.337 PERIOD_DIFF(MySQL 模式) 用法: period_diff(p,n) 功能: 计算两个格式为 YYMM 或 YYYYMM 的日期 p1 和日期 p2 的间隔月份。 参数说明: p1、p2:可以表示为 YYMM 或 YYYYMM 格式的 bigint、numeric 等数值类型、double precision 等浮点数类 型。参数存在小数时,将其四舍五入转为 bigint 类型后再计算输出。若参数不能转换为 YYMM 或 YYYYMM 格式, 函数运行会报错。 注意: 若参数为 YYMM 格式,YY 属于 0 到 99 之间,系统会自动补位。其若小于 70,则系统以 2000 年后(即 20YY)计算,其余情况以 1900 年后即(19YY)计算。 返回值: bigint 类型 注意: 1. 任意参数为 NULL 时,函数返回为空; 2. 参数为空值或其他不合法格式时,返回报错。 例子: SELECT PERIOD_DIFF(202002,202001) "PERIOD_DIFF"; PERIOD_DIFF -------------1 SELECT PERIOD_DIFF(0101,9901) "PERIOD_DIFF"; PERIOD_DIFF -------------24 462 第 8 章 函数 SELECT PERIOD_DIFF(202002,NULL) "PERIOD_DIFF"; PERIOD_DIFF -------------- 8.338 PI 用法: pi() 功能: 返回一个 � 的 double 类型值 此函数将返回一个 double 类型的表示 � 的值。 例子: 以下示例演示生成一个 � 的 double 类型值。 SELECT pi(); pi ------------------3.141592653589793 (1 行记录) 8.339 POSITION 用法: position(substring in string) 功能: 463 第 8 章 函数 返回指定子串的位置。 例子: SELECT position('\000om'::bytea in 'Th\000omas'::bytea); position ---------3 (1 row) 8.340 POWER 用法: power(a dp, b dp) power(a numeric, b numeric) 功能: 返回 a 的 b 次幂。 例子: SELECT power(8, 3.0); power ---------------------512.0000000000000000 (1 row) 8.341 QUARTER(MySQL 模式) 用法: quarter(n) 功能: 返回指定日期的季度值,参数为 NULL 时返回空。 464 第 8 章 函数 参数说明: n:date、timestamp、time 等时间日期类型。当参数为 time 类型时,该参数以当前系统日期时间为值,并被隐 式转化为 timestamp 类型再进行计算。 返回值: integer 类型,值域为 1 至 4。 例子: SELECT QUARTER(DATE'2022-01-02') "QUARTER"; QUARTER -------------1 SELECT QUARTER(TIMESTAMP'2022-01-05 1:11:00') "QUARTER"; QUARTER -------------1 SELECT QUARTER(TIME'2:12:00') "QUARTER";---返回当前系统日期的季度值 QUARTER -------------2 8.342 QUERY_TO_XML 用法: query_to_xml(query text, nulls boolean, tableforest boolean, targetns text) 功能: query_to_xml 执行由参数 query 传递的查询并且映射结果集. 例子: 465 第 8 章 函数 如果 tableforest 为假,则结果的 XML 文档看起来像这样: datadata...... 如果 tableforest 为真,结果是一个看起来像这样的 XML 内容片断: datadata... 8.343 QUOTE_IDENT 用法: 466 第 8 章 函数 quote_ident(string text) 功能: 将给定字符串返回成合适的引用形式,使它可以在一个 SQL 语句字符串中被用作一个标识符。只有需要时才会 加上引号(即,如果字符串包含非标识符字符或可能是大小写折叠的)。嵌入的引号会被正确地双写。 例子: SELECT quote_ident('Foo bar'); quote_ident ------------"Foo bar" (1 row) 8.344 QUOTE_LITERAL 用法: quote_literal(string text) 功能: 将给定字符串返回成合适的引用形式,使它可以在一个 SQL 语句字符串中被用作一个字符串文字。嵌入的引号 会被正确地双写。注意 quote_literal 对空输入返回空;如果参数可能为空,quote_nullable 通常更合适。 例子: SELECT quote_literal(E'O’Reilly'); quote_literal --------------'O’Reilly' (1 row) 467 第 8 章 函数 8.345 QUOTE_NULLABLE 用法: quote_nullable(string text) quote_nullable(value anyelement) 功能: • 将给定字符串返回成合适的引用形式,使它可以在一个 SQL 语句字符串中被用作一个字符串文字;或者,如果 参数为空,返回 NULL。嵌入的引号会被正确地双写 • 强迫给定值为文本并且接着将它用引号包围作为一个文本;或者,如果参数为空,返回 NULL。嵌入的单引号 和反斜线被正确的双写。 例子: SELECT quote_nullable(NULL); quote_nullable ---------------NULL (1 row) 8.346 RADIANS 用法: radians(dp) 功能: radians(dp) 把角度 dp 转为弧度。 例子: 468 第 8 章 函数 SELECT radians(45.0); 8.347 RADIUS 用法: radius(circle) 功能: radius(circle) 求取输入圆 circle 的半径。 例子: SELECT radius(circle'((0,0),2.0)'); 8.348 RANGE_MERGE 用法: range_merge(anyrange,anyrange) 功能: range_merge(anyrange,anyrange) 返回包含两个给定范围的最小范围。 例子: SELECT range_merge('[1,2)'::int4range,'[3,4)'::int4range); 8.349 RANK 用法: 469 第 8 章 函数 • 聚合语法: rank(args) WITHIN GROUP (ORDER BY sorted_args) • 分析语法: rank() OVER ([query_partition_clause] order_by_clause) 功能: RANK 计算一个值在一组值中的排名。返回类型是 NUMBER。 • 具有相同排名标准值的行获得相同的排名。然后,KingbaseES 数据库将绑定行数添加到绑定排名以计算下一个 排名。因此,排名可能不是连续的数字。此功能对于前 N 和后 N 报告很有用。 • 作为聚合函数,RANK 计算由函数的参数标识的假设行相对于给定排序规范的排名。函数的参数必须全部计算 为每个聚合组中的常量表达式,因为它们标识每个组中的单个行。常量参数表达式和 ORDER BY 聚合子句中 的表达式按位置匹配。因此,参数的数量必须相同,并且它们的类型必须兼容。 • 作为一个分析函数,RANK 根据 order_by_clause 字句中的 value_exprs 的值,计算查询返回的每一行相对于 查询返回的其他行的排名。 例子: 以下查询返回 15,500 美元工资在员工工资中的排名: SELECT RANK(15500) WITHIN GROUP (ORDER BY salary DESC) "Rank of 15500" FROM employees; 以下为 rank() 用例: CREATE TABLE ranks( c VARCHAR(10)); INSERT INTO ranks(c) VALUES ('A'),('B'),('C'),('B'),('E'); SELECT c, RANK() OVER(ORDER BY c) RANK_NUM FROM ranks; 8.350 RAND 用法: 470 第 8 章 函数 rand() rand(seed int) 功能: 生成范围 0.0 <= x < 1.0 中的随机值。 rand 函数为 MySQL 兼容函数,仅支持在 MySQL 模式下使用。 例子: SELECT rand(); SELECT rand(1); 8.351 RANDOM 用法: random() 功能: 生成范围 0.0 <= x < 1.0 中的随机值。 例子: SELECT random(); 8.352 RATIO_TO_REPORT 用法: ratio_to_report(expr1) over (query_partions_clasue) 功能: 471 第 8 章 函数 百分比计算函数。分子是 expr 的值,分母是 over 中的值,若 over 中没有指定,则分母是所有值。expr 可以 是常量表达式,算术表达式,投影列表达式。且表达式 expr 是一个 number 类型或者可以隐式转换为 number 类型 的表达式。其它类型的表达式报错。如果 expr 的计算结果为 NULL,则 RATIO_TO_REPORT 函数的计算结果也 为 NULL。若指定了 query_partions_clasue,则分母是这个子句计算的值。不能使用 ratio_to_report 自身或者其它 windows 函数作为 expr 参数来使用, 否则报错处理。返回值类型 numeric,使用默认精度与标度。 参数说明: expr1:用于计算百分比的分子的表达式。 返回值: 返回 expr 点 over 窗口的百分比的值。 例子: select name, score, ratio_to_report(score) over(partition by name) from t1 order by name; name | score | ratio_to_report ------+-------+-----------------------joy | 93.5 | 0.48774126238914971309 joy | 98.2 | 0.51225873761085028691 lily | 86.2 | 0.47493112947658402204 lily | 95.3 | 0.52506887052341597796 lucy | 98.2 | 0.50102040816326530612 lucy | 97.8 | 0.49897959183673469388 tom | 91.6 | 0.48723404255319148936 tom | 96.4 | 0.51276595744680851064 Tony | 86.2 | 1.00000000000000000000 Tony | | (10 rows) 8.353 RAWTOHEX 用法: rawtohex(raw) 功能: 把 raw 的字节串转换为十六进制表示的字符串。注意函数 RAWTOHEX 和 raw 数据类型都需要加载插件 kdb_raw 才能使用。 参数说明: 472 第 8 章 函数 raw:raw 类型值。 返回值: varchar2 类型。 例子: select rawtohex(raw '1112') from dual; rawtohex ----------1112 8.354 RAWTONHEX 用法: rawtonhex(raw) 功能: 同 RAWTOHEX,把 raw 的字节串转换为十六进制表示的字符串。注意函数 RAWTONHEX 和 raw 数据类型都 需要加载插件 kdb_raw 才能使用。 参数说明: raw:raw 类型值。 返回值: varchar2 类型。 例子: select rawtonhex('1') from dual; rawtonhex ----------31 473 第 8 章 函数 8.355 REGEXP_COUNT 用法: regexp_count(source_char,pattern [,position [,match_param]]) 功能: 返回目标字符串 pattern(也可以使用正则表达式),在源字符串 source_char 中出现的次数。返回值若等于 0, 则表示未找到匹配项。 参数说明: source:输入源字符串 pattern:正则表达式 position:一个正整数,它表示从源字符串 source_char 的哪个位置开始分析,默认是 1。 match_param:匹配规则,其参数如下: i:大小写不敏感 c:大小写敏感 m:和 n 是一样的,加上‘m’后,“.”与“n”不匹配;插入符号(^)和美元符号($)分别解释为源 字符串中任何位置的任何行的开头和结尾,而不仅仅是整个源字符串的开头或结尾。 n:“n”敏感,加上‘n’后,“.”与“n”不匹配;插入符号(^)和美元符号($)分别解释为源字符 串中任何位置的任何行的开头和结尾,而不仅仅是整个源字符串的开头或结尾。 x:忽略空格字符。默认情况下,空格字符会匹配空格字符。 例子: 使用正则表达式匹配 a-z 任意单个字符: select regexp_count('abc123', '[a-z]'), regexp_count('a1b2c3', '[a-z]') from dual; regexp_count|regexp_count| ------------+------------+ 3| 3| 使用匹配行为‘i’、‘c’不区分大小写和区分大小写: 474 第 8 章 函数 select REGEXP_COUNT('wElcome','e',1,'i') , REGEXP_COUNT('wElcome','e',1,'c' ) from DUAL; regexp_count|regexp_count| ------------+------------+ 2| 1| 8.356 REGEXP_INSTR 用法: regexp_instr(source_char,pattern [,position [,occurrence [,return_option [,match_param [,subexpr]]]]]) 功能: 返回模式匹配字符串的起始位置,或者结束位置。 source:输入源字符串 pattern:正则表达式 position:一个正整数,它表示从源字符串 source_char 的哪个位置开始匹配,默认是 1。 occurrence:非负整数,匹配正则表达式的次数。 return_option:为 0 返回第一个匹配位置的字符索引;不为 0,返回最后一个匹配位置的字符索引。 match_param:匹配规则,其参数如下: i:大小写不敏感 c:大小写敏感 m:和 n 是一样的,加上‘m’后,“.”与“n”不匹配;插入符号(^)和美元符号($)分别解释为源 字符串中任何位置的任何行的开头和结尾,而不仅仅是整个源字符串的开头或结尾。 475 第 8 章 函数 n:“n”敏感,加上‘n’后,“.”与“n”不匹配;插入符号(^)和美元符号($)分别解释为源字符 串中任何位置的任何行的开头和结尾,而不仅仅是整个源字符串的开头或结尾。 x:忽略空格字符。默认情况下,空格字符会匹配空格字符。 subexpr:子正则表达式 例子: select regexp_instr('foobarbaquebaz','b', 1,2,9,'i'); regexp_instr| ------------+ 8 | 8.357 REGEXP_LIKE 用法: regexp_like( source, pattern [,match_param]) 功能: regexp_like 函数判断输入字符串能否通过正则表达式进行匹配,source 为输入源字符串,pattern 为正则表达 式,match_param 可以改变匹配规则,其参数如下: i:大小写不敏感 c:大小写敏感 m:和 n 是一样的,加上‘m’后,“.”与“n”不匹配;插入符号(^)和美元符号($)分别解释为源字符串 中任何位置的任何行的开头和结尾,而不仅仅是整个源字符串的开头或结尾。 n:“n”敏感,加上‘n’后,“.”与“n”不匹配;插入符号(^)和美元符号($)分别解释为源字符串中任 何位置的任何行的开头和结尾,而不仅仅是整个源字符串的开头或结尾。 x:忽略空格字符。默认情况下,空格字符会匹配空格字符。 例子: select regexp_like('Steven', '^Ste(v|ph)en$'); 476 第 8 章 函数 8.358 REGEXP_MATCH 用法: regexp_match( source, pattern [,match_param]) 功能: regexp_match 函数返回一个 POSIX 正则表达式与 source 的第一个匹配得到的子串。 source 为输入源字符串,pattern 为正则表达式,match_param 可以改变匹配规则,其参数如下: i:大小写不敏感 c:大小写敏感 m:和 n 是一样的,加上‘m’后,“.”与“n”不匹配;插入符号(^)和美元符号($)分别解释为源字符串 中任何位置的任何行的开头和结尾,而不仅仅是整个源字符串的开头或结尾。 n:“n”敏感,加上‘n’后,“.”与“n”不匹配;插入符号(^)和美元符号($)分别解释为源字符串中任 何位置的任何行的开头和结尾,而不仅仅是整个源字符串的开头或结尾。 x:忽略空格字符。默认情况下,空格字符会匹配空格字符。 例子: select regexp_match('foobarbequebaz','ba.', 'i'); 8.359 REGEXP_MATCHES 用法: regexp_matches( source, pattern [,match_param]) 功能: regexp_matches 函数返回一个 POSIX 正则表达式与 source 的匹配得到的子串 (可能有多个)。 477 第 8 章 函数 source 为输入源字符串,pattern 为正则表达式,match_param 可以改变匹配规则,其参数如下: i:大小写不敏感 c:大小写敏感 m:和 n 是一样的,加上‘m’后,“.”与“n”不匹配;插入符号(^)和美元符号($)分别解释为源字符串 中任何位置的任何行的开头和结尾,而不仅仅是整个源字符串的开头或结尾。 n:“n”敏感,加上‘n’后,“.”与“n”不匹配;插入符号(^)和美元符号($)分别解释为源字符串中任 何位置的任何行的开头和结尾,而不仅仅是整个源字符串的开头或结尾。 x:忽略空格字符。默认情况下,空格字符会匹配空格字符。 例子: select regexp_matches('foobarbequebaz','ba.', 'g'); 8.360 REGEXP_REPLACE 用法: regexp_replace(source, pattern, replacement [, match_param]) 功能: regexp_replace 函数替换匹配一个 POSIX 正则表达式的子串。 source 为输入源字符串,pattern 为正则表达式,replacement 是用来替换的字符串, match_param 可以改变匹配规则,其参数如下: i:大小写不敏感 c:大小写敏感 m:和 n 是一样的,加上‘m’后,“.”与“n”不匹配;插入符号(^)和美元符号($)分别解释为源字符串 中任何位置的任何行的开头和结尾,而不仅仅是整个源字符串的开头或结尾。 n:“n”敏感,加上‘n’后,“.”与“n”不匹配;插入符号(^)和美元符号($)分别解释为源字符串中任 何位置的任何行的开头和结尾,而不仅仅是整个源字符串的开头或结尾。 x:忽略空格字符。默认情况下,空格字符会匹配空格字符。 例子: 478 第 8 章 函数 select regexp_replace('Thomas', '.[mN]a.', 'M'); 8.361 REGEXP_REPLACE(Oracle 模式) 用法: REGEXP_REPLACE (source, pattern, replacement [, position [, occurrence [, flag ] ] ] ) 功能: 将匹配 POSIX 正则表达式模式的子串替换为新文本,如果没有匹配 pattern,则返回不加修改的 source 串。如 果有匹配,则返回被 replacement 串替换掉的 source 串。 参数 source 用作搜索的字符表达式。可以是字符串类型、大对象类型。 pattern POSIX 正则表达式。它通常是一个字符串常量,并且可以是下列任何数据类型:字符串类型(character 类型、char 类型需要加 trim() 函数)、大对象类型。 replacement replacement 可以是下列任意数据类型,字符串类型,大对象类型。replacement 可含反向引用作为子表达 式,其形式为 n,n 为数字 1~9。并且它可以包含 & 表示应该插入匹配整个模式的子串。如果在 replacement 中为反斜线字符,则需使用转移字符在其前面(), 例如,要替换 2,请输入\2。 position 可选参数,指示从 source_char 的第几个字符开始搜索。默认值为 1,表示数据库从第一个字符开始搜索 source_char。找到第一个匹配项后,将搜索第二个匹配项,该匹配项从第一个匹配项后的第一个字符开 始。 479 第 8 章 函数 occurrence 可选参数,非负整数,表示替换动作的发生位置。 • 如果为 0,则数据库将替换所有匹配项. 是默认值。 • 如果为正整数 n,则数据库将替换第 n 个匹配项。 • 如果 occurrence 大于 1,则数据库将从第二个匹配项开始查找替换,第二个匹配项开始于 pattern 第 一次出现后的第一个字符。 flag 可选的字符串常量,可以是字符串类型(char 类型、character 类型需要加 trim() 函数)和大对象类型。 它包含一个或多个单个字符,这些标志可以改变函数的行为。可以包含以下一个或多个字符: • ’i’:指定不区分大小写的匹配 • ’c’:指定区分大小写和区分的匹配 • ’m’:和 n 是一样的,加上‘m’后,有两个功能:1、“.”与“n”不匹配;2、插入符号(^)和美 元符号($)分别解释为源字符串中任何位置的任何行的开头和结尾,而不仅仅是整个源字符串的开 头或结尾。 • ’n’:“n”敏感,加上‘n’后,有两个功能“1、“.”与“n”不匹配;2、插入符号(^)和美元符 号($)分别解释为源字符串中任何位置的任何行的开头和结尾,而不仅仅是整个源字符串的开头或 结尾。 • ’x’:忽略空格字符。默认情况下,空格字符会相互匹配。 8.362 REGEXP_SPLIT_TO_ARRAY 用法: regexp_split_to_array(source, pattern, [, match_param]) 功能: regexp_split_to_array 函数使用一个 POSIX 正则表达式作为分隔符划分 source 来生成数组。 source 为输入源字符串,pattern 为正则表达式,match_param 可以改变匹配规则。 例子: 480 第 8 章 函数 select regexp_split_to_array('hello world', '\s+'); 8.363 REGEXP_SPLIT_TO_TABLE 用法: regexp_split_to_table(source, pattern, [, match_param]) 功能: regexp_split_to_table 函数使用一个 POSIX 正则表达式作为分隔符划分 source 来生成表格。 source 为输入源字符串,pattern 为正则表达式,match_param 可以改变匹配规则。 例子: select regexp_split_to_table('hello world', '\s+'); 8.364 REMAINDER 用法: remainder(n1 number, n2 number) 功能: 计算 n1 除以 n2 的余数。 例子: SELECT remainder(3.5, 2); 481 第 8 章 函数 8.365 REPEAT 用法: repeat(string text, number int) 功能: 函数返回将给定的字符串重复给定的次数后,得到的新字符串。 例子: 以下示例将给定字符串重复 3 遍: SELECT REPEAT('abc', 3) "REPEAT" FROM DUAL; +-----------+ | REPEAT | +===========+ | abcabcabc | +-----------+ 8.366 REPLACE 用法: replace(string text, from text, to text) 功能: REPLACE char 每次出现 search_string 替换为时返回 replacement_string。如果 replacement_string 省略或为 null,则 search_string 删除所有出现的。如果 search_string 为空,则 char 返回。 search_string 和 replacement_string, 以及, 都 char 可以是任何数据类型 CHAR, VARCHAR, NCHAR, NVARCHAR, CLOB, 或 NCLOB。返回的字符串与的字符集相同 char。VARCHAR 如果第一个参数不是 LOB,则函数返 回,如果第一个参数是 LOB,则返回 CLOB。 REPLACE 提供与该功能提供的功能相关的 TRANSLATE 功能。TRANSLATE 提供单字符的一对一替换。REPLACE 允许您用一个字符串替换另一个字符串以及删除字符串。 482 第 8 章 函数 例子: 以下示例替换出现的 Jwith BL: SELECT REPLACE('JACK and JUE','J','BL') "Changes" FROM DUAL; +----------------+ | Changes | +================+ | BLACK and BLUE | +----------------+ 8.367 REVERSE 用法: reverse(str) 功能: 函数返回将指定字符串反转后的新字符串。 例子: SELECT REVERSE('ABCDEF') "Changes" FROM DUAL; +----------------+ | Changes | +================+ | FEDCBA | +----------------+ 8.368 RIGHT 用法: right(string,count) 483 第 8 章 函数 功能: 获取给定字符串的从右向左数给定位数的子字符串。 例子: select right('abcde',2); +-----------+ | right | +===========+ | de | +-----------+ 8.369 ROUND 用法: round(date) round({dp|numeric}) round(v numeric, s int) 功能: 1. 参数为时间时 ROUND 返回 date 四舍五入到格式模型指定的单位 fmt。NLS_CALENDAR 该函数对会话参数不敏感。它按照 公历的规则运作。返回的值始终是数据类型 DATE,即使您为指定了不同的日期时间数据类型 date。如果省略 fmt, 则 date 四舍五入到最近的一天。date 表达式必须解析为一个 DATE 值。 也可参阅ROUND 和TRUNC 日期函数用于允许的格式模型 fmt。 484 第 8 章 函数 2. 参数为数字时 ROUND 返回 n 四舍五入到 integer 小数点右边的位置。如果省略 integer,则将 n 四舍五入到零位。如果 integer 为负数,则 n 舍入到小数点左侧。 n 可以是任何数值数据类型或任何可以隐式转换为数值数据类型的非数值数据类型。如果省略 integer,则函数返 回与 ROUND 的数值数据类型相同的数据类型的值 (n, 0) n。如果包含 integer,则函数返回 NUMBER。 ROUND 使用以下规则实现: • 如果 n 为 0,则 ROUND 始终返回 0,而不管 integer. • 如果 n 是负数,则 ROUND(n, integer) 返回 - ROUND(-n, integer)。 • 如果 n 是正数,那么 ROUND(n, integer) = FLOOR(n * POWER(10, integer) + 0.5) * POWER(10, -integer) • ROUND 应用于一个值可能与应用于以浮点表示的相同值的 NUMBER 结果略有不同。ROUND 不同的结果源 于 NUMBER 浮点值的内部表示的差异。如果出现差异,差异将在四舍五入的数字中为 1。 另请参阅: “浮点数”了解有关 KingbaseES 数据库如何处理 BINARY_FLOAT 和 BINARY_DOUBLE 取值的更多信息。 FLOOR 和 CEIL、TRUNC (number) 和 MOD 获取有关执行相关操作的功能的信息。 例子: 以下示例将日期舍入到下一年的第一天: SELECT ROUND (TO_DATE ('27-OCT-00'),'YEAR') "New Year" FROM DUAL; +-----------+ | New Year | +===========+ | 01-JAN-01 | +-----------+ 以下示例将数字四舍五入到小数点后一位: SELECT ROUND(15.193,1) "Round" FROM DUAL; +-------+ | Round | +=======+ | 15.2 | +-------+ 以下示例将数字四舍五入到小数点左侧: SELECT ROUND(15.193,-1) "Round" FROM DUAL; +-------+ 485 第 8 章 函数 | Round | +=======+ | 20 | +-------+ 8.370 ROW_COUNT(MySQL 模式) 用法: ROW_COUNT() 功能: 返回上一条语句的影响行数。 例子: create table test_t1(id int,name varchar(20)); CREATE TABLE insert into test_t1 values(1,'t1'),(2,'t2'),(3,'t3'),(4,'t4'),(5,'t5'),(6,'t6'); INSERT 0 6 create table test_t2 (like test_t1);select row_count(); CREATE TABLE row_count ----------0 (1 row) create table test_t3 as select * from test_t1;select row_count(); SELECT 6 row_count ----------6 (1 row) 8.371 ROW_NUMBER 用法: 486 第 8 章 函数 row_number() over([query_partition_clause,] order_by_clause) 功能: ROW_NUMBER 是解析函数, 用于为结果集中的每一行分配一个唯一的整数值,从 1 开始计数。 ROW_NUMBER 通过在检索 ROW_NUMBER 指定范围的值的查询中嵌套子查询,您可以从内部查询的结果 中找到精确的行子集。该函数的这种使用使您可以实现 top-N、bottom-N 和 inner-N 报告。为了获得一致的结果, 查询必须确保确定的排序顺序。 例子: 以下示例在 hr.employees 表中查找每个部门中薪酬最高的三名员工。对于少于三名员工的部门,返回少于三行。 SELECT department_id, first_name, last_name, salary FROM ( SELECT department_id, first_name, last_name, salary, ROW_NUMBER() OVER (PARTITION BY department_id ORDER BY salary desc) rn FROM employees ) WHERE rn <= 3 ORDER BY department_id, salary DESC, last_name; 8.372 ROW_TO_JSON 用法: row_to_json(record [, pretty_bool]) 功能: 把行作为一个 JSON 对象返回。如果 pretty_bool 为真,将在第 1 层元素之间增加换行。 例子: 487 第 8 章 函数 select row_to_json(row(1,'foo')); 8.373 RPAD 用法: rpad(string text, length int [, fill text]) 功能: RPAD 返回 expr1,用右填充长度 n 字符 expr2,根据需要复制多次。此函数对于格式化查询的输出很有用。 两者 expr1 和 expr2 都可以是任何数据类型 CHAR、VARCHAR、NCHAR、NVARCHAR、CLOB 或 NCLOB。VARCHAR 如果 expr1 是字符数据类型,NVARCHAR 如果 expr1 是国家字符数据类型,则返回的字符 串是数据类型,如果是 expr1LOB 数据类型,则返回 LOB。返回的字符串与的字符集相同 expr1。参数 n 必须是 NUMBER 整数或可以隐式转换为 NUMBER 整数的值。 expr1 不能为空。如果不指定 expr2,则默认为一个空白。如果 expr1 长于 n,则此函数返回 expr1 适合的部分 n。 参数 n 是显示在终端屏幕上的返回值的总长度。在大多数字符集中,这也是返回值中的字符数。但是,在某些多 字节字符集中,字符串的显示长度可能与字符串中的字符数不同。 例子: 以下示例通过用星号填充单个空格来创建一个简单的工资金额图表: SELECT last_name, RPAD(' ', salary/1000/1, '*') "Salary" FROM employees WHERE department_id = 80 ORDER BY last_name, "Salary"; +-----------+-------------+ | LAST_NAME | Salary | +===========+=============+ | Abel | ********** | +-----------+-------------+ | Ande | ***** | +-----------+-------------+ | Banda | ***** | +-----------+-------------+ | Bates | ****** | 488 第 8 章 函数 +-----------+-------------+ | Bernstein | ******** | +-----------+-------------+ | Bloom | ********* | +-----------+-------------+ | Cambrault | ********** | +-----------+-------------+ | Cambrault | ****** | +-----------+-------------+ | Doran | ****** | +-----------+-------------+ | Errazuriz | *********** | +-----------+-------------+ | Fox | ******** | +-----------+-------------+ | Greene | ******** | +-----------+-------------+ | Hall | ******** | +-----------+-------------+ | Hutton | ******* | +-----------+-------------+ | Johnson | ***** | +-----------+-------------+ | King | ********* | +-----------+-------------+ | . . . | | +-----------+-------------+ 8.374 ROWIDTOCHAR 用法: rowidtochar(rowid) 功能: 将一个 rowid 的类型转换为一个 text 类型,仅接受 rowid 或者能够合法转为 rowid 类型的数据或字段,返回一 个 text 类型,text 类型为 23 个 64 进制字符的字符串。 例子: 489 第 8 章 函数 test=# select rowidtochar(rowid) from tst1; rowidtochar ------------------------AAAAAAAAAAPiAAAAAAAAAAA (1 row) 8.375 RTRIM 用法: rtrim(string text [, characters text]) 功能: RTRIM 从字符串中出现的所有字符的右端删除 set。此函数对于格式化查询的输出很有用。 如果不指定 set,则默认为一个空白。RTRIM 工作原理与 LTRIM. 两者 char 和 set 都可以是任何数据类型 CHAR、VARCHAR、NCHAR、NVARCHAR、CLOB 或 NCLOB。 VARCHAR 如果 char 是字符数据类型,NVARCHAR 如果 char 是国家字符数据类型,则返回的字符串是数据类 型,如果是 charLOB 数据类型,则返回 LOB。 例子: 以下示例从字符串中删除所有最右边出现的小于号 ( <)、大于号 ( >) 和等号 ( ):= SELECT RTRIM('<=====>BROWNING<=====>', '<>=') "RTRIM Example" FROM DUAL; +-----------------+ | RTRIM Example | +=================+ | <=====>BROWNING | +-----------------+ 8.376 SCALE 用法: 490 第 8 章 函数 scale(numeric) 功能: SCALE 返回参数的精度(小数点后的位数)。 例子: SELECT scale(8.41); 8.377 SCORE 用法: SCORE(lable number) 功能: 在 SELECT 语句中使用 SCORE 函数返回 CONTAINS 查询生成的分数值。SCORE 操作符可以在 SELECT targetlist、ORDER BY 或 GROUP BY 子句中使用,但若 sql 中没有包含对应 label 参数的 contains 函数,则报 错。 参数说明: lable:指定标识 CONTAINS 操作生成的分数的标签,与 contains 函数对应,用于查找 contains 中计算的相关 程度评分。 返回值: 对于选定的每一行,通过查找 CONTAINS 中对应 label 的相关程度评分返回。 例子: select * from stest; id | name | adds ----+-------+-------------------1 | Tom | hebei shijiazhuang 2 | Toney | hebei zhangjiakou 3 | Lucy | henan luoyang 491 第 8 章 函数 4 | Jim | henan zhengzhou 5 | Jack | 6 | Bob | (6 rows) select id, name, score(10), score(20) from stest where CONTAINS (adds, 'hebei', 10) OR CONTAINS (adds, 'henan', 20) ORDER BY SCORE(10), SCORE(20); id | name | score | score ----+-------+------------+-----------3 | Lucy | 0 | 0.06079271 4 | Jim | 0 | 0.06079271 1 | Tom | 0.06079271 | 0 2 | Toney | 0.06079271 | 0 (4 rows) 另请参阅: CONTAINS 8.378 SECOND(MySQL 模式) 用法: second(n) 功能: 返回指定日期时间的秒值,参数为 NULL 时返回空。 参数说明: n:date、timestamp、time 等时间日期类型。 返回值: integer 类型,值域为 0 至 59。 例子: SELECT SECOND(DATE'2022-01-02') "SECOND"; SECOND -------------- 492 第 8 章 函数 0 SELECT SECOND(TIMESTAMP'2022-01-05 1:11:52') "SECOND"; SECOND -------------52 SELECT SECOND(TIME'2:12:22') "SECOND"; SECOND -------------22 8.379 SEC_TO_TIME(MySQL 模式) 用法: sec_to_time(n) 功能: 将参数 n 转换为时分秒格式并返回,参数为 NULL 时返回空。 参数说明: n:bigint、numeric 等数值类型、double。 precision 等浮点数类型、bool 类型。如参数超出 6 位的小数部分时,将其四舍五入为 6 位小数后再进行计算。 参数为 bool 类型时,转换为数值类型再进行计算。 返回值: interval 类型 例子: SELECT SEC_TO_TIME(100) "SEC_TO_TIME"; SEC_TO_TIME ------------00:01:40 493 第 8 章 函数 SELECT SEC_TO_TIME(100.123) "SEC_TO_TIME"; SEC_TO_TIME ------------00:01:40.123 SELECT SEC_TO_TIME(100.1234567) "SEC_TO_TIME"; SEC_TO_TIME ---------------00:01:40.123457 8.380 SESSION_ID 用法: session_id() 功能: SESSION_ID 返回当前会话的整数。 例子: 以下示例返回当前会话的整数: SELECT session_id(); +------------+ | session_id | +============+ | 4 | +------------+ 8.381 SESSION_USER 用法: 494 第 8 章 函数 session_user 功能: SESSION_USER 返回当前会话的用户名。返回类型为 NAME。 例子: 以下示例返回当前会话的用户名: SELECT session_user; +--------------+ | SESSION_USER | +==============+ | U1 | +--------------+ 8.382 SESSIONTIMEZONE 用法: sessiontimezone 功能: SESSIONTIMEZONE 返回当前会话的时区。返回类型是时区偏移量(格式为字符类型’[+|-]TZH:TZM’)或时区 区域名称,具体取决于用户如何在最近的 ALTER SESSION 语句中指定会话时区值。 注意: 即使客户端操作系统使用命名时区,默认客户端会话时区也是一个偏移量。如果您希望默认会话时区使用命名 时区,则将 ORA_SDTZ 客户端环境中的变量设置为 KingbaseES 时区区域名称。 例子: 以下示例返回当前会话的时区: 495 第 8 章 函数 SELECT sessiontimezone FROM DUAL; +---------+ | SESSION | +=========+ | -08:00 | +---------+ 8.383 SETSEED 用法: setseed(dp) 功能: 为后续要使用的 random 函数设置种子。 参数说明: dp:random 函数的种子值 (-1.0 和 1.0), 包括边界值。类型为 double precision。 例子: select setseed(0.12); setseed --------(1 row) 8.384 SETVAL 用法: SETVAL(regclass, bigint) 496 第 8 章 函数 功能: 设定指定序列的当前值。 参数说明: regclass:序列的名字。 bigint: 设置的值。 返回值: 返回设定值。 例子: SELECT setval('sequence_test'::text, 32); setval -------32 (1 row) 8.385 SETWEIGHT 用法: setweight(vector tsvector, weight "char") 功能: SETWEIGHT 为 vector 的每一个元素分配权重。 例子: SELECT setweight('fat:2,4 cat:3 rat:5B'::tsvector,'A'); 8.386 SHA224 用法: sha224(bytea) 497 第 8 章 函数 功能: SHA224 用于计算二进制字符串的 SHA-224 哈希值。 例子: 以下示例返回计算二进制字符串的 SHA-224 哈希值: SELECT SHA224('abc'::bytea); +------------------------------------------------------------+ | SHA224 | +============================================================+ | \x23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7 | +------------------------------------------------------------+ 8.387 SHA256 用法: sha256(bytea) 功能: SHA256 用于计算二进制字符串的 SHA-256 哈希值。 例子: 以下示例返回计算二进制字符串的 SHA-256 哈希值: SELECT SHA256('abc'::bytea); +--------------------------------------------------------------------+ | SHA256 | +====================================================================+ | \xba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad | +--------------------------------------------------------------------+ 498 第 8 章 函数 8.388 SHA384 用法: sha384(bytea) 功能: SHA384 用于计算二进制字符串的 SHA-384 哈希值。 例子: 以下示例返回计算二进制字符串的 SHA-384 哈希值: SELECT SHA384('abc'::bytea); +----------------------------------------------------------------------------------------------------+ | SHA384 | +====================================================================================================+ | \xcb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7 | +----------------------------------------------------------------------------------------------------+ 8.389 SHA512 用法: sha512(bytea) 功能: SHA512 用于计算二进制字符串的 SHA-512 哈希值。 例子: 以下示例返回计算二进制字符串的 SHA-512 哈希值: SELECT SHA512('abc'::bytea); +------------------------------------------------------------------------+ 499 第 8 章 函数 | SHA512 | +========================================================================+ | \xddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192 | | 992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f | +------------------------------------------------------------------------+ 8.390 SIGN 用法: sign({dp|numeric}) 功能: SIGN 返回的符号 n。此函数将任何数字数据类型或任何可以隐式转换为的非数字数据类型作为参数 NUMBER,并返回 NUMBER。 对于 NUMBER 类型的值,符号为: • -1 如果 n<0 • 0 如果 n= 0 • 1 如果 n>0 对于二进制浮点数 (BINARY_FLOAT 和 BINARY_DOUBLE),此函数返回数字的符号位。符号位是: • -1 如果 n<0 • +1 如果 n>=0 或 n=NaN 例子: 以下示例表明函数 ( -15) 的参数 <0: SELECT SIGN(-15) "Sign" FROM DUAL; +------+ | Sign | +======+ | -1 | +------+ 500 第 8 章 函数 8.391 SIN 用法: sin({dp|numeric}) 功能: SIN 返回(以弧度表示的角度)n 的正弦值。 此函数将任何数值数据类型或任何可以隐式转换为数值数据类型的非数值数据类型作为参数。如果参数是 BINARY_FLOAT,则函数返回 BINARY_DOUBLE。否则,函数返回与参数相同的数值数据类型。 例子: 以下示例返回 30 度的正弦值: SELECT SIN(30 * 3.14159265359/180) "Sine of 30 degrees" FROM DUAL; +--------------------+ | Sine of 30 degrees | +====================+ | .5 | +--------------------+ 8.392 SINH 用法: sinh({dp|numeric}) 功能: SINH 返回 n 的双曲正弦。 501 第 8 章 函数 此函数将任何数值数据类型或任何可以隐式转换为数值数据类型的非数值数据类型作为参数。如果参数是 BINARY_FLOAT,则函数返回 BINARY_DOUBLE。否则,函数返回与参数相同的数值数据类型。 例子: 以下示例返回 1 的双曲正弦: SELECT SINH(1) "Hyperbolic sine of 1" FROM DUAL; +----------------------+ | Hyperbolic sine of 1 | +======================+ | 1.17520119 | +----------------------+ 8.393 SPLIT_PART 用法: split_part(string text, delimiter text, field int) 功能: 函数返回给定字符串 expr1 中按给定字符 expr2 切分后的字符串数组中的第 n 个字符串。其中,指定返回的字符 串序号 n 必须大于 0 例子: 以下示例返回 3 平方: SELECT SPLIT_PART('joeuser@mydatabase','@m',2); +-------------+ | split_part | +=============+ | ydatabase | +-------------+ 502 第 8 章 函数 8.394 SQRT 用法: sqrt(n) 功能: SQRT 返回 n 的平方根。 此函数将任何数值数据类型或任何可以隐式转换为数值数据类型的非数值数据类型作为参数。该函数返回与参数 的数值数据类型相同的数据类型。 另请参阅: • 如果 n 解析为 a NUMBER,则该值 n 不能为负。SQRT 返回一个实数。 • 如果 n 解析为二进制浮点数(BINARY_FLOAT 或 BINARY_DOUBLE): • 如果 n>= 0,则结果为正。 • 如果 n= -0,则结果为 -0。 • 如果 n< 0,则结果为 NaN。 例子: 以下示例返回 26 的平方根: SELECT SQRT(26) "Square root" FROM DUAL; +-------------+ | Square root | +=============+ | 5.09901951 | +-------------+ 8.395 STATEMENT_TIMESTAMP 用法: statement_timestamp() 503 第 8 章 函数 功能: STATEMENT_TIMESTAMP 返回当前的日期和时间。返回类型为 timestamp with time zone。 例子: 以下示例返回当前的日期和时间: SELECT STATEMENT_TIMESTAMP(); +-------------------------------+ | STATEMENT_TIMESTAMP | +===============================+ | 2022-06-28 16:02:08.521282+00 | +-------------------------------+ 8.396 STDDEV 用法: STDDEV ([DISTINCT|ALL] expr) [over (analytic_clause)] 功能: STDDEV 返回一组数字 expr 的样本标准差。这是一组数字,您可以将其用作聚合函数和分析函数。它与 STDDEV_SAMP 的不同之处在于,当只有一行输入时 STDDEV 返回零,而 STDDEV_SAMP 返回 null 不同。 KingbaseES 数据库将标准差计算为为聚合函数 VARIANCE 定义的方差的平方根。 此函数将任何数值数据类型或任何可以隐式转换为数值数据类型的非数值数据类型作为参数。该函数返回与参数 的数值数据类型相同的数据类型。 如果您指定 DISTINCT,那么您只能指定 analytic_clause 字句的 query_partition_clause 字句。不允许使用 order_by_clause 字句和 windowing_clause 字句。 另请参阅: 504 第 8 章 函数 “分析函数”获取有关语法、语义和限制的信息。 聚集函数 、VARIANCE 和STDDEV_SAMP 。 SQL 表达式简介 以获取有关有效形式的信息 expr。 例子: • 聚合示例 以下示例返回样本 hr.employees 表中薪水的标准差: SELECT STDDEV(salary) "Deviation" FROM employees; +------------+ | Deviation | +============+ | 3909.36575 | +------------+ • 分析示例 以下示例中的查询返回样本表中 Department 80 工资的累积标准差,按以下 hr.employees 顺序排序 hire_date: SELECT last_name, salary, STDDEV(salary) OVER (ORDER BY hire_date) "StdDev" FROM employees WHERE department_ id = 30 ORDER BY last_name, salary, "StdDev"; +------------+--------+------------+ | LAST_NAME | SALARY | StdDev | +============+========+============+ | Baida | 2900 | 4035.26125 | +------------+--------+------------+ | Clomenares | 2500 | 3362.58829 | +------------+--------+------------+ | Himuro | 2600 | 3649.2465 | +------------+--------+------------+ | Khoo | 3100 | 5586.14357 | +------------+--------+------------+ | Raphaely | 11000 | 0 | +------------+--------+------------+ | Tobias | 2800 | 4650.0896 | +------------+--------+------------+ 8.397 STDDEV(MySQL 模式) 用法: 505 第 8 章 函数 STDDEV (expr) 功能: 聚合函数,计算所有非 NULL 输入值的总体标准差,并返回总体方差的平方根。 参数: expr 必输,列名或者表达式。 返回值: 返回所有非 NULL 输入值的总体标准差。 注意:stddev() 函数只处理那些非 NULL 的值, NULL 值会被 stddev() 函数忽略。 例子: select stddev(id) from (values(1),(2),(3),(100)) as t(id); stddev --------------------42.4411357058220109 8.398 STDDEV_POP 用法: STDDEV_POP (expr) [over (analytic_clause)] 功能: STDDEV_POP 计算总体标准差并返回总体方差的平方根。您可以将其用作聚合函数和分析函数。 此函数将任何数值数据类型或任何可以隐式转换为数值数据类型的非数值数据类型作为参数。该函数返回与参数 的数值数据类型相同的数据类型。 该函数与函数的平方根相同 VAR_POP。当 VAR_POP 返回 null 时,此函数返回 null。 另请参阅: 506 第 8 章 函数 “分析函数”获取有关语法、语义和限制的信息。 聚集函数 、VAR_POP 。 SQL 表达式简介 以获取有关有效形式的信息 expr。 例子: • 聚合示例 以下示例返回样本表中销售额的总体和样本标准差 sh.sales: SELECT STDDEV_POP(amount_sold) "Pop", STDDEV_SAMP(amount_sold) "Samp" FROM sales; +------------+------------+ | Pop | Samp | +============+============+ | 896.355151 | 896.355592 | +------------+------------+ • 分析示例 以下示例 hr.employees 按部门返回样本表中薪金的总体标准差: SELECT department_id, last_name, salary, STDDEV_POP(salary) OVER (PARTITION BY department_id) AS pop_std FROM employees ORDER BY department_id, last_name, salary, pop_std; +---------------+-----------+--------+------------+ | DEPARTMENT_ID | LAST_NAME | SALARY | POP_STD | +===============+===========+========+============+ | 10 | Whalen | 4400 | 0 | +---------------+-----------+--------+------------+ | 20 | Fay | 6000 | 3500 | +---------------+-----------+--------+------------+ | 20 | Hartstein | 13000 | 3500 | +---------------+-----------+--------+------------+ | 30 | Baida | 2900 | 3069.6091 | +---------------+-----------+--------+------------+ | 100 | Urman | 7800 | 1644.18166 | +---------------+-----------+--------+------------+ | 110 | Gietz | 8300 | 1850 | +---------------+-----------+--------+------------+ | 110 | Higgins | 12000 | 1850 | +---------------+-----------+--------+------------+ | | Grant | 7000 | 0 | +---------------+-----------+--------+------------+ 507 第 8 章 函数 8.399 STDDEV_SAMP 用法: STDDEV_SAMP (expr) [over (analytic_clause)] 功能: STDDEV_SAMP 计算累积样本标准差并返回样本方差的平方根。您可以将其用作聚合函数和分析函数。 此函数将任何数值数据类型或任何可以隐式转换为数值数据类型的非数值数据类型作为参数。该函数返回与参数 的数值数据类型相同的数据类型。 该函数与函数的平方根相同 VAR_SAMP。当 VAR_SAMP 返回 null 时,此函数返回 null。 另请参阅: “分析函数”获取有关语法、语义和限制的信息。 聚集函数 、VAR_SAMP 。 SQL 表达式简介 以获取有关有效形式的信息 expr。 例子: • 聚合示例 请参阅STDDEV_POP 的聚合示例。 • 分析示例 以下示例 employees 按部门返回表中薪水的样本标准差: SELECT department_id, last_name, hire_date, salary, STDDEV_SAMP(salary) OVER (PARTITION BY department_id ORDER BY hire_date ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS cum_sdev FROM employees ORDER BY department_id, last_name, hire_date, salary, cum_sdev; +---------------+------------+-----------+--------+------------+ | DEPARTMENT_ID | LAST_NAME | HIRE_DATE | SALARY | CUM_SDEV | +===============+============+===========+========+============+ | 10 | Whalen | 17-SEP-03 | 4400 | | +---------------+------------+-----------+--------+------------+ | 20 | Fay | 17-AUG-05 | 6000 | 4949.74747 | +---------------+------------+-----------+--------+------------+ | 20 | Hartstein | 17-FEB-04 | 13000 | | +---------------+------------+-----------+--------+------------+ 508 第 8 章 函数 | 30 | Baida | 24-DEC-05 | 2900 | 4035.26125 | +---------------+------------+-----------+--------+------------+ | 30 | Colmenares | 10-AUG-07 | 2500 | 3362.58829 | +---------------+------------+-----------+--------+------------+ | 30 | Himuro | 15-NOV-06 | 2600 | 3649.2465 | +---------------+------------+-----------+--------+------------+ | 30 | Khoo | 18-MAY-03 | 3100 | 5586.14357 | +---------------+------------+-----------+--------+------------+ | 30 | Raphaely | 07-DEC-02 | 11000 | | +---------------+------------+-----------+--------+------------+ | 100 | Greenberg | 17-AUG-02 | 12008 | 2126.9772 | +---------------+------------+-----------+--------+------------+ | 100 | Popp | 07-DEC-07 | 6900 | 1804.13155 | +---------------+------------+-----------+--------+------------+ | 100 | Sciarra | 30-SEP-05 | 7700 | 1929.76233 | +---------------+------------+-----------+--------+------------+ | 100 | Urman | 07-MAR-06 | 7800 | 1788.92504 | +---------------+------------+-----------+--------+------------+ | 110 | Gietz | 07-JUN-02 | 8300 | 2621.95194 | +---------------+------------+-----------+--------+------------+ | 110 | Higgins | 07-JUN-02 | 12008 | | +---------------+------------+-----------+--------+------------+ | | Grant | 24-MAY-07 | 7000 | | +---------------+------------+-----------+--------+------------+ 8.400 STR_TO_DATE 用法: STR_TO_DATE(str,format) 功能: 把字符串按照指定格式转换成时间戳。返回类型为 timestamp without time zone。 format 格式可以参考用于日期/时间格式化的模板模式 。 例子: 以下示例返回当前的日期和时间: 509 第 8 章 函数 select str_to_date('2022-03-14 13:14:15','yyyy-MM-dd hh24:mi:ss') from dual; str_to_date -----------------2022-03-14 13:14:15 8.401 STR_VALID 用法: str_valid(expr1 text, expr2 oid) 功能: STR_VALID 判断所给定的表达式是否为正确的日期时间。 参数说明: 参数列表有两个参数,第一个参数需要输入 text 类型字符串,第二个参数输入时间类型 OID。 例子: 以下示例判断所给定的表达式是否为正确的日期时间: SELECT STR_VALID('1981-10-19AD', CAST('DATE' AS REGTYPE)); +-----------+ | STR_VALID | +===========+ | t | +-----------+ 8.402 STRING_AGG 用法: string_agg(expr1, delimiter) 510 第 8 章 函数 功能: 非空输入连接成一个串,用 delimiter 分隔。 参数说明: expr1:用于聚集的表达式, 通常为列表达式。类型为 text 或者 bytea。 delimiter: 聚集表达式中间的分隔符。 返回值: 聚集后的 expr1 表达式。类型与 expr1 类型相同。 例子: SELECT string_agg(a,',') FROM (values('aaaa'),('bbbb'),('cccc')) g(a); string_agg ---------------aaaa,bbbb,cccc (1 row) 8.403 STRING_TO_ARRAY 用法: STRING_TO_ARRAY(expr1,delimiter [,null_expr]) 功能: 使用提供的分隔符将和可选的空串字符划分成数组元素。 参数说明: expr1:用于组成数组元素的表达式,通常为列表达式。或者常量表达式。 delimiter: expr1 中的各数组元素的分隔符。 null_expr: expr1 中的 null 元素等价符。 返回值: 511 第 8 章 函数 expr1 转换后的数组。 例子: SELECT string_to_array('1,2,3,4,*,6', ',', '*'); string_to_array -----------------{1,2,3,4,NULL,6} (1 row) 8.404 STRIP 用法: strip(tsvector) 功能: STRIP 返回删除位置和权重后的 tsvector 。返回类型为 tsvector。 例子: 以下示例返回删除位置和权重后的 tsvector : SELECT STRIP('fat:2,4 cat:3 rat:5A'::tsvector); +-------------------+ | STRIP | +===================+ | 'cat' 'fat' 'rat' | +-------------------+ 8.405 STRPOS 用法: strpos(expr1,expr2) 512 第 8 章 函数 功能: 函数返回字符串 expr1 中,第一次出现 expr2 字符串的起始位置。 例子: SELECT STRPOS('abcdefgb','de'); +-----------------+ | strpos | +=================+ | 4 | +-----------------+ 8.406 SUBSTR 用法: [ SUBSTR |SUBSTRB |SUBSTRC |SUBSTR2 |SUBSTR4 ] ( char , position [, substring_length] ) 功能: 这些 SUBSTR 函数返回的一部分 char,从字符开始 position,substring_length 字符长。SUBSTR 使用输入字 符集定义的字符计算长度。SUBSTRB 使用字节而不是字符。SUBSTRC 使用 Unicode 完整字符。SUBSTR2 使用 UCS2 代码点。SUBSTR4 使用 UCS4 代码点。 参数说明: • 如果 position 为 0,则将其视为 1。 • 如果 position 为正,则 KingbaseES 数据库从头开始计数 char 以查找第一个字符。 • 如果 position 为负数,则 KingbaseES 从末尾倒数 char。 513 第 8 章 函数 • 如果 substring_length 省略,则 KingbaseES 将所有字符返回到 char. 如果 substring_length 小于 1,则 KingbaseES 返回 null。 char 可以是任何数据类型 CHAR, VARCHAR, NCHAR, NVARCHAR, CLOB, 或 NCLOB. 例外是 SUBSTRC,SUBSTR2 和 SUBSTR4, 不允许 char 是 CLOBor NCLOB。两者 position 和都 substring_length 必须是数 据类型 NUMBER,或者任何可以隐式转换为的数据类型 NUMBER,并且必须解析为整数。返回值与的数据类型相 同 char,除了 CHAR 参数返回一个 VARCHAR 值,而 NCHAR 参数 NVARCHAR 返回一个值。作为参数传递的浮 点数 SUBSTR 会自动转换为整数。 例子: 以下示例返回“ABCDEFG”的几个指定子字符串: SELECT SUBSTR('ABCDEFG',3,4) "Substring" FROM DUAL; +-----------+ | Substring | +===========+ | CDEF | +-----------+ SELECT SUBSTR('ABCDEFG',-5,4) "Substring" FROM DUAL; +-----------+ | Substring | +===========+ | CDEF | +-----------+ Assume a double-byte database character set: SELECT SUBSTRB('ABCDEFG',5,4.2) "Substring with bytes" FROM DUAL; +----------------------+ | Substring with bytes | +======================+ | CD | +----------------------+ 8.407 SUBSTRB 用法: 514 第 8 章 函数 [ SUBSTR |SUBSTRB |SUBSTRC |SUBSTR2 |SUBSTR4 ] ( char , position [, substring_length] ) 功能: 这些 SUBSTR 函数返回的一部分 char,从字符开始 position,substring_length 字符长。SUBSTR 使用输入字 符集定义的字符计算长度。SUBSTRB 使用字节而不是字符。SUBSTRC 使用 Unicode 完整字符。SUBSTR2 使用 UCS2 代码点。SUBSTR4 使用 UCS4 代码点。 参数说明: • 如果 position 为 0,则将其视为 1。 • 如果 position 为正,则 KingbaseES 数据库从头开始计数 char 以查找第一个字符。 • 如果 position 为负数,则 KingbaseES 从末尾倒数 char。 • 如果 substring_length 省略,则 KingbaseES 将所有字符返回到 char. 如果 substring_length 小于 1,则 KingbaseES 返回 null。 char 可以是任何数据类型 CHAR, VARCHAR, NCHAR, NVARCHAR, CLOB, 或 NCLOB. 例外是 SUBSTRC,SUBSTR2 和 SUBSTR4, 不允许 char 是 CLOBor NCLOB。两者 position 和都 substring_length 必须是数 据类型 NUMBER,或者任何可以隐式转换为的数据类型 NUMBER,并且必须解析为整数。返回值与的数据类型相 同 char,除了 CHAR 参数返回一个 VARCHAR 值,而 NCHAR 参数 NVARCHAR 返回一个值。作为参数传递的浮 点数 SUBSTR 会自动转换为整数。 例子: 以下示例返回“ABCDEFG”的几个指定子字符串: SELECT SUBSTRB('ABCDEFG',3,4) "Substring" FROM DUAL; Substring --------------------CDEF SELECT SUBSTRB('ABCDEFG',-5,4) "Substring" FROM DUAL; 515 第 8 章 函数 Substring --------------------CDEF 8.408 SUBSTRING 用法: substring(string [from int] [for int]) 功能: 返回从字符串指定位置开始截取的子字符串。 参数说明: string:要截取子字符串的字符串。 from:整数类型,用于指定子串的起始位置。 for:用于指定截取子串的字符数。 例子: 以下示例返回“ABCDEFG”的几个指定子字符串: SELECT SUBSTRING('ABCDEFG',3,4) "Substring" FROM DUAL; Substring --------------------CDEF SELECT SUBSTRING('ABCDEFG',-5,4) "Substring" FROM DUAL; Substring --------------------- 516 第 8 章 函数 8.409 SUBSTRING_INDEX(MySQL 模式) 用法: substring_index(str,delimiter,count) 功能: substring_index 函数返回在分隔符 delimiter 出现计数 count 之前字符串 str 中的子字符串。 • 如果 count 为正,则返回最后定界符左边的所有内容(从左侧开始计数,计数的起始值为 1)。 • 如果 count 为负,则返回最后定界符右侧的所有内容(从右则开始计数,计数的起始值为 1) • 如果 count 为 0 或超过 int32 的范围,则返回空串。 str,delimiter 可以是 BPCHAR,VARCHAR,TEXT 或 CLOB。count 必须是数据类型 NUMBER,或者任何 可以隐式转换为的数据类型 NUMBER,并且必须解析为整数。返回值的数据类型与 str 的类型相同。 例子: 以下示例返回指定子字符串: SELECT SUBSTRING_INDEX('abc,ABC,bcd,BCD','bc',2) "Substring_index"; Substring_index --------------------abc,ABC, SELECT SUBSTRING_INDEX('中华人民共和国华北地区','华',-2.45) "Substring_index"; Substring_index --------------------人民共和国华北地区 8.410 SUBTIME(MySQL 模式) 用法: subtime(n1,n2) 功能: 517 第 8 章 函数 返回日期时间 n1 中减去时间 n2 的差值。 参数和返回值说明: 函数返回值由参数类型决定,详见下表: 表 8.410.1: SUBTIME-PARAMETER 参数 n1 参数 n2 返回值 date time timestamp interval timestamp time interval time interval interval time time time interval interval 参数范围及返回结果说明如下: 表 8.410.2: SUBTIME-PARAMETER-RANGE 参数 类型 值域 输出结果 n1 date 4713 BC 至 5874897 AD 正常输出 timestamp 4713 BC 至 294276 AD time -838:59:59 到 838:59:59 interval -178000000 年至 178000000 年 返回空 NULL n2 空值 无 报错 time -838:59:59 到 838:59:59 正常输出 interval -178000000 年至 178000000 年 报错 NULL 空值 无 见续表 518 第 8 章 函数 表 8.410.2 – 续表 参数 类型 值域 输出结果 其他类型 注意: 当参数 n1 为 date 日期类型时,若未指定时间部分,时间值默认为“00:00:00”。 例子: SELECT SUBTIME(date'2020-01-01',time'12:00:00') "SUBTIME"; SUBTIME --------------------2019-12-31 12:00:00 SELECT SUBTIME(timestamp'2020-01-01 12:00:00',interval'1 02:00:00') "SUBTIME"; SUBTIME --------------------2019-12-30 22:00:00 SELECT SUBTIME(time'12:00:00',time'02:00:00') "SUBTIME"; SUBTIME --------------------10:00:00 SELECT SUBTIME(interval'1 01:00:00',interval'1 02:00:00') "SUBTIME"; SUBTIME ------------01:00:00 8.411 SUM 用法: 519 第 8 章 函数 sum(expression) 功能: SUM 返回非空输入值的和。 参数和返回值说明: • 如果输入值为 smallint 类型或者 integer 类型时,返回类型为 bigint。 • 如果输入值为 bigint 类型或者 numeric 类型时,返回类型为 numeric。 • 如果输入值类型为 real、double precision、interval(yminterval、dsinterval) 或 money 时,返回类型与输入类型 相同。 • 如果输入值为 varchar 类型或 char 类型或 text 类型时,返回类型为 float8。 例子: 以下示例返回非空输入值的和: SELECT x, SUM(y) FROM test1 GROUP BY x HAVING sum(y) > 3; +---+-----+ | x | SUM | +===+=====+ | a | 4 | +---+-----+ | b | 5 | +---+-----+ 8.412 SUPPRESS_REDUNDANT_UPDATES_TRIGGER 用法: suppress_redundant_updates_trigger() 功能: 520 第 8 章 函数 SUPPRESS_REDUNDANT_UPDATES_TRIGGER 函数是一个内置的触发器函数,它将阻止任何不会实际更 改行中数据的更新发生,这与正常的行为不管数据是否改变始终执行更新相反。冗余更新会花费大量不必要的时间, 尤其是当如果有大量索引要改变时。SUPPRESS_REDUNDANT_UPDATES_TRIGGER 可以跳过不改变数据的更 新。但需要注意的是,触发器需要很短但不能忽略的时间来处理每条记录,所以如果大多数被一个更新影响的记录确 实被更改,此触发器的使用将实际上使更新运行得更慢。 例子: CREATE TRIGGER test_tri BEFORE UPDATE ON tablename FOR EACH ROW EXECUTE FUNCTION suppress_redundant_updates_trigger(); 8.413 SYS_BACKEND_PID 用法: sys_backend_pid() 功能: SYS_BACKEND_PID 返回附加到当前会话的服务器进程的进程 ID。 例子: 以下示例返回附加到当前会话的服务器进程的进程 ID: SELECT SYS_BACKEND_PID(); +-----------------+ | SYS_BACKEND_PID | +=================+ | 178263 | +-----------------+ 8.414 SYS_CANCEL_BACKEND 用法: 521 第 8 章 函数 sys_cancel_backend(pid int) 功能: SYS_CANCEL_BACKEND 用于取消对具有指定进程 ID 的后端进程的会话的当前查询。 注意: 1. 如果调用的用户是其后端正在被取消的角色的成员,或者调用的角色已被授予 SYS_SIGNAL_BACKEND,则 也允许操作。 2. 只有超级用户可以取消超级用户的后端。 例子: 以下示例取消对具有指定进程 ID 的后端进程的会话的当前查询: SELECT SYS_CANCEL_BACKEND(458343); +--------------------+ | SYS_CANCEL_BACKEND | +====================+ | t | +--------------------+ 8.415 SYS_COLUMN_SIZE 用法: sys_column_size(any) 功能: SYS_COLUMN_SIZE 返回用于存储任何单个数据值的字节数。 如果直接应用于表的列值,则将反映所做的任何压缩。 例子: 522 第 8 章 函数 以下示例返回用于存储任何单个数据值的字节数: SELECT SYS_COLUMN_SIZE('abc'); +-----------------+ | SYS_COLUMN_SIZE | +=================+ | 4 | +-----------------+ 8.416 SYS_CONTEXT 用法: sys_context(namespace text, parameter text, length int default 256) 功能: SYS_CONTEXT 返回当前时刻与上下文命名空间相关联的 parameter 的值。可以在 SQL 和 PL/SQL 语句中使 用该函数。SYS_CONTEXT 必须在本地执行。 参数说明: namespace:已创建的 namespace,不区分大小写,如果不存在,则返回空。 parameter:namespace 中的属性,不区分大小写,如果不存在,则报错;最大长度 30bytes。 length:length 为 INT 类型,最大值为 4000,即返回字符串最大长度为 4000 字节;如果指定的 length 值非法, 则忽略该值,而使用默认值 256。 返回值: 函数返回值类型为 varchar(256),如果返回值超过 256 字节,则需要设置 length。 例子: SELECT SYS_CONTEXT ('USERENV', 'CURRENT_SCHEMA') FROM DUAL; sys_context ------------public (1 row) 523 第 8 章 函数 8.417 SYS_DATABASE_SIZE 用法: sys_database_size({oid|name}) 功能: SYS_DATABASE_SIZE 返回指定名称或 OID 的数据库使用的总磁盘空间。返回类型为 bigint。 要使用此功能,您必须对指定的数据库有连接权限,或者您是 sys_read_all_stats 角色的成员。 输入值可以是数据库名,也可以是数据库的 OID。 例子: 以下示例返回用于存储任何单个数据值的字节数: SELECT SYS_DATABASE_SIZE('test'); +-------------------+ | SYS_DATABASE_SIZE | +===================+ | 13004643 | +-------------------+ SELECT SYS_DATABASE_SIZE(16173); +-------------------+ | SYS_DATABASE_SIZE | +===================+ | 13004643 | +-------------------+ 8.418 SYS_EVENT_TRIGGER_DDL_COMMANDS 用法: 524 第 8 章 函数 sys_event_trigger_ddl_commands() 功能: sys_event_trigger_ddl_commands 函数在在命令结束处捕捉更改。当在一个 ddl_command_end 事件触发器的 函数中调用时,sys_event_trigger_ddl_commands 返回被每一个用户动作执行的 DDL 命令的列表。如果在其他任 何环境中调用这个函数,会发生错误。sys_event_trigger_ddl_commands 为每一个被执行的基本命令返回一行,某 些只有一个单一 SQL 句子的命令可能会返回多于一行。 返回值说明: 表 8.418.1: sys_event_trigger_ddl_commands 函数返回值 名称 类型 描述 classid oid 对象所属的目录的 OID objid oid 对象本身的 OID objsubid integer 对象的子 id(例如列的属性号) command_tag text 命令标签 object_type text 对象的类型 schema_name text 该对象所属的模式的名称 object_identity text 对象标识的文本表现形式,用模式限定。如果 必要,出现在该标识中的每一个标识符都会被 引用。 in_extension bool 如果该命令是一个扩展脚本的一部分则为真。 command sys_ddl_command 以内部格式表达的该命令的一个完整表现形 式。这不能被直接输出,但是可以把它传递给 其他函数来得到有关于该命令不同部分的信 息。 525 第 8 章 函数 8.419 SYS_EVENT_TRIGGER_DROPPED_OBJECTS 用法: sys_event_trigger_dropped_objects() 功能: sys_event_trigger_dropped_objects 函数处理被 DDL 命令删除的对象,返回其 sql_drop 事件中命令所删除的 所有对象的列表。如果在任何其他环境中被调用,将抛出一个错误。 返回值说明: 526 第 8 章 函数 表 8.419.1: sys_event_trigger_ddl_commands 函数返回值 名称 类型 描述 classid oid 对象所属的目录的 OID objid oid 对象本身的 OID objsubid integer 对象的子 ID(如列的属性号) original bool 如果这是删除中的一个根对象则为真 normal bool 指示在依赖图中有一个普通依赖关系指向该对 象的标志 is_temporary bool 如果该对象是一个临时对象则为真 object_type text 对象的类型 schema_name text 对象所属模式的名称 object_name text 如果模式和名称的组合能被用于对象的一个唯 一标识符,则是对象的名称;否则是 NULL。 不应用引用,并且名称不是模式限定的。 object_identity text 对象身份的文本表现,模式限定的。每一个以 及所有身份中出现的标识符在必要时加引号。 address_names text[] 一 个 数 组, 它 可 以 和 object_type 及 address_args 一 起 通 过 sys_get_object_address() 函数在一台包含 有同类相同名称对象的远程服务器上重建该对 象地址。 address_args text[] 上述 address_names 的补充。 例子: CREATE FUNCTION test_event_trigger_for_drops() RETURNS event_trigger LANGUAGE plsql AS $$ DECLARE obj record; BEGIN FOR obj IN SELECT * FROM sys_event_trigger_dropped_objects() LOOP RAISE NOTICE '% dropped object: % %.% %', tg_tag, obj.object_type, 527 第 8 章 函数 obj.schema_name, obj.object_name, obj.object_identity; END LOOP; END $$; CREATE EVENT TRIGGER test_event_trigger_for_drops ON sql_drop EXECUTE FUNCTION test_event_trigger_for_drops(); 8.420 SYS_EVENT_TRIGGER_TABLE_REWRITE_OID 用法: sys_event_trigger_table_rewrite_oid() 功能: sys_event_trigger_table_rewrite_oid 函数提供刚刚被调用过的 table_rewrite 事件的表的 oid 信息。 返回值说明: oid,要被重写的表的 OID。 例子: CREATE FUNCTION test_event_trigger_table_rewrite_oid() RETURNS event_trigger LANGUAGE plsql AS $$ BEGIN RAISE NOTICE 'rewriting table % for reason %', sys_event_trigger_table_rewrite_oid()::regclass, sys_event_trigger_table_rewrite_reason(); END; $$; CREATE EVENT TRIGGER test_table_rewrite_oid ON table_rewrite EXECUTE FUNCTION test_event_trigger_table_rewrite_oid(); 528 第 8 章 函数 8.421 SYS_EVENT_TRIGGER_TABLE_REWRITE_REA 用法: sys_event_trigger_table_rewrite_reason() 功能: sys_event_trigger_table_rewrite_reason 函数提供刚刚被调用过的 table_rewrite 事件的表的信息。 返回值说明: int 类型,解释重写原因的代码。 例子: 参见SYS_EVENT_TRIGGER_TABLE_REWRITE_OID 函数的示例。 8.422 SYS_STAT_FILE 用法: sys_stat_file(filename text[, missing_ok boolean]) 功能: 返回关于一个文件/目录的统计信息。默认仅限于超级用户使用,但是可以给其他用户授予 EXECUTE 让他们运 行这个函数。 例子: SELECT * from sys_stat_file('base',true); SIZE | ACCESS | MODIFICATION | CHANGE | CREATION | ISDIR ------+------------------------+------------------------+------------------------+----------+------- 529 第 8 章 函数 131 | 2022-06-27 14:14:02+08 | 2022-06-17 20:39:48+08 | 2022-06-17 20:39:48+08 | | t (1 row) 8.423 SYS_READ_BINARY_FILE 用法: sys_read_binary_file(filename text [, offset bigint, length bigint [, missing_ok boolean] ]) 功能: 返回一个二进文件的内容。默认仅限于超级用户使用,但是可以给其他用户授予 EXECUTE 让他们运行这个函 数。 例子: SELECT sys_read_binary_file('11.bin'); SELECT sys_read_binary_file('11.bin',0,1024,true); 8.424 SYS_READ_FILE 用法: sys_read_file(filename text [, offset bigint, length bigint [, missing_ok boolean] ]) 功能: 530 第 8 章 函数 返回一个文件的内容。默认仅限于超级用户使用,但是可以给其他用户授予 EXECUTE 让他们运行这个函数。 例子: SELECT sys_read_binary_file('11.txt'); SELECT sys_read_binary_file('11.txt',10,1024,true); 8.425 SYS_TERMINATE_BACKEND 用法: sys_terminate_backend(pid int) 功能: 中止一个后端。如果调用角色是被取消后端的拥有者角色的成员或者调用角色已经被授予 sys_signal_backend, 这也是允许的,不过只有超级用户才能取消超级用户的后端。 例子: SELECT sys_terminate_backend(134245); SYS_TERMINATE_BACKEND ----------------------t (1 row) 8.426 SYS_TOTAL_RELATION_SIZE 用法: sys_total_relation_size (oid bigint) 功能: 指定表所用的总磁盘空间,包括所有的索引和 TOAST 数据。 531 第 8 章 函数 例子: SELECT sys_total_relation_size (1259); SYS_TOTAL_RELATION_SIZE ------------------------442368 (1 row) 8.427 SYS_FUNCTION_IS_VISIBLE 用法: sys_function_is_visible(function_oid) 功能: 判断函数在搜索路径中是否可见。 例子: \set SQLTERM / CREATE OR REPLACE FUNCTION increment(i INTEGER) RETURNS INTEGER AS BEGIN RETURN i + 1; END; / \set SQLTERM ; select oid from sys_proc where proname = 'increment'; oid ------46531 (1 row) SELECT sys_function_is_visible(46531); sys_function_is_visible ------------------------- 532 第 8 章 函数 t (1 row) 8.428 SYS_GET_CONSTRAINTDEF 用法: sys_get_constraintdef(constraint_oid) sys_get_constraintdef(constraint_oid, pretty_bool) 功能: 获得对应约束的定义。pretty_bool 为真则为优质打印方式。 例子: create table products ( product_no integer, name text, price numeric constraint positive_price check (price > 0) ); select oid from sys_constraint where conname = 'psitive_price'; oid ------247537 (1 row) SELECT sys_get_constraintdef(247537); sys_get_constraintdef -------------------------------CHECK ((price > (0)::numeric)) (1 row) 533 第 8 章 函数 SELECT sys_get_constraintdef(247537, false); sys_get_constraintdef -------------------------------CHECK ((price > (0)::numeric)) (1 row) 8.429 SYS_GET_EXPR 用法: sys_get_expr(sys_node_tree, relation_oid) sys_get_expr(sys_node_tree, relation_oid, pretty_bool) 功能: 反编译一个表达式的内部形式,假定其中的任何 Var 指向由第二个参数指示的关系。pretty_bool 为真则为优质 打印方式。 例子: select oid from sys_attrdef limit 1; oid ------16485 (1 row) \set SQLTERM / declare r record; a text; begin select * into r from sys_attrdef where oid = 16485; a = sys_get_expr(r.adbin, r.adrelid); RAISE NOTICE 'a = %', a; end; 534 第 8 章 函数 NOTICE: a = nextval('mytest_id_seq'::regclass) \set SQLTERM / declare r record; a text; begin select * into r from sys_attrdef where oid = 16485; a = sys_get_expr(r.adbin, r.adrelid, true); RAISE NOTICE 'a = %', a; end; NOTICE: a = nextval('mytest_id_seq'::regclass) 8.430 SYS_GET_FUNCTION_ARGUMENTS 用法: sys_get_function_arguments(func_oid) 功能: 获得一个函数或过程定义的参数列表(带有默认值)。 例子: \set SQLTERM / CREATE OR REPLACE FUNCTION increment(i INTEGER) RETURNS INTEGER AS BEGIN RETURN i + 1; END; / \set SQLTERM ; select oid from sys_proc where proname = 'increment'; oid ------- 535 第 8 章 函数 46531 (1 row) SELECT sys_get_function_arguments(46531); sys_get_function_arguments ---------------------------i integer (1 row) 8.431 SYS_GET_FUNCTION_IDENTITY_ARGUMENTS 用法: sys_get_function_identity_arguments (func_oid) 功能: 获得标识一个函数或过程的参数列表(不带默认值)。 例子: \set SQLTERM / CREATE OR REPLACE FUNCTION increment(i INTEGER) RETURNS INTEGER AS BEGIN RETURN i + 1; END; / \set SQLTERM ; select oid from sys_proc where proname = 'increment'; oid ------46531 (1 row) SELECT sys_get_function_identity_arguments (46531); 536 第 8 章 函数 sys_get_function_identity_arguments ------------------------------------i integer (1 row) 8.432 SYS_GET_FUNCTION_RESULT 用法: sys_get_function_result(func_oid) 功能: 获得函数的 RETURNS 子句(对过程返回空)。 例子: \set SQLTERM / CREATE OR REPLACE FUNCTION increment(i INTEGER) RETURNS INTEGER AS BEGIN RETURN i + 1; END; / \set SQLTERM ; select oid from sys_proc where proname = 'increment'; oid ------46531 (1 row) SELECT sys_get_function_result(46531); sys_get_function_result ------------------------integer (1 row) 537 第 8 章 函数 8.433 SYS_GET_FUNCTIONDEF 用法: sys_get_functiondef(func_oid) 功能: 获得一个函数或过程的定义。 例子: \set SQLTERM / CREATE OR REPLACE FUNCTION increment(i INTEGER) RETURNS INTEGER AS BEGIN RETURN i + 1; END; / \set SQLTERM ; select oid from sys_proc where proname = 'increment'; oid ------46531 (1 row) SELECT sys_get_functiondef(46531); sys_get_functiondef -------------------------------------------------------CREATE OR REPLACE FUNCTION public.increment(i integer)+ RETURNS integer + AS + BEGIN + RETURN i + 1; END + + (1 row) 538 第 8 章 函数 8.434 SYS_GET_INDEXDEF 用法: sys_get_indexdef(index_oid) sys_get_indexdef(index_oid, column_no, pretty_bool) 功能: 根据参数不同。 • 获得索引的 CREATE INDEX 命令。 • 获得索引的 CREATE INDEX 命令,或者当 column_no 为非零时, 只得到一个索引列的定义。 例子: create table films( id int, title text ); CREATE UNIQUE INDEX title_idx ON films (title); select oid from sys_class where relname = 'title_idx'; oid -------247564 (1 row) SELECT sys_get_indexdef(247564); sys_get_indexdef ------------------------------------------------------------------CREATE UNIQUE INDEX title_idx ON public.films USING btree (title) (1 row) SELECT sys_get_indexdef(247564, 0, true); sys_get_indexdef 539 第 8 章 函数 ------------------------------------------------------------------CREATE UNIQUE INDEX title_idx ON public.films USING btree (title) (1 row) 8.435 SYS_GET_KEYWORDS 用法: sys_get_keywords() 功能: 获得 SQL 关键字的列表及其分类。 例子: 以下示例为查询 SQL 关键字的列表及其分类。 select sys_get_keywords(); sys_get_keywords -----------------------------------------------------------------(abort,U,unreserved) (absolute,U,unreserved) (access,U,unreserved) (account,U,unreserved) (action,U,unreserved) (add,U,unreserved) ... ... (569 rows) 8.436 SYS_GET_OBJECT_ADDRESS 用法: sys_get_object_address(type text, name text[], args text[]) 540 第 8 章 函数 功能: 从一个数据库对象的内部表示得到它的地址。 sys_get_object_address 返回一行,其中包含有足以唯一标识由类型、对象名和参数数组指定的数据库对 象的信息。返回值可以被用在诸如 sys_depend 等系统目录中并且可以被传递给 sys_identify_object 或 sys_describe_object 等其他系统函数。“class_id“是包含该对象的系统目录 OID;“objid“是对象本身的 OID,而 “objsubid“是子对象 ID,如果没有则为零。这个函数是 sys_identify_object_as_address 的逆函数。 例子: 以下示例为查找 func_test 函数的内部地址。 \set SQLTERM / create function func_test(i int) return int as begin raise notice 'in func'; return 1; end; / \set SQLTERM ; select sys_get_object_address('function','{public,func_test}','{int}'); sys_get_object_address ----------------------(1255,41016,0) (1 row) 8.437 SYS_GET_RULEDEF 用法: sys_get_ruledef(rule_oid) sys_get_ruledef(rule_oid, pretty_bool) 功能: 重建规则的创建命令。 541 第 8 章 函数 例子: 以下示例为重建”_RETURN” 规则。 \set SQLTERM ; create table t1 (i int); insert into t1 values(10); create table t2 (i int); CREATE RULE "_RETURN" AS ON SELECT TO t2 DO INSTEAD SELECT * FROM t1; select sys_get_ruledef((select oid from sys_rewrite where rulename = '_return' and ev_class= (select oid from sys_class where relname='t2'))); sys_get_ruledef ---------------------------------------------------CREATE RULE _return AS + ON SELECT TO public.t2 DO INSTEAD SELECT t1.i+ FROM t1; (1 row) select sys_get_ruledef((select oid from sys_rewrite where rulename = '_return' and ev_class= (select oid from sys_class where relname='t2')), true); sys_get_ruledef --------------------------------------------CREATE RULE _return AS ON SELECT TO t2 DO INSTEAD + SELECT t1.i+ FROM t1; (1 row) select sys_get_ruledef((select oid from sys_rewrite where rulename = '_return' and ev_class= (select oid from sys_class where relname='t2')), false); sys_get_ruledef ---------------------------------------------------CREATE RULE _return AS ON SELECT TO public.t2 DO INSTEAD + SELECT t1.i+ FROM t1; (1 row) 542 第 8 章 函数 8.438 SYS_GET_SERIAL_SEQUENCE 用法: sys_get_serial_sequence(table_name, column_name) 功能: 获得一个序列列或标识列使用的序列的名称。 sys_get_serial_sequence 返回与一个列相关联的序列的名称,如果与列相关联的序列则返回 NULL。如果该 列是一个标识列,相关联的序列是为该标识列内部创建的序列。 对于使用序列类型之一(serial、smallserial、bigserial)创建的列,它是为那个序列列定义创建的序列。 在 后 一 种 情 况 中, 这 种 关 联 可 以 用 ALTER SEQUENCE OWNED BY 修 改 或 者 移 除 (该 函 数 可 能 应 该 已 经 被 sys_get_owned_sequence 调用,它当前的名称反映了它通常被 serial 或 bigserial 列使用)。 第一个输入参数是一个带可选模式的表名,第二个参数是一个列名。因为第一个参数可能是一个模式和表,它不 能按照一个双引号包围的标识符来对待,意味着它默认情况下是小写的。 而第二个参数只是一个列名,将被当作一个双引号包围的来处理并且会保留其大小写。函数返回的值会被适当地 格式化以便传递给序列函数(参见 序列操作函数)。 一种典型的用法是为标识列或者序列列读取当前值,例如: 例子: 一种典型的用法是为标识列或者序列列读取当前值。 \set SQLTERM ; CREATE TABLE serialTest1 (f1 text, f2 serial); INSERT INTO serialTest1 VALUES ('foo'); INSERT INTO serialTest1 VALUES ('bar'); INSERT INTO serialTest1 VALUES ('force', 100); SELECT * FROM serialTest1; SELECT currval(sys_get_serial_sequence('serialTest1', 'f2')); currval --------2 (1 row) 543 第 8 章 函数 SELECT sys_get_serial_sequence('serialTest1', 'f2'); sys_get_serial_sequence --------------------------public.serialtest1_f2_seq (1 row) 8.439 SYS_GET_STATISTICSOBJDEF 用法: sys_get_statisticsobjdef(statobj_oid) 功能: 重建一个扩展统计对象的创建命令(CREATE STATISTICS 命令)。 例子: 以下示例为重建扩展统计对象命令。 \set SQLTERM ; CREATE TABLE ab1 (a INTEGER, b INTEGER, c INTEGER); CREATE STATISTICS IF NOT EXISTS ab1_a_b_stats ON a, b FROM ab1; CREATE SCHEMA regress_schema_2; CREATE STATISTICS regress_schema_2.ab1_a_b_stats ON a, b FROM ab1; SELECT sys_get_statisticsobjdef(oid) FROM sys_statistic_ext WHERE stxname = 'ab1_a_b_stats'; sys_get_statisticsobjdef ------------------------------------------------------------------CREATE STATISTICS public.ab1_a_b_stats ON a, b FROM ab1 CREATE STATISTICS regress_schema_2.ab1_a_b_stats ON a, b FROM ab1 (2 rows) 8.440 SYS_GET_TRIGGERDEF 用法: 544 第 8 章 函数 sys_get_triggerdef(trigger_oid) sys_get_triggerdef(trigger_oid, pretty_bool) 功能: 重建一个触发器的 CREATE [ CONSTRAINT ] TRIGGER 命令。 pretty_bool 为真时,会以简洁形式重建触发器,如触发器依赖表在当前模式下则不会重建触发器依赖表的模式 名。 例子: 以下示例为重建触发器命令: \set SQLTERM ; CREATE TABLE test_table(a INT, b INT, c INT, d INT); CREATE TABLE test_result(name VARCHAR(10), c INT); \set SQLTERM / CREATE OR REPLACE TRIGGER tri_test_1 AFTER UPDATE OF c ON test_table FOR EACH ROW AS BEGIN INSERT INTO test_result VALUES('t1:new.c', :new.c); END / \set SQLTERM ; SELECT sys_get_triggerdef(oid) from sys_trigger where tgname = 'tri_test_1'; sys_get_triggerdef ------------------------------------------------------------------------------------------CREATE OR REPLACE TRIGGER tri_test_1 AFTER UPDATE OF c ON public.test_table FOR EACH ROW + BEGIN INSERT INTO test_result VALUES('t1:new.c', :new.c); END + + + (1 row) SELECT sys_get_triggerdef(oid, true) from sys_trigger where tgname = 'tri_test_1'; 545 第 8 章 函数 sys_get_triggerdef -----------------------------------------------------------------------------------CREATE OR REPLACE TRIGGER tri_test_1 AFTER UPDATE OF c ON test_table FOR EACH ROW + BEGIN + INSERT INTO test_result VALUES('t1:new.c', :new.c); END + + (1 row) SELECT sys_get_triggerdef(oid, false) from sys_trigger where tgname = 'tri_test_1'; sys_get_triggerdef ------------------------------------------------------------------------------------------CREATE OR REPLACE TRIGGER tri_test_1 AFTER UPDATE OF c ON public.test_table FOR EACH ROW + BEGIN INSERT INTO test_result VALUES('t1:new.c', :new.c); END + + + (1 row) 8.441 SYS_GET_USERBYID 用法: sys_get_userbyid(role_oid) 功能: 获得给定 OID 指定的角色名。 例子: 以下示例为重建触发器命令。 \set SQLTERM ; select sys_get_userbyid(9); sys_get_userbyid -----------------sao (1 row) 546 第 8 章 函数 8.442 SYS_GET_VIEWDEF 用法: sys_get_viewdef(view_name) sys_get_viewdef(view_name, pretty_bool) sys_get_viewdef(view_oid) sys_get_viewdef(view_oid, pretty_bool) sys_get_viewdef(view_oid, wrap_column_int) 功能: sys_get_viewdef 重构定义一个视图的 SELECT 查询。 前两种用法为通过视图名或物化视图名重建视图命令,后三种用法为通过视图 oid 或物化视图 oid 重建视图命 令。 这些函数的大部分都有两种变体,一种可以可选地“优质打印”结果。优质打印的格式可读性更强,但是默认格 式更可能被未来版本的 KingbaseES 以相同的方式解释。在转出目的中避免使用优质打印输出。为 pretty_bool 参数 传递 false 将得到和不带该参数的变体相同的结果。 wrap_column_int 为指定长度的列宽,并隐含了优质打印。 例子: 以下示例为重建触发器命令: 547 第 8 章 函数 \set SQLTERM ; create table t1(i int, j text); create view v1 as select * from t1; select sys_get_viewdef('v1'::regclass); sys_get_viewdef ---------------SELECT t1.i, + t1.j + FROM t1; (1 row) 8.443 SYS_GUID 用法: sys_guid() 功能: SYS_GUID 生成并返回一个由 32 个字节组成的全局唯一标识符(值)。在大多数平台上,生成的标识符由主机 标识符、调用函数的进程或线程的进程或线程标识符以及该进程或线程的非重复值(字节序列)组成。 返回值: 通过 guc 参数 guid_default_return_type(取值 bytea 或 name)来控制 SYS_GUID 的返回值。该参数只能在 kingbase.conf 中设置。默认值是’name’,返回 NAME 类型。如修改为’bytea’,需要修改 kingbase.conf 配置文件,重 启后再执行 select alter_sys_guid() 才能生效,返回 BYTEA 类型。 例子: 以下示例将一列添加到示例表中 hr.locations,将唯一标识符插入每一行,并返回 RAW 全局唯一标识符的 16 字 节值的 32 个字符的十六进制表示: ALTER TABLE locations ADD (uid_col RAW(16)); UPDATE locations SET uid_col = SYS_GUID(); SELECT location_id, uid_col FROM locations ORDER BY location_id, uid_col; +-------------+----------------------------------+ 548 第 8 章 函数 | LOCATION_ID | UID_COL | +=============+==================================+ | 1000 | 09F686761827CF8AE040578CB20B7491 | +-------------+----------------------------------+ | 1100 | 09F686761828CF8AE040578CB20B7491 | +-------------+----------------------------------+ | 1200 | 09F686761829CF8AE040578CB20B7491 | +-------------+----------------------------------+ | 1300 | 09F68676182ACF8AE040578CB20B7491 | +-------------+----------------------------------+ | 1400 | 09F68676182BCF8AE040578CB20B7491 | +-------------+----------------------------------+ | 1500 | 09F68676182CCF8AE040578CB20B7491 | +-------------+----------------------------------+ | . . . | | +-------------+----------------------------------+ 8.444 SYS_HAS_ROLE 用法: sys_has_role(user, role, privilege) sys_has_role(role, privilege) 功能: 检查 user 用户(未指定时使用当前用户)是否能以特定的方式访问一个角色。其参数的可能性类同于 has_table_privilege。除了 public 不允许作为一个用户名。希望的访问权限类型必须是下列值的某种组合: MEMBER 或 USAGE。MEMBER 表示该角色中的直接或间接成员关系(即使用 SET ROLE 的权力),而 USAGE 表示不做 SET ROLE 的情况下该角色的权限是否立即可用。 例子: select sys_has_role('system', 'usage'); +--------------+ 549 第 8 章 函数 | sys_has_role | +==============+ | t | +--------------+ 8.445 SYS_IDENTIFY_OBJECT 用法: sys_identify_object(catalog_id oid, object_id oid, object_sub_id integer) 功能: 返回一行数据,包含由参数目录 OID、对象 OID 和一个(可能为零的)子对象 ID 所唯一标识的数据库对象 的信息。该信息是供机器读取的,并且不会被翻译。type 标识数据库对象的类型;schema 是该对象所属的模式名, 如果对象类型不属于模式则为 NULL;,如果需要的话,可以加上引号如果该名称(如果相关的话,还可以加上模式 名)足以唯一标识该对象,则 name 就是对象的名称,必要时会被加上引号,否则为 NULL;identity 是完整的兑现 标识,它会表现为与对象类型相关的精确格式,并且如有必要,该格式中的每个部分都会被模式限定。 例子: select * from sys_identify_object(1259, 14886, 0); +------+-------------+-----------+-----------------------+ | type | schema | name | identity | +======+=============+===========+=======================+ | view | sys_catalog | sys_class | sys_catalog.sys_class | +------+-------------+-----------+-----------------------+ 8.446 SYS_IDENTIFY_OBJECT_AS_ADDRESS 用法: sys_identify_object_as_address(catalog_id oid, object_id oid, object_sub_id integer) 550 第 8 章 函数 功能: 返回一行数据,包含由参数目录 OID、对象 OID 和一个(可能为零的)子对象 ID 所唯一标识的数据库对象的信 息。返回的信息独立于当前服务器,也就是说,它可以被用来在另一个服务器中标识一个具有相同命名的对象。type 标识数据库对象的类型;object_names 和 object_args 是文本数组,它们一起构成了对对象的引用。这三个值可以 被传递给 sys_get_object_address 以获得该对象的内部地址。这个函数是 sys_get_object_address 的逆函数。 例子: select * from sys_identify_object_as_address(1259, 14886, 0); +------+-------------------------+-------------+ | type | object_names | object_args | +======+=========================+=============+ | view | {sys_catalog,sys_class} | {} | +------+-------------------------+-------------+ 8.447 SYS_INDEXES_SIZE 用法: sys_indexes_size(regclass) 功能: 接受一个表的 OID 或名称,并返回附加到该表的所有索引所使用的全部磁盘空间。 例子: 以下示例返回表的所有索引所使用的全部磁盘空间: SELECT sys_indexes_size('test'); +-----------------+ | sys_indexes_size | +=================+ | 16384 | +-----------------+ SELECT sys_indexes_size('24878'); +-----------------+ 551 第 8 章 函数 | sys_indexes_size | +=================+ | 16384 | +-----------------+ 8.448 SYS_KINGBASE_START_TIME 用法: sys_kingbase_start_time() 功能: 返回服务器启动时的 timestamp with time zone。 例子: select sys_kingbase_start_time(); +-------------------------------+ | sys_kingbase_start_time | +===============================+ | 2022-06-28 14:03:47.041437+08 | +-------------------------------+ 8.449 SYS_LS_DIR 用法: sys_ls_dir(dirname text [, missing_ok boolean, include_dot_dirs boolean]) 功能: 系统函数,列出目录中的内容。默认仅限于超级用户使用,但是可以给其他用户授予 Execute 让他们运行这个函 数。 552 第 8 章 函数 例子: SELECT SYS_LS_DIR('/', TRUE, TRUE); +---------------+ | sys_ls_dir | |---------------| | . | | .. | | boot | | dev | | proc | | run | | sys | | etc | | root | | var | | tmp | | usr | | bin | | sbin | | lib | | lib64 | | home | | media | | mnt | | opt | | srv | | .readahead | | .bash_history | | .autorelabel | +---------------+ 8.450 SYS_LS_LOGDIR 用法: sys_ls_logdir() 功能: 553 第 8 章 函数 系统函数,列出日志目录中文件的名称、尺寸以及最后修改时间。访问被授予给 sys_monitor 角色的成员,并且 可以被授予给其他非超级用户角色。 例子: SELECT SYS_LS_LOGDIR(); +---------------------------------------------------------------+ | sys_ls_logdir | |---------------------------------------------------------------| | (kingbase-2022-06-28_140347.log,562,"2022-06-28 16:15:28+08") | +---------------------------------------------------------------+ 8.451 SYS_LS_TMPDIR 用法: sys_ls_tmpdir() 功能: 系统函数,为 tablespace 列出临时目录中文件的名称、大小和最后一次修改时间。如果没有提供 tablespace,则 在临时目录中的 sys_default 表空间被使用。sys_monitor 角色的成员可以访问,其他非超级用户角色也可以访问。 例子: SELECT SYS_LS_TMPDIR(); +-----------------+ | sys_ls_tmpdir | |-----------------| +-----------------+ 8.452 SYS_LS_WALDIR 用法: sys_ls_waldir() 554 第 8 章 函数 功能: 系统函数,列出 WAL 目录中文件的名称、尺寸以及最后修改时间。访问被授予给 sys_monitor 角色的成员,并 且可以被授予给其他非超级用户角色。。 例子: SELECT SYS_LS_WALDIR(); +--------------------------------------------------------------+ | sys_ls_waldir | |--------------------------------------------------------------| | (000000010000000000000001,16777216,"2022-06-28 16:19:57+08") | +--------------------------------------------------------------+ 8.453 SYS_RELATION_FILENODE 用法: sys_relation_filenode(relation regclass) 功能: 接受一个表、索引、序列或 TOAST 表的 OID 或名称,返回当前分配给它的“filenode”号。文件结点是关系的 文件名的基本组件。对于大多数表结果和 sys_class.relfilenode 相同,但是对于某些系统目录 relfilenode 为零,并且 必须使用此函数获取正确的值。如果传递一个没有存储的关系(如视图),此函数将返回 NULL。 例子: 以下示例返回表 test 的“filenode”号: SELECT sys_relation_filenode(oid) FROM sys_class WHERE relname='test'; +-----------------------+ | sys_relation_filenode | +=======================+ | 24878 | +-----------------------+ 555 第 8 章 函数 8.454 SYS_RELATION_FILEPATH 用法: sys_relation_filepath(relation regclass) 功能: 返回关系的整个文件路径名(相对于数据库集簇的数据目录 KINGBASE_DATA)。 例子: 以下示例返回表 test 的文件路径名: SELECT sys_relation_filepath(oid) FROM sys_class WHERE relname='test'; +-----------------------+ | sys_relation_filepath | +=======================+ | base/16078/24878 | +-----------------------+ 8.455 SYS_RELATION_SIZE 用法: sys_relation_size(relation regclass, fork text) sys_relation_size(relation regclass) 功能: 接受一个表、索引或 TOAST 表的 OID 或者名称,并且返回那个关系的一个分叉所占的磁盘空间的字节尺寸。 如果只得到一个参数,它会返回该关系的主数据分叉的尺寸。提供第二个参数可以指定要检查哪个分叉(’main’、 ’fsm’、’vm’ 或’init’)使用的磁盘空间。 556 第 8 章 函数 例子: 以下示例返回分叉’main’ 所占的磁盘空间的字节尺寸: SELECT sys_relation_size('test','main'); +-------------------+ | sys_relation_size | +===================+ | 16384 | +-------------------+ SELECT sys_relation_size('test'); +-------------------+ | sys_relation_size | +===================+ | 16384 | +-------------------+ 8.456 SYS_RELOAD_CONF 用法: sys_reload_conf() 功能: SYS_RELOAD_CONF 给服务器发送一个 SIGHUP 信号,导致所有服务器进程重载配置文件, 无参数。 例子: 以下示例会使服务进程重新加载配置文件: SELECT sys_reload_conf(); sys_reload_conf ---------------t (1 row) 557 第 8 章 函数 8.457 SYS_SIZE_BYTES 用法: sys_size_bytes(text) 功能: 可以被用来从人类可读格式的字符串得到其中所表示的字节数。其输入可能带有的单位包括字节、kB、MB、 GB 或者 TB,并且对输入进行解析时是区分大小写的。如果没有指定单位,会假定单位为字节。 例子: 以下示例返回表示的字节数: SELECT size, sys_size_bytes(size) FROM (VALUES ('1'), ('123bytes'), ('1kB'), ('1MB'), (' 1 GB'), ('1.5 GB '),('1TB'), ('3000 TB'), ('1e6 MB')) x(size); +----------+------------------+ | size | sys_size_bytes | +==========+==================+ | 1 | 1 | | 123bytes | 123 | | 1kB | 1024 | | 1MB | 1048576 | | 1 GB | 1073741824 | | 1.5 GB | 1610612736 | | 1TB | 1099511627776 | | 3000 TB | 3298534883328000 | | 1e6 MB | 1048576000000 | +----------+------------------+ 8.458 SYS_SIZE_PRETTY 用法: sys_size_pretty(bigint) sys_size_pretty(numeric) 558 第 8 章 函数 功能: 可以用于把其它函数之一的结果格式化成一种人类易读的格式,可以根据情况使用字节、kB、MB、GB 或者 TB。 例子: 以下示例返回人类易读的格式: SELECT sys_size_pretty(sys_relation_size('test')); +-----------------+ | sys_size_pretty | +=================+ | 16 kB | +-----------------+ SELECT sys_size_pretty(10::bigint); +-----------------+ | sys_size_pretty | +=================+ | 10 bytes | +-----------------+ 8.459 SYS_SLEEP 用法: sys_sleep(seconds) 功能: SYS_SLEEP 让服务进程延时执行,seconds 是一个 double precision 类型的值。 例子: 以下示例会使服务进程延时 3 秒执行: 559 第 8 章 函数 SELECT sys_sleep(3); sys_sleep ----------(1 row) 8.460 SYS_SLEEP_FOR 用法: sys_sleep_for(interval) 功能: SYS_SLEEP_FOR 让服务进程延时执行, 参数是一个 interval, 通常用于较长时间的休眠。 例子: 以下示例会使服务进程延时 5 分钟执行: SELECT sys_sleep_for('5 minutes'); sys_sleep_for --------------(1 row) 8.461 SYS_SLEEP_UNTIL 用法: sys_sleep_until(timestamp with time zone) 功能: 560 第 8 章 函数 SYS_SLEEP_UNTIL 使程序休眠到一个指定的时间唤醒, 参数是 timestamp with time zone, 通常用于较长时间 的休眠。 例子: 以下示例会使服务进程直到明天三点后被唤醒: SELECT sys_sleep_until('tomorrow 03:00'); sys_sleep_until ----------------(1 row) 8.462 SYS_TABLE_IS_VISIBLE 用法: sys_table_is_visible(table_oid) 功能: 表在搜索路径中是否可见,也可被用于视图、物化视图、索引、序列和外部表。 例子: 以下示例返回表在搜索路径中是否可见: SELECT sys_table_is_visible(24878); +----------------------+ | sys_table_is_visible | +======================+ | t | +----------------------+ 8.463 SYS_TABLE_SIZE 用法: 561 第 8 章 函数 sys_table_size(regclass) 功能: 接受一个表的 OID 或名称,并返回该表所需的磁盘空间,但是排除索引(TOAST 空间、空闲空间映射和可见 性映射包含在内)。 例子: 以下示例返回该表所需的磁盘空间: SELECT sys_table_size('test'); +----------------+ | sys_table_size | +================+ | 5016616960 | +----------------+ SELECT sys_table_size(24878); +----------------+ | sys_table_size | +================+ | 5016616960 | +----------------+ 8.464 SYS_TABLESPACE_DATABASES 用法: sys_tablespace_databases(tablespace_oid) 功能: 系统函数,获得在该表空间中所有对象的数据库 OID 的集合。 例子: 562 第 8 章 函数 SELECT SYS_TABLESPACE_DATABASES(1663); +----------------------------+ | sys_tablespace_databases | |----------------------------| | 1 | | 16051 | | 16052 | | 16053 | +----------------------------+ 8.465 SYS_TABLESPACE_LOCATION 用法: sys_tablespace_location(tablespace_oid) 功能: 系统函数,获得在该表空间所在的文件系统的路径。 例子: SELECT SYS_TABLESPACE_LOCATION(1663); 8.466 SYS_TABLESPACE_SIZE 用法: sys_tablespace_size(tablespace_oid) 功能: 系统函数,获得指定 OID 的表空间使用的磁盘空间。 例子: 563 第 8 章 函数 SELECT SYS_TABLESPACE_SIZE(1663); +----------------------+ | sys_tablespace_size | |----------------------| | 672388 | +----------------------+ 8.467 SYSDATE 用法: SYSDATE() 功能: 返回当时服务器时间。 返回值: 当时服务器时间。 例子: select SYSDATE; sysdate --------------------2022-06-28 19:52:59 (1 row) select SYSDATE(); sysdate --------------------2022-06-28 19:53:08 (1 row) 8.468 TABLE_TO_XML 用法: 564 第 8 章 函数 table_to_xml(tbl regclass, nulls boolean, tableforest boolean, targetns text) 功能: table_to_xml 映射由参数 tbl 传递的命名表的内容。regclass 类型接受使用常见标记标识表的字符串,包括可选 的模式限定和双引号。 例子: 如果 tableforest 为假,则结果的 XML 文档看起来像这样: datadata...... 如果 tableforest 为真,结果是一个看起来像这样的 XML 内容片断: datadata 565 第 8 章 函数 ... 8.469 TAN 用法: tan(n) 功能: TAN 返回(以弧度表示的角度)n 的正切。 此函数将任何数值数据类型或任何可以隐式转换为数值数据类型的非数值数据类型作为参数。如果参数是 BINARY_FLOAT,则函数返回 BINARY_DOUBLE。否则,函数返回与参数相同的数值数据类型。 例子: 以下示例返回 135 度的切线: SELECT TAN(135 * 3.14159265359/180) "Tangent of 135 degrees" FROM DUAL; +------------------------+ | Tangent of 135 degrees | +========================+ | - 1 | +------------------------+ 8.470 TANH 用法: tanh(n) 功能: 566 第 8 章 函数 TANH 返回 n 的双曲正切。 此函数将任何数值数据类型或任何可以隐式转换为数值数据类型的非数值数据类型作为参数。如果参数是 BINARY_FLOAT,则函数返回 BINARY_DOUBLE。否则,函数返回与参数相同的数值数据类型。 例子: 以下示例返回 0.5 的双曲正切: SELECT TANH(.5) "Hyperbolic tangent of .5" FROM DUAL; +--------------------------+ | Hyperbolic tangent of .5 | +==========================+ | .462117157 | +--------------------------+ 8.471 TIME(MySQL 模式) 用法: time(n) 功能: 返回给定日期的时间部分,参数为 NULL 时返回空。 参数说明: n:date、timestamp、time 等时间日期类型。 注意: 当参数 n1 为 date 日期类型时,若未指定时间部分,时间值默认为“00:00:00”; 返回值: time 类型 例子: SELECT TIME(DATE'2022-01-02'); time ----------- 567 第 8 章 函数 00:00:00 SELECT TIME(TIMESTAMP'2022-01-05 1:00:00'); time -----------01:00:00 SELECT TIME(TIME'2:00:00'); time -----------02:00:00 8.472 TIMEDIFF(MySQL 模式) 用法: timediff(n1,n2) 功能: 返回时间 n1 减去时间 n2 的差值,当有多个参数任一为 NULL 时返回空,若只有一个入参且为 NULL 则报错。 参数说明: n1:date、timestamp、time 等时间日期类型。 n2:date、timestamp、time 等时间日期类型。 注意: 1. 当参数 n1 为 date 日期类型时,若未指定时间部分,时间值默认为“00:00:00”; 2. 当参数 n1 不是 interval 类型时,若 n2 指定为 interval 类型,则会返回空。 返回值: interval 类型 例子: 568 第 8 章 函数 SELECT TIMEDIFF(date'2020-01-01',date'2020-01-02') "TIMEDIFF"; TIMEDIFF --------------24:00:00 SELECT TIMEDIFF(timestamp'2020-01-01 12:00:00.1',timestamp'2020-01-02 22:23:02.9') "TIMEDIFF"; TIMEDIFF --------------34:23:02.8 SELECT TIMEDIFF(interval'1 12:00:00',interval'84:00:00') "TIMEDIFF"; TIMEDIFF --------------48:00:00 SELECT TIMEDIFF(date'2020-01-01',interval'01:00:00') "TIMEDIFF"; TIMEDIFF -------------- 8.473 TIMESTAMP(MySQL 模式) 用法: timestamp( n1 [ , n2] ) 功能: 将日期时间值 n1 与时间值 n2 相加并返回 TIMESTMAP 类型值。若不输入 n2,则返回 n1 日期时间值转换为 timestamp 类型后的值。 参数说明: n1:date、timestamp、time 等时间日期类型。 n2:time、interval 等时间类型。 569 第 8 章 函数 注意: 1. 当参数 n1 为 date 日期类型时,若未指定时间部分,时间值默认为“00:00:00”; 2. 当参数 n1 为 time 类型时,计算时日期部分取当前服务器日期; 3. 任意参数为 null 或空值,返回值为 null。 返回值: timestamp 类型 例子: select TIMESTAMP(date'2020-01-01',time’1:00:00’); timestamp ---------------------2020-01-01 01:00:00 select TIMESTAMP (timestamp'2020-01-01 1:00:00',time’1:00:00’); timestamp ----------------------2020-01-01 02:00:00 select TIMESTAMP (time'12:00:00',time’1:00:00’); timestamp ----------------------2023-04-19 13:00:00 select TIMESTAMP(date'2020-01-01', interval'1 1:00:00'); timestamp ----------------------2020-01-02 01:00:00 select TIMESTAMP (date’2022-01-01’); timestamp ----------------------2022-01-01 00:00:00 570 第 8 章 函数 8.474 TIMESTAMPADD(MySQL 模式) 用法: timestampadd('unit',interval,n) 功能: 将 unit 和 interval 共同组成的时间值添加到日期时间 n 中,参数 interval 或者 n 为 NULL 时返回空。 参数说明: unit:间隔单位,text 类型,值域为:microsecond, second, minute, hour, day, week, month, quarter, 和 year。 interval:间隔值,float 类型。 n:date、timestamp、time 等时间日期类型。 注意: 1. 参数 unit 值为 second 且参数 interval 值为小数时,若小数点后末尾含 0,则返回值位数将减去对应 0 数量; 2. 若参数 unit 不在指定值中,则返回参数 n 格式化为 timestamp 后的值。 返回值: timestamp 类型 例子: SELECT TIMESTAMPADD('year',1,date'2022-01-01') "TIMESTAMPADD"; TIMESTAMPADD --------------------2023-01-01 00:00:00 SELECT TIMESTAMPADD('second',1.40000 ,date'2022-01-01') "TIMESTAMPADD"; TIMESTAMPADD ----------------------2022-01-01 00:00:01.4 SELECT TIMESTAMPADD('second',1.40001 ,date'2022-01-01') "TIMESTAMPADD"; 571 第 8 章 函数 TIMESTAMPADD --------------------------2022-01-01 00:00:01.40001 SELECT TIMESTAMPADD('second',NULL,date'2022-01-01') "TIMESTAMPADD"; TIMESTAMPADD -------------- 8.475 TIMESTAMPDIFF(MySQL 模式) 用法: timestampdiff('unit',n1,n2) 功能: 根据间隔单位计算两个日期时间值的差值,当有多个参数任一为 NULL 时返回空,若只有一个入参且为 NULL 则报错。 参数说明: unit:text 类型,值域为:microsecond, second, minute, hour, day, week, month, quarter, 和 year。 n1:date、timestamp、time 等时间日期类型。 n2:date、timestamp、time 等时间日期类型。 注意: 1. 参数 unit 值为 second 且参数 interval 值为小数时,若小数点后末尾含 0,则返回值位数将减去对应 0 数量; 2. 若参数 unit 不在指定值中,则返回 0。 返回值: bigint 类型 例子: SELECT TIMESTAMPDIFF('year',date'2022-01-01',date'2000-01-01') "TIMESTAMPDIFF"; TIMESTAMPDIFF ------------------22 572 第 8 章 函数 SELECT TIMESTAMPDIFF('second',timestamp'2022-01-01 12:00:00',timestamp'2022-01-01 12:12:23') "TIMESTAMPDIFF "; TIMESTAMPDIFF -----------------743 SELECT TIMESTAMPDIFF(NULL,timestamp'2022-01-01 12:00:00',timestamp'2022-01-01 12:12:23') "TIMESTAMPDIFF"; TIMESTAMPDIFF ---------------- 8.476 TIME_FORMAT 用法: time_format(time,format) 功能: time_format(time,format) 将时间串按照格式输出。格式字符串值只包含时间的小时、分钟、秒、微秒部分。其 他格式字符串将返回 NULL 值或者 0。如果时间值中的小时部分大于 23,则%H 和%K 小时格式说明符会产生一个比 通常范围 0..23 大的值。其他小时格式说明符会产生为模的小时值。 -> SELECT TIME_FORMAT(’100:00:00’, ’%H %k %h %I %l’); -> ’100 100 04 04 4’ 参数说明: time:时间串。 format: 输出格式串,如下说明: 573 第 8 章 函数 序号 说明符 描述 1 %f Microseconds (000000..999999) 2 %H Hour (00..23) 3 %h Hour (01..12) 4 %I Hour (01..12) 5 %i Minutes, numeric (00..59) 6 %k Hour (0..23) 7 %l Hour (1..12) 8 %p AM or PM 9 %r Time, 12-hour (hh:mm:ss followed by AM or PM) 10 %S Seconds (00..59) 11 %s Seconds (00..59) 12 %T Time, 24-hour (hh:mm:ss) 返回值: 按照输入参数 format 输出时间串。 例子: select time_format('13:56:09','%H %h %k %l %I %i %S %s %p %r %T %f'); '13 01 13 1 01 56 09 09 PM 01:56:09 PM 13:56:09 000000' select time_format('09:56:09','%H %h %k %l %I %i %S %s %p %r %T %f'); '09 09 9 9 09 56 09 09 AM 09:56:09 AM 09:56:09 000000' 8.477 TIME_TO_SEC(MySQL 模式) 用法: TIME_TO_SEC() 功能: 将参数的时间部分值转换为秒数。 574 第 8 章 函数 参数说明: 入参可以为 time、timestamp、date 等时间日期类型。 返回值: bigint 类型 例子: select time_to_sec(time'21:30:00'); time_to_sec ------------77400 (1 row) 8.478 TIMEOFDAY 用法: TIMEOFDAY() 功能: 返回当时服务器时间。 返回值: 当时服务器时间。 例子: select timeofday(); timeofday ------------------------------------Tue Jun 28 19:51:06.984914 2022 CST (1 row) 8.479 TIMESUB 用法: 575 第 8 章 函数 TIMESUB(head, tail) 功能: 返回 head 和 tail 的时间差。单位为秒。 参数说明: head:起始时间,类型 timestamp。 tail: 终止时间,类型 timestamp。 返回值: 返回 head 和 tail 的时间差, 返回 float 类型。 例子: select timesub('2017-2-28 23:59:1'::timestamptz, '2017-3-1 1:1:1'::timestamptz); timesub --------3720 (1 row) 8.480 TO_ASCII 用法: to_ascii(string text [, encoding text]) 功能: to_ascii(string text [, encoding text]) 将 string 从另一个编码转换到 ASCII(只支持从 LATIN1、LATIN2、 LATIN9 和 WIN1250 编码的转换) 例子: 576 第 8 章 函数 SELECT to_ascii('Karel'); 8.481 TO_BASE64(MySQL 模式) 用法: to_base64(string text) 功能: to_base64 函数将传入的字符串转换为 base64 编码的形式,返回结果为具有连接字符集和排序规则的字符串。 输入参数为 null 时,返回结果为 null;输入为非字符串时,若参数为纯数字,默认转为字符串处理,其他会返回 null。to_base64 编码的字符串可以通过 from_base64 函数进行解码。 以下为 to_base64 和 from_base64 函数使用的编码加密规则: 1. 字母值为 62 的编码是‘+’。 2. 字母值为 63 的编码是‘/’。 3. 输出的编码由 4 个可见字符组成。输入数据每 3 个字符都会编码为 4 个字符。如果结尾不足 3 个字符,则用 ‘=’字符填充,长度为 4。 4. 每输出 76 个字符后换行,将长输出分为多行。 5. 解码时自动识别并忽略换行、回车、制表符和空格。 to_base64 函数为 MySQL 兼容函数,仅支持在 MySQL 模式下使用。 例子: SELECT to_base64('abc'); 8.482 TO_BINARY_DOUBLE 用法: to_binary_double( varchar|numeric ) 577 第 8 章 函数 功能: 将字符串类型或者 numeric 类型转换为 binary_double 类型。 to_binary_double 函数为 Oracle 兼容函数,仅支持在 Oracle 模式下使用。 例子: SELECT to_binary_double('5.98989'); SELECT to_binary_double(5); 8.483 TO_BLOB 用法: to_blob(raw) 功能: 把 raw 类型值转换为 blob 类型值。注意 raw 数据类型需要加载 kdb_raw 插件后才能使用。 参数说明: raw:raw 类型值。 返回值: BLOB 类型。 例子: select to_blob(raw '3132') from dual; to_blob --------12 8.484 TO_CHAR 8.484.1 TO_CHAR(bfile|blob) 用法: 578 第 8 章 函数 TO_CHAR( { bfile | blob } [, csid ] ) 功能: TO_CHAR(bfile|blob) 将数据 BFILE 或 BLOB 数据转换为数据库字符集。返回的值始终是 VARCHAR。如果 返回的值太大而无法适应 VARCHAR 数据类型,则数据将被截断。 对于 csid,指定 BFILE 或者 BLOB 数据的字符集 ID 。如果 BFILE 或者 BLOB 数据的字符集是数据库字符 集,则可以为 csid 指定值 0,或完全省略 csid。 例子: 下面的假设示例将 media_table 中的一个 BFILE 列 media_col 列作为其输入,该列使用 ID 为 873 的字符集。 该示例返回一个使用数据库字符集 VARCHAR 的值。 SELECT TO_CHAR(media_col, 873) FROM media_tab; 8.484.2 TO_CHAR(character) 用法: TO_CHAR( nchar | clob | nclob ) 功能: TO_CHAR(character) 将 NCHAR、NVARCHAR、CLOB 或 NCLOB 数据转换为数据库字符集。返回的值始 终是 VARCHAR。 使用该函数将字符 LOB 转换为数据库字符集时,如果要转换的 LOB 值大于目标类型,则数据库返回错误。 例子: 以下示例将简单字符串解释为字符数据: 579 第 8 章 函数 SELECT TO_CHAR('01110') FROM DUAL; +-------+ | TO_CH | +=======+ | 01110 | +-------+ 将此示例与 TO_CHAR (number) 的第一个示例进行比较。 以下示例将表中的一些 CLOB 数据转换 pm.print_media 为数据库字符集: SELECT TO_CHAR(ad_sourcetext) FROM print_media WHERE product_id = 2268; TO_CHAR(AD_SOURCETEXT) ----------------------------------------+ TIGER2 2268... 标准 Hayes 兼容调制解调器 产品编号:2268 宇宙中销量第一的调制解调器!Tiger2 的调制解调器包括呼叫管理和互联网配音。同时拨打实时全双工电话你在线。 TO_CHAR(字符)功能:示例 以下语句创建一个名为 empl_temp 并使用员工详细信息填充它的表: CREATE TABLE empl_temp (employee_id NUMBER(6), first_name VARCHAR(20), last_name VARCHAR(25), email VARCHAR(25), hire_date DATE DEFAULT SYSDATE, job_id VARCHAR(10), clob_column CLOB ); INSERT INTO empl_temp VALUES(111,'John','Doe','example.com','10-JAN-2015','1001','ExperiencedEmployee'); INSERT INTO empl_temp VALUES(112,'John','Smith','example.com','12-JAN-2015','1002','JuniorEmployee'); INSERT INTO empl_temp VALUES(113,'Johnnie','Smith','example.com','12-JAN-2014','1002','Mid-CareerEmployee'); INSERT INTO empl_temp VALUES(115,'Jane','Doe','example.com','15-JAN-2015','1005','ExecutiveEmployee'); 以下语句将 CLOB 数据转换为数据库字符集: SELECT To_char(clob_column) "CLOB_TO_CHAR" FROM empl_temp WHERE employee_id IN ( 111, 112, 115 ); +----------------------+ | CLOB_TO_CHAR | +======================+ 580 第 8 章 函数 | Experienced Employee | +----------------------+ | Junior Employee | +----------------------+ | Executive Employee | +----------------------+ 8.484.3 TO_CHAR(datetime) 用法: TO_CHAR( { datetime | interval } [, fmt [, 'nlsparam'] ] ) 功能: TO_CHAR(datetime) 将 DATE,TIMESTAMP,TIMESTAMP WITH TIME ZONE ,TIMESTAMP WITH LOCAL TIME ZONE , INTERVAL DAY TO SECOND 或 INTERVAL YEAR TO MONTH 数据类型转换为 VARCHAR 数据类型的值,该数据类型的格式由 DATE 类型的 fmt 指定,如果省略 fmt, date 将转换 VARCHAR 为如下值: • DATE 值将转换为默认日期格式的值。 • TIMESTAMP 并将 TIMESTAMP WITH LOCAL TIME ZONE 值转换为默认时间戳格式的值。 • TIMESTAMP WITH TIME ZONE 值将转换为具有时区格式的默认时间戳中的值。 • 区间值被转换为区间文字的数字表示。 有关日期时间格式的信息,请参阅格式模型 。 该’nlsparam’ 参数指定返回月份和日期名称和缩写所使用的语言。这个参数可以有以下形式: 'NLS_DATE_LANGUAGE = language' 如果省略’nlsparam’,则此函数使用会话的默认日期语言。 您可以将此函数与任何 XML 函数结合使用,以数据库格式而不是 XML Schema 标准格式生成日期。 另请参阅: XML 函数 用于 XML 函数的列表。 例子: 以下示例使用此表: 581 第 8 章 函数 CREATE TABLE date_tab ( ts_col TIMESTAMP, tsltz_col TIMESTAMP WITH LOCAL TIME ZONE, tstz_col TIMESTAMP WITH TIME ZONE); 该示例显示了应用于 TO_CHAR 不同 TIMESTAMP 数据类型的结果。列的结果对 TIMESTAMP WITH LOCAL TIME ZONE 会话时区敏感,而 TIMESTAMP 和 TIMESTAMP WITH TIME ZONE 列的结果对会话时区不 敏感: ALTER SESSION SET TIME_ZONE = '-8:00'; INSERT INTO date_tab VALUES ( TIMESTAMP'1999-12-01 10:00:00', TIMESTAMP'1999-12-01 10:00:00', TIMESTAMP '1999-12-01 10:00:00'); INSERT INTO date_tab VALUES ( TIMESTAMP'1999-12-02 10:00:00 -8:00', TIMESTAMP'1999-12-02 10:00:00 -8:00', TIMESTAMP'1999-12-02 10:00:00 -8:00'); SELECT TO_CHAR(ts_col, 'DD-MON-YYYY HH24:MI:SSxFF') AS ts_date, TO_CHAR(tstz_col, 'DD-MON-YYYY HH24:MI:SSxFF TZH:TZM') AS tstz_date FROM date_tab ORDER BY ts_date, tstz_date; +-----------------------------+------------------------------------+ | TS_DATE | TSTZ_DATE | +=============================+====================================+ | 01-DEC-1999 10:00:00.000000 | 01-DEC-1999 10:00:00.000000 -08:00 | +-----------------------------+------------------------------------+ | 02-DEC-1999 10:00:00.000000 | 02-DEC-1999 10:00:00.000000 -08:00 | +-----------------------------+------------------------------------+ SELECT SESSIONTIMEZONE, TO_CHAR(tsltz_col, 'DD-MON-YYYY HH24:MI:SSxFF') AS tsltz FROM date_tab ORDER BY sessiontimezone, tsltz; +------------------+-----------------------------+ | SESSIONTIM TSLTZ | | +==================+=============================+ | -08:00 | 01-DEC-1999 10:00:00.000000 | +------------------+-----------------------------+ | -08:00 | 02-DEC-1999 10:00:00.000000 | +------------------+-----------------------------+ ALTER SESSION SET TIME_ZONE = '-5:00'; SELECT TO_CHAR(ts_col, 'DD-MON-YYYY HH24:MI:SSxFF') AS ts_col, TO_CHAR(tstz_col, 'DD-MON-YYYY HH24:MI:SSxFF TZH:TZM') AS tstz_col FROM date_tab ORDER BY ts_col, tstz_col; +-----------------------------+------------------------------------+ | TS_COL | TSTZ_COL | 582 第 8 章 函数 +=============================+====================================+ | 01-DEC-1999 10:00:00.000000 | 01-DEC-1999 10:00:00.000000 -08:00 | +-----------------------------+------------------------------------+ | 02-DEC-1999 10:00:00.000000 | 02-DEC-1999 10:00:00.000000 -08:00 | +-----------------------------+------------------------------------+ SELECT SESSIONTIMEZONE, TO_CHAR(tsltz_col, 'DD-MON-YYYY HH24:MI:SSxFF') AS tsltz_col FROM date_tab ORDER BY sessiontimezone, tsltz_col; +------------+-----------------------------+ | SESSIONTIM | TSLTZ_COL | +============+=============================+ | -05:00 | 01-DEC-1999 13:00:00.000000 | +------------+-----------------------------+ | -05:00 | 02-DEC-1999 13:00:00.000000 | +------------+-----------------------------+ 以下示例将区间文字转换为文本文字: SELECT TO_CHAR(INTERVAL '123-2' YEAR(3) TO MONTH) FROM DUAL; +---------+ | TO_CHAR | +=========+ | +123-02 | +---------+ 使用 TO_CHAR 格式化日期和数字:示例 以下语句将日期值转换为 TO_CHAR 函数中指定的格式: WITH dates AS ( SELECT date'2015-01-01' d FROM dual union SELECT date'2015-01-10' d FROM dual union SELECT date'2015-02-01' d FROM dual ) SELECT d "Original Date", to_char(d, 'dd-mm-yyyy') "Day-Month-Year", to_char(d, 'hh24:mi') "Time in 24-hr format", to_char(d, 'iw-iyyy') "ISO Year and Week of Year" FROM dates; 以下语句将日期和时间戳值转换为 TO_CHAR 函数中指定的格式: WITH dates AS ( SELECT date'2015-01-01' d FROM dual union SELECT date'2015-01-10' d FROM dual union 583 第 8 章 函数 SELECT date'2015-02-01' d FROM dual union SELECT timestamp'2015-03-03 23:44:32' d FROM dual union SELECT timestamp'2015-04-11 12:34:56' d FROM dual ) SELECT d "Original Date", to_char(d, 'dd-mm-yyyy') "Day-Month-Year", to_char(d, 'hh24:mi') "Time in 24-hr format", to_char(d, 'iw-iyyy') "ISO Year and Week of Year", to_char(d, 'Month') "Month Name", to_char(d, 'Year') "Year" FROM dates; 以下语句 EXTRACT 从输入日期时间表达式中提取函数中指定的日期时间字段: WITH dates AS ( SELECT date'2015-01-01' d FROM dual union SELECT date'2015-01-10' d FROM dual union SELECT date'2015-02-01' d FROM dual union SELECT timestamp'2015-03-03 23:44:32' d FROM dual union SELECT timestamp'2015-04-11 12:34:56' d FROM dual ) SELECT extract(minute from d) minutes, extract(hour from d) hours, extract(day from d) days, extract(month from d) months, extract(year from d) years FROM dates; 以下语句按照 TO_CHAR 函数中指定的格式显示输入数字: WITH nums AS ( SELECT 10 n FROM dual union SELECT 9.99 n FROM dual union SELECT 1000000 n FROM dual --one million ) SELECT n "Input Number N", to_char(n), to_char(n, '9,999,999.99') "Number with Commas", to_char(n, '0,000,000.000') "Zero-padded Number", to_char(n, '9.9EEEE') "Scientific Notation" FROM nums; 以下语句根据 TO_CHAR 函数中指定的格式转换输入数字: WITH nums AS ( SELECT 10 n FROM dual union SELECT 9.99 n FROM dual union SELECT .99 n FROM dual union SELECT 1000000 n FROM dual --one million ) 584 第 8 章 函数 SELECT n "Input Number N", to_char(n), to_char(n, '9,999,999.99') "Number with Commas", to_char(n, '0,000,000.000') "Zero_padded Number", to_char(n, '9.9EEEE') "Scientific Notation", to_char(n, '$9,999,990.00') Monetary, to_char(n, 'X') "Hexadecimal Value" FROM nums; 以下语句根据 TO_CHAR 函数中指定的格式转换输入数字: WITH nums AS ( SELECT 10 n FROM dual union SELECT 9.99 n FROM dual union SELECT .99 n FROM dual union SELECT 1000000 n FROM dual --one million ) SELECT n "Input Number N", to_char(n), to_char(n, '9,999,999.99') "Number with Commas", to_char(n, '0,000,000.000') "Zero_padded Number", to_char(n, '9.9EEEE') "Scientific Notation", to_char(n, '$9,999,990.00') Monetary, to_char(n, 'XXXXXX') "Hexadecimal Value" FROM nums; 实时 SQL: 在使用 TO_CHAR 格式化日期和数字中查看并运行有关 KingbaseES Live SQL 的相关示例 TO_CHAR (datetime) 函数:示例 以下语句创建一个名为 empl_temp 并使用员工详细信息填充它的表: CREATE TABLE empl_temp ( employee_id NUMBER(6), first_name VARCHAR(20), last_name VARCHAR(25), email VARCHAR(25), hire_date DATE DEFAULT SYSDATE, job_id VARCHAR(10), clob_column CLOB ); INSERT INTO empl_temp VALUES(111,'John','Doe','example.com','10-JAN-2015','1001','Experienced Employee'); INSERT INTO empl_temp VALUES(112,'John','Smith','example.com','12-JAN-2015','1002','Junior Employee'); INSERT INTO empl_temp VALUES(113,'Johnnie','Smith','example.com','12-JAN-2014','1002','Mid-Career Employee '); 585 第 8 章 函数 INSERT INTO empl_temp VALUES(115,'Jane','Doe','example.com','15-JAN-2015','1005','Executive Employee'); 以下语句使用短格式和长格式显示日期: SELECT hire_date "Default", TO_CHAR(hire_date,'DS') "Short", TO_CHAR(hire_date,'DL') "Long"FROM empl_temp WHERE employee_id IN (111, 112, 115); +-----------+-----------+----------------------------+ | Default | Short | Long | +===========+===========+============================+ | 10-JAN-15 | 1/10/2015 | Saturday, January 10, 2015 | +-----------+-----------+----------------------------+ | 12-JAN-15 | 1/12/2015 | Monday, January 12, 2015 | +-----------+-----------+----------------------------+ | 15-JAN-15 | 1/15/2015 | Thursday, January 15, 2015 | +-----------+-----------+----------------------------+ 8.484.4 TO_CHAR(number) 用法: TO_CHAR( n [, fmt [, 'nlsparam'] ] ) 功能: 使用可选的数字格式 fmt 将 n 转换为 VARCHAR 数据类型的值。n 类型为 NUMBER、BINARY_FLOAT 或 BINARY_DOUBLE,如果省略了 fmt,那么 n 将转换为 VARCHAR 值,其长度恰好足以容纳其有效数字。 如果 n 为负数,则在应用格式后应用符号。因此 TO_CHAR(-1, ’$9’) 返回 -$1,而不是 $-1。 有关数字格式的信息,请参阅格式模型 。 该’nlsparam’ 参数指定由数字格式元素返回的这些字符: • 小数字符 • 组分隔符 586 第 8 章 函数 • 当地货币符号 • 国际货币符号 这个参数可以有这种形式: 'NLS_NUMERIC_CHARACTERS = ''dg'' NLS_CURRENCY = ''text'' NLS_ISO_CURRENCY = territory ' 字符 d 和 g 分别代表十进制字符和组分隔符。它们必须是不同的单字节字符。在带引号的字符串中,您必须在参 数值周围使用两个单引号。十个字符可用于货币符号。 如果省略’nlsparam’ 或省略任何一个参数,则此函数将使用会话的默认参数值。 例子: 以下语句使用隐式转换将字符串和数字组合成数字: SELECT TO_CHAR('01110' + 1) FROM DUAL; +------+ | TO_C | +======+ | 1111 | +------+ 将此示例与 TO_CHAR (character) 的第一个示例进行比较。 在下一个示例中,输出在货币符号左侧填充空白。在可选的数字格式 fmt 中,L 指定本地货币符号并 MI 指定尾 随减号。该示例显示了会话参数 NLS_TERRITORY 设置为的会话中的输出 AMERICA。 SELECT TO_CHAR(-10000,'L99G999D99MI') "Amount" FROM DUAL; +-------------+ | Amount | +=============+ | $10,000.00- | +-------------+ 在 下 一 个 示 例 中,NLS_CURRENCY 指定用作 L 数 字 格 式 元 素 的 本 地 货 币 符 号 的 字 符 串。 NLS_NUMERIC_CHARACTERS 将逗号指定为用作 D 数字格式元素的小数分隔符的字符,将句点指定为用 作数字格式元素的组分隔符的字符 G。在许多国家/地区(例如在德国)都可以使用这些字符。 SELECT TO_CHAR(-10000,'L99G999D99MI', 'NLS_NUMERIC_CHARACTERS = '',.'' NLS_CURRENCY = ''AusDollars'' ') "Amount" 587 第 8 章 函数 FROM DUAL; +----------------------+ | Amount | +======================+ | AusDollars10.000,00- | +----------------------+ 在下一个示例中,NLS_ISO_CURRENCY 指示数据库将国际货币符号用于数字格式元素的 POLAND 领土 C: SELECT TO_CHAR(-10000,'99G999D99C', 'NLS_NUMERIC_CHARACTERS = '',.'' NLS_ISO_CURRENCY=POLAND') "Amount" FROM DUAL; +---------------+ | Amount | +===============+ | -10.000,00PLN | +---------------+ TO_CHAR (number) 功能:示例 以下语句创建一个名为 empl_temp 并使用员工详细信息填充它的表: CREATE TABLE empl_temp ( employee_id NUMBER(6), first_name VARCHAR(20), last_name VARCHAR(25), email VARCHAR(25), hire_date DATE DEFAULT SYSDATE, job_id VARCHAR(10), clob_column CLOB ); INSERT INTO empl_temp VALUES(111,'John','Doe','example.com','10-JAN-2015','1001','Experienced Employee'); INSERT INTO empl_temp VALUES(112,'John','Smith','example.com','12-JAN-2015','1002','Junior Employee'); INSERT INTO empl_temp VALUES(113,'Johnnie','Smith','example.com','12-JAN-2014','1002','Mid-Career Employee '); INSERT INTO empl_temp VALUES(115,'Jane','Doe','example.com','15-JAN-2015','1005','Executive Employee'); 以下语句将数值数据转换为数据库字符集: 588 第 8 章 函数 SELECT To_char(employee_id) "NUM_TO_CHAR" FROM empl_temp WHERE employee_id IN ( 111, 112, 113, 115 ); +-------------+ | NUM_TO_CHAR | +=============+ | 111 | +-------------+ | 112 | +-------------+ | 113 | +-------------+ | 115 | +-------------+ 8.485 TO_DATE 用法: TO_DATE(char [ DEFAULT return_value ON CONVERSION ERROR ] [, fmt [, 'nlsparam' ] ]) 功能: TO_DATE 转换 char 为 DATE 数据类型的值。 对于,您可以指定任何计算结果为 CHAR、VARCHAR、NCHAR 或 NVARCHAR 数据类型 char 的字符串的表 达式。 注意: 此函数不会将数据转换为任何其他日期时间数据类型。有关其他日期时间转换的信息,请参阅TO_TIMESTAMP 、TO_TIMEST TO_YMINTERVAL 。 589 第 8 章 函数 可选子句 DEFAULT return_value ON CONVERSION ERROR 允许您指定此函数在 char 转换为 DATE 时发 生错误时返回的值。如果在评估 char 时发生错误,则此子句无效。return_value 可以是表达式或绑定变量,它的计 算结果必须为 VARCHAR、NCHAR、NVARCHAR 数据类型的 CHAR 字符串,或者为 null。该函数将 char 转换为 DATE 使用与 return_value 转换为 DATE 相同的方法。如果 return_value 无法转换为 DATE,则函数返回错误。 是指定格式的 fmt 日期时间模型格式 char。如果省略 fmt,则 char 必须采用默认日期格式。默认日期格式由 NLS_TERRITORY 初始化参数隐式确定,也可以由 NLS_DATE_FORMAT 参数显式设置。如果 fmt 是 J,对于 朱利安,则 char 必须是整数。 警告: 始终使用指定格式掩码 ( fmt) 是一种很好的做法 TO_DATE,如以下部分中的示例所示。当它不带 格式掩码使用时,该函数只有在使用与 or 参数 char 确定的相同格式时才有效。此外,除非指定显式格式掩码以 避免依赖关系,否则该函数可能在数据库之间不稳定。NLS_TERRITORYNLS_DATE_FORMAT 该’nlsparam’ 参数指定要转换为日期的文本字符串的语言。这个参数可以有这种形式: 'NLS_DATE_LANGUAGE = language' 不要使用 TO_DATE 带有参数 DATE 值的 char 函数。返回值的前两位数字 DATE 可能与原始不同 char,具体 取决于 fmt 或默认日期格式。 此函数不直接支持 CLOB 数据。但是,CLOB 可以通过隐式数据转换作为参数传入。 另请参阅: 参见 日期时间类型、数据类型格式化函数 和数据类型比较规则 了解更多信息。 例子: SELECT TO_DATE( 'January 15, 1989, 11:00 A.M.', 'Month dd, YYYY, HH:MI A.M.', 'NLS_DATE_LANGUAGE = American') FROM DUAL; +-----------+ | TO_DATE | +===========+ | 15-JAN-89 | +-----------+ 如果参数设置为“NLS_TERRITORY”,则返回的值反映默认日期格式 AMERICA。不同 NLS_TERRITORY 的值会导致不同的默认日期格式: ALTER SESSION SET NLS_TERRITORY = 'KOREAN'; 590 第 8 章 函数 SELECT TO_DATE( 'January 15, 1989, 11:00 A.M.', 'Month dd, YYYY, HH:MI A.M.', 'NLS_DATE_LANGUAGE = American') FROM DUAL; +----------+ | TO_DATE | +==========+ | 89/01/15 | +----------+ DATE 以下示例返回默认值,因为指定的表达式由于月份拼写错误而无法转换为值: SELECT TO_DATE('Febuary 15, 2016, 11:00 A.M.' DEFAULT 'January 01, 2016 12:00 A.M.' ON CONVERSION ERROR, 'Month dd, YYYY, HH:MI A.M.') "Value" FROM DUAL; +-----------+ | Value | +===========+ | 01-JAN-16 | +-----------+ 8.486 TO_DATETIME 用法: to_datetime(datetimetxt, fmt) to_datetime(datetimetxt) 功能: TO_DATETIME 转换 char 为 DATETIME 数据类型的值。 591 第 8 章 函数 对于,您可以指定任何计算结果为 CHAR、VARCHAR、NCHAR 或 NVARCHAR 数据类型 char 的字符串的表 达式。 注意: 此函数不会将数据转换为任何其他日期时间数据类型。有关其他日期时间转换的信息,请参阅TO_TIMESTAMP 、TO_TIMEST TO_YMINTERVAL 。 是指定格式的 fmt 日期时间模型格式 char。如果省略 fmt,则 char 必须采用默认日期格式。 例子: SELECT to_datetime('1991-07-09 10:08:55', 'YYYY-MM-DD HH24:MI:SS'); +---------------------+ | TO_DATETIME | +=====================+ | 1991-07-09 10:08:55 | +---------------------+ SELECT to_datetime('1991-07-09 10:08:55'); +--------------------------+ | TO_DATETIME | +==========================+ | Tue Jul 09 10:08:55 1991 | +--------------------------+ 8.487 TO_DAYS(MySQL 模式) 用法: to_days(n) 功能: 返回日期时间值 n 距离 0 年的天数,参数为 NULL 时返回空。 参数说明: 592 第 8 章 函数 n:date、timestamp、time 等时间日期类型。当参数为 time 类型时,该参数以当前系统日期时间为值,并被隐 式转化为 timestamp 类型再进行计算。 返回值: bigint 类型 例子: SELECT TO_DAYS(date'2020-01-01') "TO_DAYS"; TO_DAYS -------------737790 SELECT TO_DAYS(timestamp'2020-01-01 12:23:41') "TO_DAYS"; TO_DAYS -------------737790 SELECT TO_DAYS(time'12:23:41') "TO_DAYS";---使用当前系统的日期 TO_DAYS -------------738652 SELECT TO_DAYS(NULL) "TO_DAYS"; TO_DAYS -------------- 8.488 TO_DSINTERVAL 用法: TO_DSINTERVAL ( ' { sql_format | ds_iso_format } ' [ DEFAULT return_value ON CONVERSION ERROR ] ) sql_format::= [+ | -] days hours : minutes : seconds [. frac_secs ] ds_iso_format::= 593 第 8 章 函数 [-] P [days D] [T [hours H] [minutes M] [seconds [. frac_secs] S ] ] 功能: 将输入的格式串转换为关于日期和时间的 dsinterval。格式串见上述图片。 例子: select to_dsinterval('5 23:58:59.23574') from dual; to_dsinterval -----------------------5 days 23:58:59.235740 (1 行记录) select to_dsinterval('P5DT23H21M19.38S') from dual; to_dsinterval ------------------------ 594 第 8 章 函数 5 days 23:21:19.380000 (1 行记录) 8.489 TO_HEX 用法: to_hex(number int or bigint) 功能: 将 number 转换到它等效的十六进制表示。 例子: select to_hex(14); +-----------+ | to_hex | +===========+ | e | +-----------+ 8.490 TO_JSON 用法: to_json(anyelement) 功能: to_json(anyelement) 把该值返回为 json。数组和组合会被(递归)转换成数组和对象;对于不是数组和组合的 值,如果有从该类型到 json 的造型,造型函数将被用来执行该转换;否则将产生一个标量值。对于任何不是数字、 布尔、空值的标量类型,将使用文本表达,在这种风格下它是一个合法的 json 或者 jsonb 值。 例子: 595 第 8 章 函数 select to_json('Fred said "Hi."'::text); +-----------------------+ | to_json | +=======================+ | "Fred said \"Hi.\"" | +-----------------------+ 8.491 TO_JSONB 用法: to_jsonb(anyelement) 功能: 把该值返回为 jsonb 。数组和组合会被(递归)转换成数组和对象;对于不是数组和组合的值,如果有从该类型 到 json 的造型,造型函数将被用来执行该转换;否则将产生一个标量值。对于任何不是数字、布尔、空值的标量类 型,将使用文本表达,在这种风格下它是一个合法的 json 或者 jsonb 值。 例子: select to_jsonb('Fred said "Hi."'::text); +-----------------------+ | to_jsonb | +=======================+ | "Fred said \"Hi.\"" | +-----------------------+ 8.492 TO_MULTI_BYTE 用法: to_multi_byte(str) 596 第 8 章 函数 功能: 将所输入的半角字符转换为全角字符。 例子: test=# select to_multi_byte('123\\\\¥¥$$456') from dual; to_multi_byte -----------------------------123\\\\¥¥$$456 (1 row) 8.493 TO_NUMBER 用法: TO_NUMBER(expr [ DEFAULT return_value ON CONVERSION ERROR ] [, fmt [, 'nlsparam' ] ]) 功能: TO_NUMBER 转换 expr 为 NUMBER 数据类型的值。 expr 可以是计算结果为 CHAR 类型字符串的任何表达式,VARCHAR、NCHAR 或 NVARCHAR,类型为 NUMBER、BINARY_FLOAT 或 BINARY_DOUBL 的数值或 null 的任何表达式。如果 Eexpr 是 NUMBER,则函 数返回 null,否则,该函数将 expr 转换为一个 NUMBER 值。 如果您指定 exprof CHAR、VARCHAR、NCHAR 或 NVARCHAR 数据类型,则可以选择指定格式模型 fmt。 如果指定 exprofBINARY_FLOAT 或 BINARY_DOUBLE 数据类型,则不能指定格式模型,因为浮点数只能通 过其内部表示来解释。 有关数字格式的信息,请参阅格式模型 。 此函数中的参数与用于数字转换’nlsparam’ 的函数中的参数具有相同的目的。TO_CHAR 有关详细信息,请参 阅TO_CHAR 。 此函数不直接支持 CLOB 数据。但是,CLOBs 可以通过隐式数据转换作为参数传入。 597 第 8 章 函数 例子: 以下示例将字符串数据转换为数字: UPDATE employees SET salary = salary + TO_NUMBER('100.00', '9G999D99') WHERE last_name = 'Perkins'; SELECT TO_NUMBER('-AusDollars100','L9G999D99', ' NLS_NUMERIC_CHARACTERS = '',.'' NLS_CURRENCY = ''AusDollars'' ') "Amount" FROM DUAL; +--------+ | Amount | +========+ | -100 | +--------+ 以下示例返回默认值 of,0 因为指定的表达式无法转换为 NUMBER 值: SELECT TO_NUMBER('2,00' DEFAULT 0 ON CONVERSION ERROR) "Value" FROM DUAL; +-------+ | Value | +=======+ | 0 | +-------+ 8.494 TO_SECONDS(MySQL 模式) 用法: to_seconds(n) 功能: 返回日期时间值 n 距离 0 年的秒数,参数为 NULL 时返回空。 参数说明: 598 第 8 章 函数 n:date、timestamp、time 等时间日期类型。当参数 n 为 date 日期类型时,若未指定时间部分,时间值默认为 “00:00:00”。 返回值: bigint 类型 例子: SELECT TO_SECONDS(date'2020-01-01') "TO_SECONDS"; TO_SECONDS -------------63745056000 SELECT TO_SECONDS(timestamp'2020-01-01 12:23:41') "TO_SECONDS"; TO_SECONDS -------------63745100621 SELECT TO_SECONDS(time'12:23:41') "TO_SECONDS"; TO_SECONDS -------------63819577421 SELECT TO_SECONDS(NULL) "TO_SECONDS"; TO_SECONDS -------------- 8.495 TO_SINGLE_BYTE 用法: to_single_byte(str) 功能: 将所输入的全角字符转换为半角字符。 例子: 599 第 8 章 函数 test=# select to_single_byte('123\\\\¥¥$$456') from dual; to_single_byte -----------------123\\\\¥¥$$456 (1 row) 8.496 TO_TIMESTAMP 用法: to_timestamp (double precision ) 功能: 把 Unix 时间(从 1970-01-01 00:00:00+00 开始的秒)转换成 timestamp。返回值类型为 time stamp without time zone。 例子: select to_timestamp (1284352323); +-----------------------+ | to_timestamp | +=======================+ | 2010-09-13 04:32:03 | +-----------------------+ 8.497 TO_TIMESTAMP_TZ 用法: to_timestamp_tz(double precision ) 功能: 600 第 8 章 函数 把 Unix 时间(从 1970-01-01 00:00:00+00 开始的秒)转换成 timestamp。返回值类型为 time stamp with time zone。 例子: select to_timestamp_tz(1284352323); +-----------------------+ | to_timestamp | +=======================+ | 2010-09-13 04:32:03+00| +-----------------------+ 8.498 TO_YMINTERVAL 用法: ( ' { [+|-] years - months | ym_iso_format } ' [ DEFAULT return_value ON CONVERSION ERROR ] ) ym_iso_format::= [-] P [ years Y ] [months M] [days D] [T [hours H] [minutes M] [seconds [. frac_secs] S ] ] 601 第 8 章 函数 功能: 将输入的格式串转换为关于 YEAR 和 MONTH 的 yminterval。格式串见上述图片。 例子: select to_yminterval('5-8') from dual; to_yminterval ---------------5 years 8 mons (1 行记录) select to_yminterval('P2Y3M5DT23H') from dual; to_yminterval ---------------2 years 3 mons (1 行记录) 8.499 TRANSACTION_TIMESTAMP 用法: TRANSACTION_TIMESTAMP() 功能: 返回当时服务器时间。 返回值: 当时服务器时间。 602 第 8 章 函数 例子: select TRANSACTION_TIMESTAMP(); transaction_timestamp ------------------------------2022-06-28 19:54:41.988659+08 (1 row) select TRANSACTION_TIMESTAMP; transaction_timestamp ------------------------------2022-06-28 19:55:28.701192+08 (1 row) 8.500 TRANSLATE 用法: TRANSLATE(expr, from_string, to_string) 功能: TRANSLATE 返回 expr 其中每个字符 in 的所有出现都 from_string 替换为其对应的字符 in to_string。expr 不 在其中的字符 from_string 不会被替换。参数 from_string 可以包含比更多的字符 to_string。在这种情况下,末尾的 多余字符 from_string 在 to_string。如果这些额外的字符出现在中 expr,那么它们将从返回值中删除。 如果一个字符在中出现多次 from_string,则使用 to_string 与第一次出现对应的映射。 您不能使用空字符串从返回值 to_string 中删除所有字符。from_stringOracle 数据库将空字符串解释为 null,如 果此函数有 null 参数,则返回 null。要删除中的所有字符 from_string,请将另一个字符连接到开头 from_string 并 将此字符指定为 to_string. 例如,TRANSLATE( expr, ’ x0123456789’, ’ x’) 从中删除所有数字 expr。 TRANSLATE 提供与该功能提供的功能相关的 REPLACE 功能。REPLACE 允许您用一个字符串替换另一个字 符串,以及删除字符串。TRANSLATE 允许您在一次操作中进行多个单字符、一对一的替换。 此函数不直接支持 CLOB 数据。但是,CLOB 可以通过隐式数据转换作为参数传入。 另请参阅: 数据转换 了解更多信息和REPLACE 。 例子: 603 第 8 章 函数 以下语句将书名转换为可以用作(例如)文件名的字符串。包含四个字符:from_string 空格、星号、斜杠和撇 号(带有一个额外的撇号作为转义字符)。to_string 仅包含三个下划线。这使得中的第四个字符 from_string 没有 相应的替换,因此从返回值中删除了撇号。 SELECT TRANSLATE('SQL*Plus User''s Guide', ' */''', '___') FROM DUAL; +----------------------+ | TRANSLATE('SQL*PLUSU | +======================+ | SQL_Plus_Users_Guide | +----------------------+ 8.501 TRIM 用法: TRIM([ { { LEADING | TRAILING | BOTH } [ trim_character ] | trim_character } FROM ] trim_source ) 功能: • TRIM 使您能够从字符串中修剪前导字符或尾随字符(或两者)。如果 trim_characterortrim_source 是字符文 字,则必须将其括在单引号中。 • 如果指定 LEADING,则 KingbaseES 数据库将删除任何等于的前导字符 trim_character。 • 如果您指定 TRAILING,则 KingbaseES 将删除任何等于的尾随字符 trim_character。 • 如果您指定 BOTH 或不指定这三个字符,则 KingbaseES 将删除等于.trim_character 的前导字符和尾随字符。 • 如果不指定 trim_character,则默认值为空格。 • 如果您仅指定 trim_source,则 KingbaseES 将删除前导和尾随空格。 • 该函数返回一个数据类型为的值 VARCHAR。该值的最大长度是的长度 trim_source。 • 如果其中一个 trim_source 或 trim_character 为 null,则该 TRIM 函数返回 null。 604 第 8 章 函数 trim_character 和都 trim_source 可以是 VARCHAR 或任何可以隐式转换为的数据类型 VARCHAR。返回的字 符串是 VARCHAR( NVARCHAR) 数据类型 iftrim_source 是 CHAR 或者 VARCHAR( NCHARor NVARCHAR) 数 据类型,而如果 trim_source 是 CLOB 数据类型。返回字符串与 trim_source 的字符集相同。 例子: 此示例从 hr 架构中员工的雇用日期修剪前导零: SELECT employee_id, TO_CHAR(TRIM(LEADING 0 FROM hire_date)) FROM employees WHERE department_id = 60 ORDER BY employee_id; +-----------------------+ | EMPLOYEE_ID TO_CHAR(T | +=======================+ | 103 20-MAY-08 | +-----------------------+ | 104 21-MAY-07 | +-----------------------+ | 105 25-JUN-05 | +-----------------------+ | 106 5-FEB-06 | +-----------------------+ | 107 7-FEB-07 | +-----------------------+ 8.502 TRUNC 8.502.1 TRUNC(date) 用法: TRUNC(date [, fmt ]) 功能: 605 第 8 章 函数 TRUNC(date) 函数返回 date 一天中的时间部分,截断为格式 model 指定的单位 fmt。NLS_CALENDAR 该函 数对会话参数不敏感。它按照公历的规则运作。返回的值始终是数据类型 DATE,即使您为指定了不同的日期时间数 据类型 date。如果省略 fmt,则使用默认格式模型’ DD’,并且返回的值将被 date 截断为时间为午夜的日期。请参阅 日期时间类型了解允许使用的格式模型 fmt。 例子: 以下示例截断日期: SELECT TRUNC(TO_DATE('27-OCT-92','DD-MON-YY'), 'YEAR') "New Year" FROM DUAL; +-----------+ | New Year | +===========+ | 01-JAN-92 | +-----------+ 使用 TRUNC 格式化日期:示例 在以下示例中,TRUNC 函数返回输入日期,其中一天的时间部分按照格式模型中的指定截断: WITH dates AS ( SELECT date'2015-01-01' d FROM dual union SELECT date'2015-01-10' d FROM dual union SELECT date'2015-02-01' d FROM dual union SELECT timestamp'2015-03-03 23:45:00' d FROM dual union SELECT timestamp'2015-04-11 12:34:56' d FROM dual ) SELECT d "Original Date", trunc(d) "Nearest Day, Time Removed", trunc(d, 'ww') "Nearest Week", trunc(d, 'iw') "Start of Week", trunc(d, 'mm') "Start of Month", trunc(d, 'year') "Start of Year" FROM dates; 在以下示例中,输入日期值被截断,并且该 TO_CHAR 函数用于获取截断日期值的分钟部分: WITH dates AS ( SELECT date'2015-01-01' d FROM dual union SELECT date'2015-01-10' d FROM dual union SELECT date'2015-02-01' d FROM dual union SELECT timestamp'2015-03-03 23:45:00' d FROM dual union SELECT timestamp'2015-04-11 12:34:56' d FROM dual ) SELECT d "Original Date", trunc(d) "Date with Time Removed", to_char(trunc(d, 'mi'), 'dd-mon-yyyy hh24:mi') "Nearest Minute", trunc(d, 'iw') "Start of Week", trunc(d, 'mm') "Start of Month", 606 第 8 章 函数 trunc(d, 'year') "Start of Year" FROM dates; 以下语句更改当前会话的日期格式: ALTER SESSION SET nls_date_format = 'dd-mon-yyyy hh24:mi'; 在以下示例中,数据以新的日期格式显示: WITH dates AS ( SELECT date'2015-01-01' d FROM dual union SELECT date'2015-01-10' d FROM dual union SELECT date'2015-02-01' d FROM dual union SELECT timestamp'2015-03-03 23:44:32' d FROM dual union SELECT timestamp'2015-04-11 12:34:56' d FROM dual ) SELECT d "Original Date", trunc(d) "Date, time removed", to_char(trunc(d, 'mi'), 'dd-mon-yyyy hh24:mi') "Nearest Minute", trunc(d, 'iw') "Start of Week", trunc(d, 'mm') "Start of Month", trunc(d, 'year') "Start of Year" FROM dates; 8.502.2 TRUNC(number) 用法: TRUNC(n1 [, n2 ]) 功能: TRUNC(number) 函数返回 n1 截断到 n2 小数位。如果 n2 省略,则将 n1 截断为 0 位。n2 可以为负数以截断 (使为零)n2 小数点左侧的数字。 此函数将任何数值数据类型或任何可以隐式转换为数值数据类型的非数值数据类型作为参数。如果省略 n2,则 函数返回与参数的数值数据类型相同的数据类型。如果包含 n2,则函数返回 NUMBER。 例子: 以下示例截断数字: 607 第 8 章 函数 SELECT TRUNC(15.79,1) "Truncate" FROM DUAL; +----------+ | Truncate | +==========+ | 15.7 | +----------+ SELECT TRUNC(15.79,-1) "Truncate" FROM DUAL; +----------+ | Truncate | +==========+ | 10 | +----------+ 8.502.3 TRUNC(text) 用法: trunc(text [, int]) 功能: TRUNC(text) 函数将 text 文本隐式转换为数字类型后,对数字进行截取,保留 int 小数位,并且不进行四舍五 入。返回值为 numeric 类型。 第一个参数为 text 文本类型,并且需要为标准数字输入,没有范围限制。如果无法转换为标准数字,则报错。 如果第一个参数为 NULL 则返回 NULL。 第二个参数 int 如果省略,则将 text 文本截断为 0 位(即为整数)。如果 int 为负数,则截断小数点左侧的数字 位数。 例子: 以下示例截断 text 文本: SELECT select trunc(1.234556,3) "Truncate" FROM DUAL; Truncate 608 第 8 章 函数 -----------1.234 8.503 UCASE 用法: ucase(string) 功能: 将字符串转换成大写形式。 例子: select ucase('abcdefG5'); +-----------+ | ucase | +===========+ | ABCDEFG5 | +-----------+ 8.504 UNICODE 用法: UNICODE(character_expression) 功能: UNICODE 函数将为您提供第一个字符的整数值。对于输入表达式的第一个字符,它将返回整数值或者 Unicode 值。 例子: 609 第 8 章 函数 以下示例返回输入表达式第一个字符的整数值: SELECT UNICODE('KingbaseES'); +-----------+ | unicode | +===========+ | 75 | +-----------+ 8.505 UNIX_TIMESTAMP(MySQL 模式) 用法: select unix_timestamp; select unix_timestamp(); select unix_timestamp(date); select unix_timestamp(timestamp); select unix_timestamp(time); select unix_timestamp(integer); select unix_timestamp(bigint); select unix_timestamp(numeric); select unix_timestamp(text); 功能: 将 DATE、TIMESTAMP、TIME 类型的 n 或指定格式的数值 n 转换为对应 UTC 日期时间,返回时间戳。 参数和返回值说明: 参数范围及返回结果说明如下: 表 8.505.1: UNIX-TIMESTAMP 参数范围及返回结果说明 参数 类型 值域 输出结果 无入参 无 无 返回当前时间的时间戳 N DATE 1970-01-01 至 2154-12-31 正常输出 TIMESTAMP 1970-01-01 00:00:00 至 3001-0118 23:59:59 转化为当前会话时区 后的值 见续表 610 第 8 章 函数 表 8.505.1 – 续表 参数 类型 值域 输出结果 TIME -838:59:59 至 838:59:59 返回当前日期加上入参时间后的 时间戳 Integer、bigint 、 正确格式 YYMMDD、YYYYM- Numeric MDD、YYMMDDhhmmss、 正常输出 YYYYMMDDhhmmss 非正确格式 返回 0 NULL 无 返回空 空值 无 返回 0 函数返回值为 numeric 类型值。 例子: SELECT UNIX_TIMESTAMP(); -----1653458325 8.506 UNNEST 用法: UNNEST( array_expression [, ... ] ) [WITH ORDINALITY] [[AS] table_alias [(column_alias [, ... ])]] 611 第 8 章 函数 功能: 特殊的表函数 UNNEST 可以使用任意数量的数组参数,它会返回对应的列数。 例子: SELECT id,unnest(string_to_array(element,'')) as elem; 8.507 UPDATEXML 用法: updatexml(xml_instance xml, xpath text, value_expr xml) updatexml(xml_instance xml, xpath text, value_expr text) updatexml(xml_instance xml, xpath text, value_expr text, namespace text) 功能: 函数 updatexml 将 xml_instance 实例中 xpath 指定的节点内容替换为 value_expr 提供的值,成功则返回更 新后的 xml_instance 实例,失败则返回 ERROR。此函数使用前需要创建 kdb_utils_function 扩展。 例子: SELECT updatexml('oldnode', '/value', 'newnode'); 8.508 UPPER 用法: upper(char) 612 第 8 章 函数 功能: UPPER 返回所有字母大写。char 可以是任何数据类型 CHARACTER VARYING(N [CHAR | BYTE])、VARCHAR(N [CHAR | BYTE])、CHARACTER(N [CHAR | BYTE])、CHAR(N [CHAR | BYTE])、TEXT、CLOB 或 NCLOB,返回值与 char 的数据类型相同。非字符串类型作为 upper 函数的输入,默认隐式转换为 text 类型,返回 类型为 text。数据库根据为基础字符集定义的二进制映射设置字符的大小写。 例子: 以下示例以大写形式返回每个员工的姓氏: SELECT UPPER(last_name) "Uppercase" FROM employees; create table test( input varchar2(100 char)); create table tuppper as select upper(input) as name from test; \d tuppper Table "string_function.tuppper" Column | Type | Collation | Nullable | Default --------+-----------------------------+-----------+----------+--------name | character varying(100 char) | | | 8.509 USER 用法: USER 功能: USER 返回会话用户(登录的用户)的名称。这可能会在数据库会话期间发生变化,因为 Real Application Security 会话被附加或分离。对于企业用户,此函数返回架构。对于其他用户,它返回数据库用户名。如果 Real Application Security 会话当前附加到数据库会话,则它返回 user XS$NULL。 该函数返回一个 VARCHAR 值。 在分布式 SQL 语句中,UID 和 USER 函数共同识别本地数据库上的用户。您不能在 CHECK 约束条件下使用 这些函数。 例子: 613 第 8 章 函数 以下示例返回会话用户: SELECT USER FROM DUAL; +-----------+ | user | +===========+ | kingbase | +-----------+ 8.510 USERENV 用法: USERENV('parameter') 功能: USERENV 返回有关当前会话的信息。此信息可用于编写特定于应用程序的审计跟踪表或确定会话当前使用的特 定于语言的字符。您不能 USERENV 在 CHECK 约束条件下使用。 所有 USERENV 返回数据的调用,使用 SESSIONID、SID 和 ENTRYID 参数 VARCHAR 的调用除外,它们返 回 NUMBER。 参数和返回值说明: • CLIENT_INFO,返回值:CLIENT_INFO 返回最多 64 字节的用户会话信息,这些信息可以由使用该 DBMS_APPLICATION_INFO 包的应用程序存储。 注意: 某些商业应用程序可能正在使用此上下文值。请参阅这些应用程序的适用文档,以确定它们可能对该上下文区 域的使用施加哪些限制。 • ENTRYID,返回值:当前审计条目号。审计 entryid 序列在细粒度审计记录和常规审计记录之间共享。您不能 在分布式 SQL 语句中使用此属性。 • ISDBA,返回值:ISDBATRUE 如果用户已通过操作系统或密码文件验证为具有 DBA 特权,则返回“”。 • LANG ,返回值:LANG 返回语言名称的 ISO 缩写,比现有的’ LANGUAGE’ 参数更短的形式。 • LANGUAGE ,返回值:LANGUAGE 返回当前会话使用的语言和地区以及以下形式的数据库字符集:language_territory.characterset。 614 第 8 章 函数 • SESSIONID ,返回值:SESSIONID 返回审计会话标识符。您不能在分布式 SQL 语句中指定此参数。 • SID,返回值:SID 返回会话 ID。 • TERMINAL ,返回值:TERMINAL 返回当前会话终端的操作系统标识符。在分布式 SQL 语句中,此参数 返回本地会话的标识符。在分布式环境中,仅远程 SELECT 语句支持此参数,远程 INSERT、UPDATE 或 DELETE 操作不支持此参数。 例子: 以下示例返回 LANGUAGE 当前会话的参数: SELECT USERENV('LANGUAGE') "Language" FROM DUAL; +-------------------------------+ | Language | +===============================+ | AMERICAN_AMERICA.WE8ISO8859P1 | +-------------------------------+ 8.511 UTC_DATE(MySQL 模式) 用法: utc_date() 功能: 获取当前服务器的 utc 日期(即格林威治标准日期)。 注意: 此函数不可创建函数索引。 返回值: date 类型 例子: SELECT UTC_DATE() "UTC_DATE"; UTC_DATE 615 第 8 章 函数 -------------2022-05-18 8.512 UTC_TIME(MySQL 模式) 用法: utc_time([n]) 功能: 获取当前服务器的 utc 时间(即格林威治标准时间),参数为 NULL 时返回空。 注意: 此函数不可创建函数索引。 参数说明: n:表示时间秒值小数点后面的位数,int 整数类型,范围为 [0,6], 默认值为 0。 返回值: time 类型 例子: SELECT UTC_TIME() "UTC_TIME"; UTC_TIME -------------17:16:24 SELECT UTC_TIME(1) "UTC_TIME"; UTC_TIME -------------17:16:33.4 616 第 8 章 函数 8.513 UTC_TIMESTAMP(MySQL 模式) 用法: utc_timestamp([n]) 功能: 获取当前服务器的 utc 日期时间(即格林威治标准日期时间),参数为 NULL 时返回空。 注意: 此函数不可创建函数索引。 参数说明: n:表示时间秒值小数点后面的位数,int 整数类型,范围为 [0,6], 默认值为 0。 返回值: timestamp 类型 例子: SELECT UTC_TIMESTAMP() "UTC_TIMESTAMP"; UTC_TIMESTAMP ---------------------2022-05-21 13:36:21 SELECT UTC_TIMESTAMP(1) "UTC_TIMESTAMP"; UTC_TIMESTAMP ---------------------2022-05-21 13:36:21.4 8.514 VALUE 用法: 617 第 8 章 函数 value(x record) 功能: VALUE 函数接受一个范围表别名作为参数,返回表的 record 类型的对象实例。 例子: CREATE TYPE person_t AS OBJECT (name varchar2(100), ssn number); CREATE TABLE persons OF person_t; INSERT INTO persons VALUES (person_t('Bob', 1234)); INSERT INTO persons VALUES (person_t('Joe', 2345)); INSERT INTO persons VALUES (person_t('Tom', 5678)); SELECT value(t) FROM persons t; value -----------(Bob,1234) (Joe,2345) (Tom,5678) (3 rows) 8.515 VAR_POP 用法: var_pop(expression) 功能: VAR_POP 在丢弃该集合中的空值后返回输入值的总体方差。您可以将其用作聚合函数和分析函数。 如果函数应用于空集,则返回 null。该函数进行以下计算: SUM((expr - (SUM(expr) / COUNT(expr))) ^ 2) / COUNT(expr) 例子: 618 第 8 章 函数 select var_pop(c1) from (values(1),(2),(3),(4),(5)) as t(c1); 8.516 VAR_SAMP 用法: var_samp(expression) 功能: VAR_SAMP 在丢弃该集合中的空值后返回一组数字的样本方差。您可以将其用作聚合函数和分析函数。 如果函数应用于空集,则返回 null。该函数进行以下计算: (SUM(expr - (SUM(expr) / COUNT(expr))) ^ 2 ) / (COUNT(expr) - 1) 例子: select var_samp(c1) from (values(1),(2),(3),(4),(5)) as t(c1); 8.517 VARIANCE 用法: variance([distinct | all] expr) [over (analytic_clause)] 功能: VARIANCE 返回 expr 的方差。您可以将其用作聚合或分析函数。 KingbaseES 数据库按如下方式计算 expr 方差: • 0 如果行数 expr= 1 619 第 8 章 函数 • VAR_SAMP 如果行数 expr> 1 如果您指定 DISTINCT,那么您只能指定 query_partition_clause 的 analytic_clause。order_by_clause 和 windowing_clause 是不允许的。 此函数将任何数值数据类型或任何可以隐式转换为数值数据类型的非数值数据类型作为参数。该函数返回与参数 的数值数据类型相同的数据类型。 例子: select variance(c1) from (values(1),(2),(3),(4),(5)) as t(c1); 8.518 VARIANCE(MySQL 模式) 用法: VARIANCE(expr) 功能: 聚合函数,计算所有非 NULL 输入值的总体方差。 参数: expr 必输,列名或者表达式。 返回值: 返回所有非 null 输入值的总体方差。 注意,variance() 函数只处理那些非 NULL 的值。也就是说, NULL 值会被 variance() 函数忽略。 例子: select variance(id) from (values(1),(2),(3),(100)) as t(id); variance ----------------------1801.2500000000000000 620 第 8 章 函数 8.519 VERSION 用法: VERSION 功能: VERSION 返回 KingbaseES 数据库版本信息,包含版本号及版本编译信息。该函数返回一个 TEXT 值。 例子: 以下示例返回数据库的版本信息: SELECT VERSION FROM DUAL; +-----------------------------------------------------------------------------------------------------------------+ | version | +==================================================================================================================+ | KingbaseES V008R006B0001 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-44), 64-bit | +-----------------------------------------------------------------------------------------------------------------+ 8.520 WEEK(MySQL 模式) 用法: week(n [, mode]) 功能: 返回指定日期的是所在年份的周数值。 参数说明: 621 第 8 章 函数 n:date、timestamp、time 等时间日期类型。当参数 n 为 time 类型时,该参数以当前系统日期时间为值,并被 隐式转化为 timestamp 类型再进行计算。 mode:integer、numeric 等数值类型、double precision 等浮点数类型,默认值为 0。指定 mode 参数后的周数计 算规则如下: • 当参数 mode 为 0 时,函数将以一周第一天为周日计算,返回值范围为 0 至 53,且一年中多一个星期天。 • 当参数 mode 为 1 时,函数将以一周第一天为周一计算,返回值范围为 0 至 53。 • 当参数 mode 为 2 时,函数将以一周第一天为周日计算,返回值范围为 1 至 53,且一年中多一个星期天。 • 当参数 mode 为 3 时,函数将以一周第一天为周一计算,返回值范围为 1 至 53。 • 当参数 mode 为 4 时,函数将以一周第一天为周日计算,返回值范围为 0 至 53。 • 当参数 mode 为 5 时,函数将以一周第一天为周一计算,返回值范围为 0 至 53,且一年中多一个星期天。 • 当参数 mode 为 6 时,函数将以一周第一天为周日计算,返回值范围为 1 至 53。 • 当参数 mode 为 7 时,函数将以一周第一天为周一计算,返回值范围为 1 至 53,且一年中多一个星期天。 注意: 1. 参数 mode 存在小数时,将其四舍五入成 int 类型后进行计算; 2. 当 mode 值不在 0 至 7 范围内时,将对该 mode 值进行对 8 的取余操作,并将余数的绝对值作为 mode 参数 值。 返回值: integer 类型 例子: SELECT WEEK(DATE'2022-01-02') "WEEK"; WEEK ---------------------1 SELECT WEEK(DATE'2022-01-02',3) "WEEK"; WEEK ---------------------52 SELECT WEEK(TIMESTAMP'2022-01-05 1:00:00') "WEEK"; 622 第 8 章 函数 WEEK ---------------------1 SELECT WEEK(TIME'2:00:00') "WEEK"; WEEK ---------------------24 8.521 WEEKDAY(MySQL 模式) 用法: weekday(n) 功能: 返回指定日期的星期索引,参数为 NULL 时返回空。 参数说明: n:date、timestamp、time 等时间日期类型。当参数 n 为 time 类型时,该参数以当前系统日期时间为值,并被 隐式转化为 timestamp 类型再进行计算。 返回值: integer 类型,值域为 0 至 6。 例子: SELECT WEEKDAY(DATE'2022-01-02') "WEEKDAY"; WEEKDAY ---------------------6 SELECT WEEKDAY(TIMESTAMP'2022-01-05 1:00:00') "WEEKDAY"; WEEKDAY ---------------------2 623 第 8 章 函数 8.522 WEEKOFYEAR(MySQL 模式) 用法: weekofyear(n) 功能: 返回指定日期的所在周数值,等效于函数 week(n,3)。 参数说明: n:date、timestamp、time 等时间日期类型。当参数 n 为 time 类型时,该参数以当前系统日期时间为值,并被 隐式转化为 timestamp 类型再进行计算。 返回值: integer 类型,值域为 1 至 53。 例子: SELECT WEEKOFYEAR(DATE'2022-01-02') "WEEKOFYEAR"; WEEKOFYEAR ---------------------52 SELECT WEEKOFYEAR(TIMESTAMP'2022-01-05 1:00:00') "WEEKOFYEAR"; WEEKOFYEAR ---------------------1 8.523 WM_CONCAT 用法: wm_concat(column) 功能: WM_CONCAT 实现 column 字段合并 (此函数使用前需要创建 kdb_utils_function 扩展)。 624 第 8 章 函数 例子: CREATE EXTENSION kdb_utils_function; CREATE TABLE wm_concat_test (id integer, name text, age integer, address text, salary numeric, b bytea); INSERT INTO wm_concat_test VALUES(1, 'Paul', 32, 'California', 20000, '12345'), (2, 'Allen', 25, 'Texas', 15000, '2345'), (3, 'Teddy', 23, 'Norway', 20000, '3456'), (3, 'Mark', 25, 'Rich-Mond', 65000, '4567'), (5, 'David', 27, 'Texas', 85000, '5678'), (2, 'Kim', 22, 'South-Hall', 45000, '6789'),(7, 'James', 24, 'Houston ', 10000, '7890'), (0, 'aaa', 123, 'bbb', 2222, '0998'), (1, 'baa', 123, 'bbb', 2222, '0998'); SELECT wm_concat(name) from wm_concat_test; wm_concat ----------------------------------------------Paul,Allen,Teddy,Mark,David,Kim,James,aaa,baa (1 row) SELECT wm_concat(name) FROM wm_concat_test GROUP BY id; wm_concat -----------Teddy,Mark David aaa Allen,Kim James Paul,baa (6 rows) 8.524 XML_IS_WELL_FORMED 用法: xml_is_well_formed(text) 功能: 检查一个 text 串是不是一个良构的 XML,返回一个布尔结果。 如果 xmloption 配置参数被设置为 DOCUMENT,xml_is_well_formed 会做第一个函数的工作;如果配置参数 被设置为 CONTENT,xml_is_well_formed 会做第二个函数的工作。这意味着 xml_is_well_formed 对于检查一个 到类型 xml 的简单造型是否会成功非常有用。 例子: 625 第 8 章 函数 SELECT xml_is_well_formed(''); 8.525 XML_IS_WELL_FORMED_DOCUMENT 用法: xml_is_well_formed_document(text) 功能: 检查一个 text 串是不是一个良构的 XML,返回一个布尔结果。xml_is_well_formed_document 检查一个良构 的文档,对于检查 XMLPARSE 的对应变体是否会成功有用。 例子: SELECT xml_is_well_formed_document('bar'); 8.526 XML_IS_WELL_FORMED_CONTENT 用法: xml_is_well_formed_content(text) 功能: 检查一个 text 串是不是一个良构的 XML,返回一个布尔结果。xml_is_well_formed_content 检查良构的内 容,对于检查 XMLPARSE 的对应变体是否会成功有用。 例子: SELECT xml_is_well_formed_content('bar><'); 626 第 8 章 函数 8.527 XMLAGG 用法: XMLAGG(XMLType_instance [order_by_clause]) 功能: XMLAgg 是一个聚合函数。它接受一组 XML 片段并返回一个聚合的 XML 文档。从结果中删除任何返回 null 的 参数。 XMLAgg 类似于,SYS_XMLAgg 除了 XMLAgg 返回节点集合但不接受使用 XMLFormat 对象进行格式化。此 外,XMLAgg 不会将输出包含在标记元素 SYS_XMLAgg 中。 在中 order_by_clause,KingbaseES 数据库不会像在此子句的其他用途中那样将数字文字解释为列位置,而只 是将其解释为数字文字。 另请参阅: XMLELEMENT 例子: 以下示例生成一个 Department 元素,其中包含 Employee 具有员工职位 ID 和姓氏的元素作为元素的内容: SELECT XMLELEMENT("Department",XMLAGG(XMLELEMENT("Employee", e.job_id||' '||e.last_name) ORDER BY last_ name)) as "Dept_list" FROM employees e WHERE e.department_id = 30; Dept_list PU_CLERK BaidaPU_CLERK ColmenaresPU_CLERK HimuroPU_CLERK KhooPU_MAN RaphaelyPU_CLERK Tobias 627 第 8 章 函数 结果是单行,因为 XMLAgg 聚合了这些行。您可以使用该 GROUP BY 子句将返回的行集分组为多个组: SELECT XMLELEMENT("Department",XMLAGG(XMLELEMENT("Employee", e.job_id||' '||e.last_name))) AS "Dept_list" FROM employees e GROUP BY e.department_id; Dept_list AD_ASST WhalenMK_MAN HartsteinMK_REP FayPU_MAN RaphaelyPU_CLERK KhooPU_CLERK TobiasPU_CLERK BaidaPU_CLERK ColmenaresPU_CLERK Himuro 8.528 XMLCOMMENT 用法: 628 第 8 章 函数 XMLCOMMENT(values_expr) 功能: XMLComment 使用的评估结果生成 XML 注释 value_expr。value_expr 必须解析为字符串。它不能包含两个连 续的破折号(连字符)。函数返回的值采用以下形式: 如果 value_expr 解析为 null,则该函数返回 null。 例子: 以下示例使用该 DUAL 表来说明 XMLComment 语法: SELECT XMLCOMMENT('OrderAnalysisComp imported, reconfigured, disassembled') AS "XMLCOMMENT" FROM DUAL; 8.529 XMLCONCAT 用法: XMLCONCAT(XMLType_instance [,...]) 功能: XMLConcat 将一系列 XMLType 实例作为输入,连接每一行的一系列元素,并返回连接后的系列。XMLConcat 是 XMLSequence 的倒数。 从结果中删除空表达式。如果所有值表达式都为 null,则该函数返回 null。 例子: 以下示例为员工子集的名字和姓氏创建 XML 元素,然后连接并返回这些元素: SELECT XMLCONCAT(XMLELEMENT("First", e.first_name),XMLELEMENT("Last", e.last_name)) AS "Result"FROM employees e WHERE e.employee_id > 202; 629 第 8 章 函数 8.530 XMLELEMENT 用法: XMLELEMENT([{ENTITYESCAPING|NOENTITYESCAPING}] {NAME identifier|EVALNAME value_expr} [, XML_attributes_ clause] [,value_expr [[AS] c_alias]][,...]) XML_attributes_clause: XML_ATTRIBUTES( [{ENTITYESCAPING|NOENTITYESCAPING}] [{SCHEMACHECK|NOSCHEMACHECK}] value [{[AS] c_alias| AS EVALINAME value_expr}] ) 功能: XMLElement 获取元素名称 identifier 或评估元素名称 EVALNAME value_expr、元素的可选属性集合以及构成 元素内容的参数。它返回一个类型的实例 XMLType。XMLElement 类似于 SYS_XMLGen,除了 XMLElement 可 以在返回的 XML 中包含属性,但它不接受使用 XMLFormat 对象进行格式化。 该 XMLElement 函数通常嵌套以生成具有嵌套结构的 XML 文档,如下节中的示例所示。 630 第 8 章 函数 您必须为 KingbaseES 数据库指定一个值才能使用封闭标记。您可以通过指定 identifier(字符串文字)或指定 EVALNAME value_expr. 在后一种情况下,对值表达式求值,并将结果(必须是字符串文字)用作标识符。标识符 不必是列名或列引用。它不能是表达式或空值。初始化参数最多可以有 4000 个字符,如果是 MAX_STRING_SIZE = STANDARD32767 个字符 MAX_STRING_SIZE = EXTENDED。 构成元素内容的对象跟在 XMLATTRIBUTES 关键字后面。在中 XML_attributes_clause,如果 value_expr 为 null,则不会为该值表达式创建任何属性。的类型 value_expr 不能是对象类型或集合。如果为 value_expr 使用该 AS 子句指定别名,则如果初始化参数为,则 thec_alias 或评估值表达式 ( EVALNAME value_expr) 最多可包含 4000 个字符,如果是,则最多可包含 MAX_STRING_SIZE = STANDARD32767 个字符 MAX_STRING_SIZE = EXTENDED。 对于图 XML_attributes_clause 中的选项 value_expr: • 如果 value_expr 是标量表达式,则可以省略该 AS 子句,KingbaseES 使用列名作为元素名。 • 如果 value_expr 是对象类型或集合,则该 AS 子句是强制性的,KingbaseES 使用指定 c_alias 的作为封闭标 记。 • 如果 value_expr 为 null,则不会为该值表达式创建任何元素。 例子: 以下示例 Emp 为一系列员工生成一个元素,其中包含提供员工姓名和雇用日期的嵌套元素: SELECT XMLELEMENT("Emp", XMLELEMENT("Name", e.job_id||' '||e.last_name),XMLELEMENT("Hiredate", e.hire_ date)) as "Result" FROM employees e WHERE employee_id > 200; Result MK_MAN Hartstein2004-02-17MK_REP Fay2005-08-17HR_REP Mavris 631 第 8 章 函数 2002-06-07PR_REP Baer2002-06-07AC_MGR Higgins2002-06-07AC_ACCOUNT Gietz2002-06-07 选择了 6 行。 以下类似示例使用 XMLElement 带有的函数 XML_attributes_clause 来创建嵌套 XML 元素,其中包含顶级元 素的属性值: SELECT XMLELEMENT("Emp",XMLATTRIBUTES(e.employee_id AS "ID", e.last_name),XMLELEMENT("Dept", e.department_ id),XMLELEMENT("Salary", e.salary)) AS "Emp Element" FROM employees e WHERE e.employee_id = 206; Emp Element 1108300 632 第 8 章 函数 请注意,AS identifier 没有为 last_name 列指定子句。因此,返回的 XML 使用列名 last_name 作为默认值。 最后,下一个示例使用中的子查询将 XML_attributes_clause 另一个表中的信息检索到元素的属性中: SELECT XMLELEMENT("Emp", XMLATTRIBUTES(e.employee_id, e.last_name),XMLELEMENT("Dept", XMLATTRIBUTES(e. department_id,(SELECT d.department_name FROM departments d WHERE d.department_id = e.department_id) as "Dept_name")),XMLELEMENT("salary", e.salary),XMLELEMENT("Hiredate", e.hire_date)) AS "Emp Element" FROM employees e WHERE employee_id = 205; Emp Element 120082002-06-07 8.531 XMLEXISTS 用法: XMLEXISTS(XQuery_string [XML_passing_clause]) XML_passing_clause::= PASSING [ BY VALUE ] expr [AS identifier] [, ... ] 633 第 8 章 函数 功能: XMLExists 检查给定 XQuery 表达式是否返回非空 XQuery 序列。如果是,函数返回 TRUE; 否则,它返回 FALSE。该参数 XQuery_string 是一个文字字符串,但它可以包含您使用 XML_passing_clause。 expr 中的是 XML_passing_clause 一个表达式,它返回 XMLType 一个 SQL 标量数据类型或一个实例,用作评 估 XQuery 表达式的上下文。您只能 expr 在 PASSING 子句中指定一个而无需标识符。每个计算的结果都 expr 绑 定到 XQuery_string。如果任何 expr 后面没有 AS 子句,则评估该表达式的结果将用作评估 XQuery_string。如果 expr 是关系列,则 KingbaseES XML DB 将忽略其声明的排序规则。 例子: SELECT cit FROM CUSTOMER WHERE XMLEXISTS('$d//addr[city='tianjin']', passing info aa "d"); 8.532 XMLFOREST 用法: XMLFOREST(value_expr [as {c_alias|EVALINAME value_expr]}][,...]) 功能: XMLForest 将其每个参数参数转换为 XML,然后返回一个 XML 片段,该片段是这些转换后的参数的串联。 • 如果 value_expr 是标量表达式,则可以省略该 AS 子句,KingbaseES 数据库使用列名作为元素名。 • 如果 value_expr 是对象类型或集合,则该 AS 子句是强制性的,KingbaseES 使用指定的表达式作为封闭标记。 • 您可以通过指定 c_alias(字符串文字)或指定 EVALNAME value_expr. 在后一种情况下,对值表达式求值, 并将结果(必须是字符串文字)用作标识符。标识符不必是列名或列引用。它不能是表达式或空值。初始化参 数最多可以有 4000 个字符,如果是 MAX_STRING_SIZE = STANDARD32767 个字符 MAX_STRING_SIZE = EXTENDED。 • 如果 value_expr 为 null,则不为此创建任何元素 value_expr。 例子: 以下示例 Emp 为员工子集创建一个元素,其中嵌套 employee_id 的 last_name、和 salary 元素作为 Emp 的内 容: 634 第 8 章 函数 SELECT XMLELEMENT("Emp", XMLFOREST(e.employee_id, e.last_name, e.salary))"Emp Element" FROM employees e WHERE employee_id = 204; Emp Element 204Baer10000 8.533 XMLPARSE 用法: XMLPARSE({DOCUMENT|CONTENT} value_expr [WELLFORMED]) 功能: XMLParse 从的评估结果解析并生成一个 XML 实例 value_expr。value_expr 必须解析为字符串。如果 value_expr 解析为 null,则该函数返回 null。 • 如果指定 DOCUMENT,则 value_expr 必须解析为单根 XML 文档。 • 如果您指定 CONTENT,则 value_expr 必须解析为有效的 XML A • 当您指定时 WELLFORMED,您保证 value_expr 解析为格式正确的 XML 文档,因此数据库不会执行有效性 检查以确保输入格式正确。 例子: 以下示例使用该 DUAL 表来说明的语法 XMLParse: SELECT XMLPARSE(CONTENT '124 Acme Enterprises32987457' WELLFORMED) AS PO FROM DUAL; 635 第 8 章 函数 8.534 XMLPI 用法: XMLPI({[NAME]idenfitier|EVALNAME value_expr} [, value_expr]) 功能: XMLPIidentifier 使用和可选的评估结果生成 XML 处理指令 value_expr。处理指令通常用于向应用程序提供与 XML 文档的全部或部分相关联的信息。应用程序使用处理指令来确定如何最好地处理 XML 文档。 您必须为 KingbaseES 数据库指定一个值才能使用封闭标记。您可以通过指定 identifier(字符串文字)或指定 EVALNAME value_expr. 在后一种情况下,对值表达式求值,并将结果(必须是字符串文字)用作标识符。标识符 不必是列名或列引用。它不能是表达式或空值。初始化参数最多可以有 4000 个字符,如果是 MAX_STRING_SIZE = STANDARD32767 个字符 MAX_STRING_SIZE = EXTENDED。 可选 value_expr 必须解析为字符串。如果省略 optional value_expr,则默认为零长度字符串。函数返回的值采 用以下形式: XMLPI 受以下限制: • identifier 必须是处理指令的有效目标。 • 在任何情况下,您都不能为指定 xml 组合 identifier。 • identifier 不能包含连续?> 字符。 例子: 以下语句使用该 DUAL 表来说明 XMLPI 语法的使用: SELECT XMLPI(NAME "Order analysisComp", 'imported, reconfigured, disassembled') AS "XMLPI" FROM DUAL; 8.535 XMLROOT 注意: 该 XMLROOT 功能已弃用。它仍然支持向后兼容。但是,KingbaseES 建议您改为使用 XMLSERIALIZE 带 有版本号的 SQL/XML 函数。有关该函数的更多信息,请参阅XMLSERIALIZE 。 636 第 8 章 函数 用法: XMLROOT(value_expr,VERSION {value_expr| NO VALUE} [,STANDALONE {YES|NO|NO VALUE}]) 功能: XMLROOT 允许您通过在现有 XML 值的 XML 根信息 (prolog) 中提供版本和独立属性来创建新的 XML 值。 如果 value_expr 已经有序言,则数据库返回错误。如果输入为空,则函数返回空。 返回的值采用以下形式: • 第一个 value_expr 指定您为其提供序言信息的 XML 值。 • 在 VERSION 子句中,value_expr 必须解析为表示有效 XML 版本的字符串。如果您指定 NO VALUEfor VERSION,则版本默认为 1.0。 • 如果省略可选 STANDALONE 子句,或者使用指定它 NO VALUE,则函数返回的值中不存在独立属性。 例子: 以下语句使用该 DUAL 表来说明的语法 XMLROOT: SELECT XMLROOT ( XMLType('143598'), VERSION '1.0', STANDALONE YES) AS "XMLROOT" FROM DUAL; 8.536 XMLSEQUENCE 用法: XMLSEQUENCE(xml_instance xml) 功能: XMLSEQUENCE 函数接受一个 xml 类型的 XML 实例,返回一个包含所有顶层 XML 节点的可变数组。 例子: CREATE TABLE tab_xml (a int, b xml); INSERT INTO tab_xml VALUES (1, '12'); INSERT INTO tab_xml VALUES (2, xml ('34')); SELECT t.* FROM tab_xml, table(xmlsequence(extract(b, '/a/*'))) AS t; xml_data ---------123 637 第 8 章 函数 4 (4 rows) 8.537 XMLSERIALIZE 用法: XMLSERIALIZE({DOCUMENT|CONTENT} value_expr [AS datatype][ENCODING xml_encoding_spec][VERSION string_literal] [{NO INDENT|INDENT[SIZE=number]}] [{HIDE|SHOW} DEFAULTS]) 功能: XMLSerialize 创建一个包含 value_expr. 返回的任何 lobXMLSERIALIZE 都是只读的。 • 如果指定 DOCUMENT,则 value_expr 必须是有效的 XML 文档。 • 如果指定 CONTENT,则 value_expr 不需要是单根 XML 文档。但是,它必须是有效的 XML 内容。 • 指定的 datatype 可以是字符串类型(VARCHAR 或 VARCHAR,但不是 NVARCHAR)BLOB 或 CLOB。默 认值为 CLOB. • 如果 datatype 是 BLOB, 那 么 您 可 以 指 定 ENCODING 子 句 以 在 序 言 中 使 用 指 定 的 编 码。 这 xml_encoding_spec 是一个 XML 编码声明 ( encoding=”...”)。 • 指定 VERSION 子句以使用您 string_literal 在 XML 声明 ( ) 中提供的版本。 • 指定 NO INDENT 从输出中去除所有无关紧要的空白。指定 INDENT SIZE = N,其中 N 是一个整数,用于 使用 N 空格的相对缩进进行漂亮打印的输出。如果 N 是 0,那么漂亮打印在每个元素之后插入一个换行符,将 每个元素单独放在一行上,但在输出中省略所有其他无关紧要的空格。如果 INDENT 在没有指定的情况下存在 SIZE,则使用 2 空格缩进。如果省略此子句,则行为是不确定的。 • HIDE DEFAULTS 并且 SHOW DEFAULTS 仅适用于基于 XML 模式的数据。如果您指定 SHOW DEFAULTS 并且输入数据缺少 XML 架构为其定义默认值的任何可选元素或属性,则这些元素或属性将以其默认值包含在 输出中。如果您指定 HIDE DEFAULTS,则输出中不包含此类元素或属性。HIDE DEFAULTS 是默认行为。 例子: 以下语句使用该 DUAL 表来说明的语法 XMLSerialize: 638 第 8 章 函数 SELECT XMLSERIALIZE(CONTENT XMLTYPE('Grandco')) AS xmlserialize_doc FROM DUAL; 8.538 XMLTABLE 用法: XMLTABLE([XML_namespaces_clause,] XQuery_string XMLTABLE_option) XMLnamespaces_clause::= XMLNAMESPACES({[string AS identifier|DEFAULT sting]}[,...]) 注意:您最多可以指定一个 DEFAULT string 子句。 XMLTABLE_options::= [XML_passing_clause][RETURNING SEQUENCE BY REF][COLUMN XML_table_column [,...]] XML_passing_clause::= 639 第 8 章 函数 PASSING [BY VALUE] (expr [ as indentifier ])[,...] XML_table_column::= column {FOR ORDINALITY|{datatype|XMLTYPE[(SEQUNCE) BY REF ]}[PATH string][DEFALUT]} 功能: XMLTable 将 XQuery 评估的结果映射到相关的行和列。您可以使用 SQL 将函数返回的结果作为虚拟关系表进 行查询。 • 该 XMLNAMESPACES 子句包含一组 XML 名称空间声明。这些声明由计算行的 XQuery 表达式(求值的 XQuery_string )和 PATH 字句中的 XPath 表达式引用 XML_table_column,计算整个 XMLTable 函数的 列,如果希望在 COLUMNS 字句的 PATH 表达式中使用限定名,则需要指定 XMLNAMESPACES 字句。 • XQuery_string 是一个文字字符串。它是一个完整的 XQuery 表达式,可以包含 prolog 声明。XQuery_string 的值用作 XMLTable 函数的输入;正是这个 XQuery 结果被分解并存储为关系数据。 • expr 中的是 XML_passing_clause 一个表达式,它返回 XMLType 一个 SQL 标量数据类型或一个实例,用作评 估 XQuery 表达式的上下文。您只能 expr 在 PASSING 子句中指定一个而无需标识符。每个计算的结果都 expr 绑定到 XQuery_string. 如果任何 expr 后面没有 AS 子句,则评估该表达式的结果将用作评估 XQuery_string. 该子句仅支持按值传递,不支持按引用传递。因此,BY VALUE 关键字是可选的,是为了语义清晰而提供的。 • 可选 RETURNING SEQUENCE BY REF 子句导致 XQuery 评估的结果通过引用返回。XML_table_column 这允许您在子句中引用源数据的任何部分。 • 如果省略此子句,则 XQuery 评估的结果将按值返回。也就是说,返回目标节点的副本而不是对实际节点的引 用。在这种情况下,您不能在 XML_table_column 子句中引用不在返回副本中的任何数据。特别是,您不能引 用源数据中目标节点之前的数据。 • 可选 COLUMNS 子句定义要由创建的虚拟表的列 XMLTable。 640 第 8 章 函数 • 如果省略该 COLUMNS 子句,则 XMLTable 返回一行,其中包含一个 XMLType 名为 COLUMN_VALUE 的 伪列。 • FOR ORDINALITY 指定它 column 是一列生成的行号。最多只能有一个 FOR ORDINALITY 子句。它被创建 为一 NUMBER 列。 • 对于除列之外的每个结果列 FOR ORDINALITY,您必须指定列数据类型,可以是 XMLType 或任何其他数据 类型。 • 如果列数据类型为 XMLType,则指定 XMLTYPE 子句。如果您指定可选 (SEQUENCE) BY REF 子句,则对 表达式所针对的源数据的引用将 PATH 作为列内容返回。否则,column 包含该目标数据的副本。 • XMLType 通过引用返回数据可让您指定其他列,其路径以源数据中的节点为目标,这些节点在 PATH 列的表 达式所针对的节点之外。如果列数据类型是任何其他数据类型,则指定 datatype。 • 可选 PATH 子句指定由 XQuery 表达式字符串寻址的 XQuery 结果部分将用作列内容。 如果省略,则假定 PATHXQuery 表达式。column 例如: XMLTable(... COLUMNS xyz) 相当于 XMLTable(... COLUMNS xyz PATH 'XYZ') 您可以使用不同 PATH 的子句将 XQuery 结果拆分为不同的虚拟表列。 可选 DEFAULT 子句指定当 PATH 表达式结果为空序列时要使用的值。它 expr 是一个 XQuery 表达式,经过计 算以产生默认值。 例子: 以下示例将 XQuery ’/Warehouse’ 应用于 warehouses 表的 warehouse_spec 列中的每个值的结果转换为一个包 含 Water 和 Rail 的虚拟关系表: SELECT warehouse_name warehouse,warehouse2."Water", warehouse2."Rail" FROM warehouses,XMLTABLE('/Warehouse' PASSING warehouses.warehouse_spec COLUMNS "Water" varchar2(6) PATH 'WaterAccess',"Rail" varchar2(6) PATH 'RailAccess') warehouse2; 8.539 XPATH 用法: xpath(xpath, xml [, nsarray]) 641 第 8 章 函数 功能: 函数 xpath 在 XML 值 “xml“上计算 XPath 1.0 表达式 xpath (a text value)。它返回一个 XML 值的数组,该 数组对应于该 XPath 表达式产生的结点集合。如果该 XPath 表达式返回一个标量值而不是一个结点集合,将会返回 一个单一元素的数组。第二个参数必须是一个良构的 XML 文档,它必须有一个单一根结点元素。该函数可选的第三 个参数是一个名字空间映射的数组。这个数组应该是一个二维 text 数组,其第二轴长度等于 2(即它应该是一个数组 的数组,其中每一个都由刚好两个元素组成)。每个数组项的第一个元素是名字空间的名称(别名),第二个元素是 名字空间的 URI。并不要求在这个数组中提供的别名和在 XML 文档本身中使用的那些名字空间相同(换句话说,在 XML 文档中和在 xpath 函数环境中,别名都是本地的)。 例子: SELECT xpath('/my:a/text()', 'test', ARRAY[ARRAY['my', 'http:// example.com']]); 要处理默认(匿名)命名空间,可以按使用下面的方法: SELECT xpath('//mydefns:b/text()', 'test', ARRAY[ARRAY['mydefns', 'http://example.com']]); 8.540 XPATH_EXISTS 用法: xpath_exists(xpath, xml [, nsarray]) 功能: 函数 xpath_exists 是 xpath 函数的一种特殊形式。这个函数不是返回满足 XPath 1.0 表达式的单一 XML 值, 它返回一个布尔值表示查询是否被满足 (具体来说,它是否产生了空节点集以外的任何值)。这个函数等价于标准的 XMLEXISTS 谓词,不过它还提供了对一个名字空间映射参数的支持。 例子: 642 第 8 章 函数 SELECT xpath_exists('/my:a/text()', 'test', ARRAY[ARRAY['my', 'http://example.com']]); 8.541 YEAR 用法: year(text) 功能: 抽取字符串中的年份字段。 例子: SELECT year('2021-10-05'); 8.542 YEARWEEK(MySQL 模式) 用法: yearweek(n [, mode]) 功能: 返回指定日期的年份与日期所在当年周数值。 参数说明: n:date、timestamp、time 等时间日期类型。当参数 n 为 time 类型时,该参数以当前系统日期时间为值,并被 隐式转化为 timestamp 类型再进行计算。 mode:integer、numeric 等数值类型、double precision 等浮点数类型,默认值为 0。指定 mode 参数后的周数计 算规则如下: 643 第 8 章 函数 • 当参数 mode 为 0 时,函数将以一周第一天为周日计算,返回值范围为 0 至 53,且一年中多一个星期天。 • 当参数 mode 为 1 时,函数将以一周第一天为周一计算,返回值范围为 0 至 53。 • 当参数 mode 为 2 时,函数将以一周第一天为周日计算,返回值范围为 1 至 53,且一年中多一个星期天。 • 当参数 mode 为 3 时,函数将以一周第一天为周一计算,返回值范围为 1 至 53。 • 当参数 mode 为 4 时,函数将以一周第一天为周日计算,返回值范围为 0 至 53。 • 当参数 mode 为 5 时,函数将以一周第一天为周一计算,返回值范围为 0 至 53,且一年中多一个星期天。 • 当参数 mode 为 6 时,函数将以一周第一天为周日计算,返回值范围为 1 至 53。 • 当参数 mode 为 7 时,函数将以一周第一天为周一计算,返回值范围为 1 至 53,且一年中多一个星期天。 注意: 1. 参数 mode 存在小数时,将其四舍五入成 int 类型后进行计算; 2. 当 mode 值不在 0 至 7 范围内时,将对该 mode 值进行对 8 的取余操作,并将余数的绝对值作为 mode 参数 值。 返回值: integer 类型 例子: SELECT YEARWEEK(DATE'2022-01-02') "YEARWEEK"; YEARWEEK ------------202152 SELECT YEARWEEK(TIMESTAMP'2022-01-05 1:00:00') "YEARWEEK"; YEARWEEK ------------202201 8.543 用户自定义函数 您可以使用 PL/SQL、Java 或 C 编写用户定义的函数,以提供 SQL 或 SQL 内置函数中不可用的功能。用户定 义的函数可以出现在 SQL 语句中可能出现表达式的任何位置。 例如,用户定义的函数可用于以下情况: 644 第 8 章 函数 • SELECT 语句的选择列表 • WHERE 条款的条件 • CONNECT BY, START WITH, ORDER BY, 和 GROUP BY 子句 • INSERT 语句的 VALUES 子句 • UPDATE 语句的 SET 子句 提示: KingbaseES SQL 不支持调用带有布尔参数或返回的函数。因此,如果您的用户定义函数将从 SQL 语句中调 用,您必须将它们设计为返回数字(0 或 1)或字符串(’ TRUE’ 或’ FALSE’)。 用户定义函数: 可选表达式列表必须匹配函数、包或运算符的属性。 • 对用户定义函数的限制 DISTINCT 和 ALL 关键字仅对用户定义的聚合函数有效。 另请参阅: CREATE FUNCTION 获取有关创建函数的信息,包括对用户定义函数的限制。 • 先决条件 用户定义的函数必须创建为顶级函数或使用包规范声明,然后才能在 SQL 语句中命名。 要在 SQL 达式中使用用户函数,您必须拥有该用户函数或拥有 EXECUTE 该用户函数的权限。要查询使用用户 函数定义的视图,您必须对视图具有 READ 或 SELECT 权限。从视图中选择不需要单独 EXECUTE 的权限。 另请参阅: 645 第 8 章 函数 CREATE FUNCTION 获取有关创建顶级函数的信息,CREATE PACKAGE 获取有关指定打包函数的信息 • 名称优先级 在 SQL 语句中,数据库列的名称优先于不带参数的函数名称。例如,如果人力资源经理在 hr 架构中创建以下两 个对象: CREATE TABLE new_emps (new_sal NUMBER, ...); CREATE FUNCTION new_sal RETURN NUMBER IS BEGIN ... END; 然后在以下两个语句中,对的引用是 new_sal 指列 new_emps.new_sal: SELECT new_sal FROM new_emps; SELECT new_emps.new_sal FROM new_emps; 要访问该功能 new_sal,您将输入: SELECT hr.new_sal FROM new_emps; 以下是 SQL 表达式中允许的对用户函数的一些示例调用: circle_area (radius) payroll.tax_rate (empno) hr.employees.tax_rate (dependent, empno)@remote • 例子 tax_rate 要从 schema 调用 user 函数 hr,对 ss_no 和 sal 中的列执行它 tax_table,指定以下内容: SELECT hr.tax_rate (ss_no, sal) INTO income_tax FROM tax_table WHERE ss_no = tax_id; 该 INTO 子句是 PL/SQL,它允许您将结果放入变量 income_tax 中。 • 命名约定 如果只给出了一个可选的模式或包名,那么第一个标识符可以是模式名或包名。例如,判断是否 PAYROLL 在引用中 PAYROLL。TAX_RATE 是模式或包名称,KingbaseES 数据库按如下方式进 行: – 检查 PAYROLL 当前架构中的包。 – 如果 PAYROLL 未找到包,则查找 PAYROLL 包含顶级 TAX_RATE 函数的模式名称。如果没 有找到这样的函数,则返回错误。 646 第 8 章 函数 – 如果 PAYROLL 在当前模式中找到包,则 TAX_RATE 在包中查找函数 PAYROLL。如果没有 找到这样的函数,则返回错误。 您还可以使用您为其定义的任何同义词来引用存储的顶级函数。 647 第 9 章 常见 DDL 子句 9 第 章 常见 DDL 子句 本文档描述了出现在 SQL 语句中的一些常用数据定义子句。包含以下小节: • 约束子句 • LOG 子句 • 存储子句 9.1 约束子句 用途 SQL 允许我们在列和表上定义约束。约束让我们能够根据我们的愿望来控制表中的数据。如果一个用户试图在 一个列中保存违反一个约束的数据,一个错误会被抛出。 约束子句通常出现在以下语句中: CREATE TABLE -- 创建表时指定表列的约束。 ALTER TABLE -- 对已有表的调整。 CREATE VIEW -- 创建视图时。 ALTER VIEW -- 调整视图时。 约束名称 CONSTRAINT 是为约束命名时使用的关键字,请在约束名称之前使用,把约束定义放在名称之后。如果没有以这 种方式指定约束名称,系统将自动为约束命名。 如 constraintname: CREATE TABLE distributors ( did integer, name varchar(40), CONSTRAINT constraintname CHECK (did > 100 AND name <> '') ); 648 第 9 章 常见 DDL 子句 常见约束子句的类型有: NOT NULL 该列不允许包含空值。 NULL 该列允许包含空值。这是默认情况。 这个子句只是提供与非标准 SQL 数据库的兼容。在新的应用中不推荐使用。 CHECK ( expression ) [ NO INHERIT ] CHECK 指定一个产生布尔结果的表达式,一个插入或更新操作要想成功,其中新的或被更新的行必须满足 该表达式。计算出 TRUE 或 UNKNOWN 的表达式就会成功。只要任何一个插入或更新操作的行产生了 FALSE 结果,将报告一个错误异常并且插入或更新不会修改数据库。一个被作为列约束指定的检查约束 只应该引用该列的值,而一个出现在表约束中的表达式可以引用多列。 当前,CHECK 表达式不能包含子查询,也不能引用当前行的列之外的变量。可以引用系统列 tableoid, 但不能引用其他系统列。 一个被标记为 NO INHERIT 的约束将不会传播到子表。 当一个表有多个 CHECK 约束时,检查完 NOT NULL 约束后,对于每一行会以它们名称的字母表顺序来进 行检查(V8R3 版本之前的 KingbaseES 对于 CHECK 约束不遵从任何特定的引发顺序)。 UNIQUE (列约束) UNIQUE ( column_name [, ... ] ) [ INCLUDE ( column_name [, ...]) ] (表约束) UNIQUE 约束指定一个表中的一列或多列组成的组包含唯一的值。唯一表约束的行为与列约束的行为相 同,只是表约束能够跨越多列。 对于一个唯一约束的目的来说,空值不被认为是相等的。 每一个唯一表约束必须命名一个列的集合,并且它与该表上任何其他唯一或主键约束所命名的列集合都不 相同(否则它将是一个被列举了两次的约束)。 在为多级分区层次结构建立唯一约束时,必须在约束定义中包含目标分区表的分区键的所有列,以及它的 所有子代分区表的列。 649 第 9 章 常见 DDL 子句 添加唯一约束将自动在约束中使用的列或列组上创建唯一的 btree 索引。可选子句 INCLUDE 添加到索引 的一个或多个列上,在这些列上不强制唯一性。注意,虽然约束没有强制包含在列上,但它仍然依赖于它 们。因此,这些列上的某些操作 (例如 DROP COLUMN) 可能导致级联约束和索引删除。 PRIMARY KEY (列约束) PRIMARY KEY ( column_name [, ... ] ) [ INCLUDE ( column_name [, ...]) ] (表约束) PRIMARY KEY 约束指定表的一个或者多个列只能包含唯一(不重复)、非空的值。一个表上只能指定一个 主键,可以作为列约束或表约束。 主键约束所涉及的列集合应该不同于同一个表上定义的任何唯一约束的列集合(否则,该唯一约束是多余 的并且会被丢弃)。 PRIMARY KEY 强制的数据约束可以看成是 UNIQUE 和 NOT NULL 的组合,但是把一组列标识为主键也为模 式设计提供了元数据,因为主键标识其他表可以依赖这一个列集合作为行的唯一标识符。 PRIMARY KEY 约束与放在分区表上的 UNIQUE 约束相同。 添加 PRIMARY KEY 约束将自动在约束中使用的列或列组上创建唯一的 btree 索引。可选的 INCLUDE 子句 允许指定列的列表,这些列将包含在索引的非键部分中。虽然对包含的列不强制惟一性,但约束仍然依赖 于它们。因此,对所包含列的某些操作 (例如 DROP COLUMN) 可能导致级联约束和索引删除。 EXCLUDE [ USING index_method ] ( exclude_element WITH operator [, ... ] ) index_parameters [ WHERE ( predicate ) ] EXCLUDE 子句定一个排除约束,它保证如果任意两行在指定列或表达式上使用指定操作符进行比较,不是 所有的比较都将会返回 TRUE。如果所有指定的操作符都测试相等,这就等价于一个 UNIQUE 约束,尽管 一个普通的唯一约束将更快。但是,排除约束能够指定比简单相等更通用的约束。例如,你可以使用 && 操作符指定一个约束,要求表中没有两行包含相互覆盖的圆(见几何类型 )。 排除约束使用一个索引实现,这样每一个指定的操作符必须与用于索引访问方法 “index_method“的 650 第 9 章 常见 DDL 子句 一 个 适 当 的 操 作 符 类 (见 操 作 符 类 和 操 作 符 族) 相 关 联。 操 作 符 被 要 求 是 交 换 的。 每 一 个 “ex- clude_element“可以选择性地指定一个操作符类或者顺序选项,这些在CREATE INDEX 中有完整描述。 访问方法必须支持 amgettuple,目前这意味着 GIN 无法使用。尽管允许,但是在一个排除约束中使用 B-树或哈希索引没有意义,因为它无法做得比一个普通唯一索引更出色。因此在实践中访问方法将总是 GiST 或 SP-GiST。 “predicate“允许你在该表的一个子集上指定一个排除约束。在内部这会创建一个部分索引。注意在为此周 围的圆括号是必须的。 REFERENCES reftable [ ( refcolumn ) ] [ MATCH matchtype ] [ ON DELETE referential_action ] [ ON UPDATE referential_action ] (列约束) FOREIGN KEY ( column_name [, ... ] ) REFERENCES reftable [ ( refcolumn [, ... ] ) ] [ MATCH matchtype ] [ ON DELETE referential_action ] [ ON UPDATE referential_action ] (表约束) 这些子句指定一个外键约束,它要求新表的一列或一个列的组必须只包含能匹配被引用表的某个行在 被引用列上的值。如果 “refcolumn“列表被忽略,将使用 “reftable“的主键。被引用列必须是被引用表 中一个非可延迟唯一约束或主键约束的列。用户必须在被引用的表(或整个表或特定的引用列)上拥有 REFERENCES 权限。添加外键约束需要在相关表上加独占锁。被插入到引用列的一个值会使用给定的匹配 类型与被引用表的值进行匹配。有三种匹配类型:MATCH FULL、MATCH PARTIAL 以及 MATCH SIMPLE(这 是默认值)。MATCH FULL 将不允许一个多列外键中的一列为空,除非所有外键列都是空;如果它们都是 空,则不要求该行在被引用表中有一个匹配。MATCH SIMPLE 允许任意外键列为空,如果任一为空,则不 651 第 9 章 常见 DDL 子句 要求该行在被引用表中有一个匹配。MATCH PARTIAL 现在还没有被实现(当然,NOT NULL 约束能被应用 在引用列上来组织这些情况发生)。 另外,当被引用列中的数据被改变时,在这个表的列中的数据上可以执行特定的动作。ON DELETE 指定当 被引用表中一个被引用行被删除时要执行的动作。同样,ON UPDATE 指定当被引用表中一个被引用列被 更新为新值时要执行的动作。如果该行被更新,但是被引用列并没有被实际改变,不会做任何动作。除了 NO ACTION 检查之外的引用动作不能被延迟,即便该约束被声明为可延迟的。对每一个子句可能有以下动 作: NO ACTION 产生一个错误指示删除或更新将会导致一个外键约束违背。如果该约束被延迟,并且仍存在 引用行,这个错误将在约束检查时被产生。这是默认动作。 RESTRICT 产生一个错误指示删除或更新将会导致一个外键约束违背。这个动作与 NO ACTION 形同,但是 该检查不是可延迟的。 CASCADE 删除任何引用被删除行的行,或者把引用列的值更新为被引用列的新值。 SET NULL 将引用列设置为空。 SET DEFAULT 设置引用列为它们的默认值(如果该默认值非空,在被引用表中必须有一行匹配该默认 值,否则该操作将会失败)。 如果被引用列被频繁地更改,最好在引用列上加上一个索引,这样与外键约束相关的引用动作能够更高效 地被执行。 DEFERRABLE | NOT DEFERRABLE 这个子句控制该约束是否能被延迟。一个不可延迟的约束将在每一次命令后立刻被检查。可延迟约束的 检查将被推迟到事务结束时进行(使用SET CONSTRAINTS 命令)。NOT DEFERRABLE 是默认值。当 前,只有 UNIQUE、PRIMARY KEY、EXCLUDE 以及 REFERENCES(外键)约束接受这个子句。NOT NULL 以 及 CHECK 约束是不可延迟的。注意在包括 ON CONFLICT DO UPDATE 子句的 INSERT 语句中,可延迟约 束不能被用作冲突裁判者。 INITIALLY IMMEDIATE | INITIALLY DEFERRED 如 果 一 个 约 束 是 可 延 迟 的, 这 个 子 句 指 定 检 查 该 约 束 的 默 认 时 间。 如 果 该 约 束 是 INITIALLY IMMEDIATE,它会 在每一个语句 之后 被检查。 这是默认 值。如 果该 约束 是 INITIALLY DEFERRED,它 只会在事务结束时被检查。约束检查时间可以用SET CONSTRAINTS 命令修改。 652 第 9 章 常见 DDL 子句 ENABLE VALIDATE/NOVALIDATE | DISABLE NOVALIDATE/VALIDATE 这个子句用来设置或修改约束的状态,包括 ENABLE/DISABLE 与 VALIDATE/NOVALIDATE 两个组合,共 四个状态。如果该约束是 ENABLE,数据库中输入或者更新数据要进行约束规则检查,不符合约束规则 的数据不能输入数据库,这是默认值。相反如果该约束是 DISABLE,那么输入或更新数据将不会进行约 束规则检查。一个 VALIDATE 状态的约束表示数据库内已有数据符合约束规则。如果设置或修改约束为 ENABLE 状态时并未指定有效性状态,VALIDATE 是默认值。一个 DISABLE VALIDATE 状态的约束,为了 保证有效性状态不被破坏,会将数据库表设置为只读状态,禁用对表的 DML 操作。如果为一个存在的 表增加 VALIDATE 状态的约束,将会对表内的数据做约束规则检查。一个 NOVALIDATE 状态的约束表示 数据库表内已有数据未做约束规则检查。设置或修改约束为 DISABLE 状态时,如果未指定有效性状态, NOVALIDATE 是默认值。如果为一个存在的表增加 NOVALIDATE 状态的约束,将不会对已有数据做有效性 检查(ENABLE 状态的唯一约束和主键约束依赖于索引,创建索引会检查已有数据的唯一性)。 目前这个子句只支持检查约束、唯一约束、主键和外键约束。 在分区表上创建或修改约束状态时,约束状态会级联应用到分区上的约束。分区表上的父约束与分区上的 子约束状态总是保持相同的,不可以单独修改分区表或分区上的有继承关系约束状态,但是对于分区表或 者分区上独立的约束可以单独修改约束状态。 前置条件 需拥有语句所需的权限。 示例 为表 films 定义一个唯一表约束。唯一表约束能够被定义在表的一列或多列上: CREATE TABLE films ( code char(5), title varchar(40), did integer, date_prod date, kind varchar(10), len interval hour to minute, CONSTRAINT production UNIQUE(date_prod) ); 定义一个列检查约束: CREATE TABLE distributors ( did integer CHECK (did > 100), 653 第 9 章 常见 DDL 子句 name varchar(40) ); 定义一个表检查约束: CREATE TABLE distributors ( did integer, name varchar(40), CONSTRAINT con1 CHECK (did > 100 AND name <> '') ); 为表 films 定义一个主键表约束: CREATE TABLE films ( code char(5), title varchar(40), did integer, date_prod date, kind varchar(10), len interval hour to minute, CONSTRAINT code_title PRIMARY KEY(code,title) ); 为表 distributors 定义一个主键约束。下面的两个例子是等价的,第一个使用表约束语法,第二个使用列约束 语法: CREATE TABLE distributors ( did integer, name varchar(40), PRIMARY KEY(did) ); CREATE TABLE distributors ( did integer PRIMARY KEY, name varchar(40) ); 为列 name 赋予一个文字常量默认值,安排列 did 的默认值是从一个序列对象中选择下一个值产生,并且让 modtime 的默认值是该行被插入的时间: CREATE TABLE distributors ( name varchar(40) DEFAULT 'Luso Films', did integer DEFAULT nextval('distributors_serial'), modtime timestamp DEFAULT current_timestamp ); 654 第 9 章 常见 DDL 子句 在表 distributors 上定义两个 NOT NULL 列约束,其中之一被显式给定了一个名称: CREATE TABLE distributors ( did integer CONSTRAINT no_null NOT NULL, name varchar(40) NOT NULL ); 为 name 列定义一个唯一约束: CREATE TABLE distributors ( did integer, name varchar(40) UNIQUE ); 同样的唯一约束用表约束指定: CREATE TABLE distributors ( did integer, name varchar(40), UNIQUE(name) ); 创建相同的表,指定表和它的唯一索引指定 70% 的填充因子: CREATE TABLE distributors ( did integer, name varchar(40), UNIQUE(name) WITH (fillfactor=70) ) WITH (fillfactor=70); 创建表 circles,带有一个排除约束阻止任意两个圆重叠: CREATE TABLE circles ( c circle, EXCLUDE USING gist (c WITH &&) ); 9.2 LOG 子句 用途 LOG 子句允许数据库指定对表的操作是否记录到 WAL 日志中。 LOG 子句通常出现在以下语句中: 655 第 9 章 常见 DDL 子句 CREATE/ALTER TABLE 创建或变更表时可用存储子句。 常见 LOG 子句的类型有: LOGGED 如果指定,该表被创建为一个记录日志记录 (WAL) 的表。被写入到记录日志的表中的数据会被写到预写 式日志中。 UNLOGGED 如果指定,该表被创建为一个不受日志记录的表。被写入到不做日志的表中的数据不会被写到预写式日志 中,这让它们比普通表快非常多。但是,它们在崩溃时是不安全的:一个不做日志的表在一次崩溃或非干 净关闭之后会被自动地截断。一个不做日志的表中的内容也不会被复制到后备服务器中。在一个不做日志 的表上创建的任何索引也会自动地不被日志记录。 前置条件 需拥有语句所需的权限。 示例 创建 UNLOGGED 表 CREATE UNLOGGED TABLE test ( id int, name varchar(40)); 调整表为 LOGGED ALTER TABLE test SET LOGGED; 9.3 存储子句 用途 存储子句允许指定数据库存储相关参数,存储参数会影响访问存储在数据库中的数据所需要的时间,以及数据库 空间的使用效率。 存储子句通常出现在以下语句中: CREATE/ALTER TABLE 656 第 9 章 常见 DDL 子句 图 9.3.1: 创建或变更表时可用存储子句。 CREATE/ALTER INDEX 图 9.3.2: 创建和变更索引时。 CREATE/ALTER MATERIALIZED VIEW 图 9.3.3: 创建物化视图时。 常见存储子句的类型有: fillfactor (integer) 一个表的填充因子是一个 10 到 100 之间的百分数。100(完全填满)是默认值。当一个较小 的填充因子被指定时,INSERT 操作会把表页面只填满到指定的百分比,每个页面上剩余的空间被保留给该页上 行的更新。这就让 UPDATE 有机会把一行的已更新版本放在与其原始版本相同的页面上,这比把它放在一个不 同的页面上效率更高。对于一个项从来不会被更新的表来说,完全填满是最好的选择,但是在更新繁重的表上 则较小的填充因子更合适。这个参数不能对 TOAST 表设置。 toast_tuple_target (integer) toast_tuple_target 指定在尝试将长列值移动到 TOAST 表之前所需的最小元组长 度,也是我们在开始 toasting 后尝试将长度减少到以下的目标长度。这只影响标记为外部或扩展的列,并且只 应用于新元组——对现有行没有影响。默认情况下,该参数设置为每个块至少允许 4 个元组,其默认块大小为 2040 字节。有效值在 128 字节和 (块大小-头) 之间,默认为 8160 字节。对于很短或很长的行,更改这个值可能 没什么用。注意,默认设置通常接近于最优,在某些情况下,设置此参数可能会产生负面影响。此参数不能用 于 TOAST 表。 657 第 9 章 常见 DDL 子句 autovacuum_enabled, toast.autovacuum_enabled (boolean) 为一个特定的表启用或者禁用自动清理守护进程。 如果为真,自动清理守护进程将遵照 自动清理后台进程中讨论的规则在这个表上执行自动的 VACUUM 或者 ANALYZE 操作。如果为假,这个表不会被自动清理,但是为了阻止事务 ID 回卷时还是会对它进行自动的清理。 有关回卷阻止请见 防止事务 ID 回卷失败。如果 autovacuum 参数为假,自动清理守护进程根本就不会运行 (除非为了阻止事务 ID 回卷),设置独立的表存储参数也不会覆盖这个设置。因此显式地将这个存储参数设置 为 true 很少有大的意义,只有设置为 false 才更有用。 vacuum_index_cleanup, toast.vacuum_index_cleanup (boolean) 在此表上运行 VACUUM 时,启用或禁用索引清 理。默认值为 true。禁用索引清理可以大大加快 VACUUM 速度,但是,如果频繁修改表,也可能导致索引严重 膨胀。INDEX_CLEANUP 的参数VACUUM ,如果被指定,则重写此选项的值。 vacuum_truncate, toast.vacuum_truncate (boolean) 启用或禁用 vacuum 以尝试截断该表末尾的任何空页。默认 值为 true。如果为 true,VACUUM 和自动清理将执行截断操作,截断的页面的磁盘空间返回给操作系统。注 意,截断需要表中的 ACCESS EXCLUSIVE 锁。TRUNCATE 的参数VACUUM ,如果被指定,则重写此选项的值。 autovacuum_vacuum_threshold, toast.autovacuum_vacuum_threshold (integer) autovacuum_vacuum_threshold 参数对于每个表的值。 autovacuum_vacuum_scale_factor, toast.autovacuum_vacuum_scale_factor (float4) autovacuum_vacuum_scale_factor 参数对于每个表的值。 autovacuum_analyze_threshold (integer) autovacuum_analyze_threshold 参数对于每个表的值。 autovacuum_analyze_scale_factor (float4) autovacuum_analyze_scale_factor 参数对于每个表的值。 autovacuum_vacuum_cost_delay, toast.autovacuum_vacuum_cost_delay (floating point) autovacuum_vacuum_cost_delay 参数对于每个表的值。 autovacuum_vacuum_cost_limit, toast.autovacuum_vacuum_cost_limit (integer) autovacuum_vacuum_cost_limit 参数对于每个表的值。 autovacuum_freeze_min_age, toast.autovacuum_freeze_min_age (integer) vacuum_freeze_min_age 参数对于 每个表的值。注意自动清理将忽略超过系统范围 autovacuum_freeze_max_age 参数一半的针对每个表的 autovacuum_freeze_min_age 参数。 autovacuum_freeze_max_age, toast.autovacuum_freeze_max_age (integer) autovacuum_freeze_max_age 参数对于每个表的值。注意自动清理将忽略超过系统范围参数(只能被设置得较小)一半的针对每个表的 autovacuum_freeze_max_age 参数。 autovacuum_freeze_table_age, toast.autovacuum_freeze_table_age (integer) vacuum_freeze_table_age 参 数对于每个表的值。 autovacuum_multixact_freeze_min_age, toast.autovacuum_multixact_freeze_min_age (integer) vacuum_multixact_freeze_min_age 参数对于每个表的值。注意自动清理将忽略超过系统范围 autovacuum_multixact_freeze_max_age 参数一半的针对每个表的 autovacuum_multixact_freeze_min_age 参 数。 autovacuum_multixact_freeze_max_age, toast.autovacuum_multixact_freeze_max_age (integer) autovacuum_multixact_freeze_max_age 参数对于每个表的值。注意自动清理将忽略超过系统范围参数 (只能被设置得较小)一半的针对每个表的 autovacuum_multixact_freeze_max_age 参数。 658 第 9 章 常见 DDL 子句 autovacuum_multixact_freeze_table_age, toast.autovacuum_multixact_freeze_table_age (integer) vacuum_multixact_freeze_table_age 参数对于每个表的值。 log_autovacuum_min_duration, toast.log_autovacuum_min_duration (integer) log_autovacuum_min_duration 参数对于每个表的值。 user_catalog_table (boolean) 声明该表是一个用于逻辑复制目的的额外的目录表。不能对 TOAST 表设置这个参 数。 WITH ( storage_parameter [ = value ] [, ... ] ) 这个子句为一个表或索引指定可选的存储参数。为了向后兼 容,WITH 子句可以包含 OIDS=FALSE 以指定新表的行不应该包含 OIDs(对象标识符),OIDS=TRUE 不再被支持。 alloc_space_for_null (boolean) 声明该表是一个本地更新表,向本地更新表插入数据时会自动为 null 列预分配 内存空间,空间的大小于列的数据类型相匹配。数据库的存储机制限制了只能为固定长度的数据类型预分配 空间,表上允许存在变长数据类型,但是变长数据类型后面不允许有固定长度数据类型。该参数只适用于普通 表,不支持 view、index、临时表,全局临时表、分区表等。该参数只能在建表时指定,不支持通过 alter table 命令设置 alloc_space_for_null 参数。预分配空间的表可以用于本地更新。预分配空间的表存在诸多限制: 不支持唯一约束,外键约束,排他约束; 不支持除主键之外的索引; 不支持 dblink; 不支持显式事物;不支持 function/procedure; 不支持大部分 alter table 操作;不支持闪回查询和闪回表;不支持基于预分配空间创建物 化视图;不支持创建 trigger/rule; template_alloc_space_for_null (boolean) 声明该表为本地更新模板表,使用模板表创建新表时,新表将自动设 置 alloc_space_for_null 参数。如果该模板表上存在主键约束,新表将继承模板表的主键约束。 只支持 create table as 和 select into table 方式创建新表, 在子查询、复合查询和层次查询中使用模板表时不支 持该功能,通过 dblink 方式使用模板表创建新表时不支持该功能。 以下情况则不能继承主键约束: a) 指定了多个基表,则不能继承主键约束; b) Select 的列不包含所有的主键列; c) 基表不含主键; 示例 创建表,指定表和它的唯一索引 70% 的填充因子。 CREATE TABLE distributors ( did integer, name varchar(40), UNIQUE(name) WITH (fillfactor=70) ) WITH (fillfactor=70); 659 第 10 章 第 查询和子查询 10章 查询和子查询 本章描述 SQL 查询以及子查询。包含以下章节: • 关于查询和子查询 • 创建简单查询 • 层次查询 • 集合操作 • 查询结果排序 • JOIN 操作 • 使用子查询 • 限制嵌套查询层数 • DUAL 表查询 • PIVOT 和 UNPIVOT 行列转换 • 公共表达式 10.1 关于查询和子查询 从数据库中检索数据的过程或命令叫做查询。在 SQL 里 SELECT 命令用于指定查询。 SELECT 命令的一般语法是: [WITH with_queries] SELECT select_list FROM table_expression [sort_specification] 下面几个章节将详细介绍如何选择列表、表表达式和排序声明。 660 第 10 章 查询和子查询 一个简单类型的查询为: SELECT * FROM table1; 假设有一个表叫做 table1,这条命令将 table1 中检索所有行和所有用户定义的列(检索的方法取决于客户端 应用。例如,ksql 程序将在屏幕上显示一个 ASCII 形式的表格,而客户端库将提供函数来从检索结果中抽取单个 值)。选择列表声明 * 意味着所有表表达式提供的列。一个选择列表也可以选择可用列的一个子集或者在使用它们 之前对列进行计算。例如,如果 table1 有叫做 a、b 和 c 的列(可能还有其他),那么可以用下面的查询: SELECT a, b + c FROM table1; (假设 b 和 c 都是数字数据类型)。 FROM table1 是一种非常简单的表表达式:它只读取了一个表。通常,表表达式可以是基本表、连接和子查询组 成的复杂结构。但也可以省略整个表表达式而把 SELECT 命令当做一个计算器: SELECT 3 * 4; 如果选择列表里的表达式返回变化的结果,那么这就更有用了。例如,你可以用这种方法调用函数: SELECT random(); 子查询指定了一个派生表,它必须被包围在圆括弧里,并且可以被赋予一个表别名,若未指定别名则系统会自动 生成一个别名。例如: FROM (SELECT * FROM table1) AS alias_name 或者 FROM (SELECT * FROM table1) 这个例子等效于 FROM table1 AS alias_name。更有趣的情况是在子查询里面有分组或聚集的时候,子查询不 能被简化为一个简单的连接。 一个子查询也可以是一个 VALUES 列表: FROM (VALUES ('anne', 'smith'), ('bob', 'jones'), ('joe', 'blow')) AS names(first, last) 再次的,这里可以使用一个表别名,若未指定则系统自动生成一个别名。为 VALUES 列表中的列分配别名是可选 的,但是指定别名这样做是一个好习惯。 10.2 创建简单查询 出现在 SELECT 关键字之后的 FROM 子句之前的表达式列表成为选择列表。在选择列表中,您可以指定数据 库从一个或多个表、视图、物化视图返回的结果集中的一个或多个列。列数及其数据类型和长度由选择列表的元素决 定。 如果两个或多个表有一些共同的列名,则必须用表名限定列名。否则完全限定的列名是可选的。明确限定表和列 名是一种比较谨慎的方式,但我们在使用过程中通常会忽略表名。 661 第 10 章 查询和子查询 可以使用列的别名来标记选择列表中的表达式,这样结果集会以别名来显示列。在查询期间,别名有效的避免了 列名冲突,别名可以在 ORDER BY 子句中使用,但是不能再其子查询中使用。 10.3 层次查询 层次查询是一种特定类型的查询,用于在基于父子关系的数据中以层次顺序返回结果集中的记录。通常,层次是 用一个反转顺序的树结构表示。树由相互连接的节点组成。每个节点可能会连接 0 个或多个子节点。在层次查询中, 结果集的记录为一或多棵树中的节点。 KingbaseES 和 Oracle 均支持层次查询,且二者兼容。 下表列出了层次查询中的所有操作符: 表 10.3.1: 层次查询的操作符列表 操作符 功能 PRIOR 在当前元组的父元组上求值,如果当前元组是根(Root)元组,则求值为 NULL。 CONNECT_BY_ROOT 在当前层次查询的根(Root)元组上求值。 伪列与普通列十分相似,但其值并不是和表数据存储在一起的。层次查询具有三个伪列,具体如下表所示。 表 10.3.2: 层次查询的伪列列表 伪列 描述 LEVEL 伪列 描述当前元组的所在的层 CONNECT_BY_ISLEAF 伪列 描述当前节点是否为叶节点。若是为 1,否则为 0。 CONNECT_BY_ISCYCLE 伪列 如果一个元组的 CONNECT_BY_ISCYCLE 值是 1,则代表这 个元组有子元组,并且这个子元组又是它的祖先元组,即数据 库中的数据成环;否则为 0。 10.3.1 层次查询示例 例 10-1:层次查询应用的示例。在该例中,表 emp 表数据的树状结构图如下所示: 662 第 10 章 查询和子查询 执行以下附带层次查询的 SELECT 命令: CREATE TABLE emp (ename varchar(20), empno int, mgr int); INSERT INTO emp (ename,empno,mgr) values ('KING',7839,NULL),('JONES',7566,7839),('SCOTT',7788,7566),('ADAMS ',7876,7788),('FORD',7902,7566), ('SMITH',7369,7902),('ANDERSON',8142,7902),('BLAKE',7698,7839),('ALLEN',7499,7698),('WARD',7521,7698),( 'MARTIN',7654,7698),('TURNER',7844,7698), ('JAMES',7900,7698),('CLARK',7782,7839),('MILLER',7934,7782); SELECT ename, empno, mgr FROM emp START WITH mgr IS NULL CONNECT BY PRIOR empno = mgr; 运行结果如下所示: ename | empno | mgr ----------+-------+-----KING | 7839 | CLARK | 7782 | 7839 MILLER | 7934 | 7782 BLAKE | 7698 | 7839 JAMES | 7900 | 7698 TURNER | 7844 | 7698 663 第 10 章 MARTIN | 7654 | 7698 WARD | 7521 | 7698 ALLEN | 7499 | 7698 JONES | 7566 | 7839 FORD | 7902 | 7566 ANDERSON | 8142 | 7902 SMITH | 7369 | 7902 SCOTT | 7788 | 7566 ADAMS | 7876 | 7788 查询和子查询 (15 rows) 例 10-2:层次查询伪列的示例。通过对伪列 LEVEL 值执行 LPAD 操作,雇员名称被缩进,这样能够进一步强 调每条记录在层次中的深度。 SELECT LEVEL, LPAD (' ', 2 * (LEVEL - 1)) || ename "employee", empno, mgr FROM emp START WITH mgr IS NULL CONNECT BY PRIOR empno = mgr; 这个查询的检索结果如下所示: level | employee | empno | mgr -------+----------------+-------+-----1 | KING | 7839 | 2 | | 7782 | 7839 | 7934 | 7782 | 7698 | 7839 3 | 2 | CLARK MILLER BLAKE 3 | JAMES | 7900 | 7698 3 | TURNER | 7844 | 7698 3 | MARTIN | 7654 | 7698 3 | WARD | 7521 | 7698 3 | ALLEN | 7499 | 7698 2 | JONES | 7566 | 7839 3 | FORD | 7902 | 7566 4 | ANDERSON | 8142 | 7902 4 | SMITH | 7369 | 7902 | 7788 | 7566 | 7876 | 7788 3 | 4 | SCOTT ADAMS (15 rows) 例 10-3:层次查询对同层节点排序的示例。层次查询语句如下所示: SELECT LEVEL, LPAD (' ', 2 * (LEVEL - 1)) || ename "employee", empno, mgr FROM emp START WITH mgr IS NULL CONNECT BY PRIOR empno = mgr ORDER SIBLINGS BY ename ASC; 664 第 10 章 查询和子查询 这个查询的检索结果如下所示: level | employee | empno | mgr -------+----------------+-------+-----1 | KING | 7839 | 2 | | 7698 | 7839 BLAKE 3 | ALLEN | 7499 | 7698 3 | JAMES | 7900 | 7698 3 | MARTIN | 7654 | 7698 3 | TURNER | 7844 | 7698 3 | WARD | 7521 | 7698 2 | CLARK 3 | MILLER | 7782 | 7839 | 7934 | 7782 2 | JONES | 7566 | 7839 3 | FORD | 7902 | 7566 4 | ANDERSON | 8142 | 7902 4 | SMITH | 7369 | 7902 | 7788 | 7566 | 7876 | 7788 3 | SCOTT 4 | ADAMS (15 rows) 例 10-4:层次查询的 WHERE 过滤的示例,查询语句如下所示: SELECT LEVEL, LPAD (' ', 2 * (LEVEL - 1)) || ename "employee", empno, mgr FROM emp WHERE mgr IN (7839, 7782, 7902, 7788) START WITH ename IN ('BLAKE','CLARK','JONES') CONNECT BY PRIOR empno = mgr ORDER SIBLINGS BY ename ASC; 这个查询的检索结果如下,在下面的结果中不满足 WHERE 子句的记录不会在输出中出现。 level | employee | empno | mgr -------+--------------+-------+-----1 | BLAKE | 7698 | 7839 1 | CLARK | 7782 | 7839 2 | | 7934 | 7782 | 7566 | 7839 3 | ANDERSON | 8142 | 7902 3 | SMITH | 7369 | 7902 3 | ADAMS | 7876 | 7788 MILLER 1 | JONES (7 rows) 665 第 10 章 10.4 查询和子查询 集合操作 KingbaseES 数据库的集合运算包括: UNION,UNION ALL,INTERSECT 和 MINUS 操作。 一般情况下当两个集合中的数据都比较多时,集合运算都是比较耗时的操作,使用时需要谨慎小心。如果可能, 可以使用 UNION ALL 操作代替 UNION 操作。 10.4.1 使用连接方式的原则 1. 嵌套循环连接(NESTED LOOP) 知识点描述 嵌套循环连接操作关系到两个表,一个内部表和一个外部表。KingbaseES 比较内部数据集的每一条记录和外部 数据集的每一条记录,并返回满足条件的记录。 嵌套循环连接通常会产生巨大的数据量,所以对嵌套循环连接的使用要有严格的限制。 当一个嵌套循环连接的内部表中存在索引的情况,嵌套循环连接变为改进的有索引的嵌套循环连接 (NESTED LOOP),通常有索引的嵌套循环连接在产生较小的数据量的情况下可以较快的执行。 在使用有索引的嵌套循环连接是必须确保在查询中使用了正确的驱动表和正确的驱动数据集,通常情况下使用包 含数据量较小的表作为驱动表。 一般如果使用基于成本的优化器,系统会自动选择驱动表,如果是使用基于规则的优化器,则后表作为驱动表。 应用原则 一般的嵌套循环连接的速度较慢,产生的数据量较大,应该严格控制其使用。 在使用有索引的嵌套循环连接时,必须保证其驱动表有合适的索引,最好为主键或唯一键,同时希望在另外一张 表在相同的列上有索引。 举例 下面给出了两种连接的例子: 对于不存在索引的表 students 和 score 执行以下操作: CREATE TABLE student (sno int ,sname varchar(20) ,ssex varchar(5)); CREATE TABLE score (sno int, cno int, degree numeric); INSERT INTO student (sno,sname,ssex) VALUES (101,'James','Male'),(102,'Marry','Fema'),(203,'Todd','Male'), (201,'Clark','Male'),(103,'Smith','Male'); INSERT INTO score (sno,cno,degree) VALUES (101,1,90.5),(102,2,88),(203,1,100),(201,2,60),(103,1,80.2); \d student Table "public.student" Column | Type | Collation | Nullable | Default --------+----------------------------+-----------+----------+--------- 666 第 10 章 sno | integer | | | sname | character varying(20 char) | | | ssex | character varying(5 char) | | | 查询和子查询 \d score Table "public.score" Column | Type | Collation | Nullable | Default --------+---------+-----------+----------+--------sno | integer | | | cno | integer | | | degree | numeric | | | EXPLAIN SELECT * FROM student, score WHERE student.sno = score.sno AND student.sno = 201; QUERY PLAN --------------------------------------------------------------------Nested Loop -> (cost=0.00..44.06 rows=24 width=126) Seq Scan on score (cost=0.00..24.88 rows=6 width=40) Filter: (sno = 201) -> Materialize -> (cost=0.00..18.89 rows=4 width=86) Seq Scan on student (cost=0.00..18.88 rows=4 width=86) Filter: (sno = 201) (6 rows) 为 NESTED LOOP JOIN,因为数据库需要对表 Student 中所有的行进行处理。如果此时 student 表的 sno 列 上有索引则上述查询的方式转变为有索引的嵌套循环连接 (Nested Loop)。 CREATE INDEX student_ind1 ON student(sno); CREATE INDEX EXPLAIN SELECT * FROM student, score WHERE student.sno = score.sno AND student.sno = 201; QUERY PLAN ----------------------------------------------------------------------------------Nested Loop (cost=10000000000.13..10000000033.08 rows=6 width=126) -> Index Scan using student_ind1 on student (cost=0.13..8.15 rows=1 width=86) Index Cond: (sno = 201)\d -> Seq Scan on score (cost=10000000000.00..10000000024.88 rows=6 width=40) Filter: (sno = 201) (5 rows) 2. 散列连接 (Hash Join) 知识点描述 散列连接将驱动表加载进内存,使用散列技术将驱动表与较大的表进行连接,连接过程中,对大表的访问使用了 散列访问。散列连接可以提高等连接的速度。 如果可用的散列空间内存足够大,可以加载构建输入,那么散列连接算法能够很好地运行简单的散列连接。 667 第 10 章 查询和子查询 应用原则 一般的散列连接发生在一个大表和一个小表做连接的时候,此时小表中的数据全部被读入内存,其处理的速度较 快。 举例 EXPLAIN SELECT * FROM student, score WHERE student.sno = score.sno; QUERY PLAN ----------------------------------------------------------------------Hash Join (cost=25.98..198.70 rows=4224 width=126) Hash Cond: (score.sno = student.sno) -> Seq Scan on score (cost=0.00..21.90 rows=1190 width=40) -> Hash (cost=17.10..17.10 rows=710 width=86) -> Seq Scan on student (cost=0.00..17.10 rows=710 width=86) (5 rows) 3. 合并连接 (Merge Join) 知识点描述 合并连接是指从目标表中读取两个记录数据集,并使用连接字段将两个记录集分别排序的操作。合并过程将来自 一个数据集的每一条记录同来自另一个数据集与之匹配的记录相连接,并返回记录数据集的交集。 合并连接有几种不同的排序方法:外部合并连接,反合并连接和半合并连接。这些不同的排列方法使得合并步骤 服务于不同的目的,可以是找到记录数据集的交集,也可以是找到满足 SQL 语句中 WHERE 子句条件的那些记录。 应用原则 一般的合并连接是在散列连接不能达到应用的要求或 KingbaseES 优化器认为排序合并连接效率更高的情况下使 用。在下述的条件下排序合并连接被使用: 1) 数据表之间的连接不是等值连接而是其它连接。 2) 数据库使用的优化模式是基于 RBO 而不是 CBO。 举例 EXPLAIN SELECT * FROM student, score WHERE student.sno = score.sno; QUERY PLAN ---------------------------------------------------------------------Merge Join (cost=83.80..90.07 rows=30 width=49) Merge Cond: (student.sno = score.sno) -> Sort (cost=1.11..1.12 rows=5 width=9) Sort Key: student.sno -> Seq Scan on student (cost=0.00..1.05 rows=5 width=9) -> Sort (cost=82.69..85.66 rows=1190 width=40) Sort Key: score.sno -> Seq Scan on score (cost=0.00..21.90 rows=1190 width=40) (8 rows) 668 第 10 章 10.4.2 查询和子查询 复杂查询的原则 1. 限制表连接操作所涉及的表的个数 对于数据库的连接操作操作,可以简单的将其想象为一个循环匹配的过程,每一次匹配相当于一次循环,每一个 连接相当于一层循环,则 N 个表的连接操作就相当于一个 N-1 层的循环嵌套。 一般的情况下在数据库的查询中涉及的数据表越多,则其查询的执行计划就越复杂,其执行的效率就越低,为此 需要尽可能的限制参与连接的表的数量。 1). 3-5 个表的处理方法 对于较少的数据表的连接操作,需要合理的确定连接的驱动表,从某种意义上说,确定合理的驱动表就是 确定多层循环嵌套中的最外层的循环,可以最大限度的提高连接操作的效率,可见选择合适的驱动表的重 要性。 RBO 模式下,在 SQL 语句中 FROM 子句后面的表就是要进行连接操作的数据表,KingbaseES 按照从右 到左的顺序处理这些表,让它们轮流作为驱动表去参加连接操作,这样可以把包含参与连接的数据量最少 的表放在 FROM 子句的最右端,按照从右到左的顺序依次增加表中参与连接数据的量。 CBO 模式下,则不需要考虑表放置的位置。 2). 5 个表以上的处理方法 对于涉及较多的表 (>5+) 的数据连接查询,其查询的复杂度迅速增加,其连接的存取路径的变化更大, 存取路径的个数与连接的表的个数的阶乘有关:当 n=5 时存取路径= 1X2X3X4X5=120 个,而当连接的 表的个数为 6 时存取路径变为 1X2X3X4X5X6=720 个,数据库优化器对于数据的存取路径的判断近乎为 不可能,此时完全依赖与用户的语句书写方式。 对于较多的表的连接,要求开发人员查询返回的结果能够有所预测,同时判断出各个参与连接的表中符合 条件的记录的数量,从而控制查询的运行时间。 同时为了提高查询的效率,此时可以把部分表的一些连接所形成的中间结果来代替原来的连接表,从而减 少连接的表的数目。 3). 对表连接操作涉及的表数目不应多于 8 个表 如果查询语句拥有过多的表连接,那么它的执行计划过于复杂且可控性降低,容易引起数据库的运行效率 低下,即使在开发测试环境中已经经过充分地测试验证,也不能保证在生产系统上由于数据量的变化而引 发的相关问题。应该在应用设计阶段就避免这种由于范式过高而导致的情况出现。 2. 限制嵌套查询的层数 应用中影响数据查询的效率的因素除了参与查询连接的表的个数以外,还有查询的嵌套层数。对于非关联查询, 嵌套的子查询相当于使查询语句的复杂度在算术级数的基础上增长,而对于关联查询而言,嵌套的子查询相当于使查 询语句的复杂度在几何级数的基础上增长。 因此,降低查询的嵌套层数有助于提高查询语句的效率。 对嵌套查询层数的限制要求:如果查询语句拥有过多的嵌套层数,那么会使该查询语句的复杂度高速增加,应该 在数据库设计阶段就避免这种情况出现,不应多于 5 层。 3. 灵活应用中间表或临时表 669 第 10 章 查询和子查询 在对涉及较多表的查询和嵌套层数较多的复杂查询的优化过程中,使用中间表或临时表是优化、简化复杂查询的 一个重要的方法。 通过使用一些中间表,可以把复杂度为 M*N 的操作转化为复杂度为 M+N 的操作,当 M 和 N 都比较大时 M+N «M*N,则查询的复杂度被大大地降低。 下面显示了一个使用中间结果集来替代多表操作的例子。 INSERT INTO score (sno,cno,degree) values (102,1,59),(201,1,40); CREATE TABLE student_ng AS SELECT sno FROM score WHERE degree <= 60; SELECT 3 SELECT * FROM student_ng ; sno ----201 102 201 (3 rows) DELETE FROM student WHERE sno IN (SELECT * FROM student_ng ); DELETE 2 SELECT * FROM student; sno | sname | ssex -----+-------+-----101 | James | Male 203 | Todd | Male 103 | Smith | Male (3 rows) 上述 sql 等效于: DELETE FROM student WHERE sno IN (SELECT sno FROM score WHERE degree <= 60); DELETE 2 SELECT * FROM student; sno | sname | ssex -----+-------+-----101 | James | Male 203 | Todd | Male 103 | Smith | Male (3 rows) 4. 使用一些改写复杂查询的技巧 1). 转换连接类型 参见上文的改写查询语句部分 2). 把 OR 转换为 UNION ALL 670 第 10 章 查询和子查询 3). 区分不同的情况使用 IN 或 EXISTS 对于主查询中包含较多条件而子查询条件较少的表使用 EXISTS,对于主查询中包含较少条件而子查询条 件较多的表使用 IN。 4). 使用合理的连接方式 在不同的情况下使用不同的连接方式:散列连接适用于一个较小的表和较大的表的连接,排序合并连接需 要对小表进行排序操作,索引的嵌套循环连接对于一般连接是有效的,但是需要在连接的关键字上有索引 的存在。 应用开发人员应该根据不同的情况选取合适的连接方式。 a. 使用并行查询 如果查询的数据在表中所占的比例较大,可以考虑使用并行查询来提高查询的执行速度。 b. 使用 PL/SQL 过程和临时表代替复杂查询。 对于涉及巨大的表的连接的统计查询,由于可能会造成大量的排序统计工作,使得查询的速度变慢,此时 可以考虑使用 PLSQL 替代原来的查询。 10.5 查询结果排序 使用 ORDER BY 子句对查询选择的行进行排序。 可选的 ORDER BY 子句的形式如下: ORDER BY expression [ ASC | DESC | USING operator ] [ NULLS { FIRST | LAST } ] [, ...] ORDER BY 子句导致结果行被按照指定的表达式排序。如果两行按照最左边的表达式是相等的,则会根据下一个 表达式比较它们,依次类推。如果按照所有指定的表达式它们都是相等的,则它们被返回的顺序取决于实现。 每一个 “expression“ 可以是输出列(SELECT 列表项)的名称或者序号,它也可以是由输入列值构成的任意表达 式。 序号指的是输出列的顺序(从左至右)位置。这种特性可以为不具有唯一名称的列定义一个顺序。这不是绝对必 要的,因为总是可以使用 AS 子句为输出列赋予一个名称。 671 第 10 章 查询和子查询 也可以在 ORDER BY 子句中使用任意表达式,包括没有出现在 SELECT 输出列表中的列。因此,下面的语句是合 法的: SELECT name FROM distributors ORDER BY code; 这种特性的一个限制是一个应用在 UNION、INTERSECT 或 EXCEPT 子句结果上的 ORDER BY 只能指定输出列名称 或序号,但不能指定表达式。 如果一个 ORDER BY 表达式是一个既匹配输出列名称又匹配输入列名称的简单名称,ORDER BY 将把它解读成输 出列名称。这与在同样情况下 GROUP BY 会做出的选择相反。这种不一致是为了与 SQL 标准兼容。 可以为 ORDER BY 子句中的任何表达式之后增加关键词 ASC(上升)DESC(下降)。如果没有指定,ASC 被假定 为默认值。或者,可以在 USING 子句中指定一个特定的排序操作符名称。一个排序操作符必须是某个 B-树操作符族 的小于或者大于成员。ASC 通常等价于 USING < 而 DESC 通常等价于 USING >(但是一种用户定义数据类型的创建者 可以准确地定义默认排序顺序是什么,并且它可能会对应于其他名称的操作符)。 如果指定 NULLS LAST,空值会排在非空值之后;如果指定 NULLS FIRST,空值会排在非空值之前。如果都没 有指定,在指定或者隐含 ASC 时的默认行为是 NULLS LAST,而指定或者隐含 DESC 时的默认行为是 NULLS FIRST (因此,默认行为是空值大于非空值)。当指定 USING 时,默认的空值顺序取决于该操作符是否为小于或者大于操 作符。 注意顺序选项只应用到它们所跟随的表达式上。例如 ORDER BY x, y DESC 和 ORDER BY x DESC, y DESC 是不 同的。 字符串数据会被根据引用到被排序列上的排序规则排序。根据需要可以通过在 “expression“中包括一个 COLLATE 子句来覆盖,例如 ORDER BY mycolumn COLLATE "en_US"。 10.6 JOIN 操作 JOIN(联接) 是一种查询,它组合了两个或多个表、视图、物化视图中的行。当查询的 FROM 子句中出现多个表 时,数据库会执行联接。查询的选择列表可以从这些表中选择任何列。如果两个表中的任意两个列有相同的名字,那 么在查询过程中,必须用表名限定对这些列的引用,以免产生歧义。 KingbaseES 支持以下几种 JOIN 类型: join types • [ INNER ] JOIN • LEFT [ OUTER ] JOIN • RIGHT [ OUTER ] JOIN • FULL [ OUTER ] JOIN • CROSS JOIN 对于 INNER 和 OUTER 连接类型,必须指定一个连接条件,即 NATURAL、ON join_condition 或者 USING (join_column [, ...]) 之一(只能有一种)。其含义见下文。对于 CROSS JOIN,上述子句不能出现。 672 第 10 章 查询和子查询 一个 JOIN 子句联合两个 FROM 项(为了方便我们称之为“表”,尽管实际上它们可以是任何类型的 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 子句),它说明一次连接 中哪些行被认为相匹配。 10.7 使用子查询 子查询指定了一个派生表,它必须被包围在圆括弧里,并且可以被赋予一个表别名,若未指定别名则系统会自动 生成一个别名。例如: FROM (SELECT * FROM table1) AS alias_name 或者 FROM (SELECT * FROM table1) 这个例子等效于 FROM table1 AS alias_name。更有趣的情况是在子查询里面有分组或聚集的时候,子查询不 能被简化为一个简单的连接。 一个子查询也可以是一个 VALUES 列表: FROM (VALUES ('anne', 'smith'), ('bob', 'jones'), ('joe', 'blow')) AS names(first, last) 再次的,这里可以使用一个表别名,若未指定则系统自动生成一个别名。为 VALUES 列表中的列分配别名是可选 的,但是指定别名这样做是一个好习惯。 673 第 10 章 10.8 查询和子查询 限制嵌套查询层数 应用中影响数据查询的效率的因素除了参与查询连接的表的个数以外,还有查询的嵌套层数。对于非关联查询, 嵌套的子查询相当于使查询语句的复杂度在算术级数的基础上增长,而对于关联查询而言,嵌套的子查询相当于使查 询语句的复杂度在几何级数的基础上增长。 因此,降低查询的嵌套层数有助于提高查询语句的效率。 对嵌套查询层数的限制要求:如果查询语句拥有过多的嵌套层数,那么会使该查询语句的复杂度高速增加,应该 在数据库设计阶段就避免这种情况出现,不应多于 5 层。 10.9 DUAL 表查询 KingbaseES 兼容 Oracle 的 DUAL 伪表。该表可被所有的用户访问,但只有数据库管理员才能删除、增加、修 改 *DUAL* 表的内容。 例 10-5:伪表 DUAL 的示例。 SELECT SYSDATE AS CURRENT_DATE_TIME FROM DUAL; 10.10 PIVOT 和 UNPIVOT 行列转换 PIVOT 和 UNPIVOT 是 SELECT 的一种扩展查询方式。PIVOT 查询涉及将行置转换为列,或者使用 UNPIVOT 将 列置转换为行,以交叉表格式生成结果。 PIVOT 操作为行转列,并在转换过程中聚合数据,新的列表示不同范围的聚合数据,PIVOT 操作的输出通常比初 始数据行包含更多的列和更少的行。 UNPIVOT 是 PIVOT 的反操作,它是将多个列的内容合并到同一个列中,以多行形式展示。 关于输入结果有如下使用限制: 输入为一个查询或者子查询的结果集,当为一个子查询的时候,支持目标列的类型可以为列名、常量或者 表达式,但是为常量或者表达式的时候必须使用别名,表达式中支持使用列名和常量进行计算,且子查询 只支持单表为输入且不支持表使用别名。 10.10.1 PIVOT 行转列 PIVOT 操作是将查询结果集进行行转列 674 第 10 章 查询和子查询 SELECT select_list FROM table_expression [ PIVOT aggfunction FOR column... IN (('column_const','column_const'...) [AS alais], ....) ] PIVOT 首先计算指定的聚合函数的值。通常聚合函数必须指定 GROUP BY 子句才能返回多个值,但是在 PIVOT 子句不包含显式的 GROUP BY 子句。在 PIVOT 子句执行隐式 GROUP BY。 隐式 GROUP BY 是基于所有没有在 PIVOT 子句中引用的列,以及在在 PIVOT 的 IN 子句中指定的一组值。 根据指定的分组列和聚合值,生成的交叉表包含以下列: a. 所有没在 PIVOT 子句中引用的隐式分组列值。 b. 以及与 PIVOT 的 IN 子句中的值对应的新列,每个聚合的值被转换到适当的新列中。数据库将为每个新列生成 一个名称:如果没有为聚合函数提供别名,则使用每个 pivot 列的值作为聚合函数转置到的每个新列的名称。 如果为聚合函数提供别名,则连接 PIVOT 列名、下划线字符和聚合函数别名为每个新列生成的一个名称。 一个转换单列的例子: select * from pivot_t1; month | name | nums | other -------+--------+------+------1 | apple | 1000 | a 2 | apple | 2000 | d 3 | apple | 4000 | a 1 | orange | 400 | d 2 | orange | 500 | b 3 | orange | 500 | b 1 | grape | 3500 | c 2 | grape | 3500 | c 3 | grape | 3500 | c (9 rows) select * from (select month,name,nums from pivot_t1) pivot (sum(nums) for name in ('apple' as pingguo , 'orange' as juzi ,'grape' as putao)); month | pingguo | juzi | putao -------+---------+------+------1 | 1000 | 400 | 3500 2 | 2000 | 500 | 3500 3 | 4000 | 500 | 3500 (3 rows) 此例中将 name 列中的值转换为列并计算了他的聚合值生成一个新的结果集。 多列转换的的例子: select * from (select month,name,nums,other from pivot_t1) pivot (sum(nums) for (name,other) in ( ('apple', 'a'), ('orange','b') , ('grape','c') , ('apple','d') , ('orange','d'))); 675 第 10 章 查询和子查询 month | apple_a | orange_b | grape_c | apple_d | orange_d -------+---------+----------+---------+---------+---------1 | 1000 | | 3500 | | 2 | | 500 | 3500 | 2000 | 3 | 4000 | 500 | 3500 | | 400 此例中将 name 列和 other 列中的值转换为列并计算了他的聚合值生成一个新的结果集。 10.10.2 UNPIVOT 列转行 UNPIVOT 是 PIVOT 的反操作,它是将列转换为行。 SELECT select_list FROM table_expression [ UNPIVOT new_column... FOR new_column... IN ((column,...) [AS alais], ....) ] UNPIVOT 将列旋转为行,生成的交叉表中包含:未出现在 UNPIVOT 的 IN 子句中的所有列,以及存储参与转换 字段列名的新列(FOR 子句之后指定)和对应输出字段值的新列(FOR 子句前指定)。 INCLUDE | EXCLUDE NULLS 子句提供了包括或排除空值行的选项。INCLUDE NULLS 使 unpivot 操作包含 null 值的行;EXECLUDE NULLS 将排除具有 null 值的行。如果省略此子句,则 unpivot 操作将排除 null 值。 FOR 子句此子句指定转换后的新字段名称,用于存放参与列转行的每个输出字段的列名。 IN 子句指定要参与行列转换的原始列表,指定名称将成为 IN 子句指定新列的输入数据(列转行的值列表)。 可选 AS 子句允许输入数据列名映射到其他指定文字。 一个转换单列的例子: select * from unpivot_t1; id | name | q1 | q2 | q3 | q4 ----+--------+------+------+------+-----1 | apple | 1000 | 2000 | 3300 | 5000 2 | orange | 3000 | 3000 | 3200 | 1500 3 | banana | 2500 | 3500 | 2200 | 2500 4 | grape | 1500 | 2500 | 1200 | 3500 (4 rows) update unpivot_t1 set q4=NULL where id=4; select id,name,jidu ,xiaoshou from unpivot_t1 unpivot include nulls (xiaoshou for jidu in (q1 as 'Q1',q2 as 'Q2',q3 as 'Q3',q4 as 'Q4')) order by id,jidu; id | name | jidu | xiaoshou ----+--------+------+---------1 | apple | Q1 | 1000 1 | apple | Q2 | 2000 1 | apple | Q3 | 3300 676 第 10 章 1 | apple | Q4 | 5000 2 | orange | Q1 | 3000 2 | orange | Q2 | 3000 2 | orange | Q3 | 3200 2 | orange | Q4 | 1500 3 | banana | Q1 | 2500 3 | banana | Q2 | 3500 3 | banana | Q3 | 2200 3 | banana | Q4 | 2500 4 | grape | Q1 | 1500 4 | grape | Q2 | 2500 4 | grape | Q3 | 1200 4 | grape | Q4 | 查询和子查询 (16 rows) 多列转换的的例子: select * from unpivot_t1 unpivot ((xiaoshou,xiaoshou2) for (jidu1,jidu2) in ((q1,q2),(q3,q4))) order by 1,2, 3; id | name | jidu1 | jidu2 | xiaoshou | xiaoshou2 ----+--------+-------+-------+----------+----------1 | apple | q1_q2 | q1_q2 | 1000 | 2000 1 | apple | q3_q4 | q3_q4 | 3300 | 5000 2 | orange | q1_q2 | q1_q2 | 3000 | 3000 2 | orange | q3_q4 | q3_q4 | 3200 | 1500 3 | banana | q1_q2 | q1_q2 | 2500 | 3500 3 | banana | q3_q4 | q3_q4 | 2200 | 2500 4 | grape | q1_q2 | q1_q2 | 1500 | 2500 4 | grape | q3_q4 | q3_q4 | 1200 | (8 rows) WITH 提供了一种方式来书写在一个大型查询中使用的辅助语句。这些语句通常被称为公共表表达式或 CTE,它 们可以被看成是定义只在一个查询中存在的临时表。在 WITH 子句中的每一个辅助语句可以是一个 SELECT、INSERT、UPDATE 或 DELETE,并且 WITH 子句本身也可以被附加到一个主语句,主语句也可以是 SELECT、INSERT、UPDATE 或 DELETE。 WITH 中 SELECT 的基本价值是将复杂的查询分解称为简单的部分。一个例子: WITH regional_sales AS ( SELECT region, SUM(amount) AS total_sales FROM orders GROUP BY region ), top_regions AS ( SELECT region FROM regional_sales WHERE total_sales > (SELECT SUM(total_sales)/10 FROM regional_sales) 677 第 10 章 查询和子查询 ) SELECT region, product, SUM(quantity) AS product_units, SUM(amount) AS product_sales FROM orders WHERE region IN (SELECT region FROM top_regions) GROUP BY region, product; 它只显示在高销售区域每种产品的销售总额。WITH 子句定义了两个辅助语句 regional_sales 和 top_regions, 其中 regional_sales 的输出用在 top_regions 中而 top_regions 的输出用在主 SELECT 查询。这个例子可以不用 WITH 来书写,但是我们必须要用两层嵌套的子 SELECT。使用这种方法要更简单些。 可选的 RECURSIVE 修饰符将 WITH 从单纯的句法便利变成了一种在标准 SQL 中不能完成的特性。通过使用 RECURSIVE,一个 WITH 查询可以引用它自己的输出。一个非常简单的例子是计算从 1 到 100 的整数合的查询: WITH RECURSIVE t(n) AS ( VALUES (1) SELECT n+1 FROM t WHERE n < 100 ) SELECT sum(n) FROM t; 一个递归 WITH 查询的通常形式总是一个非递归项,然后是 UNION(或者 UNION ALL),再然后是一个递归 项,其中只有递归项能够包含对于查询自身输出的引用。这样一个查询可以被这样执行: 10.10.3 递归查询求值 1. 计算非递归项。对 UNION(但不对 UNION ALL),抛弃重复行。把所有剩余的行包括在递归查询的结果中, 并且也把它们放在一个临时的工作表中。 2. 只要工作表不为空,重复下列步骤: a. 计算递归项,用当前工作表的内容替换递归自引用。对 UNION(不是 UNION ALL),抛弃重复行以 及那些与之前结果行重复的行。将剩下的所有行包括在递归查询的结果中,并且也把它们放在一个临时的 中间表中。 b. 用中间表的内容替换工作表的内容,然后清空中间表。 注意: 严格来说,这个处理是迭代而不是递归,但是 RECURSIVE 是 SQL 标准委员会选择的术语。 在上面的例子中,工作表在每一步只有一个行,并且它在连续的步骤中取值从 1 到 100。在第 100 步,由于 WHERE 子句导致没有输出,因此查询终止。 递归查询通常用于处理层次或者树状结构的数据。一个有用的例子是这个用于找到一个产品的直接或间接部件的 查询,只要给定一个显示了直接包含关系的表: 678 第 10 章 查询和子查询 WITH RECURSIVE included_parts(sub_part, part, quantity) AS ( SELECT sub_part, part, quantity FROM parts WHERE part = 'our_product' UNION ALL SELECT p.sub_part, p.part, p.quantity FROM included_parts pr, parts p WHERE p.part = pr.sub_part ) SELECT sub_part, SUM(quantity) as total_quantity FROM included_parts GROUP BY sub_part 在使用递归查询时,确保查询的递归部分最终将不返回元组非常重要,否则查询将会无限循环。在某些时候,使 用 UNION 替代 UNION ALL 可以通过抛弃与之前输出行重复的行来达到这个目的。不过,经常有循环不涉及到完 全重复的输出行:它可能只需要检查一个或几个域来看相同点之前是否达到过。处理这种情况的标准方法是计算一个 已经访问过值的数组。例如,考虑下面这个使用 link 域搜索表 graph 的查询: WITH RECURSIVE search_graph(id, link, data, depth) AS ( SELECT g.id, g.link, g.data, 1 FROM graph g UNION ALL SELECT g.id, g.link, g.data, sg.depth + 1 FROM graph g, search_graph sg WHERE g.id = sg.link ) SELECT * FROM search_graph; 如果 link 关系包含环,这个查询将会循环。因为我们要求一个“depth”输出,仅仅将 UNION ALL 改为 UNION 不会消除循环。反过来在我们顺着一个特定链接路径搜索时,我们需要识别我们是否再次到达了一个相同的 行。我们可以项这个有循环倾向的查询增加两个列 path 和 cycle: WITH RECURSIVE search_graph(id, link, data, depth, path, cycle) AS ( SELECT g.id, g.link, g.data, 1, ARRAY[g.id], false FROM graph g UNION ALL SELECT g.id, g.link, g.data, sg.depth + 1, path || g.id, g.id = ANY(path) FROM graph g, search_graph sg WHERE g.id = sg.link AND NOT cycle ) SELECT * FROM search_graph; 除了阻止环,数组值对于它们自己的工作显示到达任何特定行的“path”也有用。在通常情况下如果需要检查多 679 第 10 章 查询和子查询 于一个域来识别一个环,请用行数组。例如,如果我们需要比较域 f1 和 f2: WITH RECURSIVE search_graph(id, link, data, depth, path, cycle) AS ( SELECT g.id, g.link, g.data, 1, ARRAY[ROW(g.f1, g.f2)], false FROM graph g UNION ALL SELECT g.id, g.link, g.data, sg.depth + 1, path || ROW(g.f1, g.f2), ROW(g.f1, g.f2) = ANY(path) FROM graph g, search_graph sg WHERE g.id = sg.link AND NOT cycle ) SELECT * FROM search_graph; 当你不确定查询是否可能循环时,一个测试查询的有用技巧是在父查询中放一个 LIMIT。例如,这个查询没有 LIMIT 时会永远循环: WITH RECURSIVE t(n) AS ( SELECT 1 UNION ALL SELECT n+1 FROM t ) SELECT n FROM t LIMIT 100; 这会起作用,因为 KingbaseES 的实现只计算 WITH 查询中被父查询实际取到的行。不推荐在生产中使用这个 技巧,因为其他系统可能以不同方式工作。同样,如果你让外层查询排序递归查询的结果或者把它们连接成某种其他 表,这个技巧将不会起作用,因为在这些情况下外层查询通常将尝试取得 WITH 查询的所有输出。 WITH 查询的一个有用的特性是在每一次父查询的执行中它们通常被计算一次,即使它们被父查询或兄弟 WITH 查询引用了超过一次。因此,在多个地方需要的昂贵计算可以被放在一个 WITH 查询中来避免冗余工作。另一种可 能的应用是阻止不希望的多个函数计算产生副作用。然而, 硬币的另一面是, 优化器不能将父查询的限制推入一个多 基准 WITH 查询, 因为这可能会影响所有使用 WITH 查询的输出, 它应该只影响一个。多基准的 WITH 查询将会被 按照所写的方式计算,而不抑制父查询以后可能会抛弃的行(但是,如上所述,如果对查询的引用只请求有限数目的 行,计算可能会提前停止)。 但是,如果一个 WITH 查询是非递归的,并且没有副作用 (也就是说,它是一个 SELECT 不包含 volatile 函 数),那么它可以被折叠到父查询中,从而允许两个查询级别的联合优化。默认情况下,它发生于父查询引用 WITH 查询查询仅一次,如果它引用和查询不止一次,则不会发生这种情况。您可以通过指定 MATERIALIZED 来强制使 用 WITH 查询分离计算,或者通过指定 NOT MATERIALIZED 来强制合并到父查询中,从而推翻这个决定。后一 种选择有 WITH 查询重复计算的风险,但是如果每次使用 WITH 查询只需要使用 WITH 查询的全部输出,它仍然 可以提供净节省。 这些规则的一个简单例子是: 680 第 10 章 查询和子查询 WITH w AS ( SELECT * FROM big_table ) SELECT * FROM w WHERE key = 123; 这个 WITH 查询将被折叠起来,生成与执行计划相同的执行计划 SELECT * FROM big_table WHERE key = 123; 特别是,如果 key 上有一个索引,那么它可能只用于获取具有 key = 123 的行。 WITH w AS ( SELECT * FROM big_table ) SELECT * FROM w AS w1 JOIN w AS w2 ON w1.key = w2.ref WHERE w2.key = 123; 另一方面,在 WITH 查询将被实例化, 生成 big_table 的临时副本,然后与自身连接(没有任何索引的好处)。 如果将此查询编写为 WITH w AS NOT MATERIALIZED ( SELECT * FROM big_table ) SELECT * FROM w AS w1 JOIN w AS w2 ON w1.key = w2.ref WHERE w2.key = 123; 因此,父查询的限制可以直接应用于 big_table 的扫描。例如,NOT MATERIALIZED 可能不受欢迎。 WITH w AS ( SELECT key, very_expensive_function(val) as f FROM some_table ) SELECT * FROM w AS w1 JOIN w AS w2 ON w1.f = w2.f; 在这里,使用 WITH 查询实现 very_expensive_function 对于每个表行只计算一次,而不是两次。 以上的例子只展示了和 SELECT 一起使用的 WITH,但是它可以被以相同的方式附加在 INSERT、UPDATE 或 DELETE 上。在每一种情况中,它实际上提供了可在主命令中引用的临时表。 可以在 WITH 中使用数据修改语句(INSERT、UPDATE 或 DELETE)。这允许你在同一个查询中执行多个而 不同操作。一个例子: WITH moved_rows AS ( DELETE FROM products WHERE "date" >= '2010-10-01' AND "date" < '2010-11-01' RETURNING * ) INSERT INTO products_log 681 第 10 章 查询和子查询 SELECT * FROM moved_rows; 这个查询实际上从 products 把行移动到 products_log。WITH 中的 DELETE 删除来自 products 的指定行,以 它的 RETURNING 子句返回它们的内容,并且接着主查询读该输出并将它插入到 products_log。 上述例子中好的一点是 WITH 子句被附加给 INSERT,而没有附加给 INSERT 的子 SELECT。这是必需的,因 为数据修改语句只允许出现在附加给顶层语句的 WITH 子句中。不过,普通 WITH 可见性规则应用,这样才可能从 子 SELECT 中引用到 WITH 语句的输出。 正如上述例子所示,WITH 中的数据修改语句通常具有 RETURNING 子句(见从修改的行中返回数据)。它是 RETURNING 子句的输出,不是数据修改语句的目标表,它形成了剩余查询可以引用的临时表。如果一个 WITH 中 的数据修改语句缺少一个 RETURNING 子句,则它形不成临时表并且不能在剩余的查询中被引用。但是这样一个语 句将被执行。一个非特殊使用的例子: WITH t AS ( DELETE FROM foo ) DELETE FROM bar; 这个例子将从表 foo 和 bar 中移除所有行。被报告给客户端的受影响行的数目可能只包括从 bar 中移除的行。 数据修改语句中不允许递归自引用。在某些情况中可以采取引用一个递归 WITH 的输出来操作这个限制,例 如: WITH RECURSIVE included_parts(sub_part, part) AS ( SELECT sub_part, part FROM parts WHERE part = 'our_product' UNION ALL SELECT p.sub_part, p.part FROM included_parts pr, parts p WHERE p.part = pr.sub_part ) DELETE FROM parts WHERE part IN (SELECT part FROM included_parts); 这个查询将会移除一个产品的所有直接或间接子部件。 WITH 中的数据修改语句只被执行一次,并且总是能结束,而不管主查询是否读取它们所有(或者任何)的输 出。注意这和 WITH 中 SELECT 的规则不同:正如前一小节所述,直到主查询要求 SELECT 的输出时,SELECT 才会被执行。 WITH 中的子语句彼此并发执行,并与主查询一起执行。因此在使用 WITH 中的数据修改语句时,指定更新 的顺序实际是以不可预测的方式发生的。所有的语句都使用同一个 snapshot 执行,因此它们不能“看见”在目标表 上另一个执行的效果。这减轻了行更新的实际顺序的不可预见性的影响,并且意味着 RETURNING 数据是在不同 WITH 子语句和主查询之间传达改变的唯一方法。其例子 WITH t AS ( UPDATE products SET price = price * 1.05 682 第 10 章 查询和子查询 RETURNING * ) SELECT * FROM products; 外层 SELECT 可以返回在 UPDATE 动作之前的原始价格,而在 WITH t AS ( UPDATE products SET price = price * 1.05 RETURNING * ) SELECT * FROM t; 外部 SELECT 将返回更新过的数据。 在一个语句中试图两次更新同一行是不被支持的。只会发生一次修改,但是该办法不能很容易地(有时是不可 能)可靠地预测哪一个会被执行。这也应用于删除一个已经在同一个语句中被更新过的行:只有更新被执行。因此你 通常应该避免尝试在一个语句中尝试两次修改同一个行。尤其是防止书写可能影响被主语句或兄弟子语句修改的相同 行。这样一个语句的效果将是不可预测的。 当前,在 WITH 中一个数据修改语句中被用作目标的任何表不能有条件规则、ALSO 规则或 INSTEAD 规则, 这些规则会扩展成为多个语句。 683 第 11 章 SQL 语句:ABORT 到 ALTER INDEX 11章 SQL 语句:ABORT 到 ALTER INDEX 第 本章描述各种类型的 SQL 语句,由于语句较多,将按字母顺序排列分组,以下为第一组 SQL 语句。包含以下章 节: • SQL 语句类型 • SQL 语句各章节是如何组织的 • ABORT • ALTER AGGREGATE • ALTER COLLATION • ALTER CONVERSION • ALTER DATABASE • ALTER DATABASE LINK • ALTER DEFAULT PRIVILEGES • ALTER EVENT TRIGGER • ALTER EXTENSION • ALTER FOREIGN DATA WRAPPER • ALTER FOREIGN TABLE • ALTER FUNCTION • ALTER GROUP • ALTER INDEX 684 第 11 章 SQL 语句:ABORT 到 ALTER INDEX 11.1 SQL 语句类型 本章各节提供了 SQL 语句的功能摘要,分为以下几类 • 数据定义语句 • 数据操作语句 • 事务控制语句 • 会话控制语句 • 系统控制语句 11.1.1 数据定义语句 数据定义语句(DDL)允许用户执行以下任务: • 创建、修改和删除数据库模式对象 • 权限授予与回收、用户管理 • 收集表、索引的统计信息 • 建立审计策略 • 为数据库对象添加注释 CREATE、ALTER、DROP 命令要求以独占方式访问数据库对象。例如用户在指定表上有打开的事务,ALTER 该表将会失败。 GRANT、REVOKE、ANALYZE、COMENT 命令不要求以独占方式访问对象。例如可以在其他用户更新表时 分析该表。 DDL 语句可以是阻塞的,也可以是非阻塞的。这两种类型的 DDL 语句都需要内部结构上的独占锁。 目前 KingbaseES 支持的 DDL 语句有: ALTER ANALYZE COMMENT CREATE DROP FLASHBACK GRANT PURGE REVOKE TRUNCATE 685 第 11 章 SQL 语句:ABORT 到 ALTER INDEX 11.1.2 数据操作语句 数据操作语句 (DML) 访问和操作现有的数据库对象中的数据。数据操作语句包括: CALL DELETE EXPLAIN INSERT LOCK TABLE MERGE SELECT UPDATE SELECT 语句是一种特殊的 DML 语句,因为它只能读取数据库中的数据。虽然 “SELECT“ 语句可以在返回结果 集之前操作访问到的数据,但是不能改变存储在数据库中的数据。 只有动态执行时,PL/SQL 才能支持 SELECT 语句。但是可以在 PL/SQL 代码中使用类似 SELECT INTO 语句。并 且不必动态执行它。只有在动态执行时,PL/SQL 才支持 CALL 和 EXPLAIN 语句。PL/SQL 完全支持所有其他 DML 语句。 11.1.3 事务控制语句 事务控制语句管理 DML 语句所做的更改,事务控制语句包括: ABORT COMMIT ROLLBACK SAVEPOINT SET TRANSACTION SET CONSTRAINTS PL/SQL 支持部分事务控制语句,但 SAVEPOINT 以及某些形式的 COMMIT 和 ROLLBACK 除外。 11.1.4 会话控制语句 会话控制语句动态管理用户会话的属性。 PL/SQL 不支持会话控制语句,会话控制语句包括: ALTER SESSION SET ROLE SET SESSION AUTHORIZATION 686 第 11 章 SQL 语句:ABORT 到 ALTER INDEX 11.1.5 系统控制语句 系统控制语句 ALTER SYSTEM 动态管理数据库示例的属性,它不会隐式提交当前事务,PL/SQL 中不支持此类语 句。 11.2 SQL 语句各章节是如何组织的 本文中关于 SQL 语句的章节分为以下几节: 用途 用途部分描述该语句的基本作用、基本用法。 前置条件 该部分列出使用该语句之前必须满足的条件,如需要拥有的权限或、必须采取的步骤等。除列出的前置条件外, 一些最基本的前置条件不会额外说明,如必须连接上数据库。除非特殊情况不做说明。 语法 说明构成 SQL 语句的关键字和参数。并非所有关键字和参数在所有情况下都有效。请务必参考每个语句和子句 的 语义部分,以了解对语法的限制。 语义 该部分描述组成语法的关键字、参数、子句的用途。以及可能适用于他们的限制条件和其他用法说明。 示例 该部分用实际的例子说明对应 SQL 语句如何使用,包括子句和参数。 兼容性 该部分不是必有的,如有对 SQL 标准的扩展等兼容性产生影响在这里描述。 其他 该部分不是必有的,如有需做其他说明的内容放在这里。 11.3 ABORT 用途 ABORT 回滚当前事务并丢弃由该事务所作的所有更新。这个命令的行为与标准 SQL 命令ROLLBACK 的行为 一样。 前置条件 需要在事物块中执行。 687 第 11 章 SQL 语句:ABORT 到 ALTER INDEX 语法 ABORT [ WORK | TRANSACTION ] [ AND [ NO ] CHAIN ] 语义 WORK TRANSACTION 可选关键词。它们没有效果。 AND CHAIN 如果 AND CHAIN 是被指定的,当一个事务完成时,立即开始一个新事务的事务特性 (参考SET TRANSACTION )。否则,不会启动任何新事务。 示例 终止所有更改: ABORT; 兼容性 这个命令是一个因为历史原因而存在的 KingbaseES 扩展。ROLLBACK 是等效的标准 SQL 命令。 其他 使用COMMIT 成功地提交一个事务。 在一个事务块之外发出 ABORT 会发出一个警告消息并且不会产生效果。 11.4 ALTER AGGREGATE 用途 ALTER AGGREGATE 更改一个聚集函数的定义。 前置条件 要使用 ALTER AGGREGATE,你必须拥有该聚集函数。要更改一个聚集函数的模式,你还必须具有新模式上的 CREATE 特权。要修改拥有者,你还必须是新拥有角色的一个直接或者间接成员,并且那个角色必须在聚集函数的模 式上拥有 CREATE 特权(这些限制强制要求拥有者不能通过丢弃并重建该聚集函数来做任何你不能做的事情。但是, 一个超级用户可以更改任何聚集函数的所有权)。 688 第 11 章 SQL 语句:ABORT 到 ALTER INDEX 语法 ALTER AGGREGATE name ( aggregate_signature ) RENAME TO new_name ALTER AGGREGATE name ( aggregate_signature ) OWNER TO { new_owner | CURRENT_USER | SESSION_USER } ALTER AGGREGATE name ( aggregate_signature ) SET SCHEMA new_schema 其中 aggregate_signature 是: * | [ argmode ] [ argname ] argtype [ , ... ] | [ [ argmode ] [ argname ] argtype [ , ... ] ] ORDER BY [ argmode ] [ argname ] argtype [ , ... ] aggregate_signature ::= 语义 name 一个现有聚集函数的名称(可以是模式限定的)。 argmode 一个参数的模式:IN 或 VARIADIC。如果省略,默认为 IN。 argname 689 第 11 章 SQL 语句:ABORT 到 ALTER INDEX 一个参数的名称。注意 ALTER AGGREGATE 并不真正关心参数名称,因为决定聚集函数的身份时只需要参 数的数据类型。 argtype 聚集函数要在其上操作的输入数据类型。要引用一个零参数聚集函数,在参数说明列表的位置写上 *。要 引用一个有序集聚集函数,在直接参数说明和聚集参数说明之间写上 ORDER BY。 new_name 聚集函数的新名称。 new_owner 聚集函数的新拥有者。 new_schema 聚集函数的新模式。 示例 要把用于类型 integer 的聚集函数 myavg 重命名为 my_average: ALTER AGGREGATE myavg(integer) RENAME TO my_average; 要把用于类型 integer 的聚集函数 myavg 的拥有者改为 joe: ALTER AGGREGATE myavg(integer) OWNER TO joe; 把 带 有 float8 类 型 直 接 参 数 和 integer``类 型 聚 集 参 数 的 有 序 集 聚 集\ ``mypercentile 移动到模式 myschema 中: ALTER AGGREGATE mypercentile(float8 ORDER BY integer) SET SCHEMA myschema; 这也能行: ALTER AGGREGATE mypercentile(float8, integer) SET SCHEMA myschema; 兼容性 在 SQL 标准中没有 ALTER AGGREGATE 语句。 其他 引用有序集聚集的推荐语法是在直接参数说明和聚集参数说明之间写上 ORDER BY,这和CREATE AGGREGATE 中的风格相同。但是,省略 ORDER BY 并且只把直接和聚集参数说明放到一个单一列表中也是可以的。在这 种简写形式中,如果在直接和聚集参数列表中都使用了 VARIADIC "any",只用写一次 VARIADIC "any"。 690 第 11 章 SQL 语句:ABORT 到 ALTER INDEX 11.5 ALTER COLLATION 用途 ALTER COLLATION 更改一个排序规则的定义。 前置条件 你必须拥有要对其使用 ALTER COLLATION 的排序规则。要更改拥有者,你必须是新的拥有角色的直接或者间接 成员,并且该角色必须在排序规则的模式上具有 CREATE 特权(这些限制强制要求拥有者不能通过丢弃并重建该排序 规则来做任何你不能做的事情。但是,一个超级用户可以更改任何排序规则的所有权)。 语法 ALTER COLLATION name REFRESH VERSION ALTER COLLATION name RENAME TO new_name ALTER COLLATION name OWNER TO { new_owner | CURRENT_USER | SESSION_USER } ALTER COLLATION name SET SCHEMA new_schema 语义 name 一个现有排序规则的名称(可以是模式限定的)。 new_name 排序规则的新名称。 new_owner 排序规则的新拥有者。 new_schema 691 第 11 章 SQL 语句:ABORT 到 ALTER INDEX 排序规则的新模式。 REFRESH VERSION 更新排序规则的版本。 示例 要把排序规则 de_DE 重命名为 german: ALTER COLLATION "de_DE" RENAME TO german; 要把排序规则 en_US 的拥有者改成 joe: ALTER COLLATION "en_US" OWNER TO joe; 兼容性 在 SQL 标准中没有 ALTER COLLATION 语句。 其他 使用 ICU 库提供的排序规则时,创建排序规则对象时,系统目录中会记录排序规则的特定 ICU 版本。使用排序 规则时,将根据记录的版本检查当前版本,并在发生不匹配时发出警告,例如: WARNING: collation "xx-x-icu" has version mismatch DETAIL: The collation in the database was created using version 1.2.3.4, but the operating system provides version 2.3.4.5. HINT: Rebuild all objects affected by this collation and run ALTER COLLATION sys_catalog."xx-x-icu" REFRESH VERSION, or build KingbaseES with the right library version. 排序规则定义的更改会导致索引损坏和其他问题,因为数据库系统依赖于具有特定排序顺序的存储对象。通常, 应该避免这种情况,但它可以在合法的情况下发生,例如使用 sys_upgrade 升级到与更新版本的 ICU 链接的服务器 二进制文件。发生这种情况时,应该重建所有依赖于该排序规则的对象,例如,使用 REINDEX。完成后,使用命令 ALTER COLLATION ... REFRESH VERSION 可以刷新排序规则版本。这将更新系统目录以记录当前的排序规则版本, 并会使警告消失。请注意,这实际上并不检查是否所有受影响的对象都已正确重建。 以下查询可用于识别当前数据库中需要刷新的所有排序规则以及依赖它们的对象: SELECT sys_describe_object(refclassid, refobjid, refobjsubid) AS "Collation", sys_describe_object(classid, objid, objsubid) AS "Object" FROM sys_depend d JOIN sys_collation c ON refclassid = 'sys_collation'::regclass AND refobjid = c.oid WHERE c.collversion <> sys_collation_actual_version(c.oid) ORDER BY 1, 2; 692 第 11 章 SQL 语句:ABORT 到 ALTER INDEX 11.6 ALTER CONVERSION 用途 ALTER CONVERSION 改变一个转换的定义。 前置条件 你必须拥有要对其使用 ALTER CONVERSION 的转换。要更改拥有者,你必须是新的拥有角色的直接或者间接成 员,并且该角色必须在转换的模式上具有 CREATE 特权(这些限制强制要求拥有者不能通过丢弃并重建该转换来做任 何你不能做的事情。但是,一个超级用户可以更改任何转换的所有权)。 语法 ALTER CONVERSION name RENAME TO new_name ALTER CONVERSION name OWNER TO { new_owner | CURRENT_USER | SESSION_USER } ALTER CONVERSION name SET SCHEMA new_schema 语义 name 一个现有转换的名称(可以是模式限定的)。 new_name 转换的新名称。 new_owner 转换的新拥有者。 new_schema 转换的新模式。 示例 要把转换 iso_8859_1_to_utf8 重命名为 latin1_to_unicode: 693 第 11 章 SQL 语句:ABORT 到 ALTER INDEX ALTER CONVERSION iso_8859_1_to_utf8 RENAME TO latin1_to_unicode; 要把转换 iso_8859_1_to_utf8 的拥有者改成 joe: ALTER CONVERSION iso_8859_1_to_utf8 OWNER TO joe; 兼容性 在 SQL 标准中没有 ALTER CONVERSION 语句。 11.7 ALTER DATABASE 用途 ALTER DATABASE 更改一个数据库的属性。 前置条件 第一种形式更改指定数据库的某些属性(详见下文)。只有数据库拥有者或者超级用户可以更改这些设置。 第二种形式更改数据库的名称。只有数据库拥有者或者超级用户可以重命名一个数据库,非超级用户拥有者还必 须拥有 CREATEDB 特权。当前数据库不能被重命名(如果你需要这样做请连接到一个不同的数据库)。 第三种形式更改数据库的拥有者。要修改拥有者,你必须拥有该数据库并且也是新拥有角色的一个直接或间接成 员,并且你必须具有 CREATEDB 特权(注意超级用户自动拥有所有这些特权)。 第四种形式更改数据库的默认表空间。只有数据库拥有者或超级用户能够这样做,你还必须对新表空间具有创建 特权。这个命令会在物理上移动位于该数据库旧的默认表空间中的任何表或索引到新的表空间中。新的默认表空间对 于这个数据库必须是空的,并且当前该数据库不存在任何连接。在非默认表空间中的表和索引不受影响。 剩下的形式用于更改一个 KingbaseES 数据库的运行时配置变量的会话默认值。接下来只要一个新的会话在该 数据库中开始,指定的值就会成为该会话的默认值。数据库相关的默认值会覆盖出现在 kingbase.conf 中或者从 kingbase 命令行接收到的设置。只有数据库拥有者或超级用户可以更改一个数据库的会话默认值。一些变量不能用 这种方式设置或者只能由超级用户更改。 语法 ALTER DATABASE name [ [ WITH ] option [ ... ] ] 这里 option 可以是: ALLOW_CONNECTIONS allowconn CONNECTION LIMIT connlimit IS_TEMPLATE istemplate ALTER DATABASE name RENAME TO new_name 694 第 11 章 SQL 语句:ABORT 到 ALTER INDEX ALTER DATABASE name OWNER TO { new_owner | CURRENT_USER | SESSION_USER } ALTER DATABASE name SET TABLESPACE new_tablespace ALTER DATABASE name SET configuration_parameter { TO | = } { value | DEFAULT } ALTER DATABASE name SET configuration_parameter FROM CURRENT ALTER DATABASE name RESET configuration_parameter ALTER DATABASE name RESET ALL 语义 name 要被修改属性的数据库名称。 allowconn 如果为假,则没有人能连接到这个数据库。 connlimit 695 第 11 章 SQL 语句:ABORT 到 ALTER INDEX 与这个数据库可以建立多少个并发连接。-1 表示没有限制。 istemplate 如果为真,则任何具有 CREATEDB 特权的用户都可以从这个数据库进行克隆。如果为假,则只有超级用户 或者这个数据库的拥有者可以克隆它。 new_name 数据库的新名称。 new_owner 数据库的新拥有者。 new_tablespace 数据库的新默认表空间。这种形式的命令不能在事务块内执行。 configuration_parameter value 将这个数据库的指定配置参数的会话默认值设置为给定值。如果 “value“是 DEFAULT,或者等效地使用了 RESET,数据库相关的设置会被移除,因此系统范围的默认设置将会在新会话中继承。使用 RESET ALL 可 清除所有数据库相关的设置。SET FROM CURRENT 会保存该会话的当前参数值作为数据库相关的值。 示例 要在数据库 test 中默认禁用索引扫描: ALTER DATABASE test SET enable_indexscan TO off; 11.8 ALTER DATABASE LINK 用途 ALTER DATABASE LINK —修改一个 database link 对象 前置条件 第一种形式更改 database link 的拥有者,要修改拥有者,你必须是该 database link 的所有者并且也是新所有者 的直接或间接成员。 第二种形式更改 database link 的名称,只有 database link 拥有者或者超级用户可以重命名一个 database link。 语法 ALTER [PUBLIC] DATABASE LINK dblink_name OWNER TO new_owner; ALTER [PUBLIC] DATABASE LINK dblink_name RENAME TO new_name; 696 第 11 章 SQL 语句:ABORT 到 ALTER INDEX 语义 dblink_name 一个现有 database link 的名称(可以是模式限定的)。 new_owner 该 database link 的新拥有者的用户名。 new_name 该 database link 的新名称。 示例 把 DATABASE LINK my_dblink 拥有者修改为 new_owner: ALTER DATABASE LINK my_dblink OWNER TO new_owner; 兼容性 ALTER DATABASE LINK 语句是一个 KingbaseES 扩展。 11.9 ALTER DEFAULT PRIVILEGES 用途 ALTER DEFAULT PRIVILEGES 允许你设置将被应用于未来要创建的对象的特权(它不会影响分配给已经存在的对 象的特权)。当前,只能修改用于模式、表(包括视图和外部表)、序列、函数和类型(包括域)的特权。其中, 可设置权限的函数包括聚集函数和过程函数。当这个命令应用于函数时,单词 FUNCTIONS 和 ROUTINES 是等效 的。(推荐使用 ROUTINES,因为它是用来囊括函数和过程的一个标准术语。在较早的 KingbaseES 发行版中,只允 许单词 FUNCTIONS。无法为函数或过程单独设置默认特权。) 前置条件 你只能改变你自己或者你属于其中的角色所创建的对象的默认特权。这些特权可以对全局范围设置(即对当前数 据库中创建的所有对象),或者只对在指定模式中创建的对象设置。被指定的针对模式的默认特权会被增加到用于特 定数据类型的全局默认特权中。如 权限中所述,用于任何对象类型的默认特权通常会把所有可授予的权限授予给对 象拥有者,并且也可能授予一些特权给 PUBLIC。但是,这种行为可以通过使用 ALTER DEFAULT PRIVILEGES 修改全 局默认特权来改变。 语法 697 第 11 章 SQL 语句:ABORT 到 ALTER INDEX ALTER DEFAULT PRIVILEGES [ FOR { ROLE | USER } target_role [, ...] ] [ IN SCHEMA schema_name [, ...] ] abbreviated_grant_or_revoke 其中 abbreviated_grant_or_revoke 是下列之一: GRANT { { SELECT | INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES | TRIGGER } [, ...] | ALL [ PRIVILEGES ] } ON TABLES TO { [ GROUP ] role_name | PUBLIC } [, ...] [ WITH GRANT OPTION ] GRANT { { USAGE | SELECT | UPDATE } [, ...] | ALL [ PRIVILEGES ] } ON SEQUENCES TO { [ GROUP ] role_name | PUBLIC } [, ...] [ WITH GRANT OPTION ] GRANT { EXECUTE | ALL [ PRIVILEGES ] } ON { FUNCTIONS | ROUTINES } TO { [ GROUP ] role_name | PUBLIC } [, ...] [ WITH GRANT OPTION ] GRANT { USAGE | ALL [ PRIVILEGES ] } ON TYPES TO { [ GROUP ] role_name | PUBLIC } [, ...] [ WITH GRANT OPTION ] GRANT { USAGE | CREATE | ALL [ PRIVILEGES ] } ON SCHEMAS TO { [ GROUP ] role_name | PUBLIC } [, ...] [ WITH GRANT OPTION ] REVOKE [ GRANT OPTION FOR ] { { SELECT | INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES | TRIGGER } [, ...] | ALL [ PRIVILEGES ] } ON TABLES FROM { [ GROUP ] role_name | PUBLIC } [, ...] [ CASCADE | RESTRICT ] REVOKE [ GRANT OPTION FOR ] { { USAGE | SELECT | UPDATE } [, ...] | ALL [ PRIVILEGES ] } ON SEQUENCES FROM { [ GROUP ] role_name | PUBLIC } [, ...] [ CASCADE | RESTRICT ] REVOKE [ GRANT OPTION FOR ] { EXECUTE | ALL [ PRIVILEGES ] } 698 第 11 章 SQL 语句:ABORT 到 ALTER INDEX ON { FUNCTIONS | ROUTINES } FROM { [ GROUP ] role_name | PUBLIC } [, ...] [ CASCADE | RESTRICT ] REVOKE [ GRANT OPTION FOR ] { USAGE | ALL [ PRIVILEGES ] } ON TYPES FROM { [ GROUP ] role_name | PUBLIC } [, ...] [ CASCADE | RESTRICT ] REVOKE [ GRANT OPTION FOR ] { USAGE | CREATE | ALL [ PRIVILEGES ] } ON SCHEMAS FROM { [ GROUP ] role_name | PUBLIC } [, ...] [ CASCADE | RESTRICT ] GRANT ::= 699 第 11 章 SQL 语句:ABORT 到 ALTER INDEX REVOKE ::= 700 第 11 章 SQL 语句:ABORT 到 ALTER INDEX 701 第 11 章 SQL 语句:ABORT 到 ALTER INDEX 语义 target_role 一个现有角色的名称,当前角色是它的一个成员。如果 FOR ROLE 被忽略,将假定为当前角色。 schema_name 一个现有模式的名称。如果被指定,以后在那个模式中创建的对象的默认特权会被修改。如果 IN SCHEMA 被忽略,全局默认特权会被修改。在使用 ON SCHEMAS 时,不能使用 IN SCHEMA,因为模式不能 嵌套。 role_name 要为其授予或者收回特权的一个现有角色的名称。这个参数以及所有 “abbreviated_grant_or_revoke“中 的其他参数会按照GRANT 或者REVOKE 中描述的方式运作,但是这里是为一整类的对象而不是特别指 定的对象设置权限。 示例 为你后续在模式 myschema 中创建的所有表(和视图)授予 SELECT 特权,并且也允许角色 webuser 向它们之 中 INSERT 数据: ALTER DEFAULT PRIVILEGES IN SCHEMA myschema GRANT SELECT ON TABLES TO PUBLIC; ALTER DEFAULT PRIVILEGES IN SCHEMA myschema GRANT INSERT ON TABLES TO webuser; 撤销上面的动作,因此后续创建的表不会有任何不寻常的权限: ALTER DEFAULT PRIVILEGES IN SCHEMA myschema REVOKE SELECT ON TABLES FROM PUBLIC; ALTER DEFAULT PRIVILEGES IN SCHEMA myschema REVOKE INSERT ON TABLES FROM webuser; 为后续由角色 admin 创建的所有函数移除通常在函数上会授予的公共 EXECUTE 权限: ALTER DEFAULT PRIVILEGES FOR ROLE admin REVOKE EXECUTE ON FUNCTIONS FROM PUBLIC; 兼容性 该在 SQL 标准中没有 ALTER DEFAULT PRIVILEGES 语句。 其他 使用 ksql 的\ddp 命令可以获得关于默认特权的现有分配信息。特权显示的含义和 权限下为\dp 命令描述的相 同。 如果你希望删除一个默认特权被修改的角色,有必要撤销其默认特权上的改变或者使用 DROP OWNED BY 来为该 角色去除默认特权项。 11.10 ALTER DOMAIN 用途 702 第 11 章 SQL 语句:ABORT 到 ALTER INDEX ALTER DOMAIN 更改一个现有域的定义。有几种形式: SET | DROP DEFAULT 这些形式设置或者移除一个域的默认值。注意默认值只会应用到后续的 INSERT 命令,它们不影 响使用该域的已经存在于表中的行。 SET | DROP NOT NULL 这些形式更改一个域是被标记为允许 NULL 值还是拒绝 NULL 值。只有当使用该域的列不包 含空值时才能 SET NOT NULL。 ADD domain_constraint [ NOT VALID ] 这种形式使用和CREATE DOMAIN 相同的语法为一个域增加一个新的 约束。当一个新的约束被增加到一个域时,所有使用该域的列都会被根据新加的约束进行检查。可以通过增 加使用 NOT VALID 选项的新约束来抑制这类检查,而该约束则可以在以后使用 ALTER DOMAIN ... VALIDATE CONSTRAINT 变为可用。新插入和更新的行总是会被根据所有约束进行检查(包括被标记为 NOT VALID 的约 束)。只有 CHECK 约束接受 NOT VALID。 DROP CONSTRAINT [ IF EXISTS ] 这种形式删除一个域上的约束。如果指定了 IF EXISTS 并且约束不存在,不会 抛出错误。在这种情况下会转而发出一个提示。 RENAME CONSTRAINT 这种形式更改一个域上的一个约束的名称。 VALIDATE CONSTRAINT 这种形式验证一个之前作为 NOT VALID 增加的约束,也就是说验证使用该域的列中所有的表 列中的值满足指定的约束。 OWNER 这种形式更改域的拥有者为指定用户。 RENAME 这种形式更改域的名称。 SET SCHEMA 这种形式更改域的模式。任何与该域关联的约束也被会移动到新的模式中。 前置条件 要使用 ALTER DOMAIN,必须拥有该域。要更改一个域的模式,还必须具有新模式上的 CREATE 特权。要更改 拥有者,还必须是新拥有角色的一个直接或者间接成员,并且该角色必须具有该域的模式上的 CREATE 特权(这些 限制强制修改拥有者不能做一些通过删除和重建域做不到的事情。但是,一个超级用户怎么都能更改任何域的所有 权。)。 语法 ALTER DOMAIN name { SET DEFAULT expression | DROP DEFAULT } ALTER DOMAIN name { SET | DROP } NOT NULL ALTER DOMAIN name ADD domain_constraint [ NOT VALID ] ALTER DOMAIN name DROP CONSTRAINT [ IF EXISTS ] constraint_name [ RESTRICT | CASCADE ] ALTER DOMAIN name RENAME CONSTRAINT constraint_name TO new_constraint_name ALTER DOMAIN name VALIDATE CONSTRAINT constraint_name ALTER DOMAIN name OWNER TO { new_owner | CURRENT_USER | SESSION_USER } 703 第 11 章 SQL 语句:ABORT 到 ALTER INDEX ALTER DOMAIN name RENAME TO new_name ALTER DOMAIN name SET SCHEMA new_schema 语义 name 要修改的一个现有域的名称(可能是模式限定的)。 domain_constraint 用于该域的新域约束。 constraint_name 要删除或重命名的一个现有约束的名称。 NOT VALID 不为约束的合法性验证现有的存储数据。 CASCADE 704 第 11 章 SQL 语句:ABORT 到 ALTER INDEX 自动删除依赖于该约束的对象,并且接着删除依赖于那些对象的所有对象。 RESTRICT 如果有任何依赖对象则拒绝删除该约束。这是默认行为。 new_name 域的新名称。 new_constraint_name 约束的新名称。 new_owner 域的新拥有者的用户名。 new_schema 域的新模式。 示例 要把一个 NOT NULL 约束加到一个域: ALTER DOMAIN zipcode SET NOT NULL; 要从一个域中移除一个 NOT NULL 约束: ALTER DOMAIN zipcode DROP NOT NULL; 要把一个检查约束增加到一个域: ALTER DOMAIN zipcode ADD CONSTRAINT zipchk CHECK (char_length(VALUE) = 5); 要从一个域移除一个检查约束: ALTER DOMAIN zipcode DROP CONSTRAINT zipchk; 要重命名一个域上的一个检查约束: ALTER DOMAIN zipcode RENAME CONSTRAINT zipchk TO zip_check; 要把域移动到一个不同的模式: ALTER DOMAIN zipcode SET SCHEMA customers; 兼容性 除 OWNER、RENAME、SET SCHEMA 以及 VALIDATE CONSTRAINT 变体之外(它们是 KingbaseES 的扩展),ALTER DOMAIN 符合 SQL 标准。ADD CONSTRAINT 变体的 NOT VALID 子句也是一个 KingbaseES 扩展。 其他 705 第 11 章 SQL 语句:ABORT 到 ALTER INDEX 尽管 ALTER DOMAIN ADD CONSTRAINT 尝试验证现有存储的数据是否满足新约束,但是这种检查并不是万无一失 的,因为命令不能“看见”新插入或更新的表行,但尚未提交。 如果存在,并发操作可能会插入错误数据,处理的方法是使用无效选项添加约束,提交命令,等到所有事务开始 之前提交已经完成了,然后发布 ALTER DOMAIN VALIDATE CONSTRAINT 搜索违反约束的数据。这个方法是可靠的, 因为一旦提交了约束,所有新的事务都保证对域类型的新值强制执行约束。 当前,如果域或者任何衍生域被数据库中的任意表的一个容器类型列(组合、数组、范围类型的列)使用, ALTER DOMAIN ADD CONSTRAINT、ALTER DOMAIN VALIDATE CONSTRAINT 和 ALTER DOMAIN SET NOT NULL 将会失 败。这些命令最终将会被改进成能够对这类嵌套值进行约束验证。 11.11 ALTER EVENT TRIGGER 用途 ALTER EVENT TRIGGER —更改一个事件触发器的定义, 更改一个现有事件触发器的属性。 前置条件 必须作为一个超级用户才能修改一个事件触发器。 语法 ALTER EVENT TRIGGER name DISABLE ALTER EVENT TRIGGER name ENABLE [ REPLICA | ALWAYS ] ALTER EVENT TRIGGER name OWNER TO { new_owner | CURRENT_USER | SESSION_USER } ALTER EVENT TRIGGER name RENAME TO new_name 语义 name 706 第 11 章 SQL 语句:ABORT 到 ALTER INDEX 要修改的现有触发器的名称。 new_owner 该事件触发器的新拥有者的用户名。 new_name 该事件触发器的新名称。 DISABLE | ENABLE [ REPLICA | ALWAYS ] TRIGGER 这些形式配置事件触发器的触发。一个被禁用的触发器对系统来说仍然是可知的,但是当其触发事件发生 时却不会执行它。另见 session_replication_role 。 示例 要把 abort_ddl 事件触发器禁用。 ALTER EVENT TRIGGER abort_ddl DISABLE; 兼容性 在 SQL 标准中没有 ALTER EVENT TRIGGER 语句。 11.12 ALTER EXTENSION 用途 ALTER EXTENSION 更改一个已安装扩展的定义。有几种子形式: UPDATE 这种形式把该扩展更新到一个新版本。该扩展必须提供一个适当的更新脚本(或者一系列脚本)来把当前 已安装的版本修改成所要求的版本。 SET SCHEMA 这种形式把该扩展的对象移动到另一个模式中。要使这个命令成功,该扩展必须是可重定位的。 ADD member_object 这种形式把一个现有的对象加入到该扩展中。这主要对扩展更新脚本有用。该对象后续将被当作该扩展的 一个成员。尤其是该对象只有通过删除扩展才能删除。 DROP member_object 这种形式从该扩展移除一个成员对象。这主要对扩展更新脚本有用。只有撤销该对象与其扩展之间的关联 后才能删除该对象。 707 第 11 章 SQL 语句:ABORT 到 ALTER INDEX 关于这些操作详见 打包相关对象到一个扩展中。 前置条件 要使用 ALTER EXTENSION,你必须拥有该扩展。ADD/DROP 形式还要求被增加/删除对象的所有权。 语法 ALTER EXTENSION name UPDATE [ TO new_version ] ALTER EXTENSION name SET SCHEMA new_schema ALTER EXTENSION name ADD member_object ALTER EXTENSION name DROP member_object 其中 member_object 是: ACCESS METHOD object_name | AGGREGATE aggregate_name ( aggregate_signature ) | CAST (source_type AS target_type) | COLLATION object_name | CONVERSION object_name | DOMAIN object_name | EVENT TRIGGER object_name | FOREIGN DATA WRAPPER object_name | FOREIGN TABLE object_name | FUNCTION function_name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ] | MATERIALIZED VIEW object_name | OPERATOR operator_name (left_type, right_type) | OPERATOR CLASS object_name USING index_method | OPERATOR FAMILY object_name USING index_method | [ PROCEDURAL ] LANGUAGE object_name | PROCEDURE procedure_name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ] | ROUTINE routine_name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ] | SCHEMA object_name | SEQUENCE object_name | SERVER object_name | TABLE object_name | TEXT SEARCH CONFIGURATION object_name | TEXT SEARCH DICTIONARY object_name | TEXT SEARCH PARSER object_name | TEXT SEARCH TEMPLATE object_name | TRANSFORM FOR type_name LANGUAGE lang_name | TYPE object_name | VIEW object_name 并且 aggregate_signature 是: * | 708 第 11 章 SQL 语句:ABORT 到 ALTER INDEX [ argmode ] [ argname ] argtype [ , ... ] | [ [ argmode ] [ argname ] argtype [ , ... ] ] ORDER BY [ argmode ] [ argname ] argtype [ , ... ] member_object ::= 709 第 11 章 SQL 语句:ABORT 到 ALTER INDEX 710 第 11 章 SQL 语句:ABORT 到 ALTER INDEX aggregate_signature ::= 语义 name 一个已安装扩展的名称。 new_version 想 要 升 级 到 的 该 扩 展 的 新 版 本。 这 可 以 写 成 一 个 标 识 符 或 者 一 个 字 符 串。 如 果 没 有 指 定,ALTER EXTENSION UPDATE 会尝试更新到该扩展的控制文件中的默认版本。 new_schema 该扩展的新模式。 object_name | aggregate_name | function_name | operator_name | procedure_name | routine_name 要从该扩展增加或者移除的对象的名称。表、聚集、域、外部表、函数、操作符、操作符类、操作符族、 过程、例程、序列、文本搜索对象、类型和视图的名称可以被模式限定。 source_type 该转换的源数据类型的名称。 target_type 该转换的目标数据类型的名称。 argmode 一个函数、过程或者聚集参数的模式:IN、OUT、INOUT 或者 VARIADIC。如果被忽略,默认值是 IN。注 意,ALTER EXTENSION 并不真正关心 OUT 参数,因为决定该函数的身份时只需要输入参数。因此列出 IN、INOUT 和 VARIADIC 参数足矣。 argname 一个函数、过程或者聚集参数的名称。注意,ALTER EXTENSION 并不真正关心参数名称,因为决定该函数 的身份时只需要参数的数据类型。 argtype 711 第 11 章 SQL 语句:ABORT 到 ALTER INDEX 一个函数、过程或者或聚集参数的数据类型。 left_type | right_type 该操作符参数的数据类型(可以用模式限定)。对一个前缀或后缀操作符的缺失的参数可以写 NONE。 PROCEDURAL 这是一个噪声词。 type_name 该转换的数据类型的名称。 lang_name 该转换的语言的名称。 示例 把 hstore 扩展更新到版本 2.0: ALTER EXTENSION hstore UPDATE TO '2.0'; 把 hstore 扩展的模式更改到 utils: ALTER EXTENSION hstore SET SCHEMA utils; 要向 hstore 扩展增加一个现有函数: ALTER EXTENSION hstore ADD FUNCTION populate_record(anyelement, hstore); 兼容性 ALTER EXTENSION 是一个 KingbaseES 扩展。 11.13 ALTER FOREIGN DATA WRAPPER 用途 ALTER FOREIGN DATA WRAPPER 更改一个外部数据包装器的定义。该命令的第一种形式用于更改外部数据包装器的支持函数或者一般选项 (至少要求一个子句)。第二种形式更改外部数据包装器的拥有者。 前置条件 只有超级用户能修改外部数据包装器。此外,只有超级用户能够拥有外部数据包装器。 语法 712 第 11 章 SQL 语句:ABORT 到 ALTER INDEX ALTER FOREIGN DATA WRAPPER name [ HANDLER handler_function | NO HANDLER ] [ VALIDATOR validator_function | NO VALIDATOR ] [ OPTIONS ( [ ADD | SET | DROP ] option ['value'] [, ... ]) ] ALTER FOREIGN DATA WRAPPER name OWNER TO { new_owner | CURRENT_USER | SESSION_USER } ALTER FOREIGN DATA WRAPPER name RENAME TO new_name 语义 name 一个已有的外部数据包装器的名称。 HANDLER handler_function 为外部数据包装器指定一个新的处理器函数。 NO HANDLER 用于指定该外部数据包装器不再具有一个处理器函数。注意使用没有处理器的外部数据包装器的外部表不 能被访问。 VALIDATOR validator_function 为外部数据包装器指定一个新的验证器函数。 注意: 新的验证器可能会认为该外部数据包装器或者依赖于它的独立服务器的已有选项、用户映射、外部 表无效。KingbaseES 不会做这种检查。在使用修改过的外部数据包装器之前确认这些选项正确是用户的 责任。但是,在这个 ALTER FOREIGN DATA WRAPPER 命令中指定的选项将会被使用新的验证器检查。 NO VALIDATOR 用于指定该外部数据包装器不再拥有一个验证器函数。 713 第 11 章 SQL 语句:ABORT 到 ALTER INDEX OPTIONS ( [ ADD | SET | DROP ] option ['value'] [, ... ] ) 为该外部数据包装器更改选项。ADD、SET 以及 DROP 指定要被执行的动作。如果没有显式地指定操作, 将假定为 ADD。选项名称必须唯一,选项名称和值(如果有)也会使用该外部数据包装器的验证器函数来 验证。 new_owner 该外部数据包装器的新拥有者的用户名。 new_name 该外部数据包装器的新名称。 示例 更改一个外部数据包装器 dbi,增加选项 foo 并删除 bar: ALTER FOREIGN DATA WRAPPER dbi OPTIONS (ADD foo '1', DROP 'bar'); 把外部数据包装器 dbi 的验证器改为 bob.myvalidator: ALTER FOREIGN DATA WRAPPER dbi VALIDATOR bob.myvalidator; 兼容性 ALTER FOREIGN DATA WRAPPER 符合 ISO/IEC 9075-9(SQL/MED)。但是 HANDLER、VALIDATOR、OWNER TO 以及 RENAME 子句是扩展。 11.14 ALTER FOREIGN TABLE 用途 ALTER FOREIGN TABLE 更改一个现有外部表的定义。有几种子形式: ADD COLUMN 这种形式使用与CREATE FOREIGN TABLE 相同的语法把一个新的列增加到该外部表。和为常规表增加 一列不同,这种形式并不影响底层的存储:这个动作只是简单地声明通过该外部表可以访问某个新的列而 已。 DROP COLUMN [ IF EXISTS ] 这种形式从一个外部表删掉一列。如果在该表外部有任何东西依赖于该列,你将需要写上 CASCADE,典 型的例子就是视图。如果指定了 IF EXISTS 并且该列不存在,将不会抛出错误。在这种情况下会转而发 出一个提示。 SET DATA TYPE 714 第 11 章 SQL 语句:ABORT 到 ALTER INDEX 这种形式更改一个外部表的一列的类型。同样,这种形式并不影响底层的存储:这个动作只是简单地更改 KingbaseES 相信该列所具有的类型。 SET | DROP DEFAULT 这些形式设置或者移除一列的默认值。默认值只会应用于后续的 INSERT 或 UPDATE 命令,它们不会导致 已经在表中的行被更改。 SET | DROP NOT NULL 把一列标记为允许或者不允许空值。 SET STATISTICS 这种形式为后续的ANALYZE 操作设置针对每列的统计收集目标。详见ALTER TABLE 的类似形式。 SET ( attribute_option = value [, ... ] ) | RESET ( attribute_option [, ... ] ) 这种形式设置或重置针对每个属性的选项。详见ALTER TABLE 的类似形式。 SET STORAGE 这种形式设置一个列的存储模式。详见ALTER TABLE 中类似的模式。注意存储模式不会产生效果,除 非该表的外部数据包装器选择处理它。 ADD table_constraint [ NOT VALID ] 这种形式为外部表增加一个新的约束,使用的语法和CREATE FOREIGN TABLE 中相同。当前只支持 CHECK 约束。 和向常规表增加约束的情况不同,为外部表增加约束时不会做任何事情来验证该约束是否正确。这个动作 只是简单地声明了该外部表中所有的行都应该满足的某种新的条件(见CREATE FOREIGN TABLE 中的 讨论)。如果该约束被标记为 NOT VALID,那么它不被假设为有效,而只是被记录下来以备未来使用。 VALIDATE CONSTRAINT 这种形式把一个之前被标记为 NOT VALID 的约束标记为有效。不会做任何动作来验证该约束,但是未来 的查询将会假定该约束是保持的。 DROP CONSTRAINT [ IF EXISTS ] 这种形式删掉在一个外部表上的指定约束。如果指定了 IF EXISTS 但约束并不存在,则不会抛出错误。 在这种情况下会发出一个提示。 DISABLE | ENABLE [ REPLICA | ALWAYS ] TRIGGER 这些形式配置属于该外部表的触发器的触发情况。详见ALTER TABLE 的类似形式。 SET WITHOUT OIDS 用于删除 oid 系统列的向后兼容性语法。由于 oid 系统列不能再添加了,所以这不会有任何影响。 INHERIT parent_table 这种形式把目标外部表作为指定的父表的新后代。详见ALTER TABLE 的类似的形式。 NO INHERIT parent_table 715 第 11 章 SQL 语句:ABORT 到 ALTER INDEX 这种形式把目标外部表从指定的父表的子女列表中移除。 OWNER 这种形式把该外部表的拥有者改成指定的用户。 OPTIONS ( [ ADD | SET | DROP ] option ['value'] [, ... ] ) 更改该外部表或者其中一个列的选项。ADD、SET 以及 DROP 指定要执行的动作。如果没有显式地指定操 作,将假定为 ADD。不允许重复的名称(但是一个表选项和一个列选项可以重名)。选项名称和值也会用 外部数据包装器库来验证。 RENAME RENAME 形式更改外部表的名称或者外部表中一个列的名称。 SET SCHEMA 这种形式把外部表移动到另一个模式中。 所有除了 RENAME 和 SET SCHEMA 的动作都能被整合到一个多修改列表以便能被并行应用。例如,可以在一个命 令中增加几个列并且/或者修改几个列的类型。 如果该命令被写作 ALTER FOREIGN TABLE IF EXISTS ... 并且该外部表不存在,则不会抛出错误。这种情况下 会发出一个提示。 前置条件 你必须拥有该表以使用 ALTER FOREIGN TABLE。要更改一个外部表的模式,你必须还拥有新模式上的 CREATE 特权。要更改拥有者,你还必须是新拥有角色的一个直接或者间接成员,并且该角色必须具有在该表的模式上的 CREATE 特权(这些限制强制修改拥有者不能做一些通过删除和重建该表做不到的事情。但是,一个超级用户怎么都 能更改任何表的所有权)。要增加一列或者修改一个列的类型,你还必须具有该数据类型上的 USAGE 特权。 语法 ALTER FOREIGN TABLE [ IF EXISTS ] [ ONLY ] name [ * ] action [, ... ] ALTER FOREIGN TABLE [ IF EXISTS ] [ ONLY ] name [ * ] RENAME [ COLUMN ] column_name TO new_column_name ALTER FOREIGN TABLE [ IF EXISTS ] name RENAME TO new_name ALTER FOREIGN TABLE [ IF EXISTS ] name SET SCHEMA new_schema 其中 action 是以下之一: ADD [ COLUMN ] column_name data_type [ COLLATE collation ] [ column_constraint [ ... ] ] DROP [ COLUMN ] [ IF EXISTS ] column_name [ RESTRICT | CASCADE ] ALTER [ COLUMN ] column_name [ SET DATA ] TYPE data_type [ COLLATE collation ] ALTER [ COLUMN ] column_name SET DEFAULT expression 716 第 11 章 SQL 语句:ABORT 到 ALTER INDEX ALTER [ COLUMN ] column_name DROP DEFAULT ALTER [ COLUMN ] column_name { SET | DROP } NOT NULL ALTER [ COLUMN ] column_name SET STATISTICS integer ALTER [ COLUMN ] column_name SET ( attribute_option = value [, ... ] ) ALTER [ COLUMN ] column_name RESET ( attribute_option [, ... ] ) ALTER [ COLUMN ] column_name SET STORAGE { PLAIN | EXTERNAL | EXTENDED | MAIN } ALTER [ COLUMN ] column_name OPTIONS ( [ ADD | SET | DROP ] option ['value'] [, ... ]) ADD table_constraint [ NOT VALID ] VALIDATE CONSTRAINT constraint_name DROP CONSTRAINT [ IF EXISTS ] constraint_name [ RESTRICT | CASCADE ] DISABLE TRIGGER [ trigger_name | ALL | USER ] ENABLE TRIGGER [ trigger_name | ALL | USER ] ENABLE REPLICA TRIGGER trigger_name ENABLE ALWAYS TRIGGER trigger_name SET WITHOUT OIDS INHERIT parent_table NO INHERIT parent_table OWNER TO { new_owner | CURRENT_USER | SESSION_USER } OPTIONS ( [ ADD | SET | DROP ] option ['value'] [, ... ]) action ::= 717 第 11 章 SQL 语句:ABORT 到 ALTER INDEX 718 第 11 章 SQL 语句:ABORT 到 ALTER INDEX 语义 name 一个要修改的现有外部表的名称(可以被模式限定)。如果在表名前指定了 ONLY,则只有该表被修改。 如果没有指定 ONLY,该表和它所有的后代表(如果有)都会被修改。可选地,在表名后面指定 * 可以显 式地表示将后代表包括在内。 column_name 一个新的或者现有列的名称。 new_column_name 一个现有列的新名称。 new_name 该表的新名称。 data_type 新列的数据类型或者一个现有列的新数据类型。 table_constraint 外部表的新表约束。 constraint_name 要删除的现有约束的名称。 CASCADE 自动删除依赖于被删除列或约束的对象(例如,引用该列的视图),并且接着删除依赖于那些对象的所有 对象。 RESTRICT 如果有任何依赖对象就拒绝删除该列或约束。这是默认行为。 trigger_name 要禁用或启用的一个触发器的名称。 ALL 禁用或者启用所有属于该外部表的触发器(如果任何触发器是内部生成的触发器,这都要求超级用户特 权。核心系统不会向外部表增加这类触发器,但是附加代码会这样做。)。 USER 禁用或者启用属于该外部表的除了内部生成的触发器之外的所有触发器。 parent_table 要与这个外部表关联或者解除关联的父表。 new_owner 719 第 11 章 SQL 语句:ABORT 到 ALTER INDEX 该表的新拥有者的用户名。 new_schema 该表要被移动到其中的模式的名称。 示例 要把一列标记为非空: ALTER FOREIGN TABLE distributors ALTER COLUMN street SET NOT NULL; 要更改一个外部表的选项: ALTER FOREIGN TABLE myschema.distributors OPTIONS (ADD opt1 'value', SET opt2 'value2', DROP opt3 'value3'); 兼容性 形式 ADD、DROP 以及 SET DATA TYPE 符合 SQL 标准。其他形式是 SQL 标准的 KingbaseES 扩展。在一个 ALTER FOREIGN TABLE 命令中指定多于一个操作也是一种扩展。 ALTER FOREIGN TABLE DROP COLUMN 可以被用来删除一个外部表的唯一一列,从而留下一个没有列的表。这是 一种 SQL 的扩展,它允许没有列的外部表。 其他 关键词 COLUMN 是噪声词并且可以被忽略。 当使用 ADD COLUMN 或 DROP COLUMN 增加或移除一列、增加一个 NOT NULL 或者 CHECK 约束或者用 SET DATA TYPE 更改一个列类型时,不会检查与外部服务器的一致性。确保该表定义匹配远端是用户的责任。 关于有效参数的进一步描述可参考CREATE FOREIGN TABLE 。 11.15 ALTER FUNCTION 用途 ALTER FUNCTION —更改一个函数的定义 前置条件 你必须拥有该函数以使用 ALTER FUNCTION。要更改一个函数的模式,你还必须具有新模式上的 CREATE 特权。 要更改拥有者,你还必须是新拥有角色的一个直接或者间接成员,并且该角色必须具有在该函数的模式上的 CREATE 特权(这些限制强制修改拥有者不能做一些通过删除和重建该函数做不到的事情。但是,一个超级用户怎么都能更改 任何函数的所有权)。 语法 ALTER FUNCTION name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ] action [ ... ] [ RESTRICT ] 720 第 11 章 SQL 语句:ABORT 到 ALTER INDEX ALTER FUNCTION name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ] RENAME TO new_name ALTER FUNCTION name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ] OWNER TO { new_owner | CURRENT_USER | SESSION_USER } ALTER FUNCTION name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ] SET SCHEMA new_schema ALTER FUNCTION name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ] DEPENDS ON EXTENSION extension_name ALTER FUNCTION name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ] COMMENT 'String' 其中 action 是以下之一: CALLED ON NULL INPUT | RETURNS NULL ON NULL INPUT | STRICT IMMUTABLE | STABLE | VOLATILE | [ NOT ] LEAKPROOF [ EXTERNAL ] SECURITY INVOKER | [ EXTERNAL ] SECURITY DEFINER PARALLEL { UNSAFE | RESTRICTED | SAFE } COST execution_cost ROWS result_rows SUPPORT support_function SET configuration_parameter { TO | = } { value | DEFAULT } SET configuration_parameter FROM CURRENT RESET configuration_parameter RESET ALL 721 第 11 章 SQL 语句:ABORT 到 ALTER INDEX action ::= 722 第 11 章 SQL 语句:ABORT 到 ALTER INDEX 723 第 11 章 SQL 语句:ABORT 到 ALTER INDEX 语义 name 一个现有函数的名称(可以被模式限定)。如果没有指定参数列表,则该名称必须在它的模式中唯一。 argmode 一个参数的模式:IN、OUT、INOUT 或者 VARIADIC。如果被忽略,默认为 IN。注意 ALTER FUNCTION 并 不真正关心 OUT 参数,因为在决定函数的身份时只需要输入参数。因此列出 IN、INOUT 以及 VARIADIC 参数即可。 argname 一个参数的名称。注意 ALTER FUNCTION 并不真正关心参数名称,因为在确定函数的身份时只需要参数的 数据类型即可。 argtype 该函数的参数(如果有)的数据类型(可以被模式限定)。 new_name 该函数的新名称。 new_owner 该函数的新拥有者。注意如果该函数被标记为 SECURITY DEFINER,它的后续执行将会使用新拥有者。 new_schema 该函数的新模式。 extension_name 该函数所依赖的扩展的名称。 CALLED ON NULL INPUT | RETURNS NULL ON NULL INPUT | STRICT CALLED ON NULL INPUT 将该函数改为在某些或者全部参数为空值时可以被调用。RETURNS NULL ON NULL INPUT 或者 STRICT 将该函数改为只要任一参数为空值就不被调用而是自动假定一个空值结果。详 见CREATE FUNCTION 。 IMMUTABLE | STABLE | VOLATILE 把该函数的稳定性更改为指定的设置。详见CREATE FUNCTION 。 [ EXTERNAL ] SECURITY INVOKER | [ EXTERNAL ] SECURITY DEFINER 更改该函数是否为一个安全性定义者。关键词 EXTERNAL 是为了符合 SQL,它会被忽略。关于这项能力的 详情请见CREATE FUNCTION 。 PARALLEL 决定该函数对于并行是否安全。详见CREATE FUNCTION 。 LEAKPROOF 724 第 11 章 SQL 语句:ABORT 到 ALTER INDEX 更改该函数是否被认为是防泄漏的。关于这项能力的详情请见CREATE FUNCTION 。 COST execution_cost 更改该函数的估计执行代价。详见CREATE FUNCTION 。 ROWS result_rows 更改一个集合返回函数的估计行数。详见CREATE FUNCTION 。 SUPPORT support_function 设置或更改计划器支持函数以用于此函数。详见 函数优化的信息。超级用户方能使用此选项。 此选项不能用于完全删除支持函数,因为它必须命名一个新的支持函数。如果需要,可以使用 CREATE OR REPLACE FUNCTION。 configuration_parameter value 当该函数被调用时,要对一个配置参数做出增加或者更改的赋值。如果 “value“是 DEFAULT 或者使用等价 的 RESET,该函数本地的设置将会被移除,这样该函数会使用其环境中存在的值执行。使用 RESET ALL 可以清除所有函数本地的设置。SET FROM CURRENT 把 ALTER FUNCTION 执行时该参数的当前值保存为进 入该函数时要应用的值。 有关允许的参数名称和值可详见SET 以及《KingbaseES 数据库参考手册》。 RESTRICT 为了符合 SQL 标准存在,被忽略。 COMMENT 'String' 修改函数的注释内容,当参数 String 为空时相当于删除注释。此功能仅限在 MySQL 模式下使用。 示例 要把用于类型 integer 的函数 sqrt 重命名为 square_root: ALTER FUNCTION sqrt(integer) RENAME TO square_root; 要把用于类型 integer 的函数 sqrt``的拥有者改为\ ``joe: ALTER FUNCTION sqrt(integer) OWNER TO joe; 要把用于类型 integer 的函数 sqrt 的模式改为 maths: ALTER FUNCTION sqrt(integer) SET SCHEMA maths; 要把类型 integer 的函数 sqrt 标记为依赖于扩展 mathlib: ALTER FUNCTION sqrt(integer) DEPENDS ON EXTENSION mathlib; 要调整一个函数的自动搜索路径: 725 第 11 章 SQL 语句:ABORT 到 ALTER INDEX ALTER FUNCTION check_password(text) SET search_path = admin, sys_temp; 要禁止一个函数的 search_path 的自动设置: ALTER FUNCTION check_password(text) RESET search_path; 这个函数将用其调用者使用的搜索路径来执行。 在 MySQL 模式的数据库下,修改一个函数的注释: ALTER FUNCTION add_em COMMENT 'CHANGE COMMENT FOR FUNCTION add_em'; 兼容性 这个语句部分兼容 SQL 标准中的 ALTER FUNCTION 语句。该标准允许修改一个函数的更多属性,但是不提供重 命名一个函数、标记一个函数为安全性定义者、为一个函数附加配置参数值或者更改一个函数的拥有者、模式或者稳 定性等功能。该标准还要求 RESTRICT 关键字,它在 KingbaseES 中是可选的。 11.16 ALTER GROUP 用途 ALTER GROUP 更改一个用户组的属性。 前两个变体向一个组增加用户或者从一个组中移除用户(为了这个目的,任何角色都可以扮演“用户”或者 “组”)。这些变体实际上等效于在被称为“组”的角色中授予或者回收成员关系,因此最好的方法是使用GRANT 或者REVOKE 。 第三种变体会更改该组的名称。这恰好等效于用 ALTERROLE 重命名该角色。 前置条件 请参照GRANT , REVOKE , ALTER ROLE 语法 ALTER GROUP role_specification ADD USER user_name [, ... ] ALTER GROUP role_specification DROP USER user_name [, ... ] 其中 role_specification 可以是: role_name | CURRENT_USER | SESSION_USER ALTER GROUP group_name RENAME TO new_name 726 第 11 章 SQL 语句:ABORT 到 ALTER INDEX role_specification ::= 语义 group_name 要修改的组(角色)的名称。 user_name 要被加入到该组或者从该组移除的用户(角色)。这些用户必须已经存在,ALTER GROUP 不会创建或者删 除用户。 new_name 该组的新名称。 示例 向一个组增加用户: ALTER GROUP staff ADD USER karl, john; 从一个组移除一个用户: ALTER GROUP workers DROP USER beth; 兼容性 这是一个被废弃的命令,但是为了向后兼容还是会被接受,因为组(以及用户)已经被更一般的角色概念替代 了。 727 第 11 章 SQL 语句:ABORT 到 ALTER INDEX 11.17 ALTER INDEX 用途 ALTER INDEX 更改一个现有索引的定义。下面描述了几个子表单。注意,每个子表单所需的锁级别可能不同。一个访问 独占的锁被持有,除非被明确的指出。当列出多个子命令时,所持有的锁将是所有子命令所要求的最严格 的锁。 RENAME RENAME 形式更改该索引的名称。如果索引与一个表约束(UNIQUE、PRIMARY KEY 或者 EXCLUDE)关联, 该约束也会被重命名。这对已存储的数据没有影响。 重命名一个索引需要一个 SHARE UPDATE EXCLUSIVE 锁。 SET TABLESPACE 这种形式更改该索引的表空间为指定的表空间,并且把与该索引相关联的数据文件移动到新的表空间中。 要更改一个索引的表空间,你必须拥有该索引并且具有新表空间上的 CREATE 特权。可以使用 ALL IN TABLESPACE 形式把当前数据库中在一个表空间内的所有索引全部移动到另一个表空间中,这将会锁定所 有要被移动的索引然后挨个移动它们。这种形式也支持 OWNED BY,即只移动属于指定角色的索引。如果 指定了 NOWAIT 选项,那么当该命令无法立刻获得所有锁时将会失败。注意这个命令不会移动系统目录, 如果想要移动系统目录,应使用 ALTER DATABASE 或者显式的 ALTER INDEX 调用。另见CREATE TABLESPACE 。 ATTACH PARTITION 导致提到的索引变成附着于被修改的索引。提及的索引必须在包含被修改索引的表的一个分区上,并且具 有一种等效的定义。一个附着索引不能被单独删除,它会在其父索引被删除时自动连带删除。 DEPENDS ON EXTENSION 这种形式把该索引标记为依赖于扩展,这样如果该扩展被删除,该索引也将被自动删除。 SET ( storage_parameter = value [, ... ] ) 这种形式为该索引更改一个或者多个索引方法相关的存储参数。可用的参数详见CREATE INDEX 。注意 这个命令不会立刻修改索引内容,根据参数你可能需要用REINDEX 重建索引来得到想要的效果。 RESET ( storage_parameter [, ... ] ) 这种形式把一个或者多个索引方法相关的存储参数重置为其默认值。正如 SET 一样,可能需要一次 REINDEX 来完全更新该索引。 ALTER [ COLUMN ] column_number SET STATISTICS integer 这种形式为后续的ANALYZE 操作设置针对每个列的统计信息收集目标,但是只能用在被定义为表达 式的索引列上。由于表达式缺少唯一的名称,我们通过该索引列的顺序号来引用它们。收集目标可以被 设置为范围 0 到 10000 之间的值。另外,把它设置为-1 会恢复到使用系统的默认统计信息目标(default_statistics_target )。 728 第 11 章 SQL 语句:ABORT 到 ALTER INDEX 前置条件 你必须拥有该索引以使用 ALTER INDEX 。要修改一个索引的表空间,你必须具有新表空间的 CREATE 特权。 索引的拥有者不能与其表的拥有者不同,更改表的拥有者会自动地更改索引的拥有者。不允许更改系统目录索引的任 何部分。 语法 ALTER INDEX [ IF EXISTS ] name RENAME TO new_name ALTER INDEX [ IF EXISTS ] name SET TABLESPACE tablespace_name ALTER INDEX name ATTACH PARTITION index_name ALTER INDEX name DEPENDS ON EXTENSION extension_name ALTER INDEX [ IF EXISTS ] name SET ( storage_parameter = value [, ... ] ) ALTER INDEX [ IF EXISTS ] name RESET ( storage_parameter [, ... ] ) ALTER INDEX [ IF EXISTS ] name ALTER [ COLUMN ] column_number SET STATISTICS integer ALTER INDEX ALL IN TABLESPACE name [ OWNED BY role_name [, ... ] ] SET TABLESPACE new_tablespace [ NOWAIT ] ALTER INDEX name UNUSABLE | REBUILD ALTER INDEX name ENABLE | DISABLE 729 第 11 章 SQL 语句:ABORT 到 ALTER INDEX 语义 IF EXISTS 如果该索引不存在不要抛出错误。这种情况下将发出一个提示。 column_number 引用该索引列的顺序(从左往右)位置的顺序号。 name 要更改的一个现有索引的名称(可能被模式限定)。 new_name 该索引的新名称。 tablespace_name 该索引将被移动到的表空间。 730 第 11 章 SQL 语句:ABORT 到 ALTER INDEX extension_name 该索引所依赖的扩展的名称。 storage_parameter 一个索引方法相关的存储参数的名称。 value 一个索引方法相关的存储参数的新值。根据该参数,这可能是一个数字或者一个词。 UNUSABLE 将索引状态修改不可用状态。 REBUILD 重建索引,将索引状态修改为可用状态。 ENABLE | DISABLE 仅应用于函数索引,启用或者禁用函数索引。 注意: 1. 可对分区索引、索引分区、子分区索引进行维护操作。详见ALTER TABLE 。 2. 不支持在 alter index 运行时,同时进行 reindex、drop index 操作。 3. 修改索引状态不改变约束状态,禁用唯一约束将删除索引。 示例 要重命名一个现有索引: ALTER INDEX distributors RENAME TO suppliers; 把一个索引移动到一个不同的表空间: ALTER INDEX distributors SET TABLESPACE fasttablespace; 更改一个索引的填充因子(假设该索引方法支持填充因子): ALTER INDEX distributors SET (fillfactor = 75); REINDEX INDEX distributors; 为一个表达式索引设置统计信息收集目标: CREATE INDEX coord_idx ON measured (x, y, (z + t)); ALTER INDEX coord_idx ALTER COLUMN 3 SET STATISTICS 1000; 将索引 index_name 修改为不可用状态: 731 第 11 章 SQL 语句:ABORT 到 ALTER INDEX ALTER INDEX index_name UNUSABLE; 将函数索引 func_index_name 修改为不可用状态: ALTER INDEX func_index_name DISABLE; 重建 index_name 索引: ALTER INDEX index_name REBUILD; 732 第 12 章 SQL 语句:ALTER LANGUAGE 到 ALTER SUBSCRIPTION 第 12章 SQL 语句:ALTER LANGUAGE 到 ALTER SUBSCRIPTION 本章包含以下 SQL 语句: • ALTER LANGUAGE • ALTER LARGE OBJECT • ALTER MATERIALIZED VIEW • ALTER OPERATOR • ALTER OPERATOR CLASS • ALTER OPERATOR FAMILY • ALTER PACKAGE • ALTER POLICY • ALTER PROCEDURE • ALTER PUBLICATION • ALTER RESOURCE GROUP • ALTER ROLE • ALTER ROUTINE • ALTER RULE • ALTER SCHEMA • ALTER SEQUENCE • ALTER SERVER • ALTER STATISTICS • ALTER SUBSCRIPTION 733 第 12 章 SQL 语句:ALTER LANGUAGE 到 ALTER SUBSCRIPTION 12.1 ALTER LANGUAGE 用途 ALTER LANGUAGE 更改一种过程语言的定义。唯一的功能是重命名该语言或者为它赋予一个新的拥有者。 前置条件 要使用 ALTER LANGUAGE,你必须是超级用户或者该语言的拥有者。 语法 ALTER [ PROCEDURAL ] LANGUAGE name RENAME TO new_name ALTER [ PROCEDURAL ] LANGUAGE name OWNER TO { new_owner | CURRENT_USER | SESSION_USER } 语义 name 语言的名称 new_name 该语言的新名称 new_owner 该语言的新拥有者 示例 重命名 ALTER LANGUAGE name RENAME TO new_name; 兼容性 在 SQL 标准中没有 ALTER LANGUAGE 语句。 734 第 12 章 SQL 语句:ALTER LANGUAGE 到 ALTER SUBSCRIPTION 12.2 ALTER LARGE OBJECT 用途 ALTER LARGE OBJECT 更改一个大对象的定义。唯一的功能是为它赋予一个新的拥有者。 前置条件 要使用 ALTER LARGE OBJECT,你必须是超级用户或者该大对象的拥有者。 语法 ALTER LARGE OBJECT large_object_oid OWNER TO { new_owner | CURRENT_USER | SESSION_USER } 语义 large_object_oid 要被修改的大对象的 OID new_owner 该大对象的新拥有者 示例 变更拥有者 ALTER LARGE OBJECT 16399 OWNER TO new_owner; 12.3 ALTER MATERIALIZED VIEW 用途 ALTER MATERIALIZED VIEW —更改一个物化视图的定义 前置条件 ALTER MATERIALIZED VIEW 更改一个现有物化视图的多个辅助属性。 要使用 ALTER MATERIALIZED VIEW,你必须拥有该物化视图。要更改一个物化视图的模式,你还必须拥有新模 式上的 CREATE 特权。要更改拥有者,你还必须是新拥有角色的一个直接或者间接成员,并且该角色必须拥有该物化 735 第 12 章 SQL 语句:ALTER LANGUAGE 到 ALTER SUBSCRIPTION 视图所在模式上的 CREATE 特权(这些限制强制修改拥有者不能做一些通过删除和重建该物化视图做不到的事情。但 是,超级用户怎么都能更改任何视图的所有权。)。 DEPENDS ON EXTENSION 形式把该物化视图标记为依赖于一个扩展,这样该扩展被删除时会自动地删除掉这个物 化视图。 可用于 ALTER MATERIALIZED VIEW 的语句形式和动作是 ALTER TABLE 的一个子集,并且在用于物化视图时具有 相同的含义。 语法 ALTER MATERIALIZED VIEW [ IF EXISTS ] name action [, ... ] ALTER MATERIALIZED VIEW name DEPENDS ON EXTENSION extension_name ALTER MATERIALIZED VIEW [ IF EXISTS ] name RENAME [ COLUMN ] column_name TO new_column_name ALTER MATERIALIZED VIEW [ IF EXISTS ] name RENAME TO new_name 736 第 12 章 SQL 语句:ALTER LANGUAGE 到 ALTER SUBSCRIPTION ALTER MATERIALIZED VIEW [ IF EXISTS ] name SET SCHEMA new_schema ALTER MATERIALIZED VIEW ALL IN TABLESPACE name [ OWNED BY role_name [, ... ] ] SET TABLESPACE new_tablespace [ NOWAIT ] 其中 action 是下列之一: ALTER [ COLUMN ] column_name SET STATISTICS integer ALTER [ COLUMN ] column_name SET ( attribute_option = value [, ... ] ) ALTER [ COLUMN ] column_name RESET ( attribute_option [, ... ] ) 737 第 12 章 SQL 语句:ALTER LANGUAGE 到 ALTER SUBSCRIPTION ALTER [ COLUMN ] column_name SET STORAGE { PLAIN | EXTERNAL | EXTENDED | MAIN } CLUSTER ON index_name SET WITHOUT CLUSTER SET ( storage_parameter = value [, ... ] ) RESET ( storage_parameter [, ... ] ) OWNER TO { new_owner | CURRENT_USER | SESSION_USER } 语义 该部分描述组成语法的关键字、参数、子句的用途。以及可能适用于他们的限制条件和其他用法说明。 name 一个现有物化视图的名称(可以是模式限定的)。 column_name 一个新的或者现有的列的名称。 extension_name 该物化视图所依赖的扩展的名称。 new_column_name 一个现有列的新名称。 new_owner 该物化视图的新拥有者的用户名。 738 第 12 章 SQL 语句:ALTER LANGUAGE 到 ALTER SUBSCRIPTION new_name 该物化视图的新名称。 new_schema 该物化视图的新模式。 示例 把物化视图 foo 重命名为 bar: ALTER MATERIALIZED VIEW foo RENAME TO bar; 12.4 ALTER OPERATOR 用途 ALTER OPERATOR —更改一个操作符的定义 前置条件 要使用 ALTER OPERATOR,你必须是该操作符的所有者。要更改操作符的所有者,你还必须是新所有者角色的一 个直接或者间接成员,并且该角色必须具有该操作符所在模式上的 CREATE 特权(这些限制强制修改拥有者不能做一 些通过删除和重建操作符做不到的事情。但是,超级用户怎么都能更改任何操作符的所有权。)。 语法 ALTER OPERATOR name ( { left_type | NONE } , { right_type | NONE } ) OWNER TO { new_owner | CURRENT_USER | SESSION_USER } ALTER OPERATOR name ( { left_type | NONE } , { right_type | NONE } ) SET SCHEMA new_schema 739 第 12 章 SQL 语句:ALTER LANGUAGE 到 ALTER SUBSCRIPTION ALTER OPERATOR name ( { left_type | NONE } , { right_type | NONE } ) SET ( { RESTRICT = { res_proc | NONE } | JOIN = { join_proc | NONE } } [, ... ] ) 语义 name 一个现有操作符的名称(可以是模式限定的)。 left_type 该操作符左操作数的数据类型,如果该操作符没有左操作数可以写成 NONE。 right_type 该操作符右操作数的数据类型,如果该操作符没有右操作数可以写成 NONE。 new_owner 该操作符的新拥有者。 new_schema 该操作符的新模式。 res_proc 740 第 12 章 SQL 语句:ALTER LANGUAGE 到 ALTER SUBSCRIPTION 这个操作符的约束选择度估算器函数,写成 NONE 可以移除现有的选择度估算器。 join_proc 这个操作符的连接选择度估算器函数,写成 NONE 可以移除现有的选择度估算器。 示例 更改类型 text 的一个自定义操作符 larg @@ rarg 的拥有者: ALTER OPERATOR @@ (text, text) OWNER TO joe; 更改类型 int[] 的自定义操作符 larg && rarg 的约束和连接选择度估算器函数: ALTER OPERATOR && (_int4, _int4) SET (RESTRICT = _int_contsel, JOIN = _int_contjoinsel); 12.5 ALTER OPERATOR CLASS 用途 ALTER OPERATOR CLASS 更改一个操作符类的定义。 前置条件 要使用 ALTER OPERATOR CLASS,你必须拥有该操作符类。要修改操作符类的拥有者,你还必须是新拥有者角色 的一个直接或间接成员,并且该角色必须具有该操作符类所在模式上的 CREATE 特权(这些限制强制修改拥有者不能 做一些通过删除和重建操作符类做不到的事情。但是,超级用户怎么都能更改任何操作符类的所有权。)。 语法 ALTER OPERATOR CLASS name USING index_method RENAME TO new_name ALTER OPERATOR CLASS name USING index_method OWNER TO { new_owner | CURRENT_USER | SESSION_USER } 741 第 12 章 SQL 语句:ALTER LANGUAGE 到 ALTER SUBSCRIPTION ALTER OPERATOR CLASS name USING index_method SET SCHEMA new_schema 语义 name 一个现有操作符类的名称(可以是模式限定的)。 index_method 这个操作符类所服务的索引方法的名称。 new_name 该操作符类的新名称。 new_owner 该操作符类的新拥有者。 new_schema 该操作符类的新模式。 示例 修改操作符类名称 ALTER OPERATOR CLASS test_operator USING gist RENAME TO test_operator_new; 兼容性 在 SQL 标准中没有 ALTER OPERATOR CLASS 语句。 其他 CREATE OPERATOR CLASS , DROP OPERATOR CLASS , ALTER OPERATOR FAMILY 12.6 ALTER OPERATOR FAMILY 用途 ALTER OPERATOR FAMILY 更改一个操作符族的定义。你能增加操作符以及支持函数到该家族、从该族中移除它们或者更改该族的名 称或者拥有者。 742 第 12 章 SQL 语句:ALTER LANGUAGE 到 ALTER SUBSCRIPTION 在用 ALTER OPERATOR FAMILY 增加操作符和支持函数到一个族中时,它们不是族内任何特定操作符类 的组成部分,而只是“松散”地存在于该族中。这表示这些操作符和函数与该族的语义兼容,但是没有 被任何特定索引的正确功能所要求(所要求的操作符和函数应该被作为一个操作符类的一部分声明, 见CREATE OPERATOR CLASS 。KingbaseES 将允许一个族的松散成员在任何时候被从该族中删除, 但是在删除一个操作符类的成员之前,必须已经删除整个类以及依赖于该成员的索引。具有代表性的是, 单一数据类型操作符和函数是操作符类的一部分,因为在特定数据类型上的索引需要它们的支持。而多数 据类型操作符和函数则被作为该族的松散成员。 ALTER OPERATOR FAMILY 目前不检测操作符族定义是否包括该索引方法所要求的所有操作符和函数,也不检查操作符和函数是否形 成了一个有理的集合。定义一个合法的操作符族是用户的责任。 前置条件 要使用 ALTER OPERATOR FAMILY,你必须是超级用户(这样的限制是因为一个错误的操作符族定义可能会造成 服务异常)。 语法 ALTER OPERATOR FAMILY name USING index_method ADD { OPERATOR strategy_number operator_name ( op_type, op_type ) [ FOR SEARCH | FOR ORDER BY sort_family_name ] | FUNCTION support_number [ ( op_type [ , op_type ] ) ] function_name [ ( argument_type [, ...] ) ] } [, ... ] ALTER OPERATOR FAMILY name USING index_method DROP { OPERATOR strategy_number ( op_type [ , op_type ] ) | FUNCTION support_number ( op_type [ , op_type ] ) } [, ... ] 743 第 12 章 SQL 语句:ALTER LANGUAGE 到 ALTER SUBSCRIPTION ALTER OPERATOR FAMILY name USING index_method RENAME TO new_name ALTER OPERATOR FAMILY name USING index_method OWNER TO { new_owner | CURRENT_USER | SESSION_USER } ALTER OPERATOR FAMILY name USING index_method SET SCHEMA new_schema 语义 name 一个现有操作符族的名称(可以是模式限定的)。 index_method 这个操作符族所应用的索引方法的名称。 strategy_number 744 第 12 章 SQL 语句:ALTER LANGUAGE 到 ALTER SUBSCRIPTION 与该操作符族相关的一个操作符的索引方法策略号。 operator_name 与该操作符族相关的一个操作符的名称(可以是模式限定的)。 op_type 在一个 OPERATOR 子句中指定该操作符的操作数数据类型,或者用 NONE 来表示一个左一元或者右一元操 作符。不同于 CREATE OPERATOR CLASS 中类似的语法,操作数数据类型总是必须被指定。 在一个 ADD FUNCTION 子句中指定该函数意图支持的操作数数据类型(如果不同于该函数的输入数据类 型)。对于 B-树比较函数和哈希函数,有必要指定 op_type ,因为该函数的输入数据类型总是正确的。 对于 B-树排序支持函数和 GiST、SP-GiST 和 GIN 操作符类中的所有函数,有必要指定该函数要使用的 操作数数据类型。 在一个 DROP FUNCTION 子句中,必须指定该函数要支持的参数的数据类型。 sort_family_name 一个现有 btree 操作符族的名称(可能是模式限定的),它描述与一个排序操作符相关的排序顺序。 如果既没有指定 FOR SEARCH 也没有指定 FOR ORDER BY,默认值是 FOR SEARCH。 support_number 一个与该操作符族相关的函数的索引方法支持过程编号。 function_name 作为该操作符族的一种索引方法支持函数的函数名称(可以是模式限定的)。如果没有指定参数列表,则 该名称必须在其模式中唯一。 argument_type 该函数的参数数据类型。 new_name 该操作符族的新名称。 new_owner 该操作符族的新拥有者。 new_schema 该操作符族的新模式。 OPERATOR 和 FUNCTION 子句可以以任何顺序出现。 示例 下列示例命令为一个操作符族增加跨数据类型的操作符和支持函数,该操作符族已经包含用于数据类型 int4 以 及 int2 的 B-树操作符类。 745 第 12 章 SQL 语句:ALTER LANGUAGE 到 ALTER SUBSCRIPTION ALTER OPERATOR FAMILY integer_ops USING btree ADD -- int4 vs int2 OPERATOR 1 < (int4, int2) , OPERATOR 2 <= (int4, int2) , OPERATOR 3 = (int4, int2) , OPERATOR 4 >= (int4, int2) , OPERATOR 5 > (int4, int2) , FUNCTION 1 btint42cmp(int4, int2) , -- int2 vs int4 OPERATOR 1 < (int2, int4) , OPERATOR 2 <= (int2, int4) , OPERATOR 3 = (int2, int4) , OPERATOR 4 >= (int2, int4) , OPERATOR 5 > (int2, int4) , FUNCTION 1 btint24cmp(int2, int4) ; 再次移除这些项: ALTER OPERATOR FAMILY integer_ops USING btree DROP -- int4 vs int2 OPERATOR 1 (int4, int2) , OPERATOR 2 (int4, int2) , OPERATOR 3 (int4, int2) , OPERATOR 4 (int4, int2) , OPERATOR 5 (int4, int2) , FUNCTION 1 (int4, int2) , -- int2 vs int4 OPERATOR 1 (int2, int4) , OPERATOR 2 (int2, int4) , OPERATOR 3 (int2, int4) , OPERATOR 4 (int2, int4) , OPERATOR 5 (int2, int4) , FUNCTION 1 (int2, int4) ; 兼容性 在 SQL 标准中没有 ALTER OPERATOR FAMILY 语句。 其他 对于 DROP FUNCTION,要指定的类型是该函数意图支持的输入数据类型。对于 GiST、SP-GiST 以及 GIN 索 引,可能无需对该函数的实际输入参数类型做任何事情。 746 第 12 章 SQL 语句:ALTER LANGUAGE 到 ALTER SUBSCRIPTION 因为索引机制在使用函数之前不会检查其上的访问权限,包括一个操作符族中的函数或操作符都等同于授予了其 上的公共执行权限。这对于操作符族中很有用的这类函数来说,这通常不成问题。 操作符应该由 SQL 函数定义。一个 SQL 函数很可能被内联到调用查询中,这将阻止优化器识别出该查询匹配一 个索引。 12.7 ALTER PACKAGE 用途 ALTER PACKAGE ———修改一个包的定义, 修改包的属性,包括:名称、属主和模式。 需要注意,包属性的修改是没有包规范和包体之分的,包体总是和包规范具有相同属性。包被修改后,该包的对 象(变量、常量、游标、函数和存储过程)的相关属性也会被修改。 前置条件 执行 ALTER PACKAGE 的用户必须是包的属主或非受限数据库管理员,并且要具有包所在模式的 USAGE 权限。 执行 OWNER TO 时,如果执行 ALTER PACKAGE 命令的用户是包的属主但不是非受限数据库管理员,那么新的用 户要具有该模式的 CREATE 权限。 执行 RENAME TO 时,要求用户具有包所在模式下的 CREATE 权限。 执行 SET SCHEMA 时,要求用户在新模式下拥有 CREATE 权限。 语法 ALTER PACKAGE name OWNER TO { new_owner | CURRENT_USER | SESSION_USER } ALTER PACKAGE name RENAME TO new_name ALTER PACKAGE name SET SCHEMA new_schema 747 第 12 章 SQL 语句:ALTER LANGUAGE 到 ALTER SUBSCRIPTION ALTER PACKAGE name COMPILE [ PACKAGE | SPECIFICATION | BODY ] 语义 name 修改的包的名字。可以有数据库名和模式名修饰,但数据库名只能是当前数据库。 new_name 包的新名字。 new_owner 包的新属主。 new_schema 包的新归属模式。 COMPILE 重新编译包,刷新其状态属性。可通过关键字 PACKAGE 指定是重新编译整个包,关键字 SPECIFICATION 指定重新编译包声明,关键字 BODY 指定重新编译包体。 示例 ALTER PACKAGE pkg OWNER TO user_a; ALTER PACKAGE pkg RENAME TO pkg2; ALTER PACKAGE test.public.pkg RENAME TO pkg3;(当前数据库为 TEST) ALTER PACKAGE pkg SET SCHEMA sch; 748 第 12 章 SQL 语句:ALTER LANGUAGE 到 ALTER SUBSCRIPTION 12.8 ALTER POLICY 用途 ALTER POLICY 更改一条现有行级安全性策略的定义。请注意,ALTER POLICY 只允许修改策略所应用的角色集 合,和要修改的 USING 和 WITH CHECK 表达式。要更改策略的其他属性,例如其应用的命令,或者是允许还是限 制,则必须删除并重新创建策略。 在 ALTER POLICY 的第二种形式中,如果指定了角色列表、using_expression 以及 check_expression,它们 会被独立地替换。当这些子句之一被省略时,策略的对应部分不会被更改。 前置条件 要使用 ALTER POLICY,你必须拥有该策略所适用的表。 语法 ALTER POLICY name ON table_name RENAME TO new_name ALTER POLICY name ON table_name [ TO { role_name | PUBLIC | CURRENT_USER | SESSION_USER } [, ...] ] [ USING ( using_expression ) ] [ WITH CHECK ( check_expression ) ] 语义 name 要更改的现有策略的名称。 749 第 12 章 SQL 语句:ALTER LANGUAGE 到 ALTER SUBSCRIPTION table_name 该策略所在的表的名称(可以被模式限定)。 new_name 该策略的新名称。 role_name 该策略适用的角色。可以一次指定多个角色。要把该策略应用于所有角色,可使用 PUBLIC。 using_expression 该策略的 USING 表达式。详见CREATE POLICY 。 check_expression 该策略的 WITH CHECK 表达式。详见CREATE POLICY 。 示例 修改策略名称 ALTER POLICY policy_name ON mytable RENAME TO new_policy_name; 兼容性 ALTER POLICY 是一种 KingbaseES 扩展。 12.9 ALTER PROCEDURE 用途 ALTER PROCEDURE —更改一个过程的定义 前置条件 要使用 ALTER PROCEDURE,你必须拥有该过程。要更改一个过程的方案,你还必须有新方案上的 CREATE 特 权。要更改拥有者,你还必须是新拥有角色的直接或间接成员,并且那个角色在该过程的方案上拥有 CREATE 特权 (这些限制强制更新拥有者无法做到通过删除和重建该过程无法做到的事情。但是,超级用户总是能够更改任何过程 的拥有关系)。 语法 ALTER PROCEDURE name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ] action [ ... ] [ RESTRICT ] 750 第 12 章 SQL 语句:ALTER LANGUAGE 到 ALTER SUBSCRIPTION ALTER PROCEDURE name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ] RENAME TO new_name ALTER PROCEDURE name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ] OWNER TO { new_owner | CURRENT_USER | SESSION_USER } ALTER PROCEDURE name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ] SET SCHEMA new_schema 751 第 12 章 SQL 语句:ALTER LANGUAGE 到 ALTER SUBSCRIPTION ALTER PROCEDURE name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ] DEPENDS ON EXTENSION extension_name ALTER PROCEDURE name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ] COMPILE ALTER PROCEDURE name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ] COMMENT 'String' 752 第 12 章 SQL 语句:ALTER LANGUAGE 到 ALTER SUBSCRIPTION 其中 action 是下列之一: [ EXTERNAL ] SECURITY INVOKER | [ EXTERNAL ] SECURITY DEFINER SET configuration_parameter { TO | = } { value | DEFAULT } SET configuration_parameter FROM CURRENT RESET configuration_parameter RESET ALL 语义 name 一个现有的过程的名字(可以被方案限定)。如果没有指定参数列表,这个名字必须在其方案中唯一。 argmode 参数的模式:IN 或 VARIADIC。如果被省略,默认是 IN。 argname 参数的名字。注意 ALTER PROCEDURE 实际上并不关心参数名,因为只需要参数的数据类型来确定过程的 身份。 argtype 如果该过程有参数,这是参数的数据类型(可以被方案限定)。 new_name 该过程的新名字。 new_owner 该过程的新拥有者。注意,如果这个过程被标记为 SECURITY DEFINER,接下来它将被作为新拥有者执 行。 new_schema 该过程的新方案。 extension_name 该过程所依赖的扩展的名称。 [ EXTERNAL ] SECURITY INVOKER | [ EXTERNAL ] SECURITY DEFINER 753 第 12 章 SQL 语句:ALTER LANGUAGE 到 ALTER SUBSCRIPTION 更改该过程是否为一个安全性定义器。关键词 EXTERNAL 由于 SQL 符合性的原因被忽略。更多有关这个 能力的信息请见CREATE PROCEDURE 。 configuration_parameter value 增加或者更改在调用该过程时,要对一个配置参数做的赋值。如果 “value“是 DEFAULT 或者等效的值,则 会使用 RESET,过程本地的设置会被移除,这样该过程的执行就会使用其所处环境中的值。使用 RESET ALL 可以清除所有的过程本地设置。SET FROM CURRENT 会把 ALTER PROCEDURE 执行时该参数的当前值 保存为进入该过程时要被应用的值。 关于允许的参数名和参数值的更多信息请见SET 和《数据库参考手册》。 RESTRICT 为了符合 SQL 标准会被忽略。 COMPILE 重新编译存储过程,刷新其状态属性。 COMMENT 'String' 修改存储过程的注释内容,当参数 String 为空时相当于删除注释。此功能仅限在 MySQL 模式下使用。 示例 要重命名具有两个 integer 类型参数的过程 insert_data 为 insert_record: ALTER PROCEDURE insert_data(integer, integer) RENAME TO insert_record; 要把具有两个 integer 类型参数的过程 insert_data 的拥有者改为 joe: ALTER PROCEDURE insert_data(integer, integer) OWNER TO joe; 要重把具有两个 integer 类型参数的过程 insert_data 的方案改为 accounting: ALTER PROCEDURE insert_data(integer, integer) SET SCHEMA accounting; 把过程 insert_data(integer, integer) 标记为依赖于扩展 myext: ALTER PROCEDURE insert_data(integer, integer) DEPENDS ON EXTENSION myext; 要调整一个过程自动设置的搜索路径: ALTER PROCEDURE check_password(text) SET search_path = admin, sys_temp; 要为一个过程禁用 search_path 的自动设置: ALTER PROCEDURE check_password(text) RESET search_path; 现在这个过程将用其调用者所使用的任何搜索路径执行。 在 MySQL 模式的数据库下,修改一个存储过程的注释: 754 第 12 章 SQL 语句:ALTER LANGUAGE 到 ALTER SUBSCRIPTION ALTER PROCEDURE increment2 COMMENT 'CHANGE COMMENT FOR PRODURE increment2'; 12.10 ALTER PUBLICATION 用途 命令 ALTER PUBLICATION 可以更改发布的属性。 前三个语句更改哪些表是该发布的一部分。SET TABLE 子句用指定的表替换发布中的表的列表。ADD TABLE 和 DROP TABLE 子句将从发布中添加和删除一个或多个表。请注意,将表添加到已订阅的发布中将需要在订阅端执行 ALTER SUBSCRIPTION ... REFRESH PUBLICATION 操作才能生效。 第四条语句可以改变在CREATE PUBLICATION 中指定的所有发布属性。该命令中未提及的属性保留其先前的 设置。 其余语句更改所有者和发布的名称。 前置条件 你必须拥有该发布才能使用 ALTER PUBLICATION。要改变所有者,你也必须是新所有者角色的直接或间接成 员。新的所有者必须在数据库上拥有 CREATE 权限。此外,FOR ALL TABLES 发布的新所有者必须是超级用户。但是, 超级用户可以在避开这些限制的情况下更改发布的所有权。 语法 ALTER PUBLICATION name ADD TABLE [ ONLY ] table_name [ * ] [, ...] ALTER PUBLICATION name SET TABLE [ ONLY ] table_name [ * ] [, ...] 755 第 12 章 SQL 语句:ALTER LANGUAGE 到 ALTER SUBSCRIPTION ALTER PUBLICATION name DROP TABLE [ ONLY ] table_name [ * ] [, ...] ALTER PUBLICATION name SET ( publication_parameter [= value] [, ... ] ) ALTER PUBLICATION name OWNER TO { new_owner | CURRENT_USER | SESSION_USER } 756 第 12 章 SQL 语句:ALTER LANGUAGE 到 ALTER SUBSCRIPTION ALTER PUBLICATION name RENAME TO new_name 语义 name 要修改定义的现有发布的名称。 table_name 现有表的名称。如果在表名之前指定了 ONLY,则只有该表受到影响。如果没有指定 ONLY,则该表及其 所有后代表(如果有的话)都会受到影响。可选地,可以在表名之后指定 * 以明确指示包含后代表。 SET ( publication_parameter [ = value ] [, ... ] ) 该子句修改最初由CREATE PUBLICATION 设置的发布参数。 new_owner 发布的新所有者的用户名。 new_name 发布的新名称。 示例 将发布修改为只发布删除和更新: ALTER PUBLICATION noinsert SET (publish = 'update, delete'); 给发布添加一些表: ALTER PUBLICATION mypublication ADD TABLE users, departments; 兼容性 ALTER PUBLICATION 是 KingbaseES 的一个扩展。 其他 参见CREATE PUBLICATION , DROP PUBLICATION , CREATE SUBSCRIPTION , ALTER SUBSCRIPTION 757 第 12 章 SQL 语句:ALTER LANGUAGE 到 ALTER SUBSCRIPTION 12.11 ALTER RESOURCE GROUP 用途 修改一个资源组的限制值。 前置条件 资源组功能依赖于操作系统的 cgroup,所以仅支持类 linux 操作系统。 语法 ALTER RESOURCE GROUP group_name SET (resource_name = value); 语义 group_name 为创建的资源组名称, 一个数据库内唯一,该对象不属于某个模式下。 resource_name 为设置控制资源类型的名称,目前支持 cpu_shares 和 cpu_cfs_quota_us。 value 为资源的值,为数字类型。 示例 设置一个资源组的相对 CPU 使用率基于 cgroup 的 cpu 子系统,可以调用 CPU 的获取量,这里采用了完全公平 调度程序(CFS),一个比例分配调度程序,可根据任务优先级 ∕ 权重或资源组分得的份额,在任务群组(cgroups) 间按比例分配 CPU 时间(CPU 带宽)。 在 CFS 中,如果系统有足够的空闲 CPU 周期,资源组可获得比其自有份额更多的 CPU 可用量,因为该调度程 序有连续工作的特性。此情况通常会在资源组根据相关共享消耗 CPU 时间时出现。 value 默认值:10000 ,取值范围:10-10000 alter resource group rgroup1 set (cpu_shares = 5000); 12.12 ALTER ROLE 用途 ALTER ROLE 更改一个 KingbaseES 角色的属性。 前面列出的这个命令的第一种变体能够更改CREATE ROLE 中指定的很多角色属性(覆盖了所有可能的属性, 但是没有增加和移除成员关系的选项,如果要增加和移除成员关系可使用GRANT 和REVOKE )。该命令中没有提 758 第 12 章 SQL 语句:ALTER LANGUAGE 到 ALTER SUBSCRIPTION 到的属性保持它们之前的设置。数据库超级用户能够更改任何角色的任何这些设置。具有 CREATEROLE 特权的角色能 够更改任何这些设置,但是只能为非超级用户和非复制角色修改。普通角色只能更改它们自己的口令。 第二种变体更改该角色的名称。数据库超级用户能重命名任何角色。具有 CREATEROLE 特权的角色能够重命名任 何非超级用户角色。当前的会话用户不能被重命名(如果需要这样做,请以一个不同的用户连接)。由于 MD5 加密的 口令使用角色名作为 salt,因此如果一个角色的口令是 MD5 加密的,重命名该角色会清空其口令。 其余的变体用于更改一个角色的配置变量的会话默认值,可以为所有数据库设置,或者只为 IN DATABASE 中指 定的数据库设置。如果指定的是 ALL 而不是一个角色名,将会为所有角色更改该设置。把 ALL 和 IN DATABASE 一起 使用实际上和使用命令 ALTER DATABASE ... SET ... 相同。 只要改角色后续开始一个新会话,指定的值将会成为该会话的默认值,并且会覆盖 kingbase.conf 中存在的值 或者从 kingbase 命令行收到的值。这只在登录时发生,执行SET ROLE 或者SET SESSION AUTHORIZATION 不 会导致新的配置值被设置。对于所有数据库设置的值会被附加到一个角色的数据库相关的设置所覆盖。特定数据库或 角色的设置会覆盖为所有角色所作的设置。 前置条件 超级用户能够更改任何人的会话默认值。具有 CREATEROLE 特权的角色能够更改非超级用户的默认值。普通角色 只能为它们自己设置默认值。某些配置变量不能以这种方式设置,或者只能由超级用户发出的命令设置。只有超级用 户能够更改所有角色在所有数据库中的设置。 语法 ALTER ROLE role_specification [ WITH ] option [ ... ] 其中 option 可以是: SUPERUSER | NOSUPERUSER | CREATEDB | NOCREATEDB | CREATEROLE | NOCREATEROLE | INHERIT | NOINHERIT | LOGIN | NOLOGIN | REPLICATION | NOREPLICATION | BYPASSRLS | NOBYPASSRLS | CONNECTION LIMIT connlimit | [ ENCRYPTED ] PASSWORD 'password' | PASSWORD NULL | VALID UNTIL 'timestamp' 759 第 12 章 SQL 语句:ALTER LANGUAGE 到 ALTER SUBSCRIPTION 760 第 12 章 SQL 语句:ALTER LANGUAGE 到 ALTER SUBSCRIPTION ALTER ROLE name RENAME TO new_name ALTER ROLE { role_specification | ALL } [ IN DATABASE database_name ] SET configuration_parameter { TO | = } { value | DEFAULT } ALTER ROLE { role_specification | ALL } [ IN DATABASE database_name ] SET configuration_parameter FROM CURRENT ALTER ROLE { role_specification | ALL } [ IN DATABASE database_name ] RESET configuration_parameter ALTER ROLE { role_specification | ALL } [ IN DATABASE database_name ] RESET ALL 761 第 12 章 SQL 语句:ALTER LANGUAGE 到 ALTER SUBSCRIPTION 其中 role_specification 可以是: role_name | CURRENT_USER | SESSION_USER 语义 name 要对其属性进行修改的角色的名称。 CURRENT_USER 修改当前用户而不是一个显式标识的角色。 SESSION_USER 修改当前会话用户而不是一个显式标识的角色。 SUPERUSER | NOSUPERUSER | CREATEDB | NOCREATEDB | CREATEROLE | NOCREATEROLE | INHERIT | NOINHERIT | LOGIN | NOLOGIN | REPLICATION | NOREPLICATION | BYPASSRLS | NOBYPASSRLS | CONNECTION LIMIT connlimit | [ ENCRYPTED ] PASSWORD 'password' | PASSWORD NULL | VALID UNTIL 'timestamp' 这些子句修改原来有CREATE ROLE 设置的属性。更多信息请见CREATE ROLE 参考页。 new_name 该角色的新名称。 database_name 要在其中设置该配置变量的数据库名称。 configuration_parameter value 把这个角色的指定配置参数的会话默认值设置为给定值。如果 value 为 DEFAULT 或者等效地使用 了 RESET,角色相关的变量设置会被移除,这样该角色将会在新会话中继承系统范围的默认设置。使用 762 第 12 章 SQL 语句:ALTER LANGUAGE 到 ALTER SUBSCRIPTION RESET ALL 可清除所有角色相关的设置。SET FROM CURRENT 可以把会话中该参数的当前值保存为角色相 关的值。如果指定了 IN DATABASE ,只会为给定的角色和数据库设置或者移除该配置参数。 角色相关的变量设置只在登录时生效,SET ROLE 以及SET SESSION AUTHORIZATION 不会处理角色 相关的变量设置。 关于允许的参数名称和值详见SET 和《KingbaseES 数据库参考手册》。 示例 更改一个角色的口令: ALTER ROLE davide WITH PASSWORD 'hu8jmn3'; 移除一个角色的口令: ALTER ROLE davide WITH PASSWORD NULL; 更改一个口令的失效日期,指定该口令应该在 2015 年 5 月 4 日中午(在一个比 UTC 快 1 小时的时区)过期: ALTER ROLE chris VALID UNTIL 'May 4 12:00:00 2015 +1'; 让一个口令永远有效: ALTER ROLE fred VALID UNTIL 'infinity'; 让一个角色能够创建其他角色和新的数据库: ALTER ROLE miriam CREATEROLE CREATEDB; 为一个角色指定 maintenance_work_mem 参数的非默认设置: ALTER ROLE worker_bee SET maintenance_work_mem = 100000; 为一个角色指定 client_min_messages 参数的数据库相关的非默认设置: ALTER ROLE fred IN DATABASE devel SET client_min_messages = DEBUG; 其他 使用CREATE ROLE 增加新角色,使用DROP ROLE 移除一个角色。 ALTER ROLE 无法更改一个角色成员关系。可以使用GRANT 和REVOKE 来实现。 在使用这个命令指定一个未加密口令时要多加小心。该口令将会以明文传送到服务器,并且它还可能会被记录在 客户端的命令历史或者服务器日志中。ksql 包含了一个命令 password,它可以被用来更改一个角色的口令而不暴露 明文口令。 也可以把一个会话默认值绑定到一个指定的数据库而不是一个角色,详见: ALTER DATABASE 。如果出现冲 突,数据库角色相关的设置会覆盖角色相关的设置,角色相关的又会覆盖数据库相关的设置。 763 第 12 章 SQL 语句:ALTER LANGUAGE 到 ALTER SUBSCRIPTION 12.13 ALTER ROUTINE 用途 ALTER ROUTINE 更改一个例程的定义,它可以是聚集函数、普通函数或者过程。参数的描述、更多的例子以及进 一步的细节请参考ALTER AGGREGATE 、ALTER FUNCTION 以及ALTER PROCEDURE 。 前置条件 你必须拥有该例程以使用 ALTER ROUTINE 。要重命名例程名或更改例程名的属主,那么这个例程名必须不存 在。要修改某个模式下的例程,那么这个模式下必须存在这个例程。 语法 ALTER ROUTINE name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ] action [ ... ] [ RESTRICT ] ALTER ROUTINE name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ] RENAME TO new_name ALTER ROUTINE name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ] OWNER TO { new_owner | CURRENT_USER | SESSION_USER } 764 第 12 章 SQL 语句:ALTER LANGUAGE 到 ALTER SUBSCRIPTION ALTER ROUTINE name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ] SET SCHEMA new_schema ALTER ROUTINE name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ] DEPENDS ON EXTENSION extension_name 其中 action 是下列之一: IMMUTABLE | STABLE | VOLATILE | [ NOT ] LEAKPROOF [ EXTERNAL ] SECURITY INVOKER | [ EXTERNAL ] SECURITY DEFINER PARALLEL { UNSAFE | RESTRICTED | SAFE } COST execution_cost ROWS result_rows SET configuration_parameter { TO | = } { value | DEFAULT } SET configuration_parameter FROM CURRENT 765 第 12 章 SQL 语句:ALTER LANGUAGE 到 ALTER SUBSCRIPTION RESET configuration_parameter RESET ALL 示例 将类型 integer 的例程 foo 重命名为 foobar: ALTER ROUTINE foo(integer) RENAME TO foobar; 不管 foo 是聚集、函数还是过程,这个命令都能使用。 兼容性 这个语句与 SQL 标准中的 ALTER ROUTINE 语句部分兼容。更多细节请参考ALTER FUNCTION 和ALTER PROCEDURE 。允许例程名称引用聚集函数是一种 KingbaseES 的扩展。 其他 参见ALTER AGGREGATE , ALTER FUNCTION , ALTER PROCEDURE , DROP ROUTINE 注意没有 CREATE ROUTINE 命令。 12.14 ALTER RULE 用途 ALTER RULE 更改一条现有规则的定义。当前,唯一可用的动作是更改规则的名称。 前置条件 要使用 ALTER RULE,你必须拥有该规则适用的表或者视图。 语法 ALTER RULE name ON table_name RENAME TO new_name 语义 name 766 第 12 章 SQL 语句:ALTER LANGUAGE 到 ALTER SUBSCRIPTION 要修改的一条现有规则的名称。 table_name 该规则适用的表或视图的名称(可以是模式限定的)。 new_name 该规则的新名称。 示例 要重命名一条现有的规则: ALTER RULE notify_all ON emp RENAME TO notify_me; 兼容性 ALTER RULE 是一种 KingbaseES 的语言扩展,整个查询重写系统也是。 12.15 ALTER SCHEMA 用途 ALTER SCHEMA 更改一个模式的定义。 前置条件 要使用 ALTER SCHEMA,你必须拥有该模式。要重命名一个模式,你还必须拥有该数据库的 CREATE 特权。要更 改拥有者,你还必须是新拥有角色的一个直接或者间接成员,并且该角色必须具有该数据库上的 CREATE 特权(注意 超级用户自动拥有所有这些特权)。 语法 ALTER SCHEMA name RENAME TO new_name ALTER SCHEMA name OWNER TO { new_owner | CURRENT_USER | SESSION_USER } 语义 name 一个现有模式的名称。 767 第 12 章 SQL 语句:ALTER LANGUAGE 到 ALTER SUBSCRIPTION new_name 该模式的新名称。新名称不能以 sys_ 开始,因为这些名称被保留用于系统模式。 new_owner 该模式的新拥有者。 示例 要重命名一条现有的规则: ALTER SCHEMA test RENAME TO test1; 兼容性 在 SQL 标准中没有 ALTER SCHEMA 语句。 12.16 ALTER SEQUENCE 用途 ALTER SEQUENCE 更改一个现有序列发生器的参数。任何没有在 ALTER SEQUENCE 命令中明确设置的参数保持它 们之前的设置。 前置条件 要使用 ALTER SEQUENCE,你必须拥有该序列。要更改一个序列的模式,你还必须拥有新模式上的 CREATE 特 权。要更改拥有者,你还必须是新拥有角色的一个直接或者间接成员,并且该角色必须具有该域的模式上的 CREATE 特权(这些限制强制修改拥有者不能做一些通过删除和重建该序列做不到的事情。但是,超级用户怎么都能更改任何 序列的所有权。)。 语法 ALTER SEQUENCE [ IF EXISTS ] name [ AS data_type ] [ INCREMENT [ BY ] increment ] [ MINVALUE minvalue | NO MINVALUE ] [ MAXVALUE maxvalue | NO MAXVALUE ] [ START [ WITH ] start ] [ RESTART [ [ WITH ] restart ] ] [ CACHE cache ] [ NOCACHE ] [ [ NO ] CYCLE ] [ NOCYCLE ] [ ORDER ] [ NOORDER ] [ OWNED BY { table_name.column_name | NONE } ] 768 第 12 章 SQL 语句:ALTER LANGUAGE 到 ALTER SUBSCRIPTION ALTER SEQUENCE [ IF EXISTS ] name OWNER TO { new_owner | CURRENT_USER | SESSION_USER } ALTER SEQUENCE [ IF EXISTS ] name RENAME TO new_name ALTER SEQUENCE [ IF EXISTS ] name SET SCHEMA new_schema 769 第 12 章 SQL 语句:ALTER LANGUAGE 到 ALTER SUBSCRIPTION 语义 name 要修改的序列的名称(可以是模式限定的)。 IF EXISTS 在序列不存在时不要抛出一个错误。这种情况下会发出一个提示。 data_type 可选子句 AS data_type 改变序列的数据类型。有效类型是 smallint、integer 和 bigint。 当且仅当先前的最小值和最大值是旧数据类型的最小值或最大值时(换句话说,如果序列是使用 NO MINVALUE 或 NO MAXVALUE,隐式或显式创建的),则更改数据类型会自动更改序列的最小值和最大值。 否则,将保留最小值和最大值,除非将新值作为同一命令的一部分给出。如果最小值和最大值不符合新的 数据类型,则会生成错误。 increment 子句 INCREMENT BY increment 是可选的。一个正值将产生一个上升序列,一个负值会产生一个下降序 列。如果没有指定,旧的增量值将被保持。 minvalue | NO MINVALUE 可选的子句 MINVALUE minvalue 决定一个序列能产生的最小值。如果指定了 NO MINVALUE,上升序列和 下降序列的默认值分别是 1 和数据类型的最小值。如果这些选项都没有被指定,将保持当前的最小值。 maxvalue | NO MAXVALUE 可选的子句 MAXVALUE maxvalue 决定一个序列能产生的最大值。如果指定了 NO MAXVALUE,上升序列和 下降序列的默认值分别是数据类型的最大值和 -1。如果这些选项都没有被指定,将保持当前的最大值。 start 可选的子句 START WITH start 更改该序列被记录的开始值。这对于当前序列值没有影响,它会简单地设置 未来 ALTER SEQUENCE RESTART 命令将会使用的值。 restart 可选的子句 RESTART [ WITH restart ] 更改该序列的当前值。这类似于用 is_called = false 调用 setval 函数:被指定的值将会被下一次 nextval 调用返回。写上没有 “restart“值的 RESTART 等效于提 供被 CREATE SEQUENCE 记录的或者上一次被 ALTER SEQUENCE START WITH 设置的开始值。 与 setval 调用相比,序列上的 RESTART 操作是事务性的并阻止并发事务从同一序列中获取数字。如果 这不是所需的操作模式,则应使用 setval。 cache | NOCYCLE 子句 CACHE cache 使得序列数字被预先分配并且保存在内存中以便更快的访问。最小值是 1(每次只产 生一个值,即无缓存)。如果没有指定,旧的缓冲值将被保持。 指定 NOCACHE,即没有缓存,缓存值为 1。 CYCLE 770 第 12 章 SQL 语句:ALTER LANGUAGE 到 ALTER SUBSCRIPTION 可选的 CYCLE 关键词可以被用来允许该序列在达到 “maxvalue“(上升序列)或 “minvalue“(下降序列) 时回卷。如果到达该限制,下一个被产生的数字将分别是 “minvalue“或者 “maxvalue“。 NO CYCLE | NOCYCLE 如果指定了可选的 NO CYCLE 关键词,任何在该序列到达其最大值后的 nextval 调用将会返回一个错 误。如果既没有指定 CYCLE 也没有指定 NO CYCLE,旧的循环行为将被保持。 NOCYCLE 等价于 NO CYCLE。 ORDER | NOORDER ORDER 与 NOORDER 只在语法层面兼容 Oracle 数据库,并没有实现相应的功能。 OWNED BY table_name.column_name | OWNED BY NONE OWNED BY 选项导致该序列与一个特定的表列相关联,这样如果该列(或者整个表)被删除,该序列也会 被自动删除。如果指定,这种关联会替代之前为该序列指定的任何关联。被指定的表必须具有相同的拥有 者并且与该序列在同一个模式中。指定 OWNED BY NONE 可以移除任何现有的关联,让该序列“自立”。 new_owner 该序列的新拥有者的用户名。 new_name 该序列的新名称。 new_schema 该序列的新模式。 示例 从 105 重启一个被称为 serial 的序列: ALTER SEQUENCE serial RESTART WITH 105; 其他 ALTER SEQUENCE 将不会立即影响除当前后端外其他后端中的 nextval 结果,因为它们有预分配(缓存)的序列 值。在注意到序列生成参数被更改之前它们将用尽所有缓存的值。当前后端将被立刻影响。 ALTER SEQUENCE 不会影响该序列的 currval 状态(在 KingbaseES V9 之前有时会影响)。 ALTER SEQUENCE 阻塞并发 nextval、currval、lastval 和 setval 调用。 由于历史原因,ALTER TABLE 也可以被用于序列,但是只有等效于上述形式的 ALTER TABLE 变体才被允许用于 序列。 12.17 ALTER SERVER 用途 771 第 12 章 SQL 语句:ALTER LANGUAGE 到 ALTER SUBSCRIPTION ALTER SERVER 更改一个外部服务器的定义。第一种形式更改该服务器的版本字符串或者该服务器的一般选项 (至少要求一个子句)。第二种形式更改该服务器的拥有者。 前置条件 要修改该服务器,你必须是它的拥有者。此外为了修改拥有者,你必须拥有该服务器并且是新拥有角色的一个直 接或者间接成员,并且你必须具有该服务器的外部数据包装器上的 USAGE 特权(注意超级用户自动满足所有这些政 策)。 语法 ALTER SERVER name [ VERSION 'new_version' ] [ OPTIONS ( [ ADD | SET | DROP ] option ['value'] [, ... ] ) ] ALTER SERVER name OWNER TO { new_owner | CURRENT_USER | SESSION_USER } ALTER SERVER name RENAME TO new_name 772 第 12 章 SQL 语句:ALTER LANGUAGE 到 ALTER SUBSCRIPTION 语义 name 一个现有服务器的名称。 new_version 新的服务器版本。 OPTIONS ( [ ADD | SET | DROP ] option ['value'] [, ... ] ) 更改该服务器的选项。ADD、SET 和 DROP 指定要执行的动作。如果没有显式地指定操作,将会假定为 ADD。选项名称必须唯一,名称和值也会使用该服务器的外部数据包装器库进行验证。 new_owner 该外部服务器的新拥有者的用户名。 new_name 该外部服务器的新名称。 示例 修改服务器 foo,增加连接选项: ALTER SERVER foo OPTIONS (host 'foo', dbname 'foodb'); 修改服务器 foo,更改版本、更改 host 选项: ALTER SERVER foo VERSION '8.4' OPTIONS (SET host 'baz'); 兼容性 ALTER SERVER 符合 ISO/IEC 9075-9 (SQL/MED)。OWNER TO 和 RENAME 形式是 KingbaseES 扩展。 12.18 ALTER STATISTICS 用途 ALTER STATISTICS 更改现有扩展统计对象的参数。任何在 ALTER STATISTICS 命令中没有明确设定的参数保持 它们之前的设置。 前置条件 您必须拥有统计对象才能使用 ALTER STATISTICS。要更改统计对象的模式,还必须在新模式上具有 CREATE 权 限。要更改所有者,还必须是新所有者角色的直接或间接成员,且该角色在统计对象的模式上必须具有 CREATE 权 限。(这些限制强制了通过删除和重新创建统计对象来改变所有者不会做任何你不能做的事情,但是超级用户可以改 变任何统计对象的所有权。) 语法 773 第 12 章 SQL 语句:ALTER LANGUAGE 到 ALTER SUBSCRIPTION ALTER STATISTICS name OWNER TO { new_owner | CURRENT_USER | SESSION_USER } ALTER STATISTICS name RENAME TO new_name ALTER STATISTICS name SET SCHEMA new_schema 语义 name 要修改的统计对象的名称(可能有模式修饰)。 new_owner 统计对象的新所有者的用户名。 new_name 统计对象的新名称。 new_schema 统计对象的新模式。 示例 使用CREATE STATISTICS 中示例创建的统计对象 s1,将其名称修改为 s1_t1。 ALTER STATISTICS s1 RENAME TO s1_t1; 兼容性 SQL 标准中没有 ALTER STATISTICS 命令。 774 第 12 章 SQL 语句:ALTER LANGUAGE 到 ALTER SUBSCRIPTION 12.19 ALTER SUBSCRIPTION 用途 ALTER SUBSCRIPTION 可以修改大部分可以在CREATE SUBSCRIPTION 中指定的订阅属性。 前置条件 要使用 ALTER SUBSCRIPTION,你必须拥有该订阅。要改变所有者,你也必须是新所有者的直接或间接成员。新 所有者必须是超级用户。(目前,所有的订阅所有者必须是超级用户,所以所有者的检查将在实践中被绕过,但这可 能在未来发生变化。) 语法 ALTER SUBSCRIPTION name CONNECTION 'conninfo' ALTER SUBSCRIPTION name SET PUBLICATION publication_name [, ...] [ WITH (set_publication_option [= value] [, ... ] ) ] ALTER SUBSCRIPTION name REFRESH PUBLICATION [ WITH ( refresh_option [= value] [, ... ] ) ] 775 第 12 章 SQL 语句:ALTER LANGUAGE 到 ALTER SUBSCRIPTION ALTER SUBSCRIPTION name ENABLE ALTER SUBSCRIPTION name DISABLE ALTER SUBSCRIPTION name SET ( subscription_parameter [= value] [, ... ] ) ALTER SUBSCRIPTION name OWNER TO { new_owner | CURRENT_USER | SESSION_USER } ALTER SUBSCRIPTION name RENAME TO new_name 776 第 12 章 SQL 语句:ALTER LANGUAGE 到 ALTER SUBSCRIPTION 语义 name 要修改属性的订阅的名称。 CONNECTION 'conninfo' 该子句修改最初由CREATE SUBSCRIPTION 设置的连接属性。 SET PUBLICATION publication_name 更改订阅发布的列表。参阅CREATE SUBSCRIPTION 获取更多信息。默认情况下,此命令也将像 REFRESH PUBLICATION 一样工作。 set_publication_option 指定了这个操作的附加选项。支持的选项是: refresh (boolean) 如果为 false,则该命令将不会尝试刷新表信息。然后应单独执行 REFRESH PUBLICATION。默认 值是 true。 此外,可以指定 REFRESH PUBLICATION 下描述的刷新选项。 REFRESH PUBLICATION 从 发 布 者 获 取 缺 少 的 表 信 息。 这 将 开 始 复 制 自 上 次 调 用 REFRESH PUBLICATION 或 从 CREATE SUBSCRIPTION 以来添加到订阅发布中的表。 refresh_option 指定了刷新操作的附加选项。支持的选项有: copy_data (boolean) 指定在复制启动后是否应复制正在订阅的发布中的现有数据。默认值是 true。 ENABLE 启用先前禁用的订阅,在事务结束时启动逻辑复制工作。 DISABLE 禁用正在运行的订阅,在事务结束时停止逻辑复制工作。 SET ( subscription_parameter [= value ] [, ... ] ) 该 子 句 修 改 原 先 由CREATE SUBSCRIPTION 设 置 的 参 数。 允 许 的 选 项 是 slot_name 和 synchronous_commit。 new_owner 订阅的新所有者的用户名。 new_name 订阅的新名称。 示例 将订阅的发布更改为 insert_only: 777 第 12 章 SQL 语句:ALTER LANGUAGE 到 ALTER SUBSCRIPTION ALTER SUBSCRIPTION mysub SET PUBLICATION insert_only; 禁用(停止)订阅: ALTER SUBSCRIPTION mysub DISABLE; 兼容性 ALTER SUBSCRIPTION 是 KingbaseES 的一个扩展。 其他 参见CREATE SUBSCRIPTION , DROP SUBSCRIPTION , CREATE PUBLICATION , ALTER PUBLICATION 778 第 13 章 SQL 语句:ALTER SYNONYM 到 COMMENT 13章 SQL 语句:ALTER SYNONYM 到 第 COMMENT 本章包含以下 SQL 语句: • ALTER SYNONYM • ALTER SYSTEM • ALTER TABLE • ALTER TABLESPACE • ALTER TEXT SEARCH CONFIGURATION • ALTER TEXT SEARCH DICTIONARY • ALTER TEXT SEARCH PARSER • ALTER TEXT SEARCH TEMPLATE • ALTER TRIGGER • ALTER TYPE • ALTER USER • ALTER USER MAPPING • ALTER VIEW • ANALYZE • BEGIN • CALL/EXEC • CHECKPOINT • CLOSE • CLUSTER • COMMENT 779 第 13 章 SQL 语句:ALTER SYNONYM 到 COMMENT 13.1 ALTER SYNONYM 用途 ALTER SYNONYM 更改一个同义词的多种辅助属性(如果想要修改同义词的定义,应使用 CREATE OR REPLACE SYNONYM)。 前置条件 要使用 ALTER SYNONYM,用户必须拥有该同义词的权限。要更改一个同义词的模式,必须具有新模式上的 CREATE 特权。要更改拥有者,必须是新拥有角色的一个直接或者间接成员,并且该角色必须具有该同义词的模式上 的 “CREATE“特权(超级用户拥有更改任何同义词的所有权)。 语法 ALTER [ PUBLIC ] SYNONYM syn_name OWNER TO { new_owner | CURRENT_USER | SESSION_USER } ALTER [ PUBLIC ] SYNONYM [ IF EXISTS ] syn_name RENAME TO new_name 语义 syn_name 一个现有同义词的名称(可以是模式限定的)。 IF EXISTS 该同义词不存在时不要抛出一个错误,这种情况下会发出一个提示。 new_owner 该同义词的新拥有者的用户名。 new_name 该同义词的新名称。 示例 例 1:把同义词 syn_tab 重命名为 syntab: ALTER SYNONYM syn_tab RENAME TO syntab; 例 2:把同义词 syn_tab 拥有者修改为 U1: 780 第 13 章 SQL 语句:ALTER SYNONYM 到 COMMENT ALTER SYNONYM syn_tab OWNER TO U1; 13.2 ALTER SYSTEM 用途 ALTER SYSTEM 被用来在整个数据库集簇范围内更改服务器配置参数。它比传统的手动编辑 kingbase.conf 文件 的方法更方便。ALTER SYSTEM 会把给出的参数设置写入到 kingbase.auto.conf 文件中,该文件会随着 kingbase. conf 一起被读入。把一个参数设置为 DEFAULT 或者使用 RESET 变体可以把该配置项从 kingbase.auto.conf 文件 中移除。使用 RESET ALL 可以移除所有这类配置项。 用 ALTER SYSTEM 设置的值将在下一次重载服务器配置后生效,那些只能在服务器启动时更改的参数则会在下一 次服务器重启后生效。重载服务器配置可以通过以下做法实现:调用 SQL 函数 sys_reload_conf(),运行 sys_ctl reload 或者向主服务器进程发送一个 SIGHUP 信号。 使用 ALTER SYSTEM SET 相关语法修改数据库设置时会在日志内写入警示信息,警示内容包括进行该修改的用户 和变更参数。 前置条件 只有超级用户能够使用 ALTER SYSTEM。还有,由于这个命令直接作用于文件系统并且不能被回滚,不允许在一 个事务块或者函数中使用它。 语法 ALTER SYSTEM SET configuration_parameter { TO | = } { value | 'value' | DEFAULT } ALTER SYSTEM RESET configuration_parameter ALTER SYSTEM RESET ALL 语义 configuration_parameter 一个可设置配置参数的名称。可用的参数可见《KingbaseES 数据库参考手册》。 781 第 13 章 SQL 语句:ALTER SYNONYM 到 COMMENT value 该参数的新值。值可以被指定为字符串常量、标识符、数字或者以上这些构成的逗号分隔的列表,值的具 体形式取决于特定的参数。写上 DEFAULT 可以用来把该参数及其值从 kingbase.auto.conf 中移除。 示例 设置 wal_level: ALTER SYSTEM SET wal_level = replica; 撤销以上的设置,恢复 kingbase.conf 中有效的设置: ALTER SYSTEM RESET wal_level; 13.3 ALTER TABLE 用途 ALTER TABLE 更改一个现有表的定义。下文描述了几种形式。注意每一种形式所要求的锁级别可能不同。如果没 有明确说明,将会持有一个 ACCESS EXCLUSIVE 所。当列出多个子命令时,所持有的锁将是子命令所要求的最严格的 那一个。 使用 ALTER TABLE 相关语法修改表结构时日志中将会写入警告信息, 记录该操作的用户及修改动作。 前置条件 要使用 ALTER TABLE,你必须拥有该表。要更改一个表的模式或者表空间,你还必须拥有新模式或表空间上的 CREATE 特权。要把一个表作为一个父表的新子表加入,你必须也拥有该父表。此外,要把一个表挂接为另一个表的 新分区,你必须拥有被挂接的表。要更改拥有者,你还必须是新拥有角色的一个直接或者间接成员,并且该角色必须 具有该表的模式上的 CREATE 特权(这些限制强制修改拥有者不能做一些通过删除和重建表做不到的事情。但是,一 个超级用户怎么都能更改任何表的所有权。)。要增加一个列、修改一列的类型或者使用 OF 子句,你还必须具有该 数据类型上的 USAGE 特权。 语法 ALTER TABLE [CONCURRENTLY] [ IF EXISTS ] [ ONLY ] name [ * ] action [, ... ] ALTER TABLE [ IF EXISTS ] [ ONLY ] name [ * ] RENAME [ COLUMN ] column_name TO new_column_name ALTER TABLE [ IF EXISTS ] [ ONLY ] name [ * ] RENAME CONSTRAINT constraint_name TO new_constraint_name ALTER TABLE [ IF EXISTS ] name RENAME TO new_name ALTER TABLE [ IF EXISTS ] name SET SCHEMA new_schema ALTER TABLE ALL IN TABLESPACE name [ OWNED BY role_name [, ... ] ] 782 第 13 章 SQL 语句:ALTER SYNONYM 到 COMMENT SET TABLESPACE new_tablespace [ NOWAIT ] ALTER TABLE [ IF EXISTS ] name ATTACH PARTITION partition_name { FOR VALUES partition_bound_spec | DEFAULT } ALTER TABLE [ IF EXISTS ] name DETACH PARTITION partition_name ALTER TABLE [ IF EXISTS ] name ADD { PARTITION partition partition_bound_spec_ex [ TABLESPACE tablespace_name ] [, ... ] } [ UPDATE [ GLOBAL ] INDEXES | INVALIDATE GLOBAL INDEXES ] ALTER TABLE [ IF EXISTS ] name DROP { PARTITION partition | PARTITIONS partition [, ... ] } [ UPDATE [ GLOBAL ] INDEXES | INVALIDATE GLOBAL INDEXES ] ALTER TABLE [ IF EXISTS ] name DROP { SUBPARTITION subpartition | SUBPARTITIONS subpartition [, ... ] } [ UPDATE [ GLOBAL ] INDEXES | INVALIDATE GLOBAL INDEXES ] ALTER TABLE [ IF EXISTS ] name TRUNCATE { PARTITION partition | PARTITIONS partition [, ... ] } [ { DROP [ALL] | REUSE } STORAGE ] [ CASCADE ] [ UPDATE [ GLOBAL ] INDEXES | INVALIDATE GLOBAL INDEXES ] ALTER TABLE [ IF EXISTS ] name TRUNCATE { SUBPARTITION subpartition | SUBPARTITIONS subpartition [, ... ] } [ { DROP [ ALL ] | REUSE } STORAGE ] [ CASCADE ] [ UPDATE [ GLOBAL ] INDEXES | INVALIDATE GLOBAL INDEXES ] ALTER TABLE [ IF EXISTS ] name SET SUBPARTITION TEMPLATE ( [ SUBPARTITION subpartition [subpartition_bound_spec] [ TABLESPACE tablespace_name ] [, ... ] ] ) ALTER TABLE [ IF EXISTS ] name EXCHANGE PARTITION partition_name WITH TABLE table_name [ INCLUDING | EXCLUDEING INDEXES ] [ WITH | WITHOUT VALIDATION ] [ UPDATE [ GLOBAL ] INDEXES | INVALIDATE GLOBAL INDEXES ] ALTER TABLE [ IF EXISTS ] name MODIFY PARTITION partition [ REBUILD ] UNUSABLE LOCAL INDEXES ALTER TABLE [ IF EXISTS ] name MODIFY SUBPARTITION subpartition [ REBUILD ] UNUSABLE LOCAL INDEXES ALTER TABLE [ IF EXISTS ] name SET INTERVAL ( [ interval_expr ] ) ALTER TABLE [ IF EXISTS ] name SET STORE IN ( [ tablespace_name [, ...] ] ) ALTER TABLE [ IF EXISTS ] name ENCRYPTED | NOT ENCYPTED ALTER TABLE [ IF EXISTS ] name (SET { WITH | WITHOUT } ROWID) ALTER TABLE [ IF EXISTS ] [ ONLY ] name [ *] MODIFY ( mysql_modify_column_clause [ , ... ] ) ALTER TABLE name COMMENT [=] 'String' 783 第 13 章 SQL 语句:ALTER SYNONYM 到 COMMENT 其中 action 是以下之一: ADD [ COLUMN ] [ IF NOT EXISTS ] column_name data_type [ COLLATE collation ] [ column_constraint [ ... ] ] ADD [ COLUMN ] [ IF NOT EXISTS ] ( column_name data_type [ COLLATE collation ] [ column_constraint [ ... ] ] [, ... ] ) DROP [ COLUMN ] [ IF EXISTS ] column_name [ RESTRICT | CASCADE ] ALTER [ COLUMN ] column_name [ SET DATA ] TYPE data_type [ COLLATE collation ] [ USING expression ] ALTER [ COLUMN ] column_name SET DEFAULT expression ALTER [ COLUMN ] column_name DROP DEFAULT ALTER [ COLUMN ] column_name { SET | DROP } NOT NULL ALTER [ COLUMN ] column_name { INVISIBLE | VISIBLE } MODIFY column_name [ datatype ][ NULL | NOT NULL ] MODIFY ( column_name [ datatype ][ NULL | NOT NULL ][, ... ] ) MODIFY column_name { INVISIBLE | VISIBLE} MODIFY ( column_name { INVISIBLE | VISIBLE } [, ...]) ALTER [ COLUMN ] column_name ADD GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY [ ( sequence_options ) ] ALTER [ COLUMN ] column_name ADD IDENTITY [ NumericOnly , NumericOnly ] ALTER [ COLUMN ] column_name { SET GENERATED { ALWAYS | BY DEFAULT } | SET sequence_option | RESTART [ [ WITH ] restart ] } [...] ALTER [ COLUMN ] column_name DROP IDENTITY [ IF EXISTS ] ALTER [ COLUMN ] column_name SET STATISTICS integer ALTER [ COLUMN ] column_name SET ( attribute_option = value [, ... ] ) ALTER [ COLUMN ] column_name RESET ( attribute_option [, ... ] ) ALTER [ COLUMN ] column_name SET STORAGE { PLAIN | EXTERNAL | EXTENDED | MAIN } ADD table_constraint [ NOT VALID ] ADD table_constraint_using_index ALTER CONSTRAINT constraint_name [ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ] VALIDATE CONSTRAINT constraint_name DROP CONSTRAINT [ IF EXISTS ] constraint_name [ RESTRICT | CASCADE ] DISABLE TRIGGER [ trigger_name | ALL | USER ] ENABLE TRIGGER [ trigger_name | ALL | USER ] ENABLE ALL TRIGGERS DISABLE ALL TRIGGERS ENABLE REPLICA TRIGGER trigger_name ENABLE ALWAYS TRIGGER trigger_name DISABLE RULE rewrite_rule_name ENABLE RULE rewrite_rule_name ENABLE REPLICA RULE rewrite_rule_name ENABLE ALWAYS RULE rewrite_rule_name DISABLE ROW LEVEL SECURITY ENABLE ROW LEVEL SECURITY FORCE ROW LEVEL SECURITY 784 第 13 章 SQL 语句:ALTER SYNONYM 到 COMMENT NO FORCE ROW LEVEL SECURITY CLUSTER ON index_name SET WITHOUT CLUSTER SET WITHOUT OIDS SET TABLESPACE new_tablespace SET { LOGGED | UNLOGGED } SET ( storage_parameter = value [, ... ] ) RESET ( storage_parameter [, ... ] ) INHERIT parent_table NO INHERIT parent_table OF type_name NOT OF OWNER TO { new_owner | CURRENT_USER | SESSION_USER } REPLICA IDENTITY { DEFAULT | USING INDEX index_name | FULL | NOTHING } MODIFY constraint { ENABLE | DISABLE } [ VALIDATE | NOVALIDATE ] { ENABLE | DISABLE } [ VALIDATE | NOVALIDATE ] constraint [ ... ] ADD [ COLUMN ] [ IF NOT EXISTS ] column_name data_type COMMENT 'String' MODIFY mysql_modify_column_clause MODIFY col_name data_type ON UPDATE {CURRENT_TIMESTAMP | LOCALTIMESTAMP | LOCALTIME} [COMMENT 'String'] CHANGE [COLUMN] col_name new_name datatype [NULL| NOT NULL][ DEFAULT expr][COMMENT 'String'] and partition_bound_spec is: IN ( partition_bound_expr [, ...] ) | FROM ( { partition_bound_expr | MINVALUE | MAXVALUE } [, ...] ) TO ( { partition_bound_expr | MINVALUE | MAXVALUE } [, ...] ) | WITH ( MODULUS numeric_literal, REMAINDER numeric_literal ) and column_constraint is: [ CONSTRAINT constraint_name ] { NOT NULL | NULL | CHECK ( expression ) [ NO INHERIT ] | DEFAULT default_expr | GENERATED ALWAYS AS ( generation_expr ) STORED | GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY [ ( sequence_options ) ] | IDENTITY [ NumericOnly, NumericOnly ] | UNIQUE index_parameters | PRIMARY KEY index_parameters | REFERENCES reftable [ ( refcolumn ) ] [ MATCH FULL | MATCH PARTIAL | MATCH SIMPLE ] [ ON DELETE referential_action ] [ ON UPDATE referential_action ] } 785 第 13 章 SQL 语句:ALTER SYNONYM 到 COMMENT [ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ] [ { ENABLE | DISABLE } [ VALIDATE | NOVALIDATE ] ] 而 table_constraint 是: [ CONSTRAINT constraint_name ] { CHECK ( expression ) [ NO INHERIT ] | UNIQUE ( column_name [, ... ] ) index_parameters | PRIMARY KEY ( column_name [, ... ] ) index_parameters | EXCLUDE [ USING index_method ] ( exclude_element WITH operator [, ... ] ) index_parameters [ WHERE ( predicate ) ] | FOREIGN KEY ( column_name [, ... ] ) REFERENCES reftable [ ( refcolumn [, ... ] ) ] [ MATCH FULL | MATCH PARTIAL | MATCH SIMPLE ] [ ON DELETE referential_action ] [ ON UPDATE referential_ action ] } [ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ] [ { ENABLE | DISABLE } [ VALIDATE | NOVALIDATE ] ] 并且 table_constraint_using_index 是: [ CONSTRAINT constraint_name ] { UNIQUE | PRIMARY KEY } USING INDEX index_name [ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ] UNIQUE、PRIMARY KEY 以及 EXCLUDE 约束中的 index_parameters 是: [ INCLUDE ( column_name [, ... ] ) ] [ WITH ( storage_parameter [= value] [, ... ] ) ] [ USING INDEX TABLESPACE tablespace_name ] exclude_element in an EXCLUDE constraint is: { column_name | ( expression ) } [ opclass ] [ ASC | DESC ] [ NULLS { FIRST | LAST } ] 其中 constraint 是: { CONSTRAINT constraint_name | UNIQUE ( column_name [, ... ] ) | PRIMARY KEY } partition_bound_spec_ex 是: VALUES LESS THEN ( { partition_bound_expr | MAXVALUE } [, ... ] ) | VALUES ( partition_bound_expr [, ... ] | DEFAULT ) subpartition_bound_spec 是: 786 第 13 章 SQL 语句:ALTER SYNONYM 到 COMMENT VALUES LESS THEN ( { partition_bound_expr | MAXVALUE } [, ... ] ) | VALUES ( partition_bound_expr [, ... ] | DEFAULT ) mysql_modify_column_clause 是: [ COLUMN ] col_name datatype [ NULL| NOT NULL ][ DEFAULT expr ][ COMMENT 'String' ] | col_name { datatype| NULL| NOT NULL| DEFAULT expr| COMMENT 'String' } 787 第 13 章 SQL 语句:ALTER SYNONYM 到 COMMENT 788 第 13 章 SQL 语句:ALTER SYNONYM 到 COMMENT action ::= 789 第 13 章 SQL 语句:ALTER SYNONYM 到 COMMENT 790 第 13 章 SQL 语句:ALTER SYNONYM 到 COMMENT partition_bound_spec ::= column_constraint ::= table_constraint ::= 791 第 13 章 SQL 语句:ALTER SYNONYM 到 COMMENT table_constraint_using_index ::= index_parameters ::= 792 第 13 章 SQL 语句:ALTER SYNONYM 到 COMMENT exclude_element in an EXCLUDE constraint ::= constraint ::= partition_bound_spec_ex ::= 793 第 13 章 SQL 语句:ALTER SYNONYM 到 COMMENT subpartition_bound_spec ::= mysql_modify_column_clause ::= 794 第 13 章 SQL 语句:ALTER SYNONYM 到 COMMENT 语义 CONCURRENTLY 当使用了该选项时,KingbaseES 进行在线修改表结构。标准的修改表结构将会锁住目标表以阻塞对表的 并发读写操作,而通过在线方式修改表结构可以降低对目标表并发读写操作的阻塞。当前只支持在线增加 单个列、删除单个列及修改单个列的类型。 IF EXISTS 如果表不存在则不要抛出一个错误。这种情况下会发出一个提示。 name 要修改的一个现有表的名称(可以是模式限定的)。如果在表名前指定了 ONLY,则只会修改该表。如果 没有指定 ONLY,该表及其所有后代表(如果有)都会被修改。可选地,在表名后面可以指定 * 用来显式 地指示包括后代表。 column_name 一个新列或者现有列的名称。 new_column_name 一个现有列的新名称。 new_name 该表的新名称。 data_type 一个新列的数据类型或者一个现有列的新数据类型。 table_constraint 该表的新的表约束。 constraint_name 一个新约束或者现有约束的名称。 CASCADE 自动删除依赖于被删除列或约束的对象(例如引用该列的视图),并且接着删除依赖于那些对象的所有对 象。 RESTRICT 如果有任何依赖对象时拒绝删除列或者约束。这是默认行为。 trigger_name 一个要禁用或启用的触发器的名称。 ALL 795 第 13 章 SQL 语句:ALTER SYNONYM 到 COMMENT 禁用或者启用属于该表的所有触发器(如果有任何触发器是内部产生的约束触发器则需要超级用户特权, 例如那些被用来实现外键约束或者可延迟一致性和排他约束的触发器)。 USER 禁用或者启用属于该表的所有触发器,内部产生的约束触发器(例如那些被用来实现外键约束或者可延迟 一致性和排他约束的触发器)除外。 index_name 一个现有索引的名称。 storage_parameter 一个表存储参数的名称。 value 一个表存储参数的新值。根据该参数,该值可能是一个数字或者一个词。 parent_table 要与这个表关联或者解除关联的父表。 new_owner 该表的新拥有者的用户名。 new_tablespace 要把该表移入其中的表空间的名称。 new_schema 要把该表移入其中的模式的名称。 partition_name 要被作为新分区附着到这个表或者从这个表上分离的表的名称。 partition_bound_spec 新分区的分区边界说明。更多细节请参考CREATE TABLE 中相同的语法。 partition 要被作为当前操作的分区名称。 subpartition 要被作为当前操作的子分区名称。 partition_bound_spec_ex 不能与分区表的其他分区重叠。对于范围分区表只能在现有最高分区的后面增加新的分区。如果现有最高 分区中每个分区键的上限是 MAXVALUE,则无法将分区添加到表中。使用 TABLESPACE 可以为分区单独指 定表空间,如果省略会则使用分区表的表空间。 ADD COLUMN [ IF NOT EXISTS ] 796 第 13 章 SQL 语句:ALTER SYNONYM 到 COMMENT 这种形式向该表增加一个新列,使用与CREATE TABLE 相同的语法。如果指定了 IF NOT EXISTS 并且 使用这个名字的列已经存在,则不会抛出错误。 此外也可以通过小括号包围向该表增加多列,括号内的每个新增列,使用与CREATE TABLE 相同的语 法。如果指定了 IF NOT EXISTS 并且使用这个名字的列已经存在,则不会抛出错误。 DROP COLUMN [ IF EXISTS ] 这种形式从表删除一列。涉及到该列的索引和表约束也将会被自动删除。如果该列的移除会导致引用它的 多元统计信息仅包含单一列的数据,则该多元统计信息也将被移除。如果在该表之外有任何东西(例如外 键引用或者视图)依赖于该列,你将需要用到 CASCADE。如果指定了 IF EXISTS 但该列不存在,则不会 抛出错误。这种情况中会发出一个提示。 SET DATA TYPE 这种形式更改表中一列的类型。涉及到该列的索引和简单表约束将通过重新解析最初提供的表达式被自动 转换为使用新的列类型。可选的 COLLATE 子句为新列指定一种排序规则,如果被省略,排序规则会是新 列类型的默认排序规则。可选的 USING 子句指定如何从旧的列值计算新列值,如果被省略,默认的转换 和从旧类型到新类型的赋值造型一样。如果没有从旧类型到新类型的隐式或者赋值造型,则必须提供一个 USING 子句。 SET DEFAULT | DROP DEFAULT 这些形式为一列设置或者移除默认值。默认值只在后续的 INSERT 或 UPDATE 命令中生效,它们不会导致 已经在表中的行改变。 SET NOT NULL | DROP NOT NULL 这些形式更改一列是否被标记为允许空值或者拒绝空值。 SET NOT NULL 可以只应用于一个列,前提是表中没有一条记录包含该列的 NULL 值。通常在 ALTER TABLE 扫描整个表时检查这个。但如果找到有效的检查约束,证明不存在 NULL,则跳过表扫描。 如果这个表是一个分区,对于在父表中被标记为 NOT NULL 的列,不能在其上执行 DROP NOT NULL。要 从所有的分区中删除 NOT NULL 约束,可以在父表上执行 DROP NOT NULL。即使在父表上没有 NOT NULL 约束,这样的约束还是能被增加到分区上。也就是说,即便父表允许空值,子表也可以不允许空值,但反 过来不行。 MODIFYNULL|NOT NULL 这些形式更改一列是否被标记为允许空值或者拒绝空值。 MODIFY NOT NULL 可以只应用于一个列,前提是表中没有一条记录包含该列的 NULL 值。通常在 ALTER TABLE 扫描整个表时检查这个。但如果找到有效的检查约束,证明不存在 NULL,则跳过表扫描。 如果这个表是一个分区,对于在父表中被标记为 NOT NULL 的列,不能在其上执行 MODIFY NOT NULL。 要从所有的分区中删除 NOT NULL 约束,可以在父表上执行 MODIFY NOT NULL。即使在父表上没有 NOT NULL 约束,这样的约束还是能被增加到分区上。也就是说,即便父表允许空值,子表也可以不允许空 值,但反过来不行。 MODIFYINVISIBLE|VISIBLE 这些形式兼容了 Oracle 变更列隐含属性的语法,允许用户更改该列的属性为隐含或者非隐含。 797 第 13 章 SQL 语句:ALTER SYNONYM 到 COMMENT ADD GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY | SET GENERATED { ALWAYS | BY DEFAULT } | ADD IDENTITY [ NumericOnly , NumericOnly ] | SET IDENTITY [ NumericOnly , NumericOnly ] | DROP IDENTITY [ IF EXISTS ] 这些形式更改一列是否是一个标识列,或者是更改一个已有的标识列的产生属性。详情请参考CREATE TABLE 。 如果 DROP IDENTITY IF EXISTS 被指定并且该列不是一个标识列,则不会有错误被抛出。在这种情况下 会发出一个提示。 SET sequence_option RESTART 这些形式修改位于一个现有标识列之下的序列。“sequence_option“是一个ALTER SEQUENCE 所支持的 选项,例如 INCREMENT BY。 SET STATISTICS 这种形式为后续的 ANALYZE < :ref:‘ANALYZE 操作设置针对每列的统计收集目标。目标可以 被设置在范围 0 到 10000 之间,还可以把它设置为 -1 来恢复到使用系统默认的统计目标(default_statistics_target)。 SET STATISTICS 要求一个 SHARE UPDATE EXCLUSIVE 锁。 SET ( attribute_option = value [, ... ] ) | RESET ( attribute_option [, ... ] ) 这种形式设置或者重置每个属性的选项。当前,已定义的针对每个属性的选项只有 n_distinct 和 n_distinct_inherited,它们会覆盖后续 ANALYZE < :ref:‘ANALYZE 操作所得到的可区分值数量估 计。n_distinct 影响该表本身的统计信息,而 n_distinct_inherited 影响为该表外加其继承子女收集 的统计信息。当被设置为一个正值时,ANALYZE 将假定该列刚好包含指定数量的可区分非空值。当被设置 为一个负值(必须大于等于-1)时,ANALYZE 将假定可区分非空值的数量与表的尺寸成线性比例,确切的 计数由估计的表尺寸乘以给定数字的绝对值计算得到。例如,值 -1 表示该列中所有的值都是可区分的, 而值 -0.5 则表示每一个值平均出现两次。当表的尺寸随时间变化时,这会有所帮助,因为这种计算只有在 查询规划时才会被执行。指定值为 0 将回到正常的估计可区分值数量的做法。 更改针对每个属性的选项要求一个 “SHARE UPDATE EXCLUSIVE“锁。 SET STORAGE 这种形式为一列设置存储模式。这会控制这列是会被保持在线内还是放在一个二级 TOAST 表中,以及数 据是否应被压缩。对于 integer 之类的定长、线内、未压缩值必须使用 PLAIN。MAIN 用于线内、可压缩 的数据。EXTERNAL 用于外部的、未压缩数据。而 EXTENDED 用于外部的、压缩数据。对于大部分支持非PLAIN 存储的数据类型,EXTENDED 是默认值。使用 EXTERNAL 将会让很大的 text 和 bytea 之上的子串 操作运行得更快,但是代价是存储空间会增加。注意 SET STORAGE 本身并不改变表中的任何东西,它只 是设置在未来的表更新时要追求的策略。 ADD table_constraint [ NOT VALID ] 这种形式使用和CREATE TABLE 相同的语法外加 NOT VALID 选项为一个表增加一个新的约束,该选项 当前只被允许用于外键和 CHECK 约束。 通常,此表单将导致对表进行扫描,以验证表中所有现有行都满足新约束。但是,如果使用了 NOT 798 第 13 章 SQL 语句:ALTER SYNONYM 到 COMMENT VALID 选项,则跳过此潜在冗长的扫描。对于后续的插入或更新,约束仍将被强制执行 (即,对于外键, 除非引用表中有匹配的行,否则它们将失败,或者除非新行符合指定的检查条件,否则它们将失败)。但 是,在使用 VALIDATE constraint 选项进行验证之前,数据库不会假定约束适用于表中的所有行。有关 使用 NOT VALID 选项的更多信息。 外键约束的增加要求在被引用表上的一个 SHARE ROW EXCLUSIVE 锁,除了接收约束的表上的锁之外。 当唯一或者主键约束被添加到分区表时,会有额外的限制,请参考CREATE TABLE 。此外,分区表上的 外键约束可能无法声明为 NOT VALID 。 ADD table_constraint_using_index 这种形式基于一个已有的唯一索引为一个表增加新的 PRIMARY KEY 或 UNIQUE 约束。该索引中的所有列 将被包括在约束中。 该索引不能有表达式列或者是一个部分索引。还有,它必须是一个带有默认排序顺序的 B-树索引。这些 限制确保该索引等效于使用常规 ADD PRIMARY KEY 或者 ADD UNIQUE 命令时创建的索引。 如果 PRIMARY KEY 被指定,并且该索引的列没有被标记 NOT NULL,那么这个命令将尝试对每一个这样 的列做 ALTER COLUMN SET NOT NULL。这需要一次全表扫描来验证这些列不包含空值。在所有其他情况 中,这都是一种很快的操作。 如果提供了一个约束名,那么该索引将被重命名以匹配该约束名。否则该约束将被命名成索引的名称。 这个命令被执行后,该索引被增加的约束“拥有”,这和用常规 ADD PRIMARY KEY 或 ADD UNIQUE 命令 创建的索引一样。特别地,删掉该约束将会导致该索引也消失。 当前在分区表上不支持这种形式。 注意: 如果需要增加一个新的约束但是不希望长时间阻塞表更新,那么使用现有索引增加约束会有所帮 助。要这样做,用 CREATE INDEX CONCURRENTLY 创建该索引,并且接着使用这种语法把它安装为一个正 式的约束。例子见下文。 ALTER CONSTRAINT 这种形式修改之前创建的一个约束的属性。当前只能修改外键约束。 VALIDATE CONSTRAINT 此表单通过扫描表以确保没有不满足约束的行来验证以前创建的 NOT VALID 的外键或检查约束。如果约 束已经被标记为有效,则什么也不会发生。 DROP CONSTRAINT [ IF EXISTS ] 这种形式在一个表上删除指定的约束,还有位于该约束之下的任何索引。如果 IF EXISTS 被指定并且该 约束不存在,不会抛出错误。在这种情况下会发出一个提示。 ENABLE ALL TRIGGERS 启用所有触发器,与 ENABLE TRIGGER ALL 功能一致。 DISABLE ALL TRIGGERS 799 第 13 章 SQL 语句:ALTER SYNONYM 到 COMMENT 禁用所有触发器,与 DISABLE TRIGGER ALL 功能一致。 DISABLE | ENABLE [ REPLICA | ALWAYS ] TRIGGER 这些形式配置属于该表的触发器的触发设置。系统仍然知道被禁用触发器的存在,但是即使它的触发事 件发生也不会执行它。对于一个延迟触发器,会在事件发生时而不是触发器函数真正被执行时检查其启用 状态。可以禁用或者启用用名称指定的单个触发器、表上的所有触发器、用户拥有的触发器(这个选项会 排除内部生成的约束触发器,例如用来实现外键约束或可延迟唯一和排除约束)。禁用或者启用内部生成 的约束触发器要求超级用户特权,这样做要小心因为如果这类触发器不被执行,约束的完整性当然无法保 证。 触发器引发机制也受到配置变量 session_replication_role 的影响。当复制角色是“origin”(默认)或 者“local”时,被简单启用的触发器将被触发。被配置为 ENABLE REPLICA 的触发器只有在会话处于 “replica”模式时才将被触发。被配置为 ENABLE ALWAYS 的触发器的触发不会考虑当前复制角色。 这种机制的效果就是,在默认配置中,触发器不会在复制体上引发。这种效果很有用,因为如果一个触发 器在源头上被用来在表之间传播数据,那么复制系统也将复制被传播的数据,并且触发器不应该在复制体 上引发第二次,因为那会导致重复。但是,如果一个触发器被用于另一种目的(例如创建外部告警),那 么将它设置为 ENABLE ALWAYS 可能更加合适,这样它在复制体上也会被引发。 这个命令要求一个 SHARE ROW EXCLUSIVE 锁。 DISABLE | ENABLE [ REPLICA | ALWAYS ] RULE 这些形式配置属于表的重写规则的触发设置。系统仍然知道一个被禁用规则的存在,但在查询重写时不会 应用它。其语义与禁用的/启用的触发器的一样。对于 ON SELECT 规则会忽略这个配置,即使当前会话处 于一种非默认的复制角色,这类规则总是会被应用以保持视图工作正常。 规则引发机制也受到配置变量 session_replication_role 的影响,这和上述的触发器类似。 DISABLE | ENABLE ROW LEVEL SECURITY 这些形式控制属于该表的行安全性策略的应用。如果被启用并且该表上不存在策略,则将应用一个默认否 定的策略。注意即使行级安全性被禁用,在表上还是可以存在策略。在这种情况下,这些策略将不会被应 用并且会被忽略。另见CREATE POLICY 。 NO FORCE | FORCE ROW LEVEL SECURITY 这些形式控制当用户是表拥有者时表上的行安全性策略的应用。如果被启用,当用户是表拥有者时,行 级安全性策略将被应用。如果被禁用(默认),则当用户是表拥有者时,行级安全性将不会被应用。另 见CREATE POLICY 。 CLUSTER ON 这种形式为未来的CLUSTER 操作选择默认的索引。它不会真正地对表进行聚簇。 改变聚簇选项要求一个 SHARE UPDATE EXCLUSIVE 锁。 SET WITHOUT CLUSTER 这种形式从表中移除最近使用的CLUSTER 索引说明。这会影响未来的不指定索引的聚簇操作。 改变聚簇选项要求一个 SHARE UPDATE EXCLUSIVE 锁。 800 第 13 章 SQL 语句:ALTER SYNONYM 到 COMMENT SET WITHOUT OIDS 用于删除 oid 系统列的向后兼容语法。由于 oid 系统列不能再添加了,所以这不会有任何影响。 SET TABLESPACE 这种形式把该表的表空间更改为指定的表空间并且把该表相关联的数据文件移动到新的表空间中。表上的 索引(如果有)不会被移动,但是它们可以用额外的 SET TABLESPACE 命令单独移动。当应用于一个分区 表时,不会移动任何内容,但是之后使用 CREATE table PARTITION OF > 创建的任何分区都将使用这个 表空间,除非使用 TABLESPACE 子句来覆盖它。 当前数据库在一个表空间中的所有表可以用 ALL IN TABLESPACE 形式移动,这将会首先锁住所有将被 移动的表然后逐个移动。这种形式也支持 OWNED BY,它将只移动指定角色所拥有的表。如果指定了 NOWAIT 选项,则命令将在无法立刻获得所有所需要的锁时失败。注意这个命令不移动系统目录,如果 想要移动系统目录,应该用 ALTER DATABASE 或者显式的 ALTER TABLE 调用。对于这种形式来说, information_schema 关系不被认为是系统目录的一部分,因此它们将会被移动。另见CREATE TABLESPACE 。 SET { LOGGED | UNLOGGED } 此表单将表从未登录更改为已登录,反之亦然。它不能被应用于一个临时表。 SET ( storage_parameter = value [, ... ] ) 这种形式为该表更改一个或者更多存储参数。可用的参数请见存储参数 < CREATETABLE -STORAGEPARAMETERS 。注意这个命令将不会立刻修改表内容,这取决于重写表以得到想要的结果可能需要的 参数。可以用VACUUM 、CLUSTER 或者 ALTER TABLE 的一种形式来强制一次表重写。对于规划器相关 的参数,更改将从该表下一次被锁定开始生效,因此当前执行的查询不会受到影响。 对 fillfactor、toast 以及 UPDATE EXCLUSIVE autovacuum 存储参数,还有下面的规划器相关参数,将会拿取 SHARE 锁:effective_io_concurrency、parallel_workers、seq_page_cost、 random_page_cost、n_distinct 以及 n_distinct_inherited。 RESET ( storage_parameter [, ... ] ) 这种形式把一个或者更多存储参数重置到它们的默认值。和 “SET“一样,可能需要一次表重写来更新整个 表。 INHERIT parent_table 这种形式把目标表增加为指定父表的一个新子女。随后,针对父亲的查询将包括目标表中的记录。要被增 加为一个子女,目标表必须已经包含和父表完全相同的列(也可以有额外的列)。这些列必须具有匹配的 数据类型,并且如果它们在父表中具有 NOT NULL 约束,它们在子表中也必须有 NOT NULL 约束。 也必须把子表约束与所有父表的 CHECK 约束进行匹配,但是父表中那些被标记为非可继承(也就是用 ALTER TABLE ... ADD CONSTRAINT ... NO INHERIT 创建的)除外,它们会被忽略。所有匹配得上的子 表约束不能被标记为不可继承。当前,UNIQUE、PRIMARY KEY 以及 FOREIGN KEY 约束没有被考虑,但是 这种情况可能会在未来发生变化。 NO INHERIT parent_table 这种形式把目标表从指定父表的子女列表中移除。针对父表的查询将不再包括来自目标表的记录。 801 第 13 章 SQL 语句:ALTER SYNONYM 到 COMMENT OF type_name 这种形式把该表链接到一种组合类型,就好像 CREATE TABLE OF 所做的那样。该表的列名和类型列表必 须精确地匹配该组合类型。该表必须不从任何其他表继承。这些限制确保 CREATE TABLE OF 能允许一个 等价的表定义。 NOT OF 这种形式解除一个有类型的表和其类型之间的关联。 OWNER TO 这种形式把表、序列、视图、物化视图或外部表的拥有者改为指定用户。 REPLICA IDENTITY 这种形式更改被写入到预写式日志来标识被更新或删除行的信息。除非使用逻辑复制,这个选项将不会 产生效果。DEFAULT(非系统表的默认值)记录主键列(如果有)的旧值。USING INDEX 记录被所提到的 索引所覆盖的列的旧值,该索引必须是唯一索引、不是部分索引、不是可延迟索引并且只包括被标记成 NOT NULL 的列。FULL 记录行中所有列的旧值。NOTHING 不记录有关旧行的任何信息(这是系统表的默认 值)。在所有情况下,除非至少有一个要被记录的列在新旧行版本之间发生变化,将不记录旧值。 RENAME RENAME 形式更改一个表(或者一个索引、序列、视图、物化视图或者外部表)的名称、表中一个列的名 称或者表的一个约束的名称。在重命名一个具有底层索引的约束时,该索引也会被重命名。它对已存储的 数据没有影响。 SET SCHEMA 这种形式把该表移动到另一个模式中。相关的该表列拥有的索引、约束和序列也会被移动。 ATTACH PARTITION partition_name { FOR VALUES partition_bound_spec | DEFAULT } 这种形式把一个已有表(自身也可能被分区)作为一个分区挂接到目标表。该表可以为特定的值使用 FOR VALUES 挂接为分区,或者用 DEFAULT 挂接为一个默认分区。对于目标表中的每一个索引,在被挂接 的表上都将创建一个响应的索引,如果已经存在等效的索引,该索引将被挂接到目标表的索引,就像执 行了 ALTER INDEX ATTACH PARTITION 一样。请注意,如果现有表是一个外部表,那么如果目标表上有 UNIQUE 索引,则当前不允许将该表附加到目标表的分区中。(参见CREATE FOREIGN TABLE ) 一个使用 FOR VALUES 的分区使用与CREATE TABLE 中 “partition_bound_spec“相同的语法。分区边 界说明必须对应于目标表的分区策略以及分区键。要被挂接的表必须具有和目标表完全相同的所有列,并 且不能有多出来的列,而且列的类型也必须匹配。此外,它必须有目标表上所有的 NOT NULL 以及 CHECK 约束。当前不考虑 FOREIGN KEY 约束。来自于父表的 UNIQUE 和 PRIMARY KEY 约束将被创建在分区上 (如果它们还不存在)。如果被挂接的表上的任何 CHECK 约束被标记为 NO INHERIT,则命令将失败,这 类约束必须被重建且重建时不能有 NO INHERIT 子句。 如果新分区是一个常规表,会执行一次全表扫描来检查表中没有现有行违背分区约束。可以通过对表增 加一个有效的 CHECK 约束来避免这种扫描,该约束可以在运行这个命令之前仅允许满足所需分区约束的 行。使用这样一个约束,就可以让表无需被扫描就能验证分区约束。但是,如果任一分区键是一个表达式 802 第 13 章 SQL 语句:ALTER SYNONYM 到 COMMENT 并且该分区不接受 NULL 值,这种方式就无效了。如果挂接一个不接受 NULL 值的列表分区,还应该为分 区键列增加 NOT NULL 约束,除非它是一个表达式。 如果新分区是一个外部表,则不需要验证该外部表中的所有行遵守分区约束(有关外部表上的约束请参 考CREATE FOREIGN TABLE 中的讨论)。 当一个表有默认分区时,定义新分区会更改默认分区的分区约束。默认分区不能包含任何需要被移动到 新分区中的行,并且将被扫描以验证不存在那样的行。如果一个合适的 CHECK 约束存在,这种扫描(和 新分区的扫描一样)可以被避免。还是和新分区的扫描一样,当默认分区是外部表时这种扫描总是会被跳 过。 DETACH PARTITION partition_name 这种形式会分离目标表的指定分区。被分离的分区继续作为独立的表存在,但是与它之前挂接的表不再有 任何联系。任何被挂接到目标表索引的索引也会被分离。 ADD PARTITION partition_name 这种形式会向已有单层分区表中添加新的分区。新分区自动继承分区表的全部列定义、主外键索引和约 束、唯一索引和约束、NOT NULL 约束、CHECK 约束、局部索引和行级触发器。新分区自动继承分区 表的全局或者本地临时表属性。使用 TABLESPACE 可以为分区单独指定表空间,如果省略会则使用分 区表的表空间。对于范围分区表,只能在现有最高分区的后面增加新的范围分区,如果现有最高分区中每 个分区键的上限是 MAXVALUE,则无法将分区添加到表中。对于哈希分区表,每次只能添加一个哈希分 区,这个操作将导致数据在分区之间重分布,数据库会根据哈希函数判定相关分区,对其中的行重新计算 哈希值,并扩展到新分区。 DROP PARTITION partition 这种形式会删除单层分区表或者复合分区表中的一个分区,从分区表中删除分区以及这些分区的数据。 DROP PARTITIONS partition 这种形式会删除单层分区表或者复合分区表中的多个分区,从分区表中删除分区以及这些分区的数据。指 定多个分区时,需按分区名称依次指定所有分区。 DROP SUBPARTITION subpartition 这种形式会删除复合分区表中的一个子分区,从分区表中删除子分区以及这些子分区的数据。 DROP SUBPARTITIONS subpartition 这种形式会删除复合分区表中的多个子分区,从分区表中删除子分区以及这些子分区的数据。指定多个子 分区时,须按子分区名称依次指定所有的子分区。 TRUNCATE PARTITION partition 这种形式会清空单层分区表或者复合分区表中的一个分区,从分区表中删除这些分 区的数据。 TRUNCATE PARTITIONS partition 这种形式会清空单层分区表或者复合分区表中的多个分区,从分区表中删除这些分区的数据。指定多个分 区时,需按分区名称依次指定所有分区。 TRUNCATE SUBPARTITION subpartition 803 第 13 章 SQL 语句:ALTER SYNONYM 到 COMMENT 这种形式会清空复合分区表中的一个子分区,从分区表中删除这些子分区的数据。 TRUNCATE SUBPARTITIONS subpartition 这种形式会清空复合分区表中的多个子分区,从分区表中删除这些子分区的数据。指定多个子分区时,须 按子分区名称依次指定所有的子分区。 SET SUBPARTITION TEMPLATE 这种形式会设置复合分区表中的子分区模板。可以创建、替换或删除已存在的子分区模板。它不影响已存 在的子分区或者分区索引,新建分区将使用新的子分区模板创建子分区。 EXCHANGE PARTITION partition_name WITH TABLE table_name 使用 EXCHANGE PARTITON 语法可以实现一个分区表与普通表的数据交换。EXCHANGE 后面的参数 必须是分区,且为 ALTER 语句中主表的分区,否则报错。分区名称不可省略,服务器自动在分区名称前 加上 “table_name“前缀作为分区的表名。 INCLUDING| EXCLUDING INDEXS 语法可以实现对交换数据后的分区进行索引重建,默认是 EXCLUDING INDEXS。WITH|WITHOUT VALIDATION 会检查或者忽略检查参与交换的表内的数据是 否符合分区表的边界范围,默认是 WITH VALIDATION。 SET INTERVAL ( [ interval_expr ] ) 这种形式会设置 Interval 分区表中的间隔参数。其中 interval_expr 参见CREATE TABLE 中 “INTERVAL“子句语法。 使用带有 interval_expr 参数的 SET INTERVAL 子句,可以将已有普通范围分区表转换为 Interval 分 区表。已有普通范围分区表必须满足 Interval 分区表的条件,只能有唯一的分区键,分区键中不能包含 NULL 值,已有最高范围分区边界上限不能是 MAXVALUE。 使用带有 interval_expr 参数的 SET INTERVAL 子句,也可以修改已有间隔分区的间隔值。新的间隔值 不会改变已有分区的边界值,而是只会影响新间隔分区的边界值。 使用不含 interval_expr 参数的 SET INTERVAL 子句,可以将已有间隔分区转换为普通范围分区,不支 持对普通范围分区使用 SET INTERVAL() 子句。 SET STORE IN ( [ tablespace_name [, ... ] ] ) 这种形式会设置 Interval 分区表中的表空间。使用 SET STORE IN 子句可以为 Interval 分区表指定新分区 的表空间列表,且不会影响已有分区的表空间存储。 ENCRYPTED NOT ENCRYPTED 设 置 表 的 加 密 状 态,ENCRYPTED 将 表 变 为 加 密 表, 生 成 随 机 秘 钥 对 表 的 数 据 加 密。NOT EN- CRYPTED 将表变为非加密表。当加密状态发生改变时会重新生成数据文件,变更的代价较大。 UNUSABLE LOCAL INDEXES 禁用分区、子分区上的索引。 REBUILD UNUSABLE LOCAL INDEXES 重建分区、子分区上的索引。 804 第 13 章 SQL 语句:ALTER SYNONYM 到 COMMENT UPDATE GLOBAL INDEXES | UPDATE INDEXES 更新全局索引。 INVALIDATE GLOBAL INDEXES 使全局索引失效。 SET WITH | WITHOUT ROWID 添加/移除 ROWID 的隐含列。 COMMENT [=] 'String' 添加、修改表的注释内容,其中 [=] 代表‘=’可省略,当参数 String 为空时相当于删除表注释。ALTER TABLE 语句中包含 COMMENT 子句的功能都仅限在 MySQL 模式下使用。 COMMENT 'String' 添加、修改列的注释内容,当参数 String 为空时相当于删除注释。ALTER TABLE 语句中包含 COMMENT 子句的功能都仅限在 MySQL 模式下使用。 mysql_modify_column_clause MySQL 模式下,修改列级非空和默认值、注释的子句。 除了 RENAME、SET SCHEMA、ATTACH PARTITION 和 DETACH PARTITION 之外,所有形式的 ALTER TABLE 都 作用在单个表上,前面这些形式可以被组合成一个多修改的列表被一起应用。例如,可以在一个命令中增加多个列并 且/或者修改多个列的类型。对于大型表来说这会特别有用,因为只需要对表做一趟操作。 示例 在线修改表增加单个列,可降低对目标表并发读写操作的阻塞: ALTER TABLE CONCURRENTLY emp ADD COLUMN address text default 'CN'; 要向一个表增加一个类型为 varchar 的列: ALTER TABLE distributors ADD COLUMN address varchar(30); 要从表中删除一列: ALTER TABLE distributors DROP COLUMN address RESTRICT; 要在一个操作中更改两个现有列的类型: ALTER TABLE distributors ALTER COLUMN address TYPE varchar(80), ALTER COLUMN name TYPE varchar(100); 通过一个 USING 子句更改一个包含 Unix 时间戳的整数列为 timestamp with time zone: 805 第 13 章 SQL 语句:ALTER SYNONYM 到 COMMENT ALTER TABLE foo ALTER COLUMN foo_timestamp SET DATA TYPE timestamp with time zone USING timestamp with time zone 'epoch' + foo_timestamp * interval '1 second'; 同样的,当该列具有一个不能自动造型成新数据类型的默认值表达式时: ALTER TABLE foo ALTER COLUMN foo_timestamp DROP DEFAULT, ALTER COLUMN foo_timestamp TYPE timestamp with time zone USING timestamp with time zone 'epoch' + foo_timestamp * interval '1 second', ALTER COLUMN foo_timestamp SET DEFAULT now(); 重命名一个现有列: ALTER TABLE distributors RENAME COLUMN address TO city; 重命名一个现有的表: ALTER TABLE distributors RENAME TO suppliers; 重命名一个现有的约束: ALTER TABLE distributors RENAME CONSTRAINT zipchk TO zip_check; 为一列增加一个非空约束: ALTER TABLE distributors ALTER COLUMN street SET NOT NULL; 从一列移除一个非空约束: ALTER TABLE distributors ALTER COLUMN street DROP NOT NULL; 向一个表及其所有子女增加一个检查约束: ALTER TABLE distributors ADD CONSTRAINT zipchk CHECK (char_length(zipcode) = 5); 只向一个表增加一个检查约束(不为其子女增加): ALTER TABLE distributors ADD CONSTRAINT zipchk CHECK (char_length(zipcode) = 5) NO INHERIT; (该检查约束也不会被未来的子女继承)。 从一个表及其子女移除一个检查约束: 806 第 13 章 SQL 语句:ALTER SYNONYM 到 COMMENT ALTER TABLE distributors DROP CONSTRAINT zipchk; 只从一个表移除一个检查约束: ALTER TABLE ONLY distributors DROP CONSTRAINT zipchk; (该检查约束仍为子女表保留在某个地方)。 为一个表增加一个外键约束: ALTER TABLE distributors ADD CONSTRAINT distfk FOREIGN KEY (address) REFERENCES addresses (address); 为一个表增加一个外键约束,并且尽量不要影响其他工作: ALTER TABLE distributors ADD CONSTRAINT distfk FOREIGN KEY (address) REFERENCES addresses (address) NOT VALID; ALTER TABLE distributors VALIDATE CONSTRAINT distfk; 为一个表增加一个(多列)唯一约束: ALTER TABLE distributors ADD CONSTRAINT dist_id_zipcode_key UNIQUE (dist_id, zipcode); 为一个表增加一个自动命名的主键约束,注意一个表只能拥有一个主键: ALTER TABLE distributors ADD PRIMARY KEY (dist_id); 把一个表移动到一个不同的表空间: ALTER TABLE distributors SET TABLESPACE fasttablespace; 把一个表移动到一个不同的模式: ALTER TABLE myschema.distributors SET SCHEMA yourschema; 重建一个主键约束,并且在重建索引期间不阻塞更新: CREATE UNIQUE INDEX CONCURRENTLY dist_id_temp_idx ON distributors (dist_id); ALTER TABLE distributors DROP CONSTRAINT distributors_pkey, ADD CONSTRAINT distributors_pkey PRIMARY KEY USING INDEX dist_id_temp_idx; 要把一个分区挂接到一个范围分区表上: ALTER TABLE measurement ATTACH PARTITION measurement_y2016m07 FOR VALUES FROM ('2016-07-01') TO ('2016-08-01'); 要把一个分区挂接到一个列表分区表上: 807 第 13 章 SQL 语句:ALTER SYNONYM 到 COMMENT ALTER TABLE cities ATTACH PARTITION cities_ab FOR VALUES IN ('a', 'b'); 要把一个分区挂接到一个哈希分区表上: ALTER TABLE orders ATTACH PARTITION orders_p4 FOR VALUES WITH (MODULUS 4, REMAINDER 3); 要把一个默认分区挂接到一个分区表上: ALTER TABLE ATTACH PARTITION cities_partdef DEFAULT; 从一个分区表分离一个分区: ALTER TABLE measurement DETACH PARTITION measurement_y2015m12; 向一个分区表添加一个分区: ALTER TABLE sales ADD PARTITION q1_2006 VALUES LESS THAN ('2006-04-01'); 从一个分区表删除一个或多个分区: ALTER TABLE sales DROP PARTITION q1_2006; ALTER TABLE sales DROP PARTITIONS q1_2006,q2_2006; 把一个分区表中的一个或多个分区、子分区清空: ALTER TABLE sales TRUNCATE PARTITION q1_2006; ALTER TABLE sales TRUNCATE PARTITIONS q1_2006,q2_2006; ALTER TABLE sales TRUNCATE SUBPARTITION q1_2006_jan; ALTER TABLE sales TRUNCATE SUBPARTITIONS q1_2006_jan,q1_2006_feb; 维护分区表的索引状态: ALTER TABLE sales ADD PARTITION q1_2006 VALUES LESS THAN ('2006-04-01') UPDATE INDEXES; ALTER TABLE sales TRUNCATE SUBPARTITION q1_2006_jan UPDATE GLOBAL INDEXES; ALTER TABLE sales TRUNCATE SUBPARTITION q1_2006_jan INVALIDATE GLOBAL INDEXES; 在 MySQL 模式的数据库下,修改表和列的注释内容: ALTER TABLE test_comment ADD COLUMN age char COMMENT 'age of table'; ALTER TABLE test_comment comment= ''; 808 第 13 章 SQL 语句:ALTER SYNONYM 到 COMMENT 兼容性 形 式 ADD(没 有 USING INDEX)、DROP [COLUMN]、DROP IDENTITY、RESTART、SET DEFAULT、SET DATA TYPE(没有 USING)、SET GENERATED 以及 SET sequence_option 服从 SQL 标准。其他形式都是 KingbaseES 对 SQL 标准的扩展。此外,在单个 ALTER TABLE 命令中指定多个操作的能力是一种扩展。 ALTER TABLE DROP COLUMN 可以被用来删除一个表的唯一的列,从而留下一个零列的表。这是一种 SQL 的扩 展,SQL 中不允许零列的表。 13.4 ALTER TABLESPACE 用途 ALTER TABLESPACE 可以被用于更改一个表空间的定义。 前置条件 要更改一个表空间的定义,你必须拥有它。要修改拥有者,你还必须是新拥有角色的一个直接或间接成员(注意 超级用户自动拥有这些特权)。 语法 ALTER TABLESPACE name RENAME TO new_name ALTER TABLESPACE name OWNER TO { new_owner | CURRENT_USER | SESSION_USER } ALTER TABLESPACE name SET ( tablespace_option = value [, ... ] ) ALTER TABLESPACE name RESET ( tablespace_option [, ... ] ) ALTER TABLESPACE name { ONLINE | OFFLINE | READ WRITE | READ ONLY } 809 第 13 章 SQL 语句:ALTER SYNONYM 到 COMMENT 语义 name 一个现有表空间的名称。 new_name 该表空间的新名称。新名称不能以 sys_ 开始,因为这类名称被保留用于系统表空间。 new_owner 该表空间的新拥有者。 tablespace_option 要设置或者重置的一个表空间参数。当前,唯一可用的参数是 seq_page_cost、random_page_cost 和 effective_io_concurrency。为一个特定表空间设定这两个参数值将覆盖规划器对从该表空间中 的表读取页面代价的估计值,这些估计值由具有相同名称配置参数建立(见 seq_page_cost 、random_page_cost 、effective_io_concurrency )。如果一个表空间位于一个比其余 I/ O 子系统更快 或者更慢的磁盘上时,这些参数就能派上用场。此外不允许修改加密框架相关参数的值(encryption、 enckey)。 还有和表空间模式相关的参数 online_mode、readonly_mode, 以上两个参数均为 bool 类型, 分别表空表 空间的一级模式 ONLINE/OFFLINE 和二级模式 READONLY /READWRITE。这两个参数对于 ALTER TABLESPACE ... SET/RESET 命令是可以分别设置的(不支持在同一个 SET/RESET 语句中 810 第 13 章 SQL 语句:ALTER SYNONYM 到 COMMENT 同时指定 online_mode 和 readonly_mode 参数)。关于 online_mode 的说明参考CREATE TABLE 。 readonly_mode 参数表示表空间的读写模式,该模式仅可以通过 ALTER TABLESPACE 命令进行修改。 设置为 true 表示表空间是只读的,用户对于该表空间下的所有对象的读操作都是允许的,对于所有写操 作包含意向写都是禁止的。 注意: 表空间只读或者离线状态设置前,请先关闭参数 skip_tablespace_check(仅超级用户有修改和查 看权限,默认是开启的),该参数开启状态下不会检查当前操作是否满足表空间状态。 示例 将表空间 index_space 重命名为 fast_raid: ALTER TABLESPACE index_space RENAME TO fast_raid; 更改表空间 index_space 的拥有者: ALTER TABLESPACE index_space OWNER TO mary; 更改表空间 tblspace 为只读模式: ALTER TABLESPACE tblspace SET (READONLY = TRUE); 也可以通过 oracle 语法更改表空间 tblspace 为离线模式: ALTER TABLESPACE tblspace OFFLINE; 兼容性 在 SQL 标准中没有 ALTER TABLESPACE 语句。 13.5 ALTER TEXT SEARCH CONFIGURATION 用途 ALTER TEXT SEARCH CONFIGURATION 更改一个文本搜索配置的定义。你可以修改其从记号类型到词典的映射或 者更改该配置的名称或者拥有者。 前置条件 要使用 ALTER TEXT SEARCH CONFIGURATION,必须是该配置的拥有者。 语法 ALTER TEXT SEARCH CONFIGURATION name ADD MAPPING FOR token_type [, ... ] WITH dictionary_name [, ... ] ALTER TEXT SEARCH CONFIGURATION name 811 第 13 章 SQL 语句:ALTER SYNONYM 到 COMMENT ALTER MAPPING FOR token_type [, ... ] WITH dictionary_name [, ... ] ALTER TEXT SEARCH CONFIGURATION name ALTER MAPPING REPLACE old_dictionary WITH new_dictionary ALTER TEXT SEARCH CONFIGURATION name ALTER MAPPING FOR token_type [, ... ] REPLACE old_dictionary WITH new_dictionary ALTER TEXT SEARCH CONFIGURATION name DROP MAPPING [ IF EXISTS ] FOR token_type [, ... ] ALTER TEXT SEARCH CONFIGURATION name RENAME TO new_name ALTER TEXT SEARCH CONFIGURATION name OWNER TO { new_owner | CURRENT_USER | SESSION_USER } ALTER TEXT SEARCH CONFIGURATION name SET SCHEMA new_schema 语义 name 一个现有文本搜索配置的名称(可以是模式限定的)。 token_type 812 第 13 章 SQL 语句:ALTER SYNONYM 到 COMMENT 由该配置的解析器发出的记号类型的名称。 dictionary_name 在其中查阅指定记号类型的文本搜索字典的名称。如果列出了多个字典,会按照指定的顺序查阅它们。 old_dictionary 在映射中要替换的文本搜索字典的名称。 new_dictionary 被用来替代 old_dictionary 的文本搜索字典的名称。 new_name 该文本搜索配置的新名称。 new_owner 该文本搜索配置的新拥有者。 new_schema 该文本搜索配置的新模式。 ADD MAPPING FOR 形式会安装一些词典(用列表列出)用于在其中查阅指定的记号类型。如果对任一记号类型已 经有一个映射,则会发生错误。ALTER MAPPING FOR 形式做同样的事情,但是首先会移除这些记号类型的任何现有 映射。ALTER MAPPING REPLACE 形式用 new_dictionary 来替换任何位置上的 old_dictionary。当出现 FOR 时, 只会为指定的记号类型做这样的事情。如果不出现 FOR,则会为该配置中所有的映射都这样做 DROP MAPPING 形式会 移除指定记号类型的所有字典,导致该文本搜索配置忽略这些类型。除非出现 IF EXISTS,在那些记号类型没有任 何映射时会发生错误。 示例 下面的例子把 my_config 中任何位置上的 english 字典替换为 swedish 字典。 ALTER TEXT SEARCH CONFIGURATION my_config; ALTER MAPPING REPLACE english WITH swedish; 兼容性 在 SQL 标准中没有 ALTER TEXT SEARCH CONFIGURATION 语句。 其他 参见CREATE TEXT SEARCH CONFIGURATION , DROP TEXT SEARCH CONFIGURATION 13.6 ALTER TEXT SEARCH DICTIONARY 用途 813 第 13 章 SQL 语句:ALTER SYNONYM 到 COMMENT ALTER TEXT SEARCH DICTIONARY 更改一个文本搜索字典的定义。你可以更改该字典的与模板相关的选项,或者 更改该字典的名称或者拥有者。 前置条件 要使用 ALTER TEXT SEARCH DICTIONARY,你必须是超级用户。 语法 ALTER TEXT SEARCH DICTIONARY name ( option [ = value ] [, ... ] ) ALTER TEXT SEARCH DICTIONARY name RENAME TO new_name ALTER TEXT SEARCH DICTIONARY name OWNER TO { new_owner | CURRENT_USER | SESSION_USER } ALTER TEXT SEARCH DICTIONARY name SET SCHEMA new_schema 语义 name 一个现有的文本搜索字典的名称(可以是模式限定的)。 option 要为这个字典设置的与模板相关的选项的名称。 value 用于一个模板相关选项的新值。如果等号和值被忽略,则会从该字典中移除该选项之前的设置而允许使用 默认值。 new_name 该文本搜索字典的新名称。 new_owner 该文本搜索字典的新拥有者。 814 第 13 章 SQL 语句:ALTER SYNONYM 到 COMMENT new_schema 该文本搜索字典的新模式。 模板相关的选项可以以任何顺序出现。 示例 下面的命令更改一个基于 Snowball 的字典的停用词列表。其他参数保持不变。 ALTER TEXT SEARCH DICTIONARY my_dict ( StopWords = newrussian ); 下面的命令更改语言选项为 dutch,并且完全移除停用词选项。 ALTER TEXT SEARCH DICTIONARY my_dict ( language = dutch, StopWords ); 下面的命令“更新”该字典的定义,但是实际没有做任何更改。 ALTER TEXT SEARCH DICTIONARY my_dict ( dummy ); (之所以能这样做是因为选项移除代码在选项不存在时也不会报错)。这种技巧在为该字典更改配置文件时有 用,ALTER 将强制现有的数据库会话重读配置文件,否则如果会话之前已经读取过就不会再次读取。 兼容性 在 SQL 标准中没有 ALTER TEXT SEARCH DICTIONARY 语句。 其他 参见CREATE TEXT SEARCH DICTIONARY , DROP TEXT SEARCH DICTIONARY 13.7 ALTER TEXT SEARCH PARSER 用途 ALTER TEXT SEARCH PARSER 更改一个文本搜索解析器的定义。 前置条件 要使用 ALTER TEXT SEARCH PARSER,你必须是超级用户。 语法 ALTER TEXT SEARCH PARSER name RENAME TO new_name ALTER TEXT SEARCH PARSER name SET SCHEMA new_schema 815 第 13 章 SQL 语句:ALTER SYNONYM 到 COMMENT 语义 name 一个现有文本搜索解析器的名称(可以是模式限定的)。 new_name 该文本搜索解析器的新名称。 new_schema 该文本搜索解析器的新模式。 示例 将文本解析器 org_name 的名称更改为 new_name; ALTER TEXT SEARCH PARSER org_name RENAME TO new_name; 兼容性 在 SQL 标准中没有 ALTER TEXT SEARCH PARSER 语句。 其他 参见CREATE TEXT SEARCH PARSER , DROP TEXT SEARCH PARSER 13.8 ALTER TEXT SEARCH TEMPLATE 用途 ALTER TEXT SEARCH TEMPLATE 更改一个文本搜索模板的定义。 前置条件 要使用 ALTER TEXT SEARCH TEMPLATE,你必须是超级用户。 语法 ALTER TEXT SEARCH TEMPLATE name RENAME TO new_name ALTER TEXT SEARCH TEMPLATE name SET SCHEMA new_schema 语义 name 816 第 13 章 SQL 语句:ALTER SYNONYM 到 COMMENT 一个现有文本搜索模板的名称(可以是模式限定的)。 new_name 该文本搜索模板的新名称。 new_schema 该文本搜索模板的新模式。 示例 将文本搜索模板 org_name 名称更改为 new_name ALTER TEXT SEARCH TEMPLATE org_name RENAME TO new_name 兼容性 在 SQL 标准中没有 ALTER TEXT SEARCH TEMPLATE 语句。 其他 参见CREATE TEXT SEARCH TEMPLATE , DROP TEXT SEARCH TEMPLATE 13.9 ALTER TRIGGER 用途 ALTER TRIGGER 更改一个现有触发器的属性。RENAME 子句更改给定触发器的名称而不更改其定义。DEPENDS ON EXTENSION 子句把该触发器标记为依赖于一个扩展,这样如果扩展被删除,该触发器也会被自动删除。可使用 ENABLE 启用或 DISABLE 禁用指定触发器。 前置条件 要更改一个触发器的属性,你必须拥有该触发器所作用的表。 语法 ALTER TRIGGER name ON table_name RENAME TO new_name ALTER TRIGGER name ON table_name DEPENDS ON EXTENSION extension_name ALTER TRIGGER name ENABLE ALTER TRIGGER name DISABLE ALTER TRIGGER name COMPILE 817 第 13 章 SQL 语句:ALTER SYNONYM 到 COMMENT 语义 name 要修改的一个现有触发器的名称。 table_name 这个触发器所作用的表的名称。 new_name 该触发器的新名称。 extension_name 该触发器所依赖的扩展的名称。 COMPILE 重新编译触发器,刷新其状态属性。 示例 要重命名一个现有的触发器: ALTER TRIGGER emp_stamp ON emp RENAME TO emp_track_chgs; 要把一个触发器标记为依赖于一个扩展: ALTER TRIGGER emp_stamp ON emp DEPENDS ON EXTENSION bloom; 启用一个触发器: ALTER TRIGGER emp_stamp ENABLE; 禁用一个触发器: ALTER TRIGGER emp_stamp DISABLE; 兼容性 ALTER TRIGGER 是一种 KingbaseES 的 SQL 标准扩展。 818 第 13 章 SQL 语句:ALTER SYNONYM 到 COMMENT 13.10 ALTER TYPE 用途 ALTER TYPE 更改一种现有类型的定义。它有几种形式: ADD ATTRIBUTE 这种形式为一种组合类型增加一个新属性,使用的语法和CREATE TYPE 相同。 DROP ATTRIBUTE [ IF EXISTS ] 这种形式从一种组合类型删除一个属性。如果指定了 IF EXISTS 并且该属性不存在,则不会抛出错误。 这种情况下会发出一个提示。 SET DATA TYPE 这种形式更改一种组合类型的一个属性类型。 OWNER 这种形式更改该类型的拥有者。 RENAME 这种形式更改该类型的名称或者一种组合类型的一个属性的名称。 SET SCHEMA 这种形式把该类型移动到另一个模式中。 ADD VALUE [ IF NOT EXISTS ] [ BEFORE | AFTER ] 这种形式为一种枚举类型增加一个新值。可以用 BEFORE 或者 AFTER 一个现有值来指定新值在枚举顺序中 的位置。否则,新项会被增加在值列表的最后。 如果指定了 IF NOT EXISTS,该类型已经包含新值时不会发生错误:会发出一个提示但是不采取其他行 动。否则,如果新值已经存在会发生错误。 RENAME VALUE 该形式重命名枚举类型的值。该值在枚举排序中的位置不受影响。如果指定的值不存在或新名称已存在, 则会发生错误。 ADD ATTRIBUTE、DROP ATTRIBUTE 和 ALTER ATTRIBUTE 动作可以被整合到一个多个修改组成的列表中,以便被平行应用。例如,可以在一个命令中增加多个属性 并且/或者修改多个属性的类型。 前置条件 要使用 ALTER TYPE,你必须拥有该类型。要更改一个类型的模式,你还必须拥有新模式上的 CREATE 特权。要 更改拥有者,你还必须是新拥有角色的一个直接或者间接成员,并且该角色必须具有该类型的模式上的 CREATE 特权 (这些限制强制修改拥有者不能做一些通过删除和重建该类型做不到的事情。但是,一个超级用户怎么都能更改任何 类型的所有权。)。要增加一个属性或者修改一个属性类型,你还必须具有该数据类型上的 USAGE 特权。 819 第 13 章 SQL 语句:ALTER SYNONYM 到 COMMENT 语法 ALTER TYPE name action [, ... ] ALTER TYPE name OWNER TO { new_owner | CURRENT_USER | SESSION_USER } ALTER TYPE name RENAME ATTRIBUTE attribute_name TO new_attribute_name [ CASCADE | RESTRICT ] ALTER TYPE name RENAME TO new_name ALTER TYPE name SET SCHEMA new_schema ALTER TYPE name ADD VALUE [ IF NOT EXISTS ] new_enum_value [ { BEFORE | AFTER } neighbor_enum_value ] ALTER TYPE name ADD VALUE [ IF NOT EXISTS ] new_set_value [ { BEFORE | AFTER } neighbor_set_value ] ALTER TYPE name RENAME VALUE existing_enum_value TO new_enum_value ALTER TYPE name RENAME VALUE existing_set_value TO new_set_value ALTER TYPE name ADD ATTRIBUTE (attribute_name data_type [, ... ]) [ CASCADE | RESTRICT ] ALTER TYPE name MODIFY ATTRIBUTE (attribute_name data_type [, ... ]) [ CASCADE | RESTRICT ] ALTER TYPE name DROP ATTRIBUTE (attribute_name [, ... ]) [ CASCADE | RESTRICT ] ALTER TYPE name COMPILE [ SPECIFICATION | BODY ] 这里 action 是以下之一: ADD ATTRIBUTE attribute_name data_type [ COLLATE collation ] [ CASCADE | RESTRICT ] DROP ATTRIBUTE [ IF EXISTS ] attribute_name [ CASCADE | RESTRICT ] ALTER ATTRIBUTE attribute_name [ SET DATA ] TYPE data_type [ COLLATE collation ] [ CASCADE | RESTRICT ] MODIFY ATTRIBUTE attribute_name data_type [ CASCADE | RESTRICT ] ADD subprogram_spec DROP subprogram_spec 820 第 13 章 SQL 语句:ALTER SYNONYM 到 COMMENT 821 第 13 章 SQL 语句:ALTER SYNONYM 到 COMMENT action ::= 语义 name 要修改的一个现有类型的名称(可能被模式限定)。 new_name 该类型的新名称。 new_owner 该类型新拥有者的用户名。 new_schema 该类型的新模式。 attribute_name 要增加、修改或者删除的属性名称。 new_attribute_name 要被重命名的属性的新名称。 data_type 要增加的属性的数据类型,或者是要修改的属性的新类型。 new_enum_value 要被增加到一个枚举类型的值列表的新值,或将赋予现有值的新名称。和所有枚举文本一样,它需要被引 号引用。 new_set_value 要被增加到一个 SET 类型的值列表的新值,或将赋予现有值的新名称。和所有 SET 文本一样,它需要被 引号引用。 neighbor_enum_value 822 第 13 章 SQL 语句:ALTER SYNONYM 到 COMMENT 一个现有枚举值,新值应该被增加在紧接着该枚举值之前或者之后的位置上。和所有枚举文本一样,它需 要被引号引用。 neighbor_set_value 一个现有 SET 值,新值应该被增加在紧接着该 SET 值之前或者之后的位置上。和所有 SET 文本一样, 它需要被引号引用。 existing_enum_value 现有的应该重命名的枚举值。和所有的枚举文本一样,它需要被引号引用。 existing_set_value 现有的应该重命名的 SET 值。和所有的 SET 文本一样,它需要被引号引用。 subprogram_spec 对象类型的内部方法声明,详见CREATE TYPE 。 CASCADE 自动将操作传播到被更改类型的类型表及其后代。 RESTRICT 如果被更改的类型是类型表的类型,则拒绝该操作。这是默认设置。 COMPILE 重新编译类型,刷新其状态属性,可通过关键字 SPECIFICATION 指定重新编译类型声明,关键字 BODY 指定重新编译类型定义。 示例 要重命名一个数据类型: ALTER TYPE electronic_mail RENAME TO email; 把类型 email 的拥有者改为 joe: ALTER TYPE email OWNER TO joe; 把类型 email 的模式改为 customers: ALTER TYPE email SET SCHEMA customers; 增加一个新属性到一个类型: ALTER TYPE compfoo ADD ATTRIBUTE f3 int; 在一个特定的排序位置上为一个枚举类型增加一个新值: 823 第 13 章 SQL 语句:ALTER SYNONYM 到 COMMENT ALTER TYPE colors ADD VALUE 'orange' AFTER 'red'; 重命名一个枚举值: ALTER TYPE colors RENAME VALUE 'purple' TO 'mauve'; 在一个特定的排序位置上为一个 SET 类型增加一个新值: ALTER TYPE rainbow ADD VALUE 'C' BEFORE 'Y'; 重命名一个 SET 值: ALTER TYPE rainbow RENAME VALUE 'R' TO 'A'; 兼容性 增加和删除属性的变体是 SQL 标准的一部分,而其他变体是 KingbaseES 扩展。 其他 如果 ALTER TYPE ... ADD VALUE(增加一个新值到枚举或 SET 类型的形式)在一个事务块中执行,新值将不 能使用直到事务被提交之后。 涉及到一个新增加枚举值的比较有时会被只涉及原始枚举值的比较更慢。这通常只会在利用 BEFORE 或者 AFTER 来把新值的排序位置设置为非列表结尾的地方时发生。但是,有时候即使把新值增加到最后时也会发生这种情况(如 果创建了该枚举类型之后出现过 OID 计数器“回卷”,就会发生这种情况)。这种减速通常不明显,但是如果它确 实带来了麻烦,通过删除并且重建该枚举类型或者转储并且重载整个数据库可以重新得到最优性能。 13.11 ALTER USER 用途 ALTER USER —更改一个数据库角色,ALTER USER 现在是 ALTER ROLE 的一种别名,请参考ALTER ROLE 。 ALTER USER 现在是ALTER ROLE 的一种别名。 前置条件 请参考ALTER ROLE 的前置条件。 语法 ALTER USER role_specification [ WITH ] option [ ... ] 其中 option 可以是: SUPERUSER | NOSUPERUSER | CREATEDB | NOCREATEDB 824 第 13 章 SQL 语句:ALTER SYNONYM 到 COMMENT | CREATEROLE | NOCREATEROLE | INHERIT | NOINHERIT | LOGIN | NOLOGIN | ACCOUNT { UNLOCK | LOCK } | REPLICATION | NOREPLICATION | BYPASSRLS | NOBYPASSRLS | CONNECTION LIMIT connlimit | CONNECTION INTERVALS 'time1 TO time2' | [ ENCRYPTED ] PASSWORD 'password' | VALID UNTIL 'timestamp' ALTER USER name RENAME TO new_name ALTER USER { role_specification | ALL } [ IN DATABASE database_name ] SET configuration_parameter { TO | = } { value | DEFAULT } ALTER USER { role_specification | ALL } [ IN DATABASE database_name ] SET configuration_parameter FROM CURRENT ALTER USER { role_specification | ALL } [ IN DATABASE database_name ] RESET configuration_parameter ALTER USER { role_specification | ALL } [ IN DATABASE database_name ] RESET ALL 其中 role_specification 可以是: role_name | CURRENT_USER | SESSION_USER option ::= 825 第 13 章 SQL 语句:ALTER SYNONYM 到 COMMENT 826 第 13 章 SQL 语句:ALTER SYNONYM 到 COMMENT role_specification ::= 语义 请参考ALTER ROLE 。 示例 请参考ALTER ROLE 。 13.12 ALTER USER MAPPING 用途 ALTER USER MAPPING 更改一个用户映射的定义。 前置条件 一个外部服务器的拥有者可以为任何用户修改用于该服务器的用户映射。还有,如果一个用户被授予了外部服务 器上的 USAGE 特权,它就能为它们自己的用户名修改一个用户映射。 语法 ALTER USER MAPPING FOR { user_name | USER | CURRENT_USER | SESSION_USER | PUBLIC } SERVER server_name OPTIONS ( [ ADD | SET | DROP ] option ['value'] [, ... ] ) 827 第 13 章 SQL 语句:ALTER SYNONYM 到 COMMENT 语义 user_name 该映射的用户名。CURRENT_USER 和 USER 匹配当前用户的名称。PUBLIC 被用来匹配系统中所有当前以及 未来的用户名。 server_name 该用户映射的服务器名。 OPTIONS ( [ ADD | SET | DROP ] option ['value'] [, ... ] ) 为该用户映射更改选项。新选项会覆盖任何之前指定的选项。ADD、SET 和 DROP 指定要被执行的动作。 如果没有显式地指定操作,将假定为 ADD。选项名称必须为唯一,该服务器的外部数据包装器也会验证选 项。 示例 为服务器 foo 的用户映射 bob 更改口令: ALTER USER MAPPING FOR bob SERVER foo OPTIONS (SET password 'public'); 兼容性 ALTER USER MAPPING 符合 ISO/IEC 9075-9 (SQL/MED)。有一点细微的语法问题:该标准会忽略 FOR 关键字。 由于 CREATE USER MAPPING 以及 DROP USER MAPPING 都在类似的位置上使用 FOR,并且 IBM DB2 (作为其他主要 的 SQL/MED 实现)也在 ALTER USER MAPPING 中要求该关键字,因此为了一致性和互操作性,KingbaseES 在这里 的实现与标准不同。 其他 828 第 13 章 SQL 语句:ALTER SYNONYM 到 COMMENT 参见CREATE USER MAPPING , DROP USER MAPPING 13.13 ALTER VIEW 用途 ALTER VIEW 更改一个视图的多种辅助属性(如果想要修改视图的查询定义,应使用 CREATE OR REPLACE VIEW)。 前置条件 要使用 ALTER VIEW,你必须拥有该视图。要更改一个视图的模式,你还必须具有新模式上的 CREATE 特权。要 更改拥有者,你还必须是新拥有角色的一个直接或者间接成员,并且该角色必须具有该视图的模式上的 CREATE 特权 (这些限制强制修改拥有者不能做一些通过删除和重建视图做不到的事情。但是,一个超级用户怎么都能更改任何视 图的所有权。)。 语法 ALTER VIEW [ IF EXISTS ] name ALTER [ COLUMN ] column_name SET DEFAULT expression ALTER VIEW [ IF EXISTS ] name ALTER [ COLUMN ] column_name DROP DEFAULT ALTER VIEW [ IF EXISTS ] name OWNER TO { new_owner | CURRENT_USER | SESSION_USER } ALTER VIEW [ IF EXISTS ] name RENAME TO new_name ALTER VIEW [ IF EXISTS ] name SET SCHEMA new_schema ALTER VIEW [ IF EXISTS ] name SET ( view_option_name [= view_option_value] [, ... ] ) ALTER VIEW [ IF EXISTS ] name RESET ( view_option_name [, ... ] ) ALTER VIEW [ IF EXISTS ] name COMPILE 语义 829 第 13 章 SQL 语句:ALTER SYNONYM 到 COMMENT name 一个现有视图的名称(可以是模式限定的)。 IF EXISTS 该视图不存在时不要抛出一个错误。这种情况下会发出一个提示。 SET | DROP DEFAULT 这些形式为一个列设置或者移除默认值。对于任何在该视图上的 INSERT 或者 UPDATE 命令,一个视图列 的默认值会在引用该视图的任何规则或触发器之前被替换进来。因此,该视图的默认值将会优先于来自底 层关系的任何默认值。 new_owner 该视图的新拥有者的用户名。 new_name 该视图的新名称。 new_schema 该视图的新模式。 SET ( view_option_name [= view_option_value] [, ... ] ) | RESET ( view_option_name [, ... ] ) 设置或者重置一个视图选项。当前支持的选项有: check_option (string) 更改该视图的检查选项。值必须是 local 或者 cascaded。 security_barrier (boolean) 更改该视图的安全屏障属性。值必须是一个布尔值,如 true 或者 false。 COMPILE 编译视图。用于对无效视图进行编译。如果数据库在视图编译过程中没有发生错误,则更新视图的规则信 息并设置视图状态为有效;如果编译时出现错误,则返回错误,此时视图仍为无效状态。 示例 把视图 foo 重命名为 bar: ALTER VIEW foo RENAME TO bar; 要为一个可更新视图附加一个默认列值: CREATE TABLE base_table (id int, ts timestamptz); CREATE VIEW a_view AS SELECT * FROM base_table; ALTER VIEW a_view ALTER COLUMN ts SET DEFAULT now(); INSERT INTO base_table(id) VALUES(1); INSERT INTO a_view(id) VALUES(2); -- ts will receive a NULL -- ts will receive the current time 编译视图: 830 第 13 章 SQL 语句:ALTER SYNONYM 到 COMMENT CREATE TABLE people (id int, name text); CREATE VIEW teacher AS SELECT * FROM people; SELECT * FROM teacher; -- 视图有效 ALTER TABLE people DROP name; ALTER VIEW teacher COMPILE; -- 失败,视图无效 ALTER TABLE PEOPLE ADD COLUMN (name text); ALTER VIEW teacher COMPILE; -- 成功,视图有效 13.14 ANALYZE 用途 ANALYZE 收集一个数据库中的表的内容的统计信息,并且将结果存储在 sys_statistic 系统目录中。接下来,查询 规划器会使用这些统计信息来帮助确定查询最有效的执行计划。如果没有 table_and_columns 列表,ANALYZE 处理 当前用户有权分析的当前数据库中的每个表和物化视图。使用列表,ANALYZE 只处理那些表。还可以提供表的列名列 表,在这种情况下只收集这些列的统计信息。 当选项列表被圆括号包围时,可以按任何顺序写入选项。在 KingbaseES V8R3 ,不推荐使用无括号语法。 前置条件 要分析一个表,通常必须是该表的所有者或超级用户。但是,允许数据库所有者分析数据库中的所有表,共享目 录除外。(对于共享目录的限制意味着真正的数据库范围 ANALYZE 只能由超级用户执行)ANALYZE 将跳过调用用户 没有分析权限的任何表。 语法 ANALYZE [ ( option [, ...] ) ] [ table_and_columns [, ...] ] ANALYZE [ VERBOSE ] [ table_and_columns [, ...] ] 其中 option 可以是: VERBOSE [ boolean ] SKIP_LOCKED [ boolean ] table_and_columns 是: table_name [ ( column_name [, ...] ) ] 831 第 13 章 SQL 语句:ALTER SYNONYM 到 COMMENT option ::= table_and_columns ::= 语义 VERBOSE 允许显示进度消息。 SKIP_LOCKED 指定 ANALYZE 在开始处理一个关系时不应等待任何冲突锁被释放: 如果一个关系不能立即被锁定而不等 待,则跳过该关系。注意,即使使用这个选项,ANALYZE 在打开关系的索引或从分区、表继承子表和某些 类型的外部表获取样本行时仍然可能阻塞。另外,通常当 ANALYZE 处理指定分区表的所有分区时,如果 分区表上有冲突的锁,则该选项将导致 ANALYZE 跳过所有分区。 boolean 指定所选选项应该打开还是关闭。可以编写 TRUE,ON,或 1 来启用这个选项,FALSE,OFF,或 0 来禁 用它。也可以省略 boolean,此时假设 TRUE。 table_name 要分析的一个指定表的名称(可以是模式限定的)。如果省略,则分析当前数据库中的所有常规表、分区 表和物化视图 (但不分析外表)。如果指定的表是分区表,那么将更新整个分区表的继承统计信息和各个分 区的统计信息。 column_name 832 第 13 章 SQL 语句:ALTER SYNONYM 到 COMMENT 要分析的一个指定列的名称。默认是所有列。 当指定了 VERBOSE 时,ANALYZE 会发出进度消息来指示当前正在处理哪个表。还会打印有关那些表的多种统计 信息。 示例 为表 mytable 收集统计信息 ANALYZE mytable; 兼容性 SQL 标准中没有 ANALYZE 语句。 其他 只 有 被 显 式 选 中 时 才 会 分 析 外 部 表。 并 非 所 有 外 部 数 据 包 装 器 都 支 持 ANALYZE。 如 果 表 的 包 装 器 不 支 持 ANALYZE,该命令会打印一个警告并且什么也不做。 在默认的 KingbaseES 配置中,自动清理守护进程(见 自动清理后台进程)会在表第一次载入数据或者用常规操 作改变时负责表的自动分析。当启用自动清理时,定期运行 ANALYZE 是个好主意,或者可以在表内容做了大的修改 后运行 ANALYZE。准确的统计信息将帮助规划器选择最合适的查询计划,从而提升查询处理的速度。主读数据库的 一般策略是在一天中使用量最低时运行一次VACUUM 和 ANALYZE(如果有大量的更新动作则是不够的)。 ANALYZE 只要求目标表上的一个读锁,因此它可以和表上的其他动作并行。 ANALYZE 收集的统计信息通畅包括每列中最常见值的列表以及展示每列中近似数据分布的一个直方图。如果 ANALYZE 认为这些东西无趣(例如在一个唯一键列中,没有共同值)或者该列的数据类型不支持合适的操作符,以上 工作都会被省略。在 日常数据库维护工作中有与统计信息相关的更多信息。 对于大型的表,ANALYZE 会对表内容做随机采样而不是检查每一行。这允许在很少的时间内完成对大型表的分 析。但是要注意,这些统计信息只是近似值,并且即使实际表内容没有改变,每次运行 ANALYZE 时统计信息都会有 微小地改变。这可能会导致 EXPLAIN 显示的规划器估算代价有小的改变。在很少的情况下,这会非决定性地导致规 划器的查询计划选择在 ANALYZE 运行后改变。为了避免这种情况,可以按照下文所述提高 ANALYZE 所收集的统计信 息量。 通过调整 default_statistics_target 配置变量可以控制分析量,对每个列可以用 ALTER TABLE ... ALTER COLUMN ... SET STATISTICS 设置每列的统计信息目标(见ALTER TABLE )。目标值会设置最常用值列表中的最 大项数以及直方图中的最大容器数。默认目标值是 100,可以把它调大或者调小在规划器估计值精度和 ANALYZE 花 费的时间以及 sys_statistic 所占空间之间做出平衡。特别地,将统计信息目标设置为零会禁用该列的统计信息收 集。在查询的 WHERE、GROUP BY 或者 ORDER BY 子句中从不出现的列上这样做会有所帮助,因为规划器用不上这些 列上的统计信息。 被分析的列中最大的统计信息目标决定了为准备统计信息要采样的表行数。增加该目标会导致做 ANALYZE 所需 的时间和空间成比例增加。 ANALYZE 所估算的值之一是出现在每个列中的可区分值。因为只会检查行的一个子集,即便使用最大的统计信 息目标,这种估计有时也可能很不精确。如果这种不精确导致不好的查询计划,可以手工确定一个更精确的值并且用 ALTER TABLE ... ALTER COLUMN ... SET (n_distinct = ...) 设置该值(见ALTER TABLE )。 833 第 13 章 SQL 语句:ALTER SYNONYM 到 COMMENT 如果被分析的表有一个或者更多子女,ANALYZE 将会收集两次统计信息:一次只对父表的行收集,第二次则在父 表及其所有子女表的行上收集。在规划需要遍历整个继承树的查询时需要第二个统计信息集。但是,在决定是否触发 表上的自动分析时,自动清理后台进程将只考虑父表本身上的插入和更新。如果该表很少被插入或者更新,只有手工 运行 ANALYZE 时才会把继承统计信息更新到最新。 如果任何子表是外部表并且其外部数据包装器不支持 ANALYZE,在收集继承统计信息时会忽略那些子表。 如果被分析的表不完全为空,ANALYZE 将不会为该表记录新统计信息。任何现有统计信息将会被保留。 13.15 BEGIN 用途 BEGIN 开始一个事务块,也就是说所有 BEGIN 命令之后的所有语句将被在一个事务中执行,直到给出一个显式 的COMMIT 或者ROLLBACK 。默认情况下(没有 BEGIN),KingbaseES 在“自动提交”模式中执行事务,也就是 说每个语句都在自己的事务中执行并且在语句结束时隐式地执行一次提交(如果执行成功,否则会完成一次回滚)。 在一个事务块内的语句会执行得更快,因为事务的开始/提交也要求可观的 CPU 和磁盘活动。在进行多个相关更 改时,在一个事务内执行多个语句也有助于保证一致性:在所有相关更新还没有完成之前,其他会话将不能看到中间 状态。 如果指定了隔离级别、读/写模式或者延迟模式,新事务也会有那些特性,就像执行了SET TRANSACTION 一 样。 前置条件 无 语法 BEGIN [ WORK | TRANSACTION ] [ transaction_mode [, ...] ] 其中 transaction_mode 是以下之一: ISOLATION LEVEL { SERIALIZABLE | REPEATABLE READ | READ COMMITTED | READ UNCOMMITTED } READ WRITE | READ ONLY [ NOT ] DEFERRABLE 834 第 13 章 SQL 语句:ALTER SYNONYM 到 COMMENT transaction_mode ::= 语义 WORK | TRANSACTION 可选的关键词。它们没有效果。 这个语句其他参数的含义请参考SET TRANSACTION 。 示例 开始一个事务块: BEGIN; 兼容性 BEGIN 是一种 KingbaseES 语言扩展。它等效于 SQL 标准的命令START TRANSACTION ,它的参考页包含额 外的兼容性信息。 DEFERRABLE transaction_mode 是一种 KingbaseES 语言扩展。 附带地,BEGIN 关键词被用于嵌入式 SQL 中的一种不同目的。在移植数据库应用时,我们建议小心对待事务语 义。 其他 START TRANSACTION 具有和 BEGIN 相同的功能。 使用COMMIT 或者ROLLBACK 来终止一个事务块。 835 第 13 章 SQL 语句:ALTER SYNONYM 到 COMMENT 在已经在一个事务块中时发出 BEGIN 将惹出一个警告消息。事务状态不会被影响。要在一个事务块中嵌套事 务,可以使用保存点(见SAVEPOINT )。 由于向后兼容的原因,连续的 transaction_modes 之间的逗号可以被省略。 13.16 CALL/EXEC 用途 CALL/EXEC 执行一个过程。 如果过程有任何输出参数,则会返回一个结果行,返回这些参数的值。 前置条件 用户必须有过程上的 EXECUTE 特权才能调用它。 语法 CALL/EXEC name[@dblink_name] ( [ argument ] [, ...] ) 语义 name 过程的名称(可以被方案限定)。 argument 过程调用的一个输入参数。函数和过程调用语法的完整细节(包括参数的使用)请参考 调用函数。 示例 CALL/EXEC do_db_maintenance(); 其他 要调用一个函数(不是存储过程),应使用 SELECT。 如果在事务块中执行 CALL/EXEC,那么被调用的过程不能执行事务控制语句。只有当 CALL/EXEC 在其自身的事 务中执行时,才允许过程执行事务控制语句。 SQL 下允许使用 CALL/EXEC 调用函数,但有如下限制: 836 第 13 章 SQL 语句:ALTER SYNONYM 到 COMMENT 1. PL/SQL 块内不支持使用 CALL/EXEC 函数; 2. 不支持 CALL/EXEC 有 OUT 参数或返回集合的函数。 PL/SQL 以不同的方式处理 CALL/EXEC 中的输出参数。 支持使用 CALL 调用远程用户自定义存储过程。目前仅支持 KingbaseES 数据库。在 dlbink 用户有执行权限的 情况下,允许跨模式调用其他用户定义的存储过程。另外,当同一模式下存在同名存储过程时,该存储过程不能通过 dblink 远程调用。 目前仅支持 in 参数,不支持 out 参数和 inout 参数。存储过程的参数个数不大于 98 个。 13.17 CHECKPOINT 用途 一个检查点是事务日志序列中的一个点,在该点上所有数据文件都已经被更新为反映日志中的信息。所有数据文 件将被刷写到磁盘。 CHECKPOINT 命令在发出时强制一个立即的检查点,而不用等待由系统规划的常规检查点(由 预写式日志中的设 置控制)。CHECKPOINT 不是用来在普通操作中使用的命令。 如果在恢复期间执行,CHECKPOINT 命令将强制一个重启点而不是写一个新检查点。 前置条件 只有超级用户能够调用 CHECKPOINT。 语法 CHECKPOINT 语义 无 示例 执行检查点命令: CHECKPOINT; 兼容性 CHECKPOINT 命令是一种 KingbaseES 语言扩展。 837 第 13 章 SQL 语句:ALTER SYNONYM 到 COMMENT 13.18 CLOSE 用途 CLOSE 释放与一个已打开游标相关的资源。在游标被关闭后,不允许在其上做后续的操作。当不再需要使用一个 游标时应该关闭它。 当一个事务被 COMMIT 或者 ROLLBACK 终止时,每一个非可保持的已打开游标会被隐式地关闭。当创建一个可保 持游标的事务通过 ROLLBACK 中止时,该可保持游标会被隐式地关闭。如果该创建事务成功地提交,可保持游标会保 持打开,直至执行一个显式的 CLOSE 或者客户端连接断开。 前置条件 无 语法 CLOSE { name | ALL } 语义 name 要关闭的已打开游标的名称。 ALL 关闭所有已打开的游标。 示例 关闭游标 liahona: CLOSE liahona; 兼容性 CLOSE 完全服从 SQL 标准。CLOSE ALL 是一种 KingbaseES 扩展。 其他 KingbaseES 没有一个显式的 OPEN 游标语句,一个游标在被声明时就被认为是打开的。使用DECLARE 语句可 以声明游标。 通过查询 sys_cursors 系统视图可以看到所有可用的游标。 838 第 13 章 SQL 语句:ALTER SYNONYM 到 COMMENT 如果一个游标在一个保存点之后关闭,并且后来回滚到了这个保存点,那么 CLOSE 不会被回滚,也就是说回滚 后游标仍然保持关闭。 13.19 CLUSTER 用途 CLUSTER 指示 KingbaseES 基于 index_name 所指定的索引来聚簇 table_name 所指定的表。该索引必须已经定 义在 table_name 上。 当一个表被聚簇时,会基于索引信息对它进行物理上的排序。聚簇是一种一次性的操作:当表后续被更新时,更 改没有被聚簇。也就是说,不会尝试根据新行或者被更新行的索引顺序来存储它们(如果想这样做,可以周期性地通 过发出该命令重新聚簇。还有,把表的 fillfactor 存储参数设置为小于 100% 有助于在更新期间保持聚簇顺序,因 为如果空间足够会把被更新行保留在同一个页面中)。 当一个表被更新时,KingbaseES 会记住它是按照哪个索引聚簇的。形式 CLUSTER table_name 会使用前面所用 的同一个索引对表重新聚簇。你也可以使用 CLUSTER 或者ALTER TABLE 的 SET WITHOUT CLUSTER 形式把索引设 置为可用于未来的聚簇操作,或者清除任何之前的设置。 前置条件 不带任何参数的 CLUSTER 会重新聚簇调用用户所拥有的当前数据库中已经被聚簇过的表(如果是超级用户调 用,则是所有已被聚簇过的表)。这种形式的 CLUSTER 不能在一个事务块内执行。 当一个表被聚簇时,会在其上要求一个 ACCESS EXCLUSIVE 锁。这会阻止任何其他数据库操作(包括读和写)在 CLUSTER 结束前在该表上操作。 语法 CLUSTER [VERBOSE] table_name [ USING index_name ] CLUSTER [VERBOSE] 语义 table_name 一个表的名称(可能是模式限定的)。 index_name 一个索引的名称。 839 第 13 章 SQL 语句:ALTER SYNONYM 到 COMMENT VERBOSE 在每一个表被聚簇时打印一个进度报告。 示例 基于索引 employees_ind 聚簇表 employees: CLUSTER employees USING employees_ind; 使用之前用过的同一个索引聚簇 employees 表: CLUSTER employees; 对数据库中以前被聚簇过的所有表进行聚簇: CLUSTER; 兼容性 在 SQL 标准中没有 CLUSTER 语句。 为了兼容 V8R3 之前的 KingbaseES 版本,以下语法也被支持: CLUSTER index_name ON table_name 其他 在随机访问一个表中的行时,表中数据的实际顺序是无关紧要的。但是,如果你想要更多地访问其中一些数据, 并且有一个索引把它们分组在一起,使用 CLUSTER 就会带来好处。如果你从一个表中要求一个范围的被索引值或者 多行都匹配的一个单一值,CLUSTER 就会有所帮助,因为一旦该索引标识出了第一个匹配行所在的表页,所有其他匹 配行很可能就在同一个表页中,并且因此节省了磁盘访问并且提高了查询速度。 CLUSTER 可以使用指定索引上的一次索引扫描或者遵循排序的一次顺序扫描(如果索引是 B 树)对表重新排序。 它将会基于规划器代价参数以及可用的统计信息来选择较快的方法。 在使用索引扫描时,会创建该表的一份临时拷贝,其中包含按索引顺序排列的表数据。该表上每一个索引的临时 拷贝也会被创建。因此,在磁盘上需要至少等于表尺寸加上索引尺寸的综合的空闲空间。 在使用顺序扫描以及排序时,也会创建一个临时排序文件,因此临时空间需求的峰值也就是表尺寸的两倍外 加索引尺寸。这种方法通常比索引扫描方法更快,但是如果磁盘空间需求是不能接受的,你可以通过临时地把 enable_sort 设置为 off 来禁用这种选择。 建议在聚簇前把 maintenance_work_mem 设置为一个合理地比较大的值(但是不能超过你可以用于 CLUSTER 操 作的 RAM 容量)。 因为规划器会记录有关表顺序的统计信息,建议在新近被聚簇的表上运行ANALYZE 。否则,规划器可能会产生 很差的查询计划。 因为 CLUSTER 会记住哪些索引被聚簇,我们可以第一次手动聚簇想要聚簇的表,然后设置一个定期运行的维护 脚本,其中执行不带任何参数的 CLUSTER,这样那些表就会被周期性地重新聚簇。 840 第 13 章 SQL 语句:ALTER SYNONYM 到 COMMENT 13.20 COMMENT 用途 COMMENT 存储关于一个数据库对象的注释。对每一个对象只保存一个注释字符串,因此为了修改一段注释,对同 一个对象发出一个新的 COMMENT 命令。要移除一段注释,可在文本字符串的位置上写上 NULL。当对象被删除时, 其注释也会被自动删除。 前置条件 对大部分类型的对象,只有对象的拥有者可以设置注释。角色没有拥有者,因此 COMMENT ON ROLE 的规则是你 必须作为一个超级用户来对一个超级用户角色设置注释,或者具有 CREATEROLE 特权来对非超级用户角色设置注释。 同样的,访问方法也没有拥有者,你必须作为一个超级用户来对一个访问方法设置注释。当然,一个超级用户可以对 任何东西设置注释。 语法 COMMENT ON { ACCESS METHOD object_name | AGGREGATE aggregate_name ( aggregate_signature ) | CAST (source_type AS target_type) | COLLATION object_name | COLUMN relation_name.column_name | CONSTRAINT constraint_name ON table_name | CONSTRAINT constraint_name ON DOMAIN domain_name | CONVERSION object_name | DATABASE object_name | DOMAIN object_name | EXTENSION object_name | EVENT TRIGGER object_name | FOREIGN DATA WRAPPER object_name | FOREIGN TABLE object_name | FUNCTION function_name ( [ [ argmode ] [ argname ] argtype [, ...] ] ) | INDEX object_name | LARGE OBJECT large_object_oid | MATERIALIZED VIEW object_name | OPERATOR operator_name (left_type, right_type) | OPERATOR CLASS object_name USING index_method | OPERATOR FAMILY object_name USING index_method | PACKAGE package_name | POLICY policy_name ON table_name | [ PROCEDURAL ] LANGUAGE object_name | PROCEDURE procedure_name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ] | ROLE object_name | RULE rule_name ON table_name | SCHEMA object_name | 841 第 13 章 SQL 语句:ALTER SYNONYM 到 COMMENT SEQUENCE object_name | SERVER object_name | TABLE object_name | TABLESPACE object_name | TEXT SEARCH CONFIGURATION object_name | TEXT SEARCH DICTIONARY object_name | TEXT SEARCH PARSER object_name | TEXT SEARCH TEMPLATE object_name | TRANSFORM FOR type_name LANGUAGE lang_name | TRIGGER trigger_name ON table_name | TYPE object_name | VIEW object_name } IS 'text' 其中 aggregate_signature 是: * | [ argmode ] [ argname ] argtype [ , ... ] | [ [ argmode ] [ argname ] argtype [ , ... ] ] ORDER BY [ argmode ] [ argname ] argtype [ , ... ] aggregate_signature ::= 语义 object_name | relation_name.column_name | aggregate_name | constraint_name | function_name | 842 第 13 章 SQL 语句:ALTER SYNONYM 到 COMMENT procedure_name | package_name | operator_name | policy_name | rule_name | trigger_name 要被注释的对象的名称。表、聚集、排序方式、转换、域、外部表、函数、存储过程、包、索引、操作 符、操作符类、操作符族、序列、统计信息、文本搜索对象、类型和视图的名称可以被模式限定。在注释 一列时,“relation_name“必须引用一个表、视图、组合类型或者外部表。 table_name | domain_name 当在一个约束、触发器、规则或者策略上创建一段注释时,这些参数指定在其上定义该对象的表或域的名 称。 source_type 造型的源数据类型的名称。 target_type 造型的目标数据类型的名称。 argmode 一个函数或者聚集的参数的模式:IN、OUT、INOUT 或者 VARIADIC。如果被省略,默认值是 IN。注意 COMMENT 并不真正关心 OUT 参数,因为决定函数的身份只需要输入参数。因此列出 IN、INOUT 和 VARIADIC 参数就足够了。 argname 一个函数或者聚集参数的名称。注意 COMMENT 并不真正关心参数名称,因为决定函数的身份只需要参数 数据类型。 argtype 一个函数或者聚集参数的数据类型。 large_object_oid 大对象的 OID。 left_type | right_type 操作符的参数的数据类型(可以是模式限定的)。对一个前缀后后缀操作符的缺失参数可以写 NONE。 PROCEDURAL 这是一个噪声词。 type_name 该转换的数据类型的名称。 lang_name 该转换的语言的名称。 text 写成一个字符串的新注释。如果要删除注释,写成 NULL。 843 第 13 章 SQL 语句:ALTER SYNONYM 到 COMMENT 示例 为表 mytable 附加一段注释: COMMENT ON TABLE mytable IS 'This is my table.'; 移除它: COMMENT ON TABLE mytable IS NULL; 更多的一些例子: COMMENT ON ACCESS METHOD rtree IS 'R-Tree access method'; COMMENT ON AGGREGATE my_aggregate (double precision) IS 'Computes sample variance'; COMMENT ON CAST (text AS int4) IS 'Allow casts from text to int4'; COMMENT ON COLLATION "fr_CA" IS 'Canadian French'; COMMENT ON COLUMN my_table.my_column IS 'Employee ID number'; COMMENT ON CONVERSION my_conv IS 'Conversion to UTF8'; COMMENT ON CONSTRAINT bar_col_cons ON bar IS 'Constrains column col'; COMMENT ON CONSTRAINT dom_col_constr ON DOMAIN dom IS 'Constrains col of domain'; COMMENT ON DATABASE my_database IS 'Development Database'; COMMENT ON DOMAIN my_domain IS 'Email Address Domain'; COMMENT ON EXTENSION hstore IS 'implements the hstore data type'; COMMENT ON FOREIGN DATA WRAPPER mywrapper IS 'my foreign data wrapper'; COMMENT ON FOREIGN TABLE my_foreign_table IS 'Employee Information in other database'; COMMENT ON FUNCTION my_function (timestamp) IS 'Returns Roman Numeral'; COMMENT ON INDEX my_index IS 'Enforces uniqueness on employee ID'; COMMENT ON LANGUAGE plpython IS 'Python support for stored procedures'; COMMENT ON LARGE OBJECT 346344 IS 'Planning document'; COMMENT ON MATERIALIZED VIEW my_matview IS 'Summary of order history'; COMMENT ON OPERATOR ^ (text, text) IS 'Performs intersection of two texts'; COMMENT ON OPERATOR - (NONE, integer) IS 'Unary minus'; COMMENT ON OPERATOR CLASS int4ops USING btree IS '4 byte integer operators for btrees'; COMMENT ON OPERATOR FAMILY integer_ops USING btree IS 'all integer operators for btrees'; COMMENT ON PACKAGE my_pkg is 'Test package'; COMMENT ON POLICY my_policy ON mytable IS 'Filter rows by users'; COMMENT ON PROCEDURE my_proc (integer, integer) IS 'Runs a report'; COMMENT ON ROLE my_role IS 'Administration group for finance tables'; COMMENT ON RULE my_rule ON my_table IS 'Logs updates of employee records'; COMMENT ON SCHEMA my_schema IS 'Departmental data'; COMMENT ON SEQUENCE my_sequence IS 'Used to generate primary keys'; COMMENT ON SERVER myserver IS 'my foreign server'; COMMENT ON STATISTICS my_statistics IS 'Improves planner row estimations'; COMMENT ON TABLE my_schema.my_table IS 'Employee Information'; COMMENT ON TABLESPACE my_tablespace IS 'Tablespace for indexes'; COMMENT ON TEXT SEARCH CONFIGURATION my_config IS 'Special word filtering'; COMMENT ON TEXT SEARCH DICTIONARY swedish IS 'Snowball stemmer for Swedish language'; 844 第 13 章 SQL 语句:ALTER SYNONYM 到 COMMENT COMMENT ON TEXT SEARCH PARSER my_parser IS 'Splits text into words'; COMMENT ON TEXT SEARCH TEMPLATE snowball IS 'Snowball stemmer'; COMMENT ON TRANSFORM FOR hstore LANGUAGE plpythonu IS 'Transform between hstore and Python dict'; COMMENT ON TRIGGER my_trigger ON my_table IS 'Used for RI'; COMMENT ON TYPE complex IS 'Complex number data type'; COMMENT ON VIEW my_view IS 'View of departmental costs'; 兼容性 SQL 标准中没有 COMMENT 命令。 其他 当前对查看注释没有安全机制:任何连接到一个数据库的用户能够看到该数据库中所有对象的注释。对于数据 库、角色、表空间这类共享对象,注释被全局存储,因此连接到集簇中任何数据库的任何用户可以看到共享对象的所 有注释。因此,不要在注释中放置有安全性风险的信息。 845 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE 14章 SQL 语句:COMMIT 到 CREATE 第 LANGUAGE 本章包含以下 SQL 语句: • COMMIT • COMMIT PREPARED • COPY • CREATE ACCESS METHOD • CREATE AGGREGATE • CREATE CAST • CREATE COLLATION • CREATE CONTEXT • CREATE CONVERSION • CREATE DATABASE • CREATE DATABASE LINK • CREATE DIRECTORY • CREATE DOMAIN • CREATE EVENT TRIGGER • CREATE EXTENSION • CREATE FOREIGN DATA WRAPPER • CREATE FOREIGN TABLE • CREATE FUNCTION • CREATE GROUP • CREATE INDEX 846 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE • CREATE LANGUAGE 14.1 COMMIT 用途 COMMIT 提交当前事务。所有由该事务所作的更改会变得对他人可见并且被保证在崩溃发生时仍能持久。 前置条件 提交当前事务不需要任何权限。 语法 COMMIT [ WORK | TRANSACTION ] [ AND [ NO ] CHAIN ] 语义 WORK TRANSACTION 可选的关键词。它们没有效果。 AND CHAIN 如果指定了 AND CHAIN,立即启动具有相同事务特征的新事务 (参见SET TRANSACTION ) 作为刚刚完 成的一个。否则, 不启动新的事务。 示例 要提交当前事务并且让所有更改持久化: COMMIT; 兼容性 COMMIT 命令符合 SQL 标准。COMMIT TRANSACTION 是 KingbaseES 的扩展。 14.2 COMMIT PREPARED 用途 847 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE COMMIT PREPARED 提交一个处于预备状态的事务。 前置条件 要提交一个预备的事务,你必须是原先执行该事务的同一用户或者超级用户。但是不需要处于执行该事务的同一 会话中。 这个命令不能在一个事务块中执行。该预备事务将被立刻提交。 sys_prepared_xacts 系统视图中列出了所有当前可用的预备事务。 语法 COMMIT PREPARED transaction_id 语义 transaction_id 要被提交的事务的事务标识符。 示例 提交由事务标识符 foobar 标识的事务: COMMIT PREPARED 'foobar'; 兼容性 COMMIT PREPARED 是一种 KingbaseES 扩展。其意图是用于外部事务管理系统,其中有些已经被标准涵盖(例如 X/Open XA),但是那些系统的 SQL 方面未被标准化。 14.3 COPY 用途 COPY 在 KingbaseES 表和标准文件系统文件之间移动数据。COPY TO 把一个表的内容复制到一个文件,而 COPY FROM 则从一个文件复制数据到一个表(把数据追加到表中原有数据)。COPY TO 也能复制一个 SELECT 查询的结果。 如果指定了一个列列表,COPY 将只把指定列的数据复制到文件或者从文件复制数据到指定列。如果表中有列不 在列列表中,COPY FROM 将会为那些列插入默认值。 带一个文件名的 COPY 指示 KingbaseES 服务器直接从一个文件读取或者写入到一个文件。该文件必须是 KingbaseES 用户(运行服务器的用户 ID)可访问的并且应该以服务器的视角来指定其名称。当指定了 PROGRAM 时,服务 器执行给定的命令并且从该程序的标准输出读取或者写入到该程序的标准输入。该程序必须以服务器的视角指定,并 且必须是 KingbaseES 用户可执行的。在指定 STDIN 或者 STDOUT 时,数据会通过客户端和服务器之间的连接传输。 848 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE 前置条件 COPY TO 只能被用于纯粹的表,不能用于视图。但是你可以写 COPY (SELECT * FROM viewname) TO... 来拷贝 一个视图的当前内容。 COPY FROM 可以被用于普通表、外部表、分区表或者具有 INSTEAD OF INSERT 触发器的视图。 COPY 只处理提到的表,它不会从子表复制数据或者复制数据到子表中。例如 COPY table TO 会显示与 SELECT * FROM ONLY table 相同的数据。而 COPY (SELECT * FROM table) TO ... 可以被用来转储一个继承层次中的所 有数据。 你必须拥有被 COPY TO 读取的表上的选择特权,以及被 COPY FROM 插入的表上的插入特权。拥有在命令中列出 的列上的特权就足够了。 如果对表启用了行级安全性,相关的 SELECT 策略将应用于 COPY table TO 语句。当前,有行级安全性的表不 支持 COPY FROM。但是可以使用等效的 INSERT 语句。 语法 COPY table_name [ ( column_name [, ...] ) ] FROM { 'filename' | PROGRAM 'command' | STDIN } [ [ WITH ] ( option [, ...] ) ] [ WHERE condition ] COPY { table_name [ ( column_name [, ...] ) ] | ( query ) } TO { 'filename' | PROGRAM 'command' | STDOUT } [ [ WITH ] ( option [, ...] ) ] 849 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE 其中 option 可以是: FORMAT format_name FREEZE [ boolean ] DELIMITER 'delimiter_character' TERMINATOR 'terminator_character' NULL 'null_string' HEADER [ boolean ] QUOTE 'quote_character' ESCAPE 'escape_character' FORCE_QUOTE { ( column_name [, ...] ) | * } FORCE_NOT_NULL ( column_name [, ...] ) FORCE_NULL ( column_name [, ...] ) ENCODING 'encoding_name' SKIP_ERRORS [‘errors_num’ ] 850 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE 语义 table_name 一个现有表的名称(可以是模式限定的)。 column_name 可选的要被复制的列列表。如果没有指定列列表,则该表的所有列(除了生成列)都会被复制。 query 其结果要被复制的SELECT 、VALUES 、INSERT 、UPDATE 或者DELETE 命令。注意查询周围的圆 括号是必要的。 对于 INSERT、UPDATE 以及 DELETE 查询,必须提供一个 RETURNING 子句并且目标关系不能具有会扩 展成多条语句的条件规则、ALSO 规则或者 INSTEAD 规则。 filename 输入或者输出文件的路径名。一个输入文件的名称可以是一个绝对或相对路径,但一个输出文件的名称必 须是绝对路径。Windows 用户可能需要使用一个 E''字符串并且双写路径名称中使用的任何反斜线。 PROGRAM 一个要执行的命令。在 COPY FROM 中,输入将从该命令的标准输出读取,而在 COPY TO 中,输出会写入 到该命令的标准输入。 注意该命令是由 shell 调用,因此如果你需要传递任何来自不可信来源的参数给 shell 命令,你必须小心地 剥离那些可能对 shell 有特殊意义的特殊字符。出于安全原因,最好使用一个固定的命令字符串,或者至 851 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE 少避免传递任何用户输入到其中。 STDIN 指定输入来自客户端应用。 STDOUT 指定输出会去到客户端应用。 boolean 指定选中的选项是应该被关闭还是打开。可以写 TRUE、ON 或 1 来启用选项,写 FALSE、OFF 或 0 禁用 它。“boolean“值也可以被省略,那样会假定为 TRUE。 FORMAT 选择要读取或者写入的数据格式:text、csv(逗号分隔值)或者 binary。默认是 text。 FREEZE 请求复制已经完成了行冻结的数据,就好像在运行 VACUUM FREEZE 命令之后复制。这是为了初始数据载 入的性能而设计的。只有被载入表已经在当前子事务中被创建或截断、该事务中没有游标打开并且该事务 没有持有更旧的快照时,行才会被冻结。目前无法在分区表上执行 COPY FREEZE。 注意一旦成功地载入,所有其他会话将能立即看到该数据。这违背了普通的 MVCC 可见性规则,指定该 选项的用户应该注意这可能会导致的潜在问题。 DELIMITER 指定分隔文件每行中各列的字符。文本格式中默认是一个制表符,而 CSV 格式中默认是一个逗号。KingbaseES 支持设置不大于 8 个字节的分隔符。使用 binary 格式时不允许这个选项。 TERMINATOR 指定文本中每行中换行的字符。默认换行符为\r、\n、\r\n。KingbaseES 支持设置不大于 8 个字节的分 隔符, 使用 binary 格式时不允许这个选项。KingbaseES 兼容 Oracle 模式支持,而兼容 PostgreSQL 模 式不支持。 NULL 指定表示一个空值的字符串。文本格式中默认是 \N(反斜线-N),CSV 格式中默认是一个未加引用的空 串。在你不想区分空值和空串的情况下,即使在文本格式中你也可能更喜欢空串。使用 binary 格式时不 允许这个选项。 注意: 在使用 COPY FROM 时,任何匹配这个串的数据项将被存储为空值,因此你应该确定你使用的是和 COPY TO 时相同的串。 HEADER 指定文件包含标题行,其中有每一列的名称。在输出时,第一行包含来自表的列名。在输入时,第一行会 被忽略。只有使用 CSV 格式时才允许这个选项。 852 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE QUOTE 指定一个数据值被引用时使用的引用字符。默认是双引号。这必须是一个单一的单字节字符。只有使用 CSV 格式时才允许这个选项。 ESCAPE 指定应该出现在一个匹配 QUOTE 值的数据字符之前的字符。默认和 QUOTE 值一样(这样如果引用字符出 现在数据中,它会被双写)。这必须是一个单一的单字节字符。只有使用 CSV 格式时才允许这个选项。 FORCE_QUOTE 强制必须对每个指定列中的所有非 NULL 值使用引用。NULL 输出不会被引用。如果指定了 *,所有列的 非 NULL 值都将被引用。只有在 COPY TO 中使用 CSV 格式时才允许这个选项。 FORCE_NOT_NULL 不要把指定列的值与空值串匹配。在空值串就是空串的默认情况下,这意味着空串将被读作长度为零的字 符串而不是空值(即使它们没有被引用)。只有在 COPY FROM 中使用 CSV 格式时才允许这个选项。 FORCE_NULL 将指定列的值与空值串匹配(即使它已经被加上引号),并且在找到匹配时将该值设置为 NULL。在空值 串就是空串的默认情况下,这会把一个被引用的空串转换为 NULL。只有在 COPY FROM 中使用 CSV 格式 时才允许这个选项。 ENCODING 指定文件被以 “encoding_name“编码。如果省略这个选项,将使用当前的客户端编码。详见下文的注解。 SKIP_ERRORS 指定 copy from 中允许跳过最大错误行数 “errors_num“。如果省略这个选项,不允许跳过,出错退出。 如果指定该选项,但不指定 “errors_num“,表示一直允许跳过错误行。如果指定该选项,且指定 “errors_num“,超过最大错误行后退出。 WHERE 可选的 WHERE 子句具有一般形式 WHERE condition 其中 “condition“是计算出类型 boolean 的结果的任何表达式。任何不满足此条件的行都不会被插入到表中。当 实际的行值被替换为任何变量引用时,如果行返回 true,则满足该条件。 目前,在 WHERE 表达式中不允许使用子查询,并且计算时不会看到由 COPY 本身所做的任何更改 (当表达式包含 对 VOLATILE 函数的调用时,这一点很重要)。 示例 下面的例子使用竖线(|)作为域定界符把一个表复制到客户端: COPY country TO STDOUT (DELIMITER '|'); 853 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE 从一个文件中复制数据到 country 表中: COPY country FROM '/usr1/proj/bray/sql/country_data'; 只把名称以’A’ 开头的国家复制到一个文件中: COPY (SELECT * FROM country WHERE country_name LIKE 'A%') TO '/usr1/proj/bray/sql/a_list_countries.copy'; 要复制到一个压缩文件中,你可以用管道把输出导到一个外部压缩程序: COPY country TO PROGRAM 'gzip > /usr1/proj/bray/sql/country_data.gz'; 这里是一个适合于从 STDIN 复制到表中的数据: AF AFGHANISTAN AL ALBANIA DZ ALGERIA ZM ZAMBIA ZW ZIMBABWE 注意每一行上的空白实际是一个制表符。 下面是用二进制格式输出的相同数据。该数据是用 Unix 工具 od -c 过滤后显示的。该表具有三列,第一列类型 是 char(2),第二列类型是 text,第三列类型是 integer。所有行在第三列都是空值。 0000000 P G C O P Y \n 377 0000020 \0 \0 \0 \0 003 \0 0000040 F G H A N 0000060 \0 \0 \0 002 A 0000100 A 377 377 377 377 0000120 007 \r \n \0 \0 \0 \0 \0 \0 \0 \0 002 A F \0 \0 \0 013 A I S T A N 377 377 377 377 L \0 \0 \0 007 \0 003 \0 \0 A 377 377 377 377 \0 003 A L B A N I \0 002 D Z \0 \0 \0 \0 003 \0 \0 A L G E R I \0 002 Z M \0 \0 \0 006 Z A M B I A 377 377 0000160 377 377 \0 003 \0 \0 \0 002 Z W \0 \0 \0 \b 0000200 A W E 377 377 377 377 377 377 0000140 M B B Z I 兼容性 SQL 标准中没有 COPY 语句。 下列语法用于 KingbaseES V8R2 之前的版本,并且仍然被支持: COPY table_name [ ( column_name [, ...] ) ] FROM { 'filename' | STDIN } [ [ WITH ] [ BINARY ] [ OIDS ] [ DELIMITER [ AS ] 'delimiter' ] 854 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE [ NULL [ AS ] 'null string' ] [ CSV [ HEADER ] [ QUOTE [ AS ] 'quote' ] [ ESCAPE [ AS ] 'escape' ] [ FORCE NOT NULL column_name [, ...] ] ] ] COPY { table_name [ ( column_name [, ...] ) ] | ( query ) } TO { 'filename' | STDOUT } [ [ WITH ] [ BINARY ] [ OIDS ] [ DELIMITER [ AS ] 'delimiter' ] [ NULL [ AS ] 'null string' ] [ CSV [ HEADER ] [ QUOTE [ AS ] 'quote' ] [ ESCAPE [ AS ] 'escape' ] [ FORCE QUOTE { column_name [, ...] | * } ] ] ] 注意在这种语法中,BINARY 和 CSV 被视作独立的关键词,而不是 FORMAT 选项的参数。 下列语法用于 KingbaseES V7 之前的版本,并且仍然被支持: COPY [ BINARY ] table_name FROM { 'filename' | STDIN } [ [USING] DELIMITERS 'delimiter' ] [ WITH NULL AS 'null string' ] COPY [ BINARY ] table_name TO { 'filename' | STDOUT } [ [USING] DELIMITERS 'delimiter' ] [ WITH NULL AS 'null string' ] 其他 1. 输出 在成功完成时,一个 COPY 命令会返回一个形为如下所示的命令标签: COPY count *``count``*\ 是被复制的行数。 注意: 如果命令不是 COPY ... TO STDOUT 或者等效的 ksql 元命令\copy ... to stdout,ksql 将只打印这个命令 标签。这是为了防止弄混命令标签和刚刚打印的数据。 855 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE 2. 注解 COPY 命令中提到的文件会被服务器(而不是客户端应用)直接读取或写入。因此它们必须位于数据库服务器 (不是客户端)的机器上或者是数据库服务器可以访问的。它们必须是 KingbaseES 用户(运行服务器的用户 ID) 可访问的并且是可读或者可写的。类似地,用 PROGRAM 指定的命令也会由服务器(不是客户端应用)直接执行, 它也必须是 KingbaseES 用户可以执行的。只允许数据库超级用户或者授予了默认角色 sys_read_server_files、 sys_write_server_files 及 sys_execute_server_program 之一的用户 COPY 一个文件或者命令,因为它允许读取 或者写入服务器有特权访问的任何文件或者运行服务器有特权访问的程序。 不要把 COPY 和 ksql 指令 \copy 弄混。\copy 会调用 COPY FROM STDIN 或者 COPY TO STDOUT,然后读取/存储 一个 ksql 客户端可访问的文件中的数据。因此,在使用\copy 时,文件的可访问性和访问权利取决于客户端而不是服 务器。 我们推荐在 COPY 中使用的文件名总是指定为一个绝对路径。在 COPY TO 的情况下服务器会强制这一点,但是 对于 COPY FROM 你可以选择从一个用相对路径指定的文件中读取。该路径将根据服务器进程(而不是客户端)的工 作目录(通常是集簇的数据目录)解释。 用 PROGRAM 执行一个命令可能会受到操作系统的访问控制机制(如 SELinux)的限制。 COPY FROM 将调用目标表上的任何触发器和检查约束。但是它不会调用规则。 对于标识列,COPY FROM 命令将总是写上输入数据中提供的列值,这和 INSERT 的选项 OVERRIDING SYSTEM VALUE 的行为一样。 COPY 输入和输出受到 DateStyle 的影响。为了确保到其他可能使用非默认 DateStyle 设置的 KingbaseES 安装 的可移植性,在使用 COPY TO 前应该把 DateStyle 设置为 ISO。避免转储把 IntervalStyle 设置为 sql_standard 的数据也是一个好主意,因为负的区间值可能会被具有不同 IntervalStyle 设置的服务器解释错误。 即使数据会被服务器直接从一个文件读取或者写入一个文件而不通过客户端,输入数据也会被根据 ENCODING 选 项或者当前客户端编码解释,并且输出数据会被根据 ENCODING 或者当前客户端编码进行编码。 COPY 会在第一个错误处停止操作。这在 COPY TO 的情况下不会导致问题,但是在 COPY FROM 中目标表将已经收 到了一些行。这些行将不会变得可见或者可访问,但是它们仍然占据磁盘空间。如果在一次大型的复制操作中出现错 误,这可能浪费相当可观的磁盘空间。你可能希望调用 VACUUM 来恢复被浪费的空间。 FORCE_NULL 和 FORCE_NOT_NULL 可以被同时用在同一列上。这会导致把已被引用的空值串转换为空值并且把未 引用的空值串转换为空串。 KingbaseES 支持导入和导出数据中包含 0x00 字节的场景,受 guc 变量 ignore_char_null_check 控制, 当变 量打开时,将支持此特性,变量默认值为关闭状态。在从文件等方式导入包含有 0x00 字节的数据时,需要使用二进 制编辑工具保证输入的数据是二进制 0x00 字节,而不是”0x00” 字符串。导出数据时,KingbaseES 也会将数据中的 0x00 字节使用二进制方式导出到目标输出端。在显示 0x00 字节时,不同的终端可能有不同的显示风格。 在以文本格式导入数据时,KingbaseES 总是尝试将”\0” 开始的字符串,转换为八进制数据,转换时会尝试读取” \0” 后面的两个 0-7 的数字字符,比如当读到”\040” 时,会转为空格(0x20 字节)。如果想在文本方式导入时,使 用”\0” 表示 0x00 字节,避免使用二进制工具编辑 0x00 字节,KingbaseES 提供了 guc 变量 ignore_char_converter 来控制,当此变量设置为打开状态时,遇到”\0” 将不会尝试八进制转换,而认为是 0x00 字节,此变量默认值为关闭 状态。 3. 文件格式 856 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE • 文本格式 在使用 text 格式时,读取或写入的是一个文本文件,其中每一行就是表中的一行。一行中的列被定界字符分 隔。列值本身是由输出函数产生的或者是可被输入函数接受的属于每个属性数据类型的字符串。在为空值的列的位置 使用指定的空值串。如果输入文件的任何行包含比预期更多或者更少的列,COPY FROM 将会抛出一个错误。 数据的结束可以表示为一个只包含反斜线-点号(\.)的单一行。从一个文件读取时,数据结束标记并不是必要 的,因为文件结束符就已经足够用了。只有使用 3.0 客户端协议之前的客户端应用复制数据时才需要它。 反斜线字符(\)可以被用在 COPY 数据中来引用被用作行或者列定界符的字符。特别地,如果下列字符作为一个 列值的一部分出现,它们必须被前置一个反斜线:反斜线本身、新行、回车以及当前的定界符字符。 COPY TO 会不加任何反斜线返回指定的空值串。相反,COPY FROM 会在移除反斜线之前把输入与空值串相匹配。 因此,一个空值串(例如\N)不会与实际的数据值\N(它会被表示为\\N)搞混。 COPY FROM 识别下列特殊的反斜线序列: 序列 表示 \b 退格 (ASCII 8) \f 换页 (ASCII 12) \n 新行 (ASCII 10) \r 回车 (ASCII 13) \t 制表 (ASCII 9) \v 纵向制表 (ASCII 11) \“digits“ 反斜线后跟一到三个十进制位表示该数字代码对应的字符 \x“digits“ 反斜线加 x 后跟一到三个十六进制位表示该数字代码对应的字符 当前,COPY TO 不会发出一个十进制或十六进制位反斜线序列,但是它确实把上面列出的其他序列用于那些控制 字符。 任何上述表格中没有提到的其他反斜线字符将被当作表示其本身。但是,要注意增加不必要的反斜线,因为那可 能意外地产生一个匹配数据结束标记(\.)或者空值串(默认是\N)的字符串。这些字符串将在完成任何其他反斜线 处理之前被识别。 强烈建议产生 COPY 数据的应用把数据新行和回车分别转换为\n 和\r 序列。当前可以把一个数据回车表示为一 个反斜线和回车,把一个数据新行表示为一个反斜线和新行。但是,未来的发行可能不会接受这些表示。如果在不同 的机器之间(例如从 Unix 到 Windows)传输 COPY 文件,它们也很容易受到破坏。 COPY TO 将用一个 Unix 风格的新行(“\n”)终止每一行。运行在 Microsoft Windows 上的服务器则会输出回 车/新行(“\r\n”),但是只对 COPY 到一个服务器文件这样做。为了做到跨平台一致,COPY TO STDOUT 总是发送 “\n”而不管服务器平台是什么。COPY FROM 能够处理以新行、回车或者回车/新行结尾的行。为了减少由作为数据 的未加反斜线的新行或者回车带来的风险,如果输出中的行结束并不完全相似,COPY FROM 将会抱怨。 857 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE • CSV 格式 这种格式选项被用于导入和导出很多其他程序(例如电子表格)使用的逗号分隔值(CSV)文件格式。不同于 KingbaseES 标准文本格式使用的转义规则,它产生并且识别一般的 CSV 转义机制。 每个记录中的值用 DELIMITER 字符分隔。如果值包含定界符字符、QUOTE 字符、NULL 字符串、一个回车或者换 行字符,那么整个值会被加上 QUOTE 字符作为前缀或者后缀,并且在该值内 QUOTE 字符或者 ESCAPE 字符的任何一 次出现之前放上转义字符。在输出指定列中非 NULL 值时,还可以使用 FORCE_QUOTE 来强制加上引用。 CSV 格式没有标准方式来区分 NULL 值和空字符串。KingbaseES 的 COPY 用引用来处理这种区分工作。NULL 被 按照 NULL 参数字符串输出并且不会被引用,而匹配 NULL 参数字符串的非 NULL``值会被加上引用。例如,使用默 认设置时,\ ``NULL 被写作一个未被引用的空字符串,而一个空字符串数据值会被写成带双引号("")。值的读取 遵循类似的规则。你可以用 FORCE_NOT_NULL 来防止对指定列的 NULL 输入比较。你还可以使用 FORCE_NULL 把带引 用的空值字符串数据值转换成 NULL。 因为反斜线在 CSV 格式中不是一种特殊字符,数据结束标记 \. 也可以作为一个数据值出现。为了避免任何解释 误会,在一行上作为孤项出现的\. 数据值输出时会自动被引用,并且输入时如果被引用,则不会被解释为数据结束 标记。如果正在载入一个由另一个应用创建的文件并且其中具有一个未被引用的列且可能具有 \. 值,你可能需要在 输入文件中引用该值。 注意: CSV 格式中,所有字符都是有意义的。一个被空白或者其他非 DELIMITER 字符围绕的引用值将包括那些字 符。在导入来自用空白填充 CSV 行到固定长度的系统的数据时,这可能会导致错误。如果出现这种情况,在导入数 据到 KingbaseES 之前,你可能需要预处理该 CSV 文件以移除拖尾的空白。 注意: CSV 格式将识别并且产生带有包含嵌入的回车和换行的引用值的 CSV 文件。因此文件并不限于文本格式文件 的每个表行一行的形式。 注意: 很多程序会产生奇怪的甚至偶尔是不合常理的 CSV 文件,因此该文件格式更像是一种习惯而不是标准。因此 你可能会碰到一些无法使用这种机制导入的文件,并且 COPY 也可能产生其他程序无法处理的文件。 • 二进制格式 binary 格式选项导致所有数据被以二进制格式而不是文本格式存储/读取。它比文本和 CSV 格式要快一些,但 是二进制格式文件在不同的机器架构和 KingbaseES 版本之间的可移植性要差些。还有,二进制格式与数据格式非常 相关。例如不能从一个 smallint 列中输出二进制数据并且把它读入到一个 integer 列中,虽然这样做在文本格式 中是可行的。 binary 人间格式由一个文件头、零个或者更多个包含行数据的元组以及一个文件尾构成。头部和数据都以网络 字节序表示。 4. 文件头 文件头由 15 字节的固定域构成,后面跟着一个变长的头部扩展区。固定域有: 858 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE • 签名 11-字节的序列 KBCOPY\n\377\r\n\0 —注意零字节是签名的一个必要的部分(该签名是为了能容易地发现文件 被无法正确处理 8 位字符编码的传输所破坏。这个签名将被行尾翻译过滤器、删除零字节、删除高位或者奇偶 修改等改变)。 • 标志域 32-位整数位掩码,用以表示该文件格式的重要方面。位被编号为从 0 (LSB)到 31(MSB)。注意这个域以网 络字节序存放(最高有效位在前),所有该文件格式中使用的整数域都是这样。16-31 位被保留用来表示严重的 文件格式问题,读取者如果在这个范围内发现预期之外的被设置位,它应该中止。0-15 位被保留用来表示向后 兼容的格式问题,读取者应该简单地略过这个范围内任何预期之外的被设置位。当前只定义了一个标志位,其 他位必须为零:位 16。如果为 1,表示数据中包含 OID;如果为 0,则不包含在 KingbaseES 中不再支持 Oid 系统列,但是格式仍然包含指示器。 • 头部扩展区长度 32-为整数,表示头部剩余部分的以字节计的长度,不包括其本身。当前,这个长度为零,并且其后就紧跟着第 一个元组。未来对该格式的更改可能会允许在头部中表示额外的数据。如果读取者不知道要对头部扩展区数据 做什么,可以安静地跳过它。 头部扩展区域被预期包含一个能自我解释的块的序列。该标志域并不想告诉读取者扩展数据是什么。详细的头部 扩展内容的设计留给后来的发行去做。 这种设计允许向后兼容的头部增加(增加头部扩展块或者设置低位标志位)以及非向后兼容的更改(设置高位标 志位来表示这类更改并且在需要时向扩展区域中增加支持数据)。 5. 元组 每一个元组由一个表示元组中域数量的 16 位整数计数开始(当前,一个表中的所有元组都应该具有相同的计 数,但是这可能不会总是为真)。然后是元组中的每一个域,它是一个 32 位的长度字,后面则跟随着这么多个字节 的域数据(长度字不包括其本身,并且可以是零)。作为一种特殊情况,-1 表示一个 NULL 域值。在 NULL 情况 下,后面不会跟随值字节。 在域之间没有对齐填充或者任何其他额外的数据。 当前,一个二进制格式文件中的所有数据值都被假设为二进制格式(格式代码一)。可以预见未来的扩展可能会 增加一个允许独立指定各列的格式代码的头部域。 要为实际的元组数据决定合适的二进制格式,你应该参考 KingbaseES 源码,特别是用于各列数据类型的 *send 和 *recv 函数(通常可以在源码的 src/backend/utils/adt/目录中找到这些函数)。 如果文件中包含 OID,OID 域会紧跟在域计数字之后。它是一个普通域,但是它没有被包含在域计数中。注 意,oid 系统列在当前版本的 KingbaseES 中不受支持。 6. 文件尾 文件位由一个包含 -1 的 16 位整数字组成。这很容易与一个元组的域计数字区分开。 如果一个域计数字不是 -1 也不是期望的列数,读取者应该报告错误。这提供了一种针对某种数据不同步的额外 检查。 859 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE 14.4 CREATE ACCESS METHOD 用途 CREATE ACCESS METHOD 创建一种新的访问方法。 访问方法名称在数据库中必须唯一。 前置条件 只有超级用户可以定义新的访问方法。 语法 CREATE ACCESS METHOD name TYPE access_method_type HANDLER handler_function 语义 name 要创建的访问方法的名称。 access_method_type 这个子句指定要定义的访问方法的类型。当前只支持 TABLE 和 INDEX。 handler_function handler_function 是一个之前已注册的函数的名称(可能被模式限定),该函数表示要创建的访问 方法。处理器函数必须被声明为接收一个单一的 internal 类型的参数,并且它的返回类型取决于 访问方法的类型:对于 TABLE 访问方法,它必须是 table_am_handler;INDEX 访问方法,必须是 index_am_handler;处理器函数必须实现的 C 级别 API 取决于访问方法的类型。 示例 用处理器函数 heptree_handler 创建一种索引访问方法 heptree: CREATE ACCESS METHOD heptree TYPE INDEX HANDLER heptree_handler; 兼容性 CREATE ACCESS METHOD 是一种 KingbaseES 扩展。 其他 参见DROP ACCESS METHOD , CREATE OPERATOR CLASS , CREATE OPERATOR FAMILY 860 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE 14.5 CREATE AGGREGATE 用途 CREATE AGGREGATE 定义一个新的聚集函数。CREATE OR REPLACE AGGREGATE 将定义新的聚合函数或替换现有定 义。在发布中已经包括了一些基本的和常用的聚集函数,它们的文档请见聚集函数 。如果要定义一个新类型或者需 要一个还没有被提供的聚集函数,那么 CREATE AGGREGATE 就可以被用来提供想要的特性。 在替换现有定义时,参数类型、结果类型和直接参数的数量可能不会更改。而且,新定义必须与旧定义属于同一 类 (普通集合、有序集合或假设集合)。 如果给定了一个模式名(例如 CREATE AGGREGATE myschema.myagg ...),那么该聚集会被创建在指定的模式 中。否则它会被创建在当前模式中。 一个聚集函数需要用它的名称和输入数据类型标识。同一个模式中的两个聚集可以具有相同的名称,只要它们在 不同的输入类型上操作即可。一个聚集的名称和输入数据类型必须与同一模式中的每一个普通函数区分开。这种行为 与普通函数名的重载完全一样(见CREATE FUNCTION )。 一个简单的聚集函数由一个或者多个普通函数组成:一个状态转移函数 sfunc 和一个可选的最终计算函数 ffunc。它们被这样使用: sfunc( internal-state, next-data-values ) ---> next-internal-state ffunc( internal-state ) ---> aggregate-value KingbaseES 创建一个数据类型 “stype“的临时变量来保持聚集的当前内部状态。对每一个输入行,聚集参数值会 被计算并且状态转移函数会被调用,它用当前状态值和新参数值计算一个新的内部状态值。等所有行都被处理完后, 最终函数会被调用一次来计算该聚集的返回值。如果没有最终函数,则最终的状态值会被返回。 一个聚集函数可以提供一个初始条件,即一个用于内部状态值的初始值。它被作为一个类型 text 的值指定并且 存储在数据库中,但是它必须是状态值数据类型的一个常量的合法外部表示。如果没有提供,则状态值从空值开始。 如果状态转移函数被声明为“strict”,那么不能用空值输入来调用它。如果有这种转移函数,聚集将按照下面 的行为执行。带有任何空值的行会被忽略(函数不被调用并且之前的状态值被保持)。如果初始状态值就是空值,那 么碰到第一个没有空值的行时,状态值会被替换成第一个参数值,并且对于每一个后续的没有空值的行都会调用该转 移函数。这对实现 max 这样的聚集很方便。注意只有当 state_data_type 和第一个 “arg_data_type“相同时,这种 行为才可用。当这些类型不同时,你必须提供一个非空初始条件或者使用一个非严格转移函数。 如果状态转移函数不是严格的,那么在碰到每个输入行时都将会调用它,并且它必须自行处理空值输入和空状态 值。这允许聚集的作者完全控制该聚集如何处理空值。 如果最终函数被声明为“strict”,那么当最终状态值为空时将不会调用它,而是自动地返回一个空结果(当 然,这只是严格函数的普通行为)。在任何情况下最终函数都可以返回一个空值。例如,avg 的最终函数会在看到零 个输入行时返回空。 有时候把最终函数声明成不仅采用状态值还采用对应于聚集输入值的额外参数是有用的。这样做的主要原因是, 如果最终函数是多态的,那么状态值的数据类型将不适合于用来确定结果类型。这些额外的参数总是以 NULL 形式 传递(因此使用 FINALFUNC_EXTRA 选项时,最终函数不能是严格的),但尽管如此它们都是合法参数。例如,最终 函数可以利用 get_fn_expr_argtype 来标识当前调用中的实际参数类型。 861 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE 如 用户定义的聚集中所述,一个聚集可以选择支持移动聚集模式。这要求指定 MSFUNC、MINVFUNC 以及 MSTYPE 参数,并且参数 MSSPACE, MFINALFUNC, MFINALFUNC_EXTRA, MFINALFUNC_MODIFY 和 MINITCOND 是可选的。除了 MINVFUNC,这些参数的工作都和对应的不带 M 的简单聚集参数相似,它们定义了定义了包括一个逆向转移函数的聚 集的一种独立实现。 在 参 数 列 表 中 带 有 ORDER BY 的语法会创建一种被称为 有 序 集 聚 集 的 特 殊 聚 集 类 型。 如 果 指 定 了 HYPOTHETICAL,则会创建一个 假想集聚集。这些聚集以依赖排序的方法在排好序的值上操作,因此指定一个输 入排序顺序是调用过程的重要一环。还有,它们可以有直接参数,这类参数只对每次聚集计算一次,而不是对每一个 输入行计算一次。假想集聚集是有序集聚集的一个子类,其中一些直接参数要求在数量和类型上都匹配被聚集的参数 列。这允许这些直接参数的值被当做一个附加的“假想”行被加入到聚集输入行的集合中。 如 用 户 定 义 的 聚 集 中 所 示, 一 个 聚 集 可 以 支 持 部 分 聚 集。 这 要 求 指 定 COMBINEFUNC 参 数。 如 果 state_data_type 为 internal,通常也可以提供 SERIALFUNC 和 DESERIALFUNC 参数,这样可以让并行聚集成 为可能。注意,该聚集还必须被标记为 PARALLEL SAFE 以启用并行聚集。 行为与 MIN 或 MAX 相似的聚集有时可以通过直接查看一个索引而不是扫描每一个输入行来优化。如果这个聚集 可以被这样优化,请通过指定一个排序操作符来指出。基本要求是,该聚集必须得出由该操作符产生的排序顺序中的 第一个元素,换句话说: SELECT agg(col) FROM tab; 必须等价于: SELECT col FROM tab ORDER BY col USING sortop LIMIT 1; 进一步的假定是该聚集忽略空输入,并且当且仅当没有非空输入时它才会返回一个空结果。通常,一种数据类型 的< 操作符是 MIN 的合适的排序操作符,而> 是 MAX 的合适的排序操作符。注意,除非指定的操作符是一个 B-树索 引操作符类的“小于”或者“大于”策略成员,优化将永远不会产生实际效果。 前置条件 要能够创建一个聚集函数,你必须具有参数类型、状态类型和返回类型上的 USAGE 特权,还有在支持函数上的 EXECUTE 特权。 语法 CREATE [ OR REPLACE ] AGGREGATE name ( [ argmode ] [ argname ] arg_data_type [ , ... ] ) ( SFUNC = sfunc, STYPE = state_data_type [ , SSPACE = state_data_size ] [ , FINALFUNC = ffunc ] [ , FINALFUNC_EXTRA ] [ , FINALFUNC_MODIFY = { READ_ONLY | SHAREABLE | READ_WRITE } ] [ , COMBINEFUNC = combinefunc ] [ , SERIALFUNC = serialfunc ] [ , DESERIALFUNC = deserialfunc ] [ , INITCOND = initial_condition ] 862 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE [ , MSFUNC = msfunc ] [ , MINVFUNC = minvfunc ] [ , MSTYPE = mstate_data_type ] [ , MSSPACE = mstate_data_size ] [ , MFINALFUNC = mffunc ] [ , MFINALFUNC_EXTRA ] [ , MFINALFUNC_MODIFY = { READ_ONLY | SHAREABLE | READ_WRITE } ] [ , MINITCOND = minitial_condition ] [ , SORTOP = sort_operator ] [ , PARALLEL = { SAFE | RESTRICTED | UNSAFE } ] ) 863 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE 864 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE CREATE [ OR REPLACE ] AGGREGATE name ( [ [ argmode ] [ argname ] arg_data_type [ , ... ] ] ORDER BY [ argmode ] [ argname ] arg_data_type [ , ... ] ) ( SFUNC = sfunc, STYPE = state_data_type [ , SSPACE = state_data_size ] [ , FINALFUNC = ffunc ] [ , FINALFUNC_EXTRA ] [ , FINALFUNC_MODIFY = { READ_ONLY | SHAREABLE | READ_WRITE } ] [ , INITCOND = initial_condition ] [ , PARALLEL = { SAFE | RESTRICTED | UNSAFE } ] [ , HYPOTHETICAL ] ) 865 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE 或者旧的语法: CREATE [ OR REPLACE ] AGGREGATE name ( BASETYPE = base_type, SFUNC = sfunc, STYPE = state_data_type [ , SSPACE = state_data_size ] [ , FINALFUNC = ffunc ] [ , FINALFUNC_EXTRA ] [ , FINALFUNC_MODIFY = { READ_ONLY | SHAREABLE | READ_WRITE } ] [ , COMBINEFUNC = combinefunc ] [ , SERIALFUNC = serialfunc ] [ , DESERIALFUNC = deserialfunc ] [ , INITCOND = initial_condition ] [ , MSFUNC = msfunc ] [ , MINVFUNC = minvfunc ] [ , MSTYPE = mstate_data_type ] [ , MSSPACE = mstate_data_size ] [ , MFINALFUNC = mffunc ] [ , MFINALFUNC_EXTRA ] [ , MFINALFUNC_MODIFY = { READ_ONLY | SHAREABLE | READ_WRITE } ] [ , MINITCOND = minitial_condition ] [ , SORTOP = sort_operator ] ) 866 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE 语义 name 要创建的聚集函数的名称(可以是模式限定的)。 argmode 一个参数的模式:IN 或者 VARIADIC(聚集函数不支持 OUT 参数)。如果忽略,默认值是 IN。只有最后 867 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE 一个参数能被标记为 VARIADIC。 argname 一个参数的名称。当前这只用于文档的目的。如果被忽略,该参数就没有名称。 arg_data_type 这个聚集函数操作的一个输入数据类型。要创建一个零参数的聚集函数,可以写一个 * 来替代参数说明 的列表(这类聚集的一个例子是 count(*))。 base_type 在 CREATE AGGREGATE 的旧语法中,输入数据类型是由一个 basetype 参数指定而不是写在聚集名之后。 注意这种语法只允许一个输入参数。要用这种语法定义一个零参数的聚集函数,把 basetype 指定为"ANY "(不是 *)。有序集聚集不能用旧语法定义。 sfunc 要为每一个输入行调用的状态转移函数名。对于一个正常的 “N“-参数的聚集函数,sfunc 必须接收 “N“+1 个参数,第一个参数的类型是 state_data_type 而其余的参数匹配该聚集被声明的输入数据类 型。该函数必须返回一个类型为 state_data_type 的值。这个函数会采用当前的状态值以及当前的输入 数据值,并且返回下一个状态值。 对于有序集(包括假想集)聚集,状态转移函数只接收当前的状态值和聚集参数,但无需直接参数。否则 它就和其他转移函数一样了。 state_data_type 聚集的状态值的数据类型。 state_data_size 聚 集 的 状 态 值 的 近 似 平 均 尺 寸 (以 字 节 计)。 如 果 这 个 参 数 被 忽 略 或 者 为 零, 将 使 用 一 个 基 于 state_data_type 的默认估计值。规划器使用这个值来估计一个分组聚集查询所需的内存。只有估 计哈希表能够放在 work_mem 大小的内存中时,规划器才会对这类查询使用哈希聚集。因此,对这个参 数设置大的值会阻止使用哈希聚集。 ffunc 最终函数的名称,该函数在所有输入行都被遍历之后被调用来计算聚集的结果。对于一个常规聚集, 这个函数必须只接受一个类型为 state_data_type 的单一参数。该聚集的返回数据类型被定义为 这个函数的返回类型。如果没有指定 “ffunc“,则结束状态值被用作聚集的结果,并且返回类型为 state_data_type。 对于有序集(包括假想集)聚集,最终函数不仅接收最终状态值,还会接收所有直接参数的值。 如果指定了 FINALFUNC_EXTRA,则除了最终状态值和任何直接参数之外,最终函数还接收额外的对应于 该聚集的常规(聚集)参数的 NULL 值。这主要用于在定义了一个多态聚集时允许正确地决定聚集的结 果类型。 FINALFUNC_MODIFY = { READ_ONLY | SHAREABLE | READ_WRITE } 868 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE 此选项指定最终函数是否为不修改其参数的纯函数。READ_ONLY 表示没有; 其他两个值表示可能会更 改过渡状态值。更多详细信息,参见注解 _ 。默认值是 READ_ONLY,除了排序集聚合之外,其他都是 READ_WRITE。 combinefunc combinefunc 函数可以被有选择地指定以允许聚集函数支持部分聚集。如果提供这个函数,combinefunc 必须组合两个 state_data_type 值,每一个都包含在输入值某个子集上的聚集结果,它会产生一个新的 state_data_type 来表示在两个输入集上的聚集结果。这个函数可以被看做是一个 sfunc,和后者在一个 个体输入行上操作并且把它加到运行聚集状态上不同,这个函数是把另一个聚集状态加到运行状态上。 combinefunc 必须被声明为有两个 state_data_type 参数并且返回一个 state_data_type 值。这个函 数可以有选择性地被标记为“strict”。在被标记的情况下,当任何一个输入状态为空时,将不会调用该 函数,而是把另一个状态当作正确的结果。 对 于 state_data_type 为 internal 的 聚 集 函 数,combinefunc 不能为 strict。 这 种 情 况 下, combinefunc 必须确保正确地处理空状态并且被返回的状态能被恰当地存储在聚集内存上下文中。 serialfunc state_data_type 为 internal 的 一 个 聚 集 函 数 可 以 参 与 到 并 行 聚 集 中, 当 且 仅 当 它 具 有 一 个 serialfunc 函数,该函数必须把聚集状态序列化成一个 bytea 值以传送给另一个进程。这个函数必 须有一个单一的 internal 类型参数并且返回类型 bytea。相应地也需要一个 deserialfunc。 deserialfunc 把一个之前序列化后的聚集状态反序列化为 state_data_type。这个函数必须有两个类型分别为 bytea 和 internal 的参数,并且产生一个类型 internal 的结果(注意:第二个类型为 internal 的参数是无 用的,但是为了类型安全的原因还是要求有该参数)。 initial_condition 状态值的初始设置。这必须是以数据类型 state_data_type 能够接受的形式出现的一个字符串常量。如 果没有指定,状态值会从空值开始。 msfunc 前向状态转移函数的名称,在移动聚集模式中会为每个输入行调用这个函数。它非常像常规的转移函数, 但是它的第一个参数和结果类型是 mstate_data_type,这可能与 state_data_type 不同。 minvfunc 在移动聚集模式中用到的逆向状态转移函数的名称。这个函数与 “msfunc“具有相同的参数和结果类型, 但是它被用于从当前聚集状态中移除一个值,而不是向其中增加一个值。逆向转移函数必须具有和前向状 态转移函数相同的严格性属性。 mstate_data_type 使用移动聚集模式时,用于聚集状态值的数据类型。 mstate_data_size 使用移动聚集模式时,聚集状态值的近似平均尺寸(以字节计)。它的作用和 state_data_size 相同。 869 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE mffunc 使用移动聚集模式时用到的最终函数名称,当所有输入行都被遍历后会调用它来计算聚集的结果。它 的工作和 ffunc 一样,但是它的第一个参数类型是 mstate_data_type 并且额外的空参数要通过书写 MFINALFUNC_EXTRA 来指定。mffunc 或者 mstate_data_type 决定的聚集结果类型必须匹配由聚集的常 规实现所确定的类型。 MFINALFUNC_MODIFY = { READ_ONLY | SHAREABLE | READ_WRITE } 这个选项类似于 FINALFUNC_MODIFY,但是它描述了移动-聚合最终函数的行为。 minitial_condition 使用移动聚集模式时,状态值的初始设置。它的作用和 initial_condition 一样。 sort_operator 一个 MIN- 类或者 MAX-类聚集的相关排序操作符。这只是一个操作符名称(可能被模式限定)。这个操作 符被假定为具有和该聚集(必须是一个单一参数的常规聚集)相同的输入数据类型。 PARALLEL = { SAFE | RESTRICTED | UNSAFE } PARALLEL SAFE、PARALLEL RESTRICTED 和 PARALLEL UNSAFE 的含义和CREATE FUNCTION 中的相 同。如果一个聚集被标记为 PARALLEL UNSAFE(默认)或者 PARALLEL RESTRICTED,将不会考虑将它并 行化。注意规划器不会参考聚集的支持函数的并行安全性标记,它只会考虑聚集本身的这类标记。 HYPOTHETICAL 只用于有序集聚集,这个标志指定聚集参数会被根据假想集聚集的要求进行处理:即后面的直接参数必须 匹配聚集(WITHIN GROUP)参数的数据类型。HYPOTHETICAL 标志在运行时没有任何效果,它只在命令解 析期间对确定数据类型和聚集参数的排序规则有用。 CREATE AGGREGATE 的参数可以用任意顺序书写,而无需遵照以上说明的顺序。 示例 见 用户定义的聚集。 兼容性 CREATE AGGREGATE 是一种 KingbaseES 的语言扩展。SQL 标准没有提供用户定义的聚集函数。 其他 在指定支持函数名的参数中,如果需要你可以写一个模式名,例如 SFUNC = public.sum。在这里不能写参数类 型—支持函数的参数类型是根据其他参数决定的。 通常,KingbaseES 函数应该是不修改输入值的真函数。但是,当在聚合上下文中使用聚合转换函数时,允许对 其转换状态参数进行欺骗和修改。与每次复制转换状态相比,这可以提供大量的性能优势。 同样地,虽然聚合最终函数通常不希望修改其输入值,但有时避免修改转换状态参数是不切实际的。必须使用 FINALFUNC_MODIFY 参数声明这种行为。READ_WRITE 值表示最后一个函数以未指定的方式修改转换状态。此值防止将 聚合用作窗口函数,也防止将共享相同输入值和转换函数的聚合调用的转换状态合并。SHAREABLE 值表示在最后一个 函数之后不能应用转换函数,但是可以对结束的转换状态值执行多个最终函数调用。此值阻止将聚合用作窗口函数, 870 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE 但允许合并转换状态。(也就是说,这里的优化不是重复地应用相同的最终函数,而是对相同的结束过渡状态值应用 不同的最终函数。这是允许的,只要最后一个函数没有被标记为 READ_WRITE。) 如 果 一 个 聚 集 支 持 移 动 聚 集 模 式, 当 该 聚 集 被 用 于 一 个 具 有 移 动 帧 起 点 (即 帧 起 点 模 式 不 是 UNBOUNDED PRECEDING)的窗口函数时,它将提升计算效率。在概念上,当从底部进入窗口帧时前向转移函数会把输入值加 到聚集的状态上,而逆向转移函数会在从顶部离开帧时再次移除输入值。因此,当值被移除时,它们总是按照被加入 的相同顺序被移除。无论何时调用逆向转移函数,它都将因此接收最近增加但是还未被移除的参数值。逆向转移函数 可以假定在它移除最旧的行之后至少有一行保留在当前状态中(当情况不是这样时,窗口函数机制会简单地开始一次 新的聚集,而不是使用逆向转移函数)。 用于移动聚集模式的前向转移函数不允许返回 NULL 作为新的状态值。如果逆向转移函数返回 NULL,这表明 逆向函数无法为这个特定的输入逆转状态计算,并且该聚集计算因此必须从当前帧的开始位置“从零开始”重新被计 算。在一些少见的情况中,逆转正在计算中的状态值是不切实际的,这种习惯可以允许在此类情形中使用移动聚集模 式。 如果没有提供移动聚集实现,聚集仍然可以被用于移动帧,但是只要帧起点移动,KingbaseES 都将会重新计算 整个聚集。注意不管聚集有没有支持移动聚集模式,KingbaseES 都能处理一个移动帧结束而无需重新计算,这可以 通过增加新值到聚集状态完成。这就是为什么使用聚合作为窗口函数要求最后的函数是只读的: 它不会破坏聚集的状 态值,这样即使已经为一组帧边界得到了一个聚集结果值,该聚集也能继续下去。 有序集聚集的语法允许为最后一个直接参数以及最后一个聚集(WITHIN GROUP)参数指定 VARIADIC。但是, 当前的实现限制只能以两种方式使用 VARIADIC。第一种,有续集聚集只能使用 VARIADIC "any",不能使用其他 可变数组类型。第二种,如果最后一个直接参数是 VARIADIC "any",那么只能有一个聚集参数并且它也必须是 VARIADIC "any"(在系统目录中使用的表示中,这两个参数会被合并为一个单一的 VARIADIC "any" 项,因为 sys_proc 无法表示具有超过一个 VARIADIC 参数的函数)。如果该聚集是一个假想集聚集,匹配 VARIADIC "any" 参数的直接参数就是假想参数。任何在前面的参数表示额外的直接参数,它们不被约束为需要匹配聚集参数。 当前,有序集聚集无须支持移动聚集模式,因为它们不能被用作窗口函数。 部分(包括并行)聚集当前不被有续集聚集支持。还有,包括 DISTINCT 或者 ORDER BY 子句的聚集调用将不会 使用部分聚集,因为在部分聚集时无法支持那些语义。 14.6 CREATE CAST 用途 CREATE CAST 定义一种新的造型。一种造型指定如何在两种数据类型之间执行转换。例如, SELECT CAST(42 AS float8); 通过调用一个之前指定的函数(这种情况中是 float8(int4))把整型常量 42 转换成类型 float8(如果没有定 义合适的造型,该转换会失败)。 两种类型可以是二进制可强制,这表示该转换可以被“免费”执行而不用调用任何函数。这要求相应的值使用同 样的内部表示。例如,类型 text 和 varchar 在双向都是二进制可强制的。二进制可强制性并不必是一种对称关系。 871 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE 例如,在当前实现中从 xml 到 text 的造型可以被免费执行,但是反向则需要一个函数来执行至少一次语法检查(两 种在双向都二进制值兼容的类型也被称作二进制兼容)。 通过使用 WITH INOUT 语法,你可以把一种造型定义成 I/O 转换造型。一种 I/O 转换造型执行时,会调用源数 据类型的输出函数,并且把结果字符串传递给目标数据类型的输入函数。在很多常见情况中,这种特性避免了为转换 单独定义一个造型函数。一种 I/O 转换造型表现得和一个常规的基于函数的造型相同,只是实现不同而已。 默认情况下,只有一次显式造型请求才会调用造型,形式是 CAST(x AS typename) or x :: typename。 如果造型被标记为 AS ASSIGNMENT,那么在为一个目标数据类型的列赋值时会隐式地调用它。例如,假设 foo. f1 是一个类型 text 的列,那么如果从类型 integer 到类型 text 的造型被标记为 AS ASSIGNMENT,则: INSERT INTO foo (f1) VALUES (42); 将被允许,否则不会允许(我们通常使用赋值造型来描述此类造型)。 如果造型被标记为 AS IMPLICIT,那么可以在任何上下文中隐式地调用它,无论是赋值还是在一个表达式内部 (我们通常用术语隐式造型来描述这类造型)。例如,考虑这个查询: SELECT 2 + 4.0; 解析器初始会把常量分别标记为类型 integer 和 numeric。在系统目录中没有 integer + numeric 操作符, 但是有一个 numeric + numeric 操作符。因此,如果有一种可用的从 integer 到 numeric 的造型且被标记为 AS IMPLICIT —实际上确实有—该查询将会成功。解析器将应用该隐式造型并且解决该查询,就好像它被写成: SELECT CAST ( 2 AS numeric ) + 4.0; 现在,系统目录也提供一种从 numeric 到 integer``的造型。如果这种造型被标记为\ ``AS IMPLICIT —实际 上并没有—那么解析器将面临选择:是用前面介绍的过程,还是把 numeric 常量造型成 integer 并且应用 integer + integer 操作符。由于缺少哪种选择更好的知识,解析器会放弃并且说明查询有歧义。我们能告诉解析器把一个混 合了 numeric 和 integer 的表达式解析成 numeric 更好的方法就是只让这两种造型中的一个是隐式的,没有有关 于此的内建知识。 对标记造型为隐式持保守态度是明智的。过多的隐式造型路径可能导致 KingbaseES 以令人吃惊的方式解释命 令,或者由于有多种可能解释而根本无法解析命令。一种好的经验是让一种造型只对于同一种一般类型分类中的类型 间的信息保持转换隐式可调用。例如,从 int2 到 int4 的造型可以被合理地标记为隐式,但是从 float8 到 int4 的造型可能应该只能在赋值时使用。跨类型分类的造型(如 text 到 int4)最好只被用于显式使用。 注意: 有时为了可用性或者标准兼容的原因,有必要提供在一个类型集合之间的多种隐式造型,这会导致上述不可避 免的歧义。解析器还有一招基于 类型分类和优先类型的后手,它能帮助提供这类情况下预期的行为。详见CREATE TYPE 。 前置条件 要创建一种造型,你必须拥有源数据类型和目标数据类型并且具有在其他类型上的 USAGE 特权。要创建一种二 进制可强制造型,你必须是一个超级用户(这种限制是因为错误的二进制可强制造型转换很容易让服务器崩溃)。 872 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE 语法 CREATE CAST (source_type AS target_type) WITH FUNCTION function_name [ (argument_type [, ...]) ] [ AS ASSIGNMENT | AS IMPLICIT ] CREATE CAST (source_type AS target_type) WITHOUT FUNCTION [ AS ASSIGNMENT | AS IMPLICIT ] CREATE CAST (source_type AS target_type) WITH INOUT [ AS ASSIGNMENT | AS IMPLICIT ] 语义 source_type 该造型的源数据类型的名称。 target_type 该造型的目标数据类型的名称。 function_name [( argument_type [, ...])] 被用于执行该造型的函数。函数名称可以用模式限定。如果没有被限定,将在模式搜索路径中查找该函 数。函数的结果数据类型必须是该造型的目标数据类型。它的参数讨论如下。如果没有指定参数列表,则 该函数名称在其模式中必须是唯一的。 WITHOUT FUNCTION 指示源类型可以二进制强制到目标类型,因此执行该造型不需要函数。 WITH INOUT 指示该造型是一种 I/O 转换造型,执行需要调用源数据类型的输出函数,并且把结果字符串传递给目标数 据类型的输入函数。 AS ASSIGNMENT 指示该造型可以在赋值的情况下被隐式调用。 AS IMPLICIT 指示该造型可以在任何上下文中被隐式调用。 造型实现函数可以具有 1 到 3 个参数。第一个参数类型必须等于源类型或者能从源类型二进制强制得到。第 二个参数(如果存在)必须是类型 integer,它接收与目标类型相关联的类型修饰符,如果没有类型修饰符,它会 收到-1。第三个参数(如果存在)必须是类型 boolean,如果该造型是一种显式造型,它会收到 true,否则会收到 false(奇怪地是,SQL 标准在某些情况中对显式和隐式造型要求不同的行为。这个参数被提供给必须实现这类造型 的函数。不推荐在设计自己的数据类型时用它)。 873 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE 一个造型函数的返回类型必须等于目标类型或者能二进制强制到目标类型。 通常,强制转换必须具有不同的源和目标数据类型。但是,如果它有一个具有多个参数的强制转换实现函数,则 允许声明具有相同源和目标类型的强制转换。这用于表示系统编目中特定于类型的长度强制函数。指定的函数用于将 类型的值强制转换为其第二个参数给出的类型修饰符值。 当强制类型转换具有不同的源和目标类型,且函数需要多个参数时,它支持从一种类型转换为另一种类型,并在 单个步骤中应用长度强制转换。当没有这样的条目可用时,强制转换使用类型修饰符的类型涉及两个转换步骤,一个 在数据类型之间转换,另一个应用修饰符。 向域类型强制转换或从域类型强制转换目前没有效果。向域或从域强制转换使用与其基础类型关联的强制转换。 示例 要使用函数 int4(bigint) 创建一种从类型 “bigint“到类型 int4 的赋值造型: CREATE CAST (bigint AS int4) WITH FUNCTION int4(bigint) AS ASSIGNMENT; (在系统中这种造型已经被预定义)。 兼容性 CREATE CAST 命令符合 SQL 标准,但是 SQL 没有为二进制可强制类型或者实现函数的额外参数做好准备。AS IMPLICIT 也是一种 KingbaseES 扩展。 其他 使用DROP CAST 移除用户定义的造型。 记住如果你想要能够双向转换类型,你需要在两个方向上都显式声明造型。 通常没有必要创建用户定义类型和标准字符串类型(text、varchar 和 char(n),以及被定义在字符串分类中的 用户定义类型)之间的造型。KingbaseES 会为它们提供自动的 I/O 转换造型。到字符串类型的自动造型被当做赋值 造型,而字符串类型作为源的自动造型只能是显式的。通过声明你自己的造型来替换自动造型可以覆盖这种行为,但 是这样做的唯一原因是你想让该转换比标准的设置更容易被调用。另一种可能的原因是你想让该转换的行为与该类型 的 I/O 函数不同,但这种原因足够令人感到意外,你应该考虑再三它是不是个好主意(确实有少量内建类型对转换具 有不同的行为,绝大部分是因为 SQL 标准的要求)。 虽然不必要,推荐你继续遵循这种在目标数据类型后面命名造型实现函数的习惯。很多用户习惯于能够使用一种 函数风格的记法来造型数据类型,即 typename( x )。这种记法正好是对造型实现函数的调用,这里它没有被作为造 型特殊对待。如果你的转换函数没有被指定支持这种习惯,那么你的用户会觉得意外。由于 KingbaseES 允许用不同 的参数类型重载同一个函数名,因此存在多个从不同类型到同一目标类型的同名转换函数并不困难。 注意: 实际上前一段过于简化了:有两种情况中一个函数调用结构在没有被匹配到一个实际函数时将被当作一次造型 请求。如果函数调用 name( x ) 没有正好匹配任何现有函数,但 name 是一种数据类型的名称并且 sys_cast 提供了 一种从 x 的类型到这种类型的二进制可强制造型,那么该调用将被翻译为一次二进制可强制造型。通过这种例外, 二进制可强制造型能够以函数语法调用,即便没有该函数。同样的,如果没有 sys_cast 项,但是该造型是要造型到 一种字符串类型或者是要从一种字符串类型造型,调用将被翻译成一次 I/O 转换造型。这种例外允许以函数语法调用 I/O 转换造型。 874 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE 注意: 还有一种例外中的例外:从组合类型到字符串类型的 I/O 转换造型不能使用函数语法调用,而必须被写成显 式造型语法(CAST 或者 :: 记号)。增加这种例外是因为在引入了自动提供的 I/O 转换造型之后,在想要引用一个 函数或者列时太容易意外地调用这种造型。 14.7 CREATE COLLATION 用途 CREATE COLLATION 使用指定的操作系统区域设置或者复制一个现有的排序规则来定义新的排序规则。 前置条件 要创建一种排序规则,你必须拥有目标模式上的 CREATE 特权。 语法 CREATE COLLATION [ IF NOT EXISTS ] name ( [ LOCALE = locale, ] [ LC_COLLATE = lc_collate, ] [ LC_CTYPE = lc_ctype, ] [ PROVIDER = provider, ] [ DETERMINISTIC = boolean, ] [ VERSION = version ] ) CREATE COLLATION [ IF NOT EXISTS ] name FROM existing_collation 875 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE 语义 IF NOT EXISTS 如果已经存在了同名的排序规则,则不要抛出错误。在这种情况下发出一个通知。请注意,不保证已经存 在的排序规则与要创建的这个类似。 name 排序规则的名字,可以被模式限定。如果没有用模式限定,该排序规则会被定义在当前模式中。排序规则 名称在其所处的模式中必须唯一(系统目录可以为其他编码包含具有相同名称的排序规则,但数据库编码 不匹配时它们会被忽略)。 locale 这是一种一次设置 LC_COLLATE 和 LC_CTYPE 的快捷方式。如果你指定它,你就不能指定那两个参数。 lc_collate 为 LC_COLLATE 区域分类使用指定的操作系统区域。 lc_ctype 为 LC_CTYPE 区域分类使用指定的操作系统区域。 provider 指定用于与此排序规则相关的区域服务的提供程序。可能的值是:icu、libc。默认是 libc。可用的选 择取决于操作系统和构建选项。 DETERMINISTIC 指定排序规则是否应使用确定性比较。默认值为 true。确定性比较认为那些在字节上不相等的字符串是不 相等的,即使它们在逻辑上被比较认为相等。KingbaseES 通过字节比较打破了这种联系。不确定的比较 可能使排序规则不区分大小写或不区分上下文。为此,您需要选择一个适当的 LC_COLLATE 设置并且设置 此处的排序规则为不确定。 不确定的排序仅由 ICU 提供者支持。 version 指定使用该排序规则存储的版本字符串。通常忽略该选项,这会导致版本从操作系统提供的排序规则实际 版本中计算出来。此选项旨在供 sys_upgrade 用于复制现有安装中的版本。 ALTER COLLATION 获取如何处理排序规则版本错误匹配。 existing_collation 要复制的一种现有的排序规则的名称。新的排序规则将和现有的具有同样的属性,但是它是一个独立的对 象。 876 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE 示例 从操作系统区域 fr_FR.utf8 创建一种排序规则(假定当前数据库编码是 UTF8): CREATE COLLATION french (locale = 'fr_FR.utf8'); 使用 German phone book 排序顺序使用 ICU 提供程序创建排序规则: CREATE COLLATION german_phonebook (provider = icu, locale = 'de-u-co-phonebk'); 从一个现有的排序规则创建一个新的排序规则: CREATE COLLATION german FROM "de_DE"; 能在应用中使用与操作系统无关的排序规则名称就很方便了。 兼容性 在 SQL 标准中有一个 CREATE COLLATION 语句,但是它被限制为只能复制一个现有的排序规则。创建新排序规 则的语法是一种 KingbaseES 扩展。 其他 CREATE COLLATION 需要一个 SHARE ROW EXCLUSIVE 锁, 在 sys_collation 系统目录中这是自我矛盾的„ 所以一 次只能运行一个 CREATE COLLATION 命令。 使用 DROP COLLATION 可移除用户定义的排序规则。 关于如何创建排序规则的更多信息可见 排序规则支持。 使用 libc 排序规则提供程序时,语言环境必须适用于当前的数据库编码。有关精确的规则,请参见CREATE DATABASE 。 14.8 CREATE CONTEXT 用途 CREATE CONTEXT 为 context 创建 namespace(一组应用程序定义的属性,用于验证和保护应用程序)。将 namespace 与用来设置 context 的包相关联。 可以使用 DBMS_SESSION.SET_CONTEXT 程序在关联包中设置 context 的 key-value。可在 dbms_session 中了解有关 DBMS_SESSION 包(context 中 key-value 增删改均通过该系统包)的信息。namespace 中的 key-value 只允许会话级访问,即只有设置其属性值的会话才可以访问该值,其他会话访问该属性值都为空。 可以在 DBA_OBJECTS 表中找到该上下文信息。 动态视图 V$CONTEXT 可显示当前会话所有 context 的 namespace、key 和 value。 前置条件 无 877 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE 语法 CREATE [OR REPLACE] CONTEXT namespace USING [schema.] packagename 语义 OR REPLACE 用不同的包对已有 context 重新定义。 namespace 指定 context 的名称。Namespace 始终存储在 sys 模式中。 schema 指定模式下的包,如忽略,则使用当前模式. packagename 指定在 namespace 下为用户会话设置或重置 context 中 key-value 的 PL/SQL 包。 示例 创建一个名为 context_test 的 context,关联包为 package_test: CREATE CONTEXT context_test USING package_test; 兼容性 CREATE CONTEXT 是 KingbaseES 的一种语言扩展。兼容 Oracle 重定义上下文命名空间语法。 其他 无。 14.9 CREATE CONVERSION 用途 CREATE CONVERSION 定义一种字符集编码间新的转换。还有,被标记为 DEFAULT 的转换将被自动地用于客户端 和服务器之间的编码转换。为了这个目的,必须定义两个转换(从编码 A 到 B 以及从编码 B 到 A)。 前置条件 要创建一个转换,你必须拥有该函数上的 EXECUTE 特权以及目标模式上的 CREATE 特权。 语法 878 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE CREATE [ DEFAULT ] CONVERSION name FOR source_encoding TO dest_encoding FROM function_name 语义 DEFAULT DEFAULT 子句表示这个转换是从源编码到目标编码的默认转换。在一个模式中对于每一个编码对,只应该 有一个默认转换。 name 转换的名称,可以被模式限定。如果没有被模式限定,该转换被定义在当前模式中。在一个模式中,转换 名称必须唯一。 source_encoding 源编码名称。 dest_encoding 目标编码名称。 function_name 被用来执行转换的函数。函数名可以被模式限定。如果没有,将在路径中查找该函数。 该函数必须具有一下的特征: conv_proc( integer, -- 源编码 ID integer, -- 目标编码 ID cstring, -- 源字符串(空值终止的 C 字符串) internal, -- 目标(用一个空值终止的 C 字符串填充) integer -- 源字符串长度 ) RETURNS void; 示例 使用 myfunc 创建一个从编码 UTF8 到 LATIN1 的转换: CREATE CONVERSION myconv FOR 'UTF8' TO 'LATIN1' FROM myfunc; 兼容性 879 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE CREATE CONVERSION 是一种 KingbaseES 扩展。在 SQL 标准中没有 CREATE CONVERSION 语句,但是有一个目 的和语法都类似的 CREATE TRANSLATION 语句。 其他 使用 DROP CONVERSION 可以移除用户定义的转换。 创建转换所要求的特权可能在未来的发行中被更改。 14.10 CREATE DATABASE 用途 CREATE DATABASE 创建一个新的 KingbaseES 数据库。默认情况下,新数据库是通过克隆标准系统数据库 template1 创建的。可以通过 TEMPLATE name 指定一个不同的模板数据库。特别地,通过写 TEMPLATE template0 你可以创建一个干净的数据库,它将只包含你的 KingbaseES 版本所预定义的标准对象。如果你希望避免拷贝任何可 能被加入到 template1 中的本地安装对象,这将有所帮助。 前置条件 要创建一个数据库,你必须是一个超级用户或者拥有 CREATEDB 权限。见CREATE USER 。 语法 CREATE DATABASE name [ [ WITH ] [ OWNER [=] user_name ] [ TEMPLATE [=] template ] [ ENCODING [=] encoding ] [ LC_COLLATE [=] lc_collate ] [ LC_CTYPE [=] lc_ctype ] [ TABLESPACE [=] tablespace_name ] [ ALLOW_CONNECTIONS [=] allowconn ] [ CONNECTION LIMIT [=] connlimit ] [ IS_TEMPLATE [=] istemplate ] ] 语义 name 要创建的数据库名。 user_name 新数据库所有者的名字,或者用 DEFAULT 来使用默认值(即,执行该命令的用户)。要创建一个被另一 个角色拥有的数据库,你必须是该角色的一个直接或间接成员,或者是一个超级用户。 880 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE template 创建新数据库使用的模板数据库的名字,或者用 DEFAULT 来使用默认模板(template1)。 encoding 要在新数据库中使用的字符集编码。指定一个字符串常量(例如'SQL_ASCII'),或者一个整数编码编 号,或者 DEFAULT 来使用默认的编码(即,模板数据库的编码)。KingbaseES 服务器所支持的字符集在 字符集支持中描述。附加限制见下文。 lc_collate 要在新数据库中使用的排序规则顺序(LC_COLLATE)。这会影响应用到字符串的排序顺序,例如在带 ORDER BY 的查询中,以及文本列上索引所使用的顺序。默认是使用模板数据库的排序规则顺序。附加 限制见下文。 lc_ctype 要在新数据库中使用的字符分类(LC_CTYPE)。这会影响字符的类别,如小写、大写和数字。默认是使 用模板数据库的字符分类。附加限制见下文。 tablespace_name 将与新数据库相关联的表空间名称,或者 DEFAULT 来使用模板数据库的表空间。这个表空间将是在这个 数据库中创建的对象的表空间。详见CREATE TABLESPACE 。 allowconn 如果为假,则没有人能连接到这个数据库。默认为真,表示允许连接(除了被其他机制约束以外,例如 GRANT/REVOKE CONNECT)。 connlimit 这个数据库允许多少并发连接。-1 (默认值)表示没有限制。 istemplate 如果为真,则任何具有 CREATEDB 特权的用户都可以从这个数据库克隆。如果为假(默认),则只有超级 用户或者该数据库的拥有者可以克隆它。 可选的参数可以被写成任何顺序,不用按照上面说明的顺序。 示例 要创建一个新数据库: CREATE DATABASE lusiadas; 要在一个默认表空间 salesspace 中创建一个被用户 salesapp 拥有的新数据库 sales: CREATE DATABASE sales OWNER salesapp TABLESPACE salesspace; 要用不同的语言环境创建数据库 music: 881 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE CREATE DATABASE music LC_COLLATE 'sv_SE.utf8' LC_CTYPE 'sv_SE.utf8' TEMPLATE template0; 在这个例子中,如果指定的语言环境与 template1 中的语言环境不同,则需要 TEMPLATE template0 子 句。(如果不是,则明确指定区域设置是多余的。) 要用不同的语言环境和不同的字符集编码创建数据库 music2: CREATE DATABASE music2 LC_COLLATE 'sv_SE.iso885915' LC_CTYPE 'sv_SE.iso885915' ENCODING LATIN9 TEMPLATE template0; 指定的区域设置和编码设置必须匹配,否则会报告错误。 请注意,区域名称是特定于操作系统的,因此上述命令可能无法在任何地方以相同的方式工作。 兼容性 在 SQL 标准中没有 CREATE DATABASE 语句。数据库等效于目录,而目录的创建由实现定义。 其他 CREATE DATABASE 不能在一个事务块内被执行。 带有一行“不能初始化数据库目录”的错误大部分与在数据目录上权限不足、磁盘满或其他文件系统问题有关。 使用DROP DATABASE 移除一个数据库。 程序 createdb 是这个命令的一个包装器程序,为了使用方便而提供。 不会从模板数据库中复制数据库层面的配置参数(通过ALTER DATABASE 设置)。 尽管可以通过指定一个数据库作为模板来从其中而不是 template1 复制,这(还)不是“COPY DATABASE”功 能的一般目的。主要的限制是在模板数据库被拷贝期间其他会话不能连接到它。如果 CREATE DATABASE 启动时还存 在任何其他连接,它将失败。否则,到模板数据库的新连接将被挡在外面直到 CREATE DATABASE 完成。详见 模板数 据库。 为新数据库指定的字符集编码必须与选定的区域设置(LC_COLLATE 和 LC_CTYPE)相兼容。如果区域是 C(或 者等效的 POSIX),那么所有编码都被允许,但是对于其他区域设置只有一种编码能正确工作(但是,在 Windows 上 UTF-8 编码能够与任何区域一起使用)。CREATE DATABASE 将允许超级用户指定 SQL_ASCII 编码而不管区域设 置,但是这种选择已被废弃并且可能在数据与数据库中存储的区域不是编码兼容时让字符串函数行为失当。 编码和区域设置必须匹配模板数据的编码和区域,除非 template0 被用作模板。这是因为其他数据库可能包含 不匹配指定编码的数据,或者可能包含排序顺序受 LC_COLLATE 和 LC_CTYPE 影响的索引。拷贝这种数据将导致一个 由于该新设置损坏的数据库。但是,template0 是不会含有任何可能被影响的数据或索引的。 CONNECTION LIMIT 选项大概是唯一会被强制的,如果两个新会话在大约同一时间开始并且那时该数据库只剩有 一个连接“槽”,可能两者都会失败。还有,该限制对超级用户或后台工作进程无效。 882 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE 14.11 CREATE DATABASE LINK 用途 CREATE DATABASE LINK 创建一个新的 database link 对象。 用户在创建 database link 对象时需要指定连接信息,包括远程数据库网络地址、端口、数据库名称、用户名和 密码,具体需要提供哪些信息会因为不同数据库存在差异。 前置条件 需将 kdb_database_link 加入 shared_preload_libraries 中并重启数据库。 语法 CREATE [PUBLIC] DATABASE LINK dblink CONNECT TO user IDENTIFIED BY password USING {(connect_string) | config_tag }; 语义 PUBLIC 指定 PUBLIC 创建公有 dblink 对象,所有用户都可以访问公有 dblink 对象。公有 dblink 是创建在 PUBLIC 模式下面的。未指定 PUBLIC 时创建私有 dblink,不可在 PUBLIC 模式下创建私有 dblink。 dblink 指定要创建的数据库链接的名称,同一个模式下的 dblink 不能重名。 user IDENTIFIED BY password 指定远端数据库的用户名和密码。 connect_string 配置连接串信息,connect_string 用来提供用于连接到远程数据库的信息。 config_tag 配置文件标签名, 用于指明配置文件(sys_database_link.conf)中的一项, 从而通过配置文件获取用于建 立数据库连接的远程数据库的网络地址、端口以及数据库名称。 示例 创建一个到 Oracle 数据库的数据库连接,它可以被所有数据库用户使用: 883 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE CREATE PUBLIC DATABASE LINK mylink CONNECT TO 'SYSTEM' IDENTIFIED BY 'password' USING 'ORADB'; 创建一个到 Oracle 数据库的数据库连接,直接指定连接串信息: CREATE PUBLIC DATABASE LINK mylink CONNECT TO 'SYSTEM' IDENTIFIED BY 'password' USING (DriverName='Oracle ODBC Driver', Host='192.168.0.1', Port=1521, Dbname='TEST', DbType='Oracle'); 其他 1. 在配置文件中的格式如下: [名称] DriverName= 连接驱动名称。 Host= 远程数据库网络地址。 Port= 远程数据库服务端口。 Dbname= 远程数据库名称。 DbType= 远程数据库类型。 DbType 支持 Oracle,KingbaseES,Postgres,SQLServer 四种数据库类型。 DriverName 为兼容使用老版本 KingbaseES 的程序所保留的参数,目前为可选参数。 2. 使用该功能时,需将 kdb_database_link 加入 shared_preload_libraries 中。 3. 查询外部数据库时,需创建对应的数据库插件,如: kingbase_fdw 、oracle_fdw 、tds_fdw 。 14.12 CREATE DIRECTORY 用途 在数据库中创建并管理管理服务器端的文件系统。可以让用户在数据库中灵活地对文件进行读写操作。SQL 和 PLSQL 编程时可以使用 directory 名称,而不用硬编码操作系统级文件目录。 CREATE OR REPLACE DIRECTORY 与之相似,但是如果已经存在一个同名目录,该目录会被替换。 目录只能创建在 public 模式下(例如 CREATE DIRECTORY PUBLIC.dir_name ...),PUBLIC 可以省略,目录 默认会创建在 public 模式下,指定其他模式会报错。 前置条件 只有 superuser 在数据库中创建并管理管理服务器端的文件系统。 语法 CREATE [ OR REPLACE ] DIRECTORY (public.)dir_name AS 'path_name' 884 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE 语义 dir_name 要创建的目录的名字(可以指定为 public 模式,默认为 public。)。 'path_name' 指向的文件路径,创建时不检查文件路径有效性,所以需要用户仔细设置。 示例 使用DROP DIRECTORY 语句删除目录。 创建目录: create directory dir1 as 'document'; CREATE DIRECTORY test=# select * from dba_directories; owner | directory_name | directory_path | origin_con_id -------+----------------+----------------+--------------ybli | dir1 | document | 0 可指定模式为 public: create directory public.dir2 as 'document'; CREATE DIRECTORY test=# select * from dba_directories; owner | directory_name | directory_path | origin_con_id -------+----------------+----------------+--------------ybli | dir2 | document | 0 ybli | dir1 | document | 0 兼容性 CREATE DIRECTORY 是 KingbaseES 的一种语言扩展。兼容 Oracle directory 语法。 14.13 CREATE DOMAIN 用途 CREATE DOMAIN 创建一个新的域。域本质上是一种带有可选约束(在允许的值集合上的限制)的数据类型。定义 一个域的用户将成为它的拥有者。 885 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE 如果给定一个模式名(例如 CREATE DOMAIN myschema.mydomain ...),那么域将被创建在该指定的模式中。 否则它会被创建在当前模式中。域的名称在其模式中所有的类型和域之间必须保持唯一。 域主要被用于把字段上的常用约束抽象到一个单一的位置以便维护。例如,几个表可能都包含电子邮件地址列, 而且都要求相同的 CHECK 约束来验证地址的语法。可以为此定义一个域,而不是在每个表上都单独设置一个约束。 前置条件 要创建一个域,你必须在其底层类型上拥有 USAGE 特权。 语法 CREATE DOMAIN name [ AS ] data_type [ COLLATE collation ] [ DEFAULT expression ] [ constraint [ ... ] ] 其中 constraint 是: [ CONSTRAINT constraint_name ] { NOT NULL | NULL | CHECK (expression) } 语义 name 要被创建的域的名称(可以被模式限定)。 data_type 域的底层数据类型。可以包括数组指示符。 collation 用于该域的可选的排序规则。如果没有指定排序规则,将使用底层数据类型的默认排序规则。如果指定了 COLLATE,底层类型必须是可排序的。 886 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE DEFAULT expression DEFAULT 子句为该域数据类型的列指定一个默认值。该值是任何没有变量的表达式(但不允许子查询)。 默认值表达式的数据类型必须匹配域的数据类型。如果没有指定默认值,那么默认值就是空值。 默认值表达式将被用在任何没有指定列值的插入操作中。如果为一个特定列定义了默认值,它会覆盖与域 相关的默认值。继而,域默认值会覆盖任何与底层数据类型相关的默认值。 CONSTRAINT constraint_name 一个约束的名称(可选)。如果没有指定,系统会生成一个名称。 NOT NULL 这个域的值通常不能为空值(但是看看下面的注释)。 NULL 这个域的值允许为空值。这是默认值。 这个子句只是为了与非标准 SQL 数据库相兼容而设计。在新的应用中不鼓励使用它。 CHECK (expression) CHECK 子句指定该域的值必须满足的完整性约束。每一个约束必须是一个产生布尔结果的表达式。它应该 使用关键词 VALUE 来引用要被测试的值。计算为 TRUE 或者 UNKNOWN 的表达式成功。如果该表达式 产生一个 FALSE 结果,会报告一个错误并且该值不允许被转换成该域类型。 当前,CHECK 表达式不能包含子查询,也不能引用除 VALUE 之外的其他变量。 当一个域有多个 CHECK 约束,将按照其名字的字母顺序测试它们(V8R3 版本之前的 KingbaseES 不遵循 任何用于 CHECK 约束的特定触发顺序)。 示例 这个例子创建 us_postal_code 数据类型并且把它用在一个表定义中。一个正则表达式被用来验证值是否看起来 像一个合法的 US 邮政编码: CREATE DOMAIN us_postal_code AS TEXT CHECK( VALUE ~ '^\d{5}$' OR VALUE ~ '^\d{5}-\d{4}$' ); CREATE TABLE us_snail_addy ( address_id SERIAL PRIMARY KEY, street1 TEXT NOT NULL, street2 TEXT, street3 TEXT, city TEXT NOT NULL, postal us_postal_code NOT NULL ); 887 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE 其他 在把一个值转换成域类型时会检查域约束(特别是 NOT NULL)。即使有一个这样的约束,有可能一个名义上属 于该域类型的列也会被读成空值。例如,如果在一次外连接查询中,属于该域的列出现在外连接的空值端。下面是一 个更精细的例子: INSERT INTO tab (domcol) VALUES ((SELECT domcol FROM tab WHERE false)); 空的标量子子查询将产生一个空值,它被认为是该域类型的值,因此不会在其上应用任何进一步的约束检查,并 且插入将会成功。 要避免这类问题很难,因为 SQL 的一般假设是空值也是每一种数据类型的合法值。因此,最好的方法是设计一 个允许空值的域约束,然后根据需要在该域类型的列上应用列的 NOT NULL 约束。 KingbaseES 假设检查约束的条件是不可变的,也就是说,对于相同的输入值,他们总是会给出相同的结果。只 有当一个值第一次转换为域类型时,才需要检查约束,而不是在其他时候,这种假设才合理。(这和表上的检查约束 本质上是一致的) 违反这种假设的常见方式之一是在检查表达式中引用用户定义的函数,然后更改该函数的行为。KingbaseES 不 允许这样做,但是如果域类型的存储值现在违反了检查约束,它就不会注意到。这将导致随后的数据库转储和重新加 载失败。处理此类更改的推荐方法是删除约束 (使用 ALTER DOMAIN)、调整函数定义并重新添加约束,从而根据存储 的数据重新检查约束。 14.14 CREATE EVENT TRIGGER 用途 CREATE EVENT TRIGGER 创建一个新的事件触发器。只要指定的事件发生并且与该触发器相关的 WHEN 条件(如 果有)被满足,该触发器的函数将被执行。关于事件触发器的一般性介绍可见 触发器。创建事件触发器的用户会成 为它的拥有者。 前置条件 只有超级用户能创建事件触发器。 语法 CREATE EVENT TRIGGER name ON event [ WHEN filter_variable IN (filter_value [, ... ]) [ AND ... ] ] EXECUTE { FUNCTION | PROCEDURE } function_name() 888 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE 语义 name 触发器的名称。在该数据库中这个名称必须唯一。 event 会触发对给定函数调用的事件名称。 filter_variable 用来过滤事件的变量名称。这可以用来限制触发器只为它支持的那一部分情况引发。当前唯一支持的 “filter_variable“ 是 TAG。 filter_value 与该触发器要为其引发的 “filter_variable“相关联的一个值列表。对于 TAG,这表示一个命令标签列表 (例如 'DROP FUNCTION')。 function_name 一个用户提供的函数,它被声明为没有参数并且返回类型 event_trigger。 在 CREATE EVENT TRIGGER 语法中,关键字 FUNCTION 和 PROCEDURE 是等价的,但是引用的函数 在任何情况下都必须是函数,而不是存储。由于历史原因保留了关键字 PROCEDURE,但不建议使用。 示例 禁止执行任何 数据定义命令: CREATE OR REPLACE FUNCTION abort_any_command() RETURNS event_trigger LANGUAGE plsql AS $$ BEGIN RAISE EXCEPTION 'command % is disabled', tg_tag; END; $$; 889 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE CREATE EVENT TRIGGER abort_ddl ON ddl_command_start EXECUTE FUNCTION abort_any_command(); 兼容性 在 SQL 标准中没有 CREATE EVENT TRIGGER 语句。 其他 在单用户模式(见 kingbase )中事件触发器被禁用。如果一个错误的事件触发器禁用了数据库让你甚至无法删 除它,可以重启到单用户模式,这样你就能删除它。 14.15 CREATE EXTENSION 用途 CREATE EXTENSION 在数据库中创建一个新的扩展,不能与已有扩展同名。 创建一个扩展本质上是运行该扩展的脚本文件。该脚本通常将创建新的 SQL 对象,例如函数、数据类型、操作 符以及索引支持方法。CREATE EXTENSION 会额外地记录所有被创建对象的标识,这样执行 DROP EXTENSION 时可以 删除它们。 前置条件 创建一个扩展要求创建其组件对象所要求的特权。对于大部分扩展这意味着需要超级用户或者数据库拥有者的特 权。为了以后特权检查的目的,运行 CREATE EXTENSION 的用户会成为该扩展的拥有者以及由该扩展的脚本创建的任 何对象的拥有者。 语法 CREATE EXTENSION [ IF NOT EXISTS ] extension_name [ WITH ] [ SCHEMA schema_name ] [ VERSION version ] [ FROM old_version ] [ CASCADE ] 语义 IF NOT EXISTS 890 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE 已有同名扩展存在时不要抛出错误。这种情况下会发出一个提示。注意,不保证现有的扩展与将要从当前 可用的扩展文件创建的脚本有任何相似。 extension_name 要安装的扩展的名称。KingbaseES 将使用文件 SHAREDIR/extension/“extension_name“.control 中的 信息来创建该扩展。 schema_name 假定该扩展允许其内容被重定位,则扩展所包含的对象将被创建在该模式下。被指定的模式必须已经存 在。如果没有指定 schema_name 并且该扩展的控制文件也没有指定一个模式,将使用当前的默认模式创 建对象。 如果该扩展在其控制文件中指定了一个 schema 参数,那么不能用 SCHEMA 子句覆盖该模式。通常,如 果给出了一个 SCHEMA 子句并且它与扩展的 schema 参数冲突,则会发生错误。但是,如果也指定了 CASCADE 子句,则 schema 冲突时会忽略 “schema_name“。给定的 “schema_name“ 将被用来安装任何 需要并且没有在其控制文件中指定 schema 的扩展。 记住扩展本身被认为不在任何模式中:扩展具有无限定的名称,并且要在整个数据库范围内唯一。但是属 于扩展的对象可以在模式中。 version 要安装的扩展的版本。这可以写成一个标识符或者一个字符串。默认版本在该扩展的控制文件中指定。 old_version 当且仅当尝试要安装一个扩展来替代一个“老式”的模块(它只是一组没有被打包成扩展的对象的集合) 时,才必须指定 FROM “old_version“。这个选项导致 CREATE EXTENSION 运行另一个安装脚本把现有的对 象吸收到该扩展中,而不是创建新对象。此时 SCHEMA 指定的是包含已经存在对象的模式。 用于 “old_version“的值由扩展的作者决定,且如果有多于一种版本的老式模块可以被升级到扩展, 该值还可能变化。对于老版本的 KingbaseES 提供的标准附加模块,在升级模块到扩展风格时要为 “old_version“使用 unpackaged。 CASCADE 自动安装这个扩展所依赖的任何还未安装的扩展。它们的依赖也会同样被自动安装。如果给出 SCHEMA 子 句,它会应用于这种方式下安装的所有扩展。这个语句的其他选项不会被应用于自动安装的扩展。特别 地,这些自动安装的扩展的默认版本将被选中。 示例 安装 hstore 扩展到当前数据库中: CREATE EXTENSION hstore; 升级一个 9.1 之前的 hstore 安装成为扩展: CREATE EXTENSION hstore SCHEMA public FROM unpackaged; 891 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE 要小心地指定安装现有 hstore 对象的模式。 兼容性 CREATE EXTENSION 是一种 KingbaseES 扩展。 其他 在使用 CREATE EXTENSION 载入扩展到数据库中之前,必须先安装好该扩展的支持文件。 当前可以用于载入的扩展可以在系统视图 sys_available_extensions 或者 sys_available_extension_versions 中看 到。 14.16 CREATE FOREIGN DATA WRAPPER 用途 CREATE FOREIGN DATA WRAPPER 创建一个新的外部数据包装器。定义外部数据包装器的用户将成为它的拥有 者。 在数据库内外部数据包装器名称必须唯一。 前置条件 只有超级用户能够创建外部数据包装器。 语法 CREATE FOREIGN DATA WRAPPER name [ HANDLER handler_function | NO HANDLER ] [ VALIDATOR validator_function | NO VALIDATOR ] [ OPTIONS ( option 'value' [, ... ] ) ] 892 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE 语义 name 要创建的外部数据包装器的名称。 HANDLER handler_function “handler_function“是一个以前注册好的函数的名称,它将被调用来为外部表检索执行函数。处理器函数 必须不能有参数,并且它的返回类型必须是 fdw_handler。 可以创建一个没有处理器函数的外部数据包装器,但是使用这个包装器的外部表只能被声明,不能被访 问。 VALIDATOR validator_function “validator_function“ 是一个之前已注册的函数的名称,它将被调用来检查给予该外部数据包装器的选 项,还有用于外部服务器、用户映射以及使用该外部数据包装器的外部表的选项。如果没有验证器函数或 者指定了 NO VALIDATOR,那么在创建时不会检查选项(外部数据包装器可能会在运行时忽略或者拒绝无 效的选项说明,这取决于实现)。验证器函数必须接受两个参数:一个类型是 text[],它将包含存储在 系统目录中的选项数组,另一个是类型 oid,它将是包含该选项的系统目录的 OID。返回类型会被忽略, 该函数应该使用 ereport(ERROR) 函数报告无效选项。 OPTIONS ( option 'value' [, ... ] ) 这个子句为新的外部数据包装器指定选项。允许的选项名称和值与每一个外部数据包装器有关,并且它们 会被该外部数据包装器的验证器函数验证。选项名称必须唯一。 示例 创建一个无用的外部数据包装器 dummy: CREATE FOREIGN DATA WRAPPER dummy; 用处理器函数 file_fdw_handler 创建一个外部数据包装器 “file“: CREATE EXTENSION file_fdw; CREATE FOREIGN DATA WRAPPER file HANDLER file_fdw_handler; 用一些选项创建一个外部数据包装器 mywrapper: CREATE FOREIGN DATA WRAPPER mywrapper OPTIONS (debug 'true'); 兼容性 CREATE FOREIGN DATA WRAPPER 符合 ISO/IEC 9075-9(SQL/MED),但是 HANDLER 和 VALIDATOR 子句是扩展, 并且标准子句 LIBRARY 和 LANGUAGE 还没有在 KingbaseES 中被实现。 但是要注意,整体上来说 SQL/MED 功能还没有符合。 其他 893 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE KingbaseES 的外部数据功能仍在积极的开发中。查询的优化还很原始(也是剩下工作最多的部分)。因此,未 来还有很可观的性能提升空间。 14.17 CREATE FOREIGN TABLE 用途 CREATE FOREIGN TABLE 在当前数据库中创建一个新的外部表。该表将由发出这个命令的用户所拥有。 如果给定了一个模式名称(例如 CREATE FOREIGN TABLE myschema.mytable ...),那么该表会被创建在指定 的模式中。否则它会被创建在当前模式中,该外部表的名称必须与同一个模式中的任何其他外部表、表、序列、索 引、视图或者物化视图区分开来。 CREATE FOREIGN TABLE 还将自动创建一个数据类型来表示该外部表行相应的组合类型。因此,外部表不能和同 一个模式中任何现有的数据类型同名。 如果指定了 PARTITION OF 子句,则该表被创建为具有指定边界的 parent_table 的分区。 前置条件 要创建一个外部表,你必须具有该外部服务器上的 USAGE 特权,以及该表中用到的所有列类型上的 USAGE 特 权。 语法 CREATE FOREIGN TABLE [ IF NOT EXISTS ] table_name ( [ { column_name data_type [ OPTIONS ( option 'value' [, ... ] ) ] [ COLLATE collation ] [ column_constraint [ ... ] ] | table_constraint } [, ... ] ] ) [ INHERITS ( parent_table [, ... ] ) ] SERVER server_name [ OPTIONS ( option 'value' [, ... ] ) ] 894 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE CREATE FOREIGN TABLE [ IF NOT EXISTS ] table_name PARTITION OF parent_table [ ( { column_name [ WITH OPTIONS ] [ column_constraint [ ... ] ] | table_constraint } [, ... ] ) ] partition_bound_spec SERVER server_name [ OPTIONS ( option 'value' [, ... ] ) ] 895 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE 其中 column_constraint 是: [ CONSTRAINT constraint_name ] { NOT NULL | NULL | CHECK ( expression ) [ NO INHERIT ] | DEFAULT default_expr | GENERATED ALWAYS AS ( generation_expr ) STORED } 而 table_constraint 是: [ CONSTRAINT constraint_name ] CHECK ( expression ) [ NO INHERIT ] 语义 IF NOT EXISTS 已经存在同名关系时不要抛出错误。这种情况下会发出一个提示。注意,并不保证已经存在的关系与将要 创建的那一个相似。 table_name 要创建的表的名称(可以被模式限定)。 column_name 要在新表中创建的列名。 896 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE data_type 该列的数据类型。可以包括数组指示符。更多 KingbaseES 支持的数据类型可见数据类型 。 COLLATE collation COLLATE 子句为该列(必须是一个可排序的数据类型)赋予一个排序规则。如果没有指定,则会使用该列 的数据类型的默认排序规则。 INHERITS ( parent_table [, ... ] ) 可选的 INHERITS 子句指定了一个表的列表,新的外部表会自动从中继承所有列。父表可以是普通表或者 外部表。详见CREATE TABLE 的类似形式。 PARTITION OF parent_table FOR VALUES partition_bound_spec 此表单可用于将外部表创建为具有指定分区绑定值的给定父表的分区。参见类似的CREATE TABLE 。注 意, 如果父表上有唯一的索引,不允许创建外部表作为分区表的父表。(ALTER TABLE ATTACH PARTITION 。) CONSTRAINT constraint_name 一个可选的用于列或者表约束的名字。如果该约束被违背,这个约束名字会出现在错误消息中,这样 col must be positive 这种约束名就可以被用来与客户端应用交流有用的约束信息(指定包含空格的约束名 需要使用双引号)。如果没有指定约束名,系统会自动生成一个。 NOT NULL 该列不允许包含空值。 NULL 该列可以包含空值,这是默认值。 提供这个子句只是为了兼容非标准的 SQL 数据库。在新的应用中不鼓励使用它。 CHECK ( expression ) [ NO INHERIT ] CHECK 子句指定一个产生布尔结果的表达式,该外部表中的每一行都应该满足该表达式。也就是说,对于 该外部表中所有的行,这个表达式应该产生 TRUE 或者 UNKNOWN 而不能产生 FALSE。被作为列约束 指定的检查约束应该只引用该列的值,而出现在表约束中的表达式可以引用多列。 当前,CHECK 表达式不能包含子查询,也不能引用除当前行的列之外的其他变量。可以引用系统列 tableoid,但是不能引用其他系统列。 被标记为 NO INHERIT 的约束将不会传播到子表上。 DEFAULT default_expr DEFAULT 子句为包含它的列定义赋予一个默认数据值。该值是任意不包含变量的表达式(不允许子查询和 对当前表中其他列的交叉引用)。默认值表达式的数据类型必须匹配列的数据类型。 默认值表达式将被用在任何没有指定列值的插入操作中。如果一列没有默认值,则默认值为空值。 GENERATED ALWAYS AS ( generation_expr ) STORED 897 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE 此子句将列创建为生成的列。无法写入该列,读取时将返回指定表达式的结果。 需要存储关键字来表示该列在写时被计算。(计算的值将呈现给外部数据包装器进行存储,并且必须在读 取时返回。) 生成表达式可以引用表中的其他列,但不能引用其他生成的列。所使用的任何函数和操作符都必须是不可 变的。不允许引用其他表。 server_name 要用于该外部表的一个现有外部服务器的名称。有关定义一个服务器的细节可以参考CREATE SERVER 。 OPTIONS ( option 'value' [, ...] ) 要与新外部表或者它的一个列相关联的选项。被允许的选项名称和值是与每一个外部数据包装器相关的, 并且它们会被该外部数据包装器的验证器函数验证。不允许重复的选项名称(但是一个表选项和一个列选 项重名是可以的)。 示例 创建外部表 films,通过服务器 film_server 访问它: CREATE FOREIGN TABLE films ( code char(5) NOT NULL, title varchar(40) NOT NULL, did integer NOT NULL, date_prod date, kind varchar(10), len interval hour to minute ) SERVER film_server; 有关定义一个服务器的细节可以参考 :ref:`CREATE SERVER` 。 创建外部表 measurement_y2016m07,通过服务器 server_07 访问它,作为范围分区表 measurement 的分区: CREATE FOREIGN TABLE measurement_y2016m07 PARTITION OF measurement FOR VALUES FROM ('2016-07-01') TO ('2016-08-01') SERVER server_07; 兼容性 CREATE FOREIGN TABLE 命令大部分符合 SQL 标准。但是,与CREATE TABLE 很相似,它允许 NULL 约束以 及零列外部表。能够指定列默认值也是一种 KingbaseES 扩展。KingbaseES 定义的表继承形式是非标准的。 其他 KingbaseES 核心系统不会强制外部表上的约束(例如 CHECK 或 NOT NULL 子句),大部分外部数据包装器也不 会尝试强制它们。也就是说,这类约束会被简单地认为保持为真。这种强制其实没什么意义,因为它只适用于通过该 898 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE 外部表插入或者更新的行,而对通过其他方式修改的行(例如直接在远程服务器上修改)没有作用。附着在外部表上 的约束应该表示由外部服务器强制的一个约束。 有些特殊目的的外部数据包装器可能是它们所访问的数据的唯一一种访问机制,在那种情况下让外部数据包装器 自己来强制执行约束可能是合适的。但是不应该假设包装器会这样做,除非有文档说明。 尽管 KingbaseES 不会尝试强制外部表上的约束,但假定它们对于查询优化的目的是正确的。如果在外部表中有 不满足约束的行,在该表上的查询可能会产生不正确的结果。用户需要确保约束定义是符合实际的。 类似的考虑也适用于生成的列。存储生成的列在本地 KingbaseES 服务器上的 insert 或 update 上计算,然后交 给外部数据包装器将其写入外部数据存储,但是并不强制要求查询外部表时返回的生成列的值一定是与生成表达式一 致。总之,这可能导致不正确的查询结果。 虽然可以将行从本地分区移动到外部表分区 (假设外部数据包装器支持元组路由),但是不能将它们从外部表分区 移动到另一个分区。 14.18 CREATE FUNCTION 用途 CREATE FUNCTION 定义一个新函数。CREATE OR REPLACE FUNCTION 将创建一个新函数或者替换一个现有的函 数。要定义一个函数,用户必须具有该语言上的 USAGE 特权。 如果包括了一个模式名,那么该函数会被创建在指定的模式中。否则,它会被创建在当前模式中。新函数的名称 不能匹配同一个模式中具有相同输入参数类型的任何现有函数或过程。但是,不同参数类型的函数和过程能够共享一 个名字(这被称作重载)。 要替换一个现有函数的当前定义,可以使用 CREATE OR REPLACE FUNCTION。但不能用这种方式更改函数的名称 或者参数类型(如果尝试这样做,实际上就会创建一个新的不同的函数)。还有,CREATE OR REPLACE FUNCTION 将 不会让你更改一个现有函数的返回类型。要这样做,你必须先删除再重建该函数(在使用 OUT 参数时,这意味着除 了删除函数之外无法更改任何 OUT 参数的类型)。 当 CREATE OR REPLACE FUNCTION 被用来替换一个现有的函数,该函数的拥有权和权限不会改变。所有其他的 函数属性会按照该命令中所指定的或者隐含的来赋值。必须拥有(包括成为拥有角色的成员)该函数才能替换它。 如果你删除并且重建一个函数,新函数将和旧的不一样,你将必须删掉引用旧函数的现有规则、视图、触发器 等。使用 CREATE OR REPLACE FUNCTION 更改一个函数定义不会破坏引用该函数的对象。还有,ALTER FUNCTION 可 以被用来更改一个现有函数的大部分辅助属性。 创建该函数的用户将成为该函数的拥有者。 前置条件 要创建一个函数,你必须拥有参数类型和返回类型上的 USAGE 特权。 语法 CREATE [ OR REPLACE ] [ EDITIONABLE | NONEDITIONABLE ] FUNCTION name [ ( [ [ argname ] [ argmode ] argtype [ { DEFAULT | := } default_expr ] [, ...] ] ) ] 899 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE { RETURNS | RETURN } rettype [ < invoker_rights_clause > | PIPELINED ] [ COMMENT 'String' ] { AS | IS } { [ label_name ] [ DECLARE ] [ < variable_declaration > ] [ < cursor_declaration > ] [ < exception_declaration > ] [ < NestfunctionDeclaration > ] BEGIN < sequence_of_statement > END [ label_name ] } CREATE [ OR REPLACE ] [INTERNAL] FUNCTION name ( [ [ argmode ] [ argname ] argtype [ { DEFAULT | = } default_expr ] [, ...] ] ) [ RETURNS rettype 900 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE | RETURNS TABLE ( column_name column_type [, ...] ) ] [ COMMENT 'String' ] { LANGUAGE lang_name | TRANSFORM { FOR TYPE type_name } [, ... ] | WINDOW | IMMUTABLE | STABLE | VOLATILE | [ NOT ] LEAKPROOF | CALLED ON NULL INPUT | RETURNS NULL ON NULL INPUT | STRICT | [] | PARALLEL { UNSAFE | RESTRICTED | SAFE } | COST execution_cost | ROWS result_rows | SUPPORT support_function | SET configuration_parameter { TO value | = value | FROM CURRENT } | AS 'definition' | AS 'obj_file', 'link_symbol' } ... 901 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE 902 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE ::= { AUTHID CURRENT_USER | AUTHID DEFINER | [ EXTERNAL ] SECURITY INVOKER | [ EXTERNAL ] SECURITY DEFINER } 语义 name 要创建的函数的名称(可以被模式限定)。 argmode 一个参数的模式:IN、OUT、INOUT 或者 VARIADIC。如果省略,默认为 IN。只有 OUT 参数能跟在一个 VARIADIC 参数后面。还有,OUT 和 INOUT 参数不能和 RETURNS TABLE 符号一起使用。 argname 一个参数的名称。一些语言(包括 SQL 和 PL/SQL)让你在函数体中使用该名称。对于其他语言,一个 输入参数的名字只是额外的文字(就该函数本身所关心的来说)。但是你可以在调用一个函数时使用输入 参数名来提高可读性(见 调用函数)。在任何情况下,输出参数的名称是有意义的,因为它定义了结果 行类型中的列名(如果忽略一个输出参数的名称,系统将选择一个默认的列名)。 argtype 该函数参数(如果有)的数据类型(可以是模式限定的)。参数类型可以是基本类型、组合类型或者域类 型,或者可以引用一个表列的类型。 根据实现语言,也可以允许指定 cstring 之类的“伪类型”。伪类型表示实际参数类型没有被完整指定 或者不属于普通 SQL 数据类型集合。 可以写 table_name.“column_name“%TYPE 来引用一列的类型。使用这种特性有时可以帮助创建一个不 受表定义更改影响的函数。 default_expr 903 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE 如果参数没有被指定值时要用作默认值的表达式。该表达式必须能被强制为该参数的参数类型。只有输入 (包括 INOUT)参数可以具有默认值。所有跟随在一个具有默认值的参数之后的输入参数也必须有默认 值。 rettype 返回数据类型(可能被模式限定)。返回类型可以是一种基本类型、组合类型或者域类型,也可以引用一 个表列的类型。根据实现语言,也可以允许指定 cstring 之类的“伪类型”。如果该函数不会返回一个 值,可以指定返回类型为 void。 当有 OUT 或者 INOUT 参数时,可以省略 RETURNS 子句。如果存在,该子句必须和输出参数所表示的结 果类型一致:如果有多个输出参数,则为 RECORD,否则与单个输出参数的类型相同。 SETOF 修饰符表示该函数将返回一个项的集合而不是一个单一项。 可以写 table_name.“column_name“%TYPE 来引用一列的类型。 column_name RETURNS TABLE 语法中一个输出列的名称。这实际上是另一种声明 OUT 参数的方法,但是 RETURNS TABLE 也隐含了 RETURNS SETOF。 column_type RETURNS TABLE 语法中的输出列的数据类型。 lang_name 用以实现该函数的语言的名称。可以是 sql、c、internal 或者一个用户定义的过程语言的名称,例如 plsql。不推荐用单引号包围该名称,并且要求区分大小写。 TRANSFORM { FOR TYPE type_name } [, ... ] } 一个由转换构成的列表,对该函数的调用适用于它们。转换在 SQL 类型和语言相关的数据类型之间进行 变换,详见CREATE TRANSFORM 。过程语言实现通常把有关内建类型的知识硬编码在代码中,因此 那些不需要列举在这里。如果一种过程语言实现不知道如何处理一种类型并且没有转换被提供,它将回退 到一种默认的行为来转换数据类型,但是这取决于具体实现。 WINDOW WINDOW 表示该函数是一个窗口函数而不是一个普通函数。当前只用于用 C 编写的函数。在替换一个现有 函数定义时,不能更改 WINDOW 属性。 IMMUTABLE | STABLE | VOLATILE 这些属性告知查询优化器该函数的行为。最多只能指定其中一个。如果这些都不出现,则会默认为 VOLATILE。 IMMUTABLE 表示该函数不能修改数据库并且对于给定的参数值总是会返回相同的值。也就是说,它不会做 数据库查找或者使用没有在其参数列表中直接出现的信息。如果给定合格选项,任何用全常量参数对该函 数的额调用可以立刻用该函数值替换。 STABLE 表示该函数不能修改数据库,并且对于相同的参数值,它在一次表扫描中将返回相同的结果。但 是这种结果在不同的 SQL 语句执行期间可能会变化。对于那些结果依赖于数据库查找、参数变量(例如 904 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE 当前时区)等的函数来说,这是合适的(对希望查询被当前命令修改的行的 AFTER 触发器不适合)。还 要注意 current_timestamp 函数族适合被标记为稳定,因为它们的值在一个事务内不会改变。 VOLATILE 表示该函数的值在一次表扫描中都有可能改变,因此不能做优化。在这种意义上,相对较 少的数据库函数是不稳定的,一些例子是 random()、currval()、timeofday()。但是注意任何有副作 用的函数都必须被分类为不稳定的,即便其结果是可以预测的,这是为了调用被优化掉。一个例子是 setval()。 更多细节可见 函数易变性分类。 LEAKPROOF LEAKPROOF 表示该函数没有副作用。它不会泄露有关其参数的信息(除了通过返回值)。例如,一个只对 某些参数值抛出错误消息而对另外一些却不抛出错误的函数不是防泄漏的,一个把参数值包括在任何错误 消息中的函数也不是防泄漏的。这会影响系统如何执行在使用 security_barrier 选项创建的视图或者开 启了行级安全性的表上执行查询。对于包含有非防泄漏函数的查询,系统将在任何来自查询本身的用户提 供条件之前强制来自安全策略或者安全屏障的条件,防止无意中的数据暴露。被标记为防泄漏的函数和操 作符被假定是可信的,并且可以在安全性策略和安全性屏障视图的条件之前被执行。此外,没有参数的函 数或者不从安全屏障视图或表传递任何参数的函数不一定要被标记为防泄漏的。详见CREATE VIEW 和 规则和权限。这个选项只能由超级用户设置。 CALLED ON NULL INPUT | RETURNS NULL ON NULL INPUT | STRICT CALLED ON NULL INPUT(默认)表示在某些参数为空值时应正常调用该函数。如果有必要,函数的作者 应该负责检查空值并且做出适当的相应。 RETURNS NULL ON NULL INPUT 或 STRICT 表示只要其任意参数为空值,该函数就会返回空值。如果指定 了这个参数,当有空值参数时该函数不会被执行,而是自动返回一个空值结果。 PARALLEL PARALLEL UNSAFE 表示该函数不能在并行模式中运行并且 SQL 语句中存在一个这样的函数会强制使用顺序执行计划。这是 默认选项。PARALLEL RESTRICTED 表示该函数能在并行模式中运行,但是其执行被限制在并行组的领导 者中。PARALLEL SAFE 表示该函数对于在并行模式中运行是安全的并且不受限制。 如果函数修改任何数据库状态、会使用子事务之类的方式改变事务、访问序列或者对设置(如 setval) 做出持久性的更改,它们就应该被标记为并行不安全。如果它们访问临时表、客户端连接状态、游标、预 备语句或者系统无法在并行模式中同步的本地后端状态(例如 setseed 只能在组领导者中执行,因为另 一个进程所作的更改不会在领导者中被反映出来),它们应该被标为并行受限。通常,如果一个函数是受 限的或者不安全的却被标成了安全,或者它本来是不安全的却被标成了受限,在并行查询中执行时它可能 会抛出错误或者产生错误的答案。如果被错误的标记,C 语言函数理论上可能展现出完全无法定义的行 为,因为系统没有办法保护自己不受任意的 C 代码影响,但是在大部分情况下其结果也不会比任何其他 函数差到哪里去。如果有疑问,函数应该被标为 UNSAFE,这也是默认值。 COST execution_cost 一个给出该函数的估计执行代价的正数,单位是 cpu_operator_cost 。如果该函数返回一个集合,这就是 每个被返回行的代价。如果没有指定代价,对 C 语言和内部函数会指定为 1 个单位,对其他语言的函数 则会指定为 100 单位。更大的值会导致规划器尝试避免对该函数的不必要的过多计算。 905 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE ROWS result_rows 一个正数,它给出规划器期望该函数返回的行数估计。只有当该函数被声明为返回一个集合时才允许这个 参数。默认假设为 1000 行。 SUPPORT support_function 使用此函数的计划支持函数的名称 (可选模式限定)。见 函数优化的信息。必须是超级用户才能使用这个 选项。 configuration_parameter value SET 子句导致进入该函数时指定配置参数将被设置为指定值。并且在该函数退出时恢复到该参数之 前的值。SET FROM CURRENT 会把 CREATE FUNCTION 被执行时该参数的当前值保存为进入该函数时将被 应用的值。 如果一个 SET 子句被附加到一个函数,那么在该函数内为同一个变量执行的 SET LOCAL 命令会被限制于 该函数:在函数退出时该配置参数之前的值仍会被恢复。但是,一个普通的 SET 命令(没有 LOCAL)会 覆盖 SET 子句,更像一个之前的 SET LOCAL 命令所做的那样:这种命令的效果在函数退出后将会持续, 除非当前事务被回滚。 更多有关允许的参数名和参数值的信息请见SET 和《数据库参考手册》。 definition 一个定义该函数的字符串常量,其含义取决于语言。它可以是一个内部函数名、一个对象文件的路径、一 个 SQL 命令或者用一种过程语言编写的文本。 美元引用美元引用的字符串常量 通常对书写函数定义字符串有所帮助,而普通单引号语法则不会有用。 如果没有美元引用,函数定义中的任何单引号或者反斜线必须用双写来转义。 obj_file, link_symbol 当 C 语言源代码中该函数的名称与 SQL 函数的名称不同时,这种形式的 AS 子句被用于动态可载入 C 语 言函数。字符串 “obj_file“是包含编译好的 C 函数的动态库文件的名称,它会由LOAD 命令解析。字符串 “link_symbol“是该函数的链接符号,也就是该函数在 C 语言源代码中的名称。如果省略链接符号,它将 被假定为要定义的 SQL 函数的名称。所有函数的 C 名称都必须不同,因此必须为重载的 C 函数给出不同 的 C 名称(例如把参数类型作为 C 名称的一部分)。 在重复调用引用同一对象文件的 CREATE FUNCTION 时,对每个会话该文件只会被载入一次。要卸载并且 重新装载该文件(可能是在开发期间),需要开始一个新会话。 label_name 一个标签名。 variable_declaration 定义变量,详见 数据类型与声明。 cursor_declaration 定义游标变量,详见 游标管理。 906 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE exception_declaration 定义异常,详见 PL/SQL 异常处理。 NestfunctionDeclaration 详见 嵌套函数。 sequence_of_statement PL/SQL 语言组成的函数体。 EDITIONABLE NONEDITIONABLE 未涉及功能,只为语法兼容。 [EXTERNAL] SECURITY INVOKER | [EXTERNAL] SECURITY DEFINER SECURITY INVOKER 表示要用调用该函数的用户的特权来执行它。这是默认值。SECURITY DEFINER 指定 要用创建函数的用户的特权来执行该函数。 为了符合 SQL,允许使用关键词 EXTERNAL。但是它是可选的,因为与 SQL 中不同,这个特性适用于所 有函数而不仅是那些外部函数。 AUTHID CURRENT_USER 同 SECURITY INVOKER。 AUTHID DEFINER 同 SECURITY DEFINER。 PIPELINED 在函数创建时指定 PIPELINED 子句用于创建一个 PIPELINED 函数。在函数的声明和定义中,该子句必须 保持一致。使用 PIPELINED 关键字时,必须在其函数体内使用 PIPE ROW 语句 (详见 返回语句),用于从 函数体内返回集合的单个元素 编写函数的进一步信息可以参考 用户定义的函数。 COMMENT 'String' 添加函数的注释内容,此功能仅限在 MySQL 模式下使用。 示例 下列示例可以帮用户了解函数的创建。更多信息和示例请参考 用户定义的函数。 例 1: CREATE FUNCTION add(integer, integer) RETURNS integer AS 'select $1 + $2;' LANGUAGE SQL IMMUTABLE RETURNS NULL ON NULL INPUT; 907 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE call add(1,1); 例 2:在 PL/SQL 中,使用一个参数名称增加一个整数: \set SQLTERM / CREATE OR REPLACE FUNCTION increment(i integer) RETURNS integer AS BEGIN RETURN i + 1; END; / \set SQLTERM ; call increment(1); 例 3:返回一个包含多个输出参数的记录: CREATE FUNCTION dup(in int, out f1 int, out f2 text) AS $$ SELECT $1, CAST($1 AS text) || ' is text' $$ LANGUAGE SQL; SELECT * FROM dup(42); 例 4:可用更复杂的方式(用一个显式命名的组合类型)来做同样的事情: CREATE TYPE dup_result AS (f1 int, f2 text); CREATE FUNCTION dup(int) RETURNS dup_result AS $$ SELECT $1, CAST($1 AS text) || ' is text' $$ LANGUAGE SQL; SELECT * FROM dup(42); 例 5:另一种返回多列的方法是使用一个 TABLE 函数: CREATE FUNCTION dup(int) RETURNS TABLE(f1 int, f2 text) AS $$ SELECT $1, CAST($1 AS text) || ' is text' $$ LANGUAGE SQL; SELECT * FROM dup(42); 但是,TABLE 函数与之前的例子不同,因为它实际返回了一个记录集合而不只是一个记录。 注意: KingbaseES 数据库系统默认的结束符为分号, 也可以使用 \set SQLTERM 来暂时将结束符重置成为其他符 908 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE 号,以防止和函数中的语句分隔符相冲突。 例 6:创建一个返回类型为 REFCURSOR 的用户自定义函数: CREATE TABLE student(SID INTEGER, SNAME CHAR(30)); INSERT INTO student VALUES(1, 'Tom'); INSERT INTO student VALUES(2, 'Jack'); \set SQLTERM / CREATE OR REPLACE FUNCTION return_type RETURNS REFCURSOR AS DECLARE CURSOR c1 FOR SELECT * FROM student; BEGIN OPEN c1; RETURN c1; END; / \set SQLTERM ; call return_type(); 例 7:返回值为 SETOF integer 类型: \set SQLTERM $ CREATE OR REPLACE FUNCTION return_type(IN i INTEGER) RETURNS SETOF INTEGER AS DECLARE v1 INTEGER; v2 INTEGER; v3 INTEGER; BEGIN v1 := i + 1; v2 := i + 2; v3 := i + 3; return next v1; return next v2; return next v3; END; $ \set SQLTERM ; select * from return_type(1); 例 8:返回值为 SETOF table 类型: 909 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE \set SQLTERM @ CREATE OR REPLACE function return_type() RETURNS SETOF student AS DECLARE CURSOR cc for SELECT * FROM student; rs RECORD; BEGIN OPEN cc; LOOP FETCH cc INTO rs; EXIT WHEN cc%NOTFOUND; RETURN NEXT rs; END LOOP; CLOSE cc; END; @ \set SQLTERM ; SELECT * FROM return_type(); 例 9:IN 参数的例子: \set SQLTERM @ CREATE OR REPLACE function fin(i in int) returns void AS BEGIN i := i + 1; -- 不能进行修改 创建会失败 END; @ CREATE OR REPLACE function fin(i in int) returns void AS BEGIN raise notice 'fin i = %', i; -- 成功 END; @ 例 10:OUT/INOUT 参数的例子: \set SQLTERM @ CREATE OR REPLACE function fout(i in int, j out text, k in out int) returns varchar AS BEGIN j := i || 'fout'; k := k + 1; return 'bar'::varchar; END; @ 910 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE \set SQLTERM / declare k text; c varchar(12); h int := 3; begin c := fout(1, k, h); -- 传入变量 raise notice 'k = %, c = %, h = %', k, c, h; end; / 例 11:不支持在 oracle 语法中指定语言的用例: \set SQLTERM / CREATE OR REPLACE FUNCTION f1() RETURNS INTEGER LANGUAGE plsql AS DECLARE v INTEGER := 0; BEGIN RETURN v; END; / \set SQLTERM ; 例 12:在 MySQL 模式的数据库下,创建一个包含注释的函数: CREATE FUNCTION add_em(x integer, y integer) RETURNS bigint COMMENT 'a function example' AS BEGIN SELECT x + y; END; 注意: 如需指定 LANGUAGE 语言请使用概述中的第二种语法格式创建函数。 兼容性 SQL 标准中定义了 CREATE FUNCTION 命令。KingbaseES 的版本与之类似但不完全兼容。属性是不可移植的, 不同的可用语言也是不能移植的。 对于和一些其他数据库系统的兼容性,argmode 可以被写在 argname 之前或者之后。但只有第一种方式是兼容 标准的。 911 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE 对于参数默认值,SQL 标准只指定带有 DEFAULT 关键词的语法。带有 = 的语法被用在 T-SQL 和 Firebird 中。 其他 1. 重载 KingbaseES 允许函数重载,也就是说同一个名称可以被用于多个不同的函数,只要它们具有可区分的输入参数 类型。不管是否使用它,在有些用户不信任另一些用户的数据库中调用函数时,这种兼容性需要安全性的预防措施, 请参考函数 。 如果两个函数具有相同的名称和输入参数类型,它们被认为相同(不考虑任何 OUT 参数)。因此这些声明会冲 突: CREATE FUNCTION foo(int) ... CREATE FUNCTION foo(int, out text) ... 具有不同参数类型列表的函数在创建时将不会被认为是冲突的,但是如果默认值被提供,在使用时它们有可能会 冲突。例如,考虑 CREATE FUNCTION foo(int) ... CREATE FUNCTION foo(int, int default 42) ... 调用 foo(10) 将会失败,因为在要决定应该调用哪个函数时会有歧义。 2. 安全地编写 SECURITY DEFINER 函数 因为一个 SECURITY DEFINER 函数会被以创建它的用户的特权来执行,需要小心地确保该函数不会被误用。为 了安全,search_path 应该被设置为排除任何不可信用户可写的模式。这可以阻止恶意用户创建对象(例如表、函数 以及操作符)来掩饰该函数所要用到的对象。在这方面特别重要的是临时表模式,默认情况下它会第一个被搜索并且 通常对任何用户都是可写的。可以通过强制最后搜索临时模式来得到一种安全的布局。要这样做,把 sys_temp 写成 search_path 中的最后一项。这个函数展示了安全的用法: \set SQLTERM / CREATE FUNCTION check_password(uname TEXT, pass TEXT) RETURNS BOOLEAN SECURITY DEFINER -- 设置一个安全的 search_path:受信的模式,然后是 'sys_temp'。 SET search_path = admin, sys_temp AS DECLARE passed BOOLEAN; BEGIN SELECT (pwd = $2) INTO passed FROM pwds WHERE username = $1; RETURN passed; END; / 912 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE \set SQLTERM ; 这个函数的目的是为了访问表 admin.pwds。但是如果没有 SET 子句或者带有 SET 子句却只提到 admin,该函 数会变成创建一个名为 pwds 的临时表。 在 KingbaseES V7 版本之前,SET 子句不可用,因而较老的函数可能包含相当复杂的逻辑来保存、设置以及恢复 search_path。对于这种目的,SET 子句更容易。 另一点要记住的是默认情况下,会为新创建的函数给 PUBLIC 授予执行特权(详见 权限)。你常常会希望把安 全定义器函数的使用限制在某些用户中。要这样做,你必须收回默认的 PUBLIC 特权,然后选择性地授予执行特权。 为了避免出现新函数能被所有人访问的时间窗口,应在一个事务中创建它并且设置特权。例如: BEGIN; CREATE FUNCTION check_password(uname TEXT, pass TEXT) ... SECURITY DEFINER; REVOKE ALL ON FUNCTION check_password(uname TEXT, pass TEXT) FROM PUBLIC; GRANT EXECUTE ON FUNCTION check_password(uname TEXT, pass TEXT) TO admins; COMMIT; 3. 说明 允许把完整的 SQL 类型语法用于声明一个函数的参数和返回值。但是,CREATE FUNCTION 会抛弃带圆括号的类 型修饰符(例如类型 numeric 的精度域)。例如 CREATE FUNCTION foo (varchar(10)) ... 和 CREATE FUNCTION foo (varchar) ... 完全一样。 在用 CREATE OR REPLACE FUNCTION 替换一个现有函数时,对于更改参数名是有限制的。不能更改已经分配给 任何输入参数的名称(但是可以给之前没有名称的参数增加名称)。如果有多于一个输出参数,不能更改输出参数的 名称,因为可能会改变描述函数结果的匿名组合类型的列名。这些限制是为了确保函数被替换时,已有的对该函数的 调用不会停止工作。 如果一个被声明为 STRICT 的函数带有一个 VARIADIC 参数,会严格检查该可变数组作为一个整体是否为非空。 如果该数组有空值元素,该函数仍将被调用。 14.19 CREATE GROUP 用途 CREATE GROUP —定义一个新的数据库角色, CREATE GROUP 现在是CREATE ROLE 的一种别名。 前置条件 参见CREATE ROLE 前置条件。 语法 CREATE GROUP name [ [ WITH ] option [ ... ] ] 913 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE 其中 option 可以是: SUPERUSER | NOSUPERUSER | CREATEDB | NOCREATEDB | CREATEROLE | NOCREATEROLE | INHERIT | NOINHERIT | LOGIN | NOLOGIN | [ ENCRYPTED ] PASSWORD 'password' | VALID UNTIL 'timestamp' | IN ROLE role_name [, ...] | IN GROUP role_name [, ...] | ROLE role_name [, ...] | ADMIN role_name [, ...] | USER role_name [, ...] | SYSID uid 914 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE 915 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE 语义 参见CREATE ROLE。 示例 参见CREATE ROLE。 兼容性 在 SQL 标准中没有 CREATE GROUP 语句。 14.20 CREATE INDEX 用途 CREATE INDEX 在指定关系的指定列上构建一个索引,该关系可以是一个表或者一个物化视图。索引主要被用来 提升数据库性能(但是不当的使用会导致性能变差)。 索引的键域被指定为列名或者写在圆括号中的表达式。如果索引方法支持多列索引,可以指定多个域。 一个索引域可以是一个从表行的一列或者更多列值进行计算的表达式。这种特性可以被用来获得对基于基本数据 某种变换的数据的快速访问。例如,一个在 upper(col) 上计算的索引可以允许子句 WHERE upper(col) = 'JIM'使 用索引。 KingbaseES 提供了索引方法 B-树、位图、哈希、GiST、SP-GiST、GIN 以及 BRIN。用户也可以定义自己的索 引方法,但是相对较复杂。 当 WHERE 子句存在时,会创建一个 部分索引。部分索引只包含表中一部分行的项,通常索引这一部分会比表的 其他部分更有用。例如,如果有一个表包含了已付和未付订单,其中未付订单占了整个表的一小部分并且是经常被使 用的部分,可以通过只在这一部分上创建一个索引来改进性能。另一种可能的应用是使用带有 UNIQUE 的 WHERE 在表 的一个子集上强制唯一性。更多的讨论请见 部分索引。 WHERE 子句中使用的表达式只能引用底层表的列,但它可以引用所有列而不仅仅是被索引的列。当前,WHERE 中 也禁止使用子查询和聚集表达式。同样的限制也适用于表达式索引中的表达式域。 所有在索引定义中使用的函数和操作符必须是“不可变的”,就是说它们的结果必须仅依赖于它们的参数而不受 外在因素(例如另一个表的内容和当前的时间)的影响。这种限制确保了索引的行为是良定的。要在一个索引表达式 或者 WHERE 子句中使用用户定义的函数,记住在创建函数时把它标记为不可变。 前置条件 你必须拥有该表以使用 CREATE INDEX 。要对表空间上的表创建一个索引,你必须拥有这个表空间及具有表 空间的 CREATE 特权。 语法 CREATE [ UNIQUE ] INDEX [ CONCURRENTLY ] [ [ IF NOT EXISTS ] name ] ON [ ONLY ] table_name [ USING method ] ( { column_name | ( expression ) } [ COLLATE collation ] [ opclass ] [ ASC | 916 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE DESC ] [ NULLS { FIRST | LAST } ] [, ...] ) [ INCLUDE ( column_name [, ...] ) ] [GLOBAL | LOCAL] [ WITH ( storage_parameter = value [, ... ] ) ] [ TABLESPACE tablespace_name ] [ UNUSABLE | USABLE ] [ COMMENT 'String' ] [ WHERE predicate ] 语义 UNIQUE 指定 UNIQUE 关键字时,创建索引时会检测表中已存在数据的唯一性,后续插入数据时也需要保证索引 列数据的唯一性。当插入或者更新导致数据重复时会报错。 当唯一索引被应用在分区表上时会有额外的限制,请参考CREATE TABLE 。 917 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE CONCURRENTLY 当使用了这个选项时,KingbaseES 在构建索引时不会取得任何会阻止该表上并发插入、更新或者删除的 锁。而标准的索引构建将会把表锁住以阻止对表的写(但不阻塞读),这种锁定会持续到索引创建完毕。 IF NOT EXISTS 如果一个同名关系已经存在则不要抛出错误。这种情况下会发出一个提示。注意着并不保证现有的索引与 将要创建的索引有任何相似。当 IF NOT EXISTS 被指定时,需要指定索引名。 INCLUDE 可选的 INCLUDE 子句指定一个列的列表,其中的列将被包括在索引中作为非键列。非键列不能作为索引 扫描的条件,并且该索引所强制的任何唯一性或者排除约束都不会考虑它们。但是,只用索引的扫描可以 返回非键列的内容而无需访问该索引的基表,因为在索引项中就能直接拿到它们。因此,非键列的增加允 许查询使用只用索引的扫描,否则就无法使用。 保守地向索引中增加非键列是明智的,特别是很宽的列。如果一个索引元组超过索引类型允许的最大尺 寸,数据插入将会失败。在任何情况下,非键列都会重复来自索引基表的数据并且让索引的尺寸膨胀,因 此可能会拖慢搜索。 INCLUDE 子句中列出的列不需要合适的操作符类,甚至数据类型没有为给定的访问方法定义操作符类的列 都可以包括在这个子句中。 不支持把表达式作为被包括列,因为它们不能被用在只用索引的扫描中。 当前,B-树和 GiST 索引访问方法支持这一特性。在 B-树和 GiST 索引中,INCLUDE 子句中列出的列的值 被包括在对应于堆元组的叶子元组中,但是不包括在用于树导航的上层索引项中。 name 要创建的索引名称。这里不能包括模式名,因为索引总是被创建在其基表所在的模式中。如果索引名称被 省略,KingbaseES 将基于基表名称和被索引列名称选择一个合适的名称。 ONLY 如果该表是分区表,指示不要在分区上递归创建索引。默认会递归创建索引。 GLOBAL 当指定 GLOBAL 时创建全局索引,同时指定 ONLY 和 GLOBAL 时后者生效。 LOCAL 当指定 LOCAL 时创建本地索引。对于分区表而言,当不指定 GLOBAL 或者 LOCAL 时默认创建本地索 引。对于非分区表而言,指定 GLOBAL/LOCAL 行为没有差别。 table_name 要被索引的表的名称(可以被模式限定)。 method 要使用的索引方法的名称。可以选择 btree、“bitmap“、hash、gist、spgist、gin 以及 brin。默认方 法是 btree。 918 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE column_name 一个表列的名称。 expression 一个基于一个或者更多个表列的表达式。如语法中所示,表达式通常必须被写在圆括号中。但是,如果该 表达式是一个函数调用的形式,圆括号可以被省略。 collation 要用于该索引的排序规则的名称。默认情况下,该索引使用被索引列的排序规则或者被索引表达式的结果 排序规则。当查询涉及到使用非默认排序规则的表达式时,使用非默认排序规则的索引就能派上用场。 opclass 一个操作符类的名称。详见下文。 ASC 指定上升排序(默认)。 DESC 指定下降排序。 NULLS FIRST 指定把空值排序在非空值前面。在指定 DESC 时,这是默认行为。 NULLS LAST 指定把空值排序在非空值后面。在没有指定 DESC 时,这是默认行为。 storage_parameter 索引方法相关的存储参数的名称。 tablespace_name 在其中创建索引的表空间。如果没有指定,将会使用 default_index_tablespace。或者对临时表上的索引 使用 temp_tablespaces。 如 果 default_index_tablespace 没 有 被 设 置, 并 且 CREATE INDEX 也没有显式的指定一个 TABLESPACE,那么 INDEX 的将会建立在 default_tablespace 所指定的表空间中。 predicate 部分索引的约束表达式。 USABLE|UNUSABLE 指定索引状态为可用或者不可用,默认是 USABLE 可用状态。可以通过查询系统表 sys_index 的 indisvalid 和 indisready 字段,确认索引的可用状态。 COMMENT 'String' 为索引添加注释,此功能仅限在 MySQL 模式下使用。 919 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE 示例 在表 films 中的列 title 上创建一个 B-树索引: CREATE UNIQUE INDEX title_idx ON films (title); 要在表 films 的列 title 上创建一个唯一的 B-树索引并且包括列 director 和 rating: CREATE UNIQUE INDEX title_idx ON films (title) INCLUDE (director, rating); 在表达式 lower(title) 上创建一个索引来允许高效的大小写无关搜索: CREATE INDEX ON films ((lower(title))); (在这个例子中我们选择省略索引名称,这样系统会选择一个名字,通常是 films_lower_idx)。 创建一个具有非默认排序规则的索引: CREATE INDEX title_idx_german ON films (title COLLATE "de_DE"); 创建一个具有非默认空值排序顺序的索引: CREATE INDEX title_idx_nulls_low ON films (title NULLS FIRST); 创建一个具有非默认填充因子的索引: CREATE UNIQUE INDEX title_idx ON films (title) WITH (fillfactor = 70); 创建一个禁用快速更新的 GIN 索引: CREATE INDEX gin_idx ON documents_table USING GIN (locations) WITH (fastupdate = off); 在表 films 中的列 code 上创建一个而索引并且把索引放在表空间 indexspace 中: CREATE INDEX code_idx ON films (code) TABLESPACE indexspace; 在表 company 中的列 id 上创建一个 bitmap 索引,id 列类型为 int: CREATE INDEX idx_id ON company USING bitmap(id); 在一个点属性上创建一个 GiST 索引,这样我们可以在转换函数的结果上有效地使用 box 操作符: CREATE INDEX pointloc ON points USING gist (box(location,location)); SELECT * FROM points WHERE box(location,location) && '(0,0),(1,1)'::box; 创建一个表而不排斥对表的写操作: 920 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE CREATE INDEX CONCURRENTLY sales_quantity_index ON sales_table (quantity); 在 table_name 表 column_name 列创建一个不可用状态的索引: CREATE INDEX index_name ON table_name (column_name) UNUSABLE; 在 MySQL 模式的数据库下,创建包含注释的索引: CREATE INDEX idx ON test_comment(id) COMMENT 'index for test_comment'; 兼容性 CREATE INDEX 是一种 KingbaseES 的语言扩展。在 SQL 标准中没有对于索引的规定。 其他 1. 索引存储参数 可选的 WITH 子句为索引指定存储参数。每一种索引方法都有自己的存储参数集合。B-树、哈希、GiST 以及 SP-GiST 索引方法都接受这个参数: fillfactor 索引的填充因子是一个百分数,它决定索引方法将尝试填充索引页面的充满程度。对于 B-树,在初始的 索引构建过程中,叶子页面会被填充至该百分数,当在索引右端扩展索引(增加新的最大键值)时也会这 样处理。如果页面后来被完全填满,它们就会被分裂,导致索引的效率逐渐退化。B-树使用了默认的填充 因子 90,但是也可以选择为 10 到 100 的任何整数值。如果表是静态的,那么填充因子 100 是最好的,因 为它可以让索引的物理尺寸最小化。但是对于更新负荷很重的表,较小的填充因子有利于最小化对页面分 裂的需求。其他索引方法以不同但是大致类似的方式使用填充因子,不同方法的默认填充因子也不相同。 B-树索引还额外接受这个参数: vacuum_cleanup_index_scale_factor vacuum_cleanup_index_scale_factor 针对每个索引的值。 buffer_keep 决定是否将该索引的某些页面固定在缓冲池中,被固定在缓冲池中的页面将不会参与轮换,从而提高索引 的并发访问性能。该参数适合在高频访问、且数据规模不大的索引上使用。该参数的取值决定了索引中的 哪些页面需要进行固定,合法的取值有: • ON 启用该功能,效果等同于 ROOT • ROOT 启用该功能,将根节点页面固定在缓冲池,如果根节点页面发生变化,则将也新的根节点固 定,但并不解除旧的根节点的固定状态。 • NONLEAF 启用该功能,将所有非叶子节点固定在缓冲池中,非叶子节点的数量发生变化也会对应更改 这些页面的固定状态。 • OFF 禁用该功能,将索引中所有页面解除固定状态。 GiST 还额外接受这个参数: buffering 921 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE 决定是否用缓冲构建技术来构建索引。OFF 会禁用它,ON 则启用该特性,如果设置为 AUTO 则初始会禁用 它,但是一旦索引尺寸到达 effective_cache_size 就会随时打开。默认值是 AUTO。 GIN 索引接受不同的参数: fastupdate 这个设置控制快速更新技术的使用。它是一个布尔参数:ON 启用快速更新,OFF 禁用之(ON 和 OFF 的其 他写法在 设置参数中有介绍)。默认是 ON。 注意: 通过 ALTER INDEX 关闭 fastupdate``会阻止未来的更新进入到待处理索引项列表中,但它不会自己处理之 前的待处理项。可以使用\ ``VACUUM 或者调用 “gin_clean_pending_list“确保处理完待处理列表的项。 gin_pending_list_limit 自定义 gin_pending_list_limit 参数。这个值要以千字节来指定。 BRIN 索引接受不同的参数: pages_per_range 定义用于每一个 BRIN 索引项的块范围由多少个表块组成。默认是 128。 autosummarize 定义是否只要在下一个页面上检测到插入就为前面的页面范围运行概要操作。 BITMAP 索引不接受额外的参数。 2. 并发构建索引 创建索引可能会干扰数据库的常规操作。通常 KingbaseES 会锁住要被索引的表,让它不能被写入,并且用该表 上的一次扫描来执行整个索引的构建。其他事务仍然可以读取表,但是如果它们尝试在该表上进行插入、更新或者删 除,它们会被阻塞直到索引构建完成。如果系统是一个生产数据库,这可能会导致严重的后果。索引非常大的表可能 会需要很多个小时,而且即使是较小的表,在构建索引过程中阻塞写入者一段时间在生产系统中也是不能接受的。 KingbaseES 支持构建索引时不阻塞写入。这种方法通过指定 CREATE INDEX 的 CONCURRENTLY 选项实现。当使 用这个选项时,KingbaseES 必须执行该表的两次扫描,此外它必须等待所有现有可能会修改或者使用该索引的事务 终止。因此这种方法比起标准索引构建过程来说要做更多工作并且需要更多时间。但是,由于它允许在构建索引时继 续普通操作,这种方式对于在生产环境中增加新索引很有用。当然,由索引创建带来的额外 CPU 和 I/O 开销可能会 拖慢其他操作。 在并发索引构建中,索引实际上在一个事务中被录入到系统目录,然后在两个事务中发生两次表扫描。在每一次 表扫描之前,索引构建必须等待已经修改了表的现有事务终止。在第二次扫描之后,索引构建必须等待任何持有早于 第二次扫描的快照的事务终止。然后该索引最终能被标记为准备好使用,并且 CREATE INDEX 命令终止。但是即便那 样,该索引也不是立刻可以用于查询:在最坏的情况下,只要早于索引构建开始时存在的事务存在,该索引就无法使 用。 如果在扫描表示出现问题,例如死锁或者唯一索引中的唯一性被违背,CREATE INDEX 将会失败,但留下一个 “不可用”的索引。这个索引会被查询所忽略,因为它可能不完整。但是它仍将消耗更新开销。ksql 的\d 命令将把 这类索引报告为 INVALID: 922 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE kingbase=# \d tab Table "public.tab" Column | Type | Collation | Nullable | Default --------+---------+-----------+----------+--------col | integer | | | Indexes: "idx" btree (col) INVALID 这种情况下推荐的恢复方法是删除该索引并且尝试再次执行 CREATE INDEX CONCURRENTLY(另一种可能性是用 REINDEX INDEX CONCURRENTLY 重建该索引。)。 并发构建一个唯一索引时需要注意的另一点是,当第二次表扫描开始时,唯一约束已经被强制在其他事务上。这 意味着在该索引变得可用之前,其他查询中可能就会报告该约束被违背,或者甚至在索引构建最终失败的情况中也是 这样。还有,如果在第二次扫描时发生失败,“无效的”索引也会继续强制它的唯一性约束。 表达式索引和部分索引的并发构建也被支持。在这些表达式计算过程中发生的错误可能导致和上述唯一约束违背 类似的行为。 常规索引构建允许在同一个表上同时构建其他常规索引,但是在一个表上同时只能有一个并发索引构建发生。在 两种情况下,在索引被构建时不允许表的模式修改。另一个不同是,一个常规 CREATE INDEX 命令可以在一个事务块 中执行,但是 CREATE INDEX CONCURRENTLY 不行。 目前不支持分区表上索引的并发构建。但是,您可以在每个分区上分别并发地构建索引,然后最后以非并发方式 创建分区索引,以减少对分区表的写操作被锁定的时间。在这种情况下,构建分区索引只是一个元数据操作。 3. 说明 关于索引何时能被使用、何时不被使用以及什么情况下它们有用的信息请见 索引。 当前,只有 B-树、位图、GiST、GIN 和 BRIN 索引方法支持多列索引。默认最多可以索引 32 个域(可以在构 建 KingbaseES 修改这种限制)。当前只有 B-树支持唯一索引。 为索引的每一列可以指定一个操作符类。该操作符类标识要被该索引用于该列的操作符。例如,一个四字节整数 上的 B-树索引会使用 int4_ops 类。这个操作符类包括了用于四字节整数的比较函数。实际上,通常列数据类型的 默认操作符类就足够了。对某些数据类型指定操作符类的主要原因是,可能会有多于一种有意义的顺序。例如,我们 可能想用绝对值或者实数部分对复数类型排序。我们可以通过为该数据类型定义两个操作符类来做到,并且在创建索 引时选择其中合适的类。更多 当在一个分区表上调用 CREATE INDEX 时,默认的行为是递归到所有的分区上以确保它们都具有匹配的索引。 每一个分区首先会被检查是否有一个等效的索引存在,如果有则该索引将被挂接为被创建索引的一个分区索引,而被 创建的索引将成为其父索引。如果不存在匹配的索引,则会创建一个新的索引并且自动进行挂接。如果命令中没有指 定索引名称,每个分区中的新索引的名称将被自动决定。如果指定了 ONLY 选项,则不会进行递归,并且该索引会被 标记为无效(一旦所有的分区都得到该索引,ALTER INDEX ... ATTACH PARTITION 可以把该索引标记为有效)。但 是,要注意不管是否指定这一选项,未来使用 CREATE TABLE ... PARTITION OF 创建的任何分区将自动有一个匹配 的索引,不管有没有指定 ONLY。 对于支持有序扫描的索引方法(当前只有 B-树),可以指定可选子句 ASC、DESC、NULLS FIRST 以及 NULLS LAST 来修改索引的排序顺序。由于一个有序索引能前向或者反向扫描,通常创建一个单列 DESC 索引没什么用处— 923 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE 一个常规索引已经提供了排序顺序。这些选项的价值是可以创建多列索引,让它的排序顺序匹配有混合排序要求的 查询,例如 SELECT ... ORDER BY x ASC, y DESC。如果你想要在依靠索引避免排序步骤的查询中支持“空值排序 低”这种行为,NULLS 选项就能派上用场,默认的行为是“空值排序高”。 对于大多数索引方法,索引的创建速度取决于 maintenance_work_mem 的设置。较大的值将会减少索引创建所 需的时间,当然不要把它设置得超过实际可用的内存量(那会迫使机器进行交换)。 KingbaseES 可以在构建索引时利用多个 CPU 以更快地处理表行。这种特性被称为并行索引构建。对于支持并 行构建索引的索引方法(当前只有 B-树),maintenance_work_mem 指定每次索引构建操作整体可用的最大内存量, 而不管启动了多少工作者进程。一般来说,一个代价模型(如果有)自动判断应该请求多少工作者进程。 增 加 maintenance_work_mem 可 以 让 并 行 索 引 构 建 受 益, 而 等 效 的 串 行 索 引 构 建 将 无 法 受 益 或 者 得 到 很 小 的 益 处。 注 意 maintenance_work_mem 总 的 maintenance_work_mem 可 能 会 影 响 请 求 的 工 作 者 进 程 的 数 量, 因 为 并 行 工 作 者 必 须 在 预 算 中 占 有 至 少 32MB 的 份 额。 还 必 须 有 32MB 的 份 额 留 给 领 袖 进 程。 增 加 max_parallel_maintenance_workers 可以允许使用更多的工作者,这将降低索引创建所需的时间,只要索引构 建不是 I/O 密集型的。当然,还需要有足够的 CPU 计算能力,否则工作者们会闲置。 通过ALTER TABLE 为 parallel_workers 设置一个值直接控制着 CREATE INDEX 会对表请求多少并行工作 者进程。这会完全绕过代价模型,并且防止 maintenance_work_mem 对请求多少并行工作者产生影响。通过 ALTER TABLE 将 parallel_workers 设置为 0 将禁用所有情况下的并行索引构建。 提示: 在把 parallel_workers 用于调优一次索引构建之后,你可能想要重置 parallel_workers。这可以避免对 查询计划的无意更改,因为 parallel_workers 影响所有的并行表扫描。 虽然带有 CONCURRENTLY 选项的 CREATE INDEX 支持并行构建并且没有特殊的限制,但只有第一次表扫描会实际 以并行方式执行。 使用DROP INDEX 可以移除一个索引。 以前的 KingbaseES 发行也有一种 R-树索引方法。这种方法已经被移除,因为它比起 GiST 方法来说没有什 么明显的优势。如果指定了 USING rtree,CREATE INDEX 将会把它解释为 USING gist,以便把旧的数据库转换成 GiST。 14.21 CREATE LANGUAGE 用途 CREATE LANGUAGE 为一个 KingbaseES 数据库注册一种新的过程语言。接着,可以用这种新语言定义函数和触发 器过程。 注意: 从 KingbaseES V8R2 开始,大多数过程语言已经被做成了“扩展”,并且应该用CREATE EXTENSION 而 不是 CREATE LANGUAGE 来安装。CREATE LANGUAGE 的直接使用现在应该被限制在扩展安装脚本中。如果在数据库中 924 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE 有一种“裸”语言(可能是一次升级的结果),可以用 CREATE EXTENSION langname FROM unpackaged 把它转换 成一个扩展。 CREATE LANGUAGE 实际上把该语言名称与负责执行用该语言编写的函数的处理器函数关联在一起。 有两种形式的 CREATE LANGUAGE 命令。在第一种形式中,用户只提供想要的语言的名称。KingbaseES 服务器 会查询 sys_pltemplate 系统目录来决定正确的参数。在第二种形式中,用户要提供语言参数和语言名称。第二种形 式可以被用来创建一种没有定义在 sys_pltemplate 中的语言,但是这种方法被认为即将废弃。 当服务器在 sys_pltemplate 目录中为给定的语言名称找到一个项时,即使命令中已经包括了语言参数,它也将 使用目录中的数据。这种行为简化了旧转储文件的载入,旧转储文件很可能包含过时的信息。 前置条件 通 常, 用 户 必 须 拥 有 KingbaseES 超 级 用 户 特 权 来 注 册 一 种 新 的 语 言。 但 是, 如 果 该 语 言 被 列 举 在 sys_pltemplate 目录中并且被标记为允许由数据库拥有者创建(tmpldbacreate 为真),则数据库的拥有者可以把 新语言注册在数据库中。默认是可信的语言能够由数据库拥有者创建,但是超级用户可以通过修改 sys_pltemplate 的内容来调整这种行为。语言的创建者会成为它的拥有者,并且以后可以删除它、对它重命名或者把它赋予给一个新 的拥有者。 CREATE OR REPLACE LANGUAGE 将创建或者替换一种现有的定义。如果该语言已经存在,其参数会被根据指定的 值或者来自 sys_pltemplate 的值更新。但该语言的拥有关系和权限设置不会更改,并且任何已有的用该语言编写的 函数仍然被假定有效。除了创建一种语言的普通特权需求,用户还必须是超级用户或者已有语言的拥有者。REPLACE 情况主要被用来确保该语言存在。如果该语言有一个 sys_pltemplate 项,那么 REPLACE 将不会实际更改现有定义的 任何东西,除非从该语言被创建以来 sys_pltemplate 已经被修改过(很少见的情况)。 语法 CREATE [ OR REPLACE ] [ PROCEDURAL ] LANGUAGE name CREATE [ OR REPLACE ] [ TRUSTED ] [ PROCEDURAL ] LANGUAGE name HANDLER call_handler [ INLINE inline_handler ] [ VALIDATOR valfunction ] 语义 925 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE TRUSTED TRUSTED 指定该语言不会授予用户不该具有的数据访问。如果在注册语言时这个关键词被省略,只有具有 KingbaseES 超级用户特权的用户才能使用该语言创建新函数。 PROCEDURAL 这是一个噪声词。 name 新过程语言的名称。该名称必须在该数据库的语言中唯一。 为了向后兼容,名称可以用单引号围绕。 HANDLER call_handler “call_handler“ 是一个之前注册的函数的名称,它将被调用来执行该过程语言的函数。一种过程语言的调 用处理器必须以一种编译型语言(如 C)编写并且具有版本 1 的调用约定,它必须在 KingbaseES 内注册 为一个没有参数并且返回 language_handler 类型的函数。language_handler 是一种占位符类型,它被 用来标识该函数为一个调用处理器。 INLINE inline_handler “inline_handler“* 是一个之前注册的函数的名称,它将被调用来执行一个该语言的匿名代码块(DO < :ref:‘DO‘ 命令)。如果没有指定 *“inline_handler“函数,则该语言不支持匿名代码块。该处理器函数必 须接受一个 internal 类型的参数,该参数将是 DO 命令的内部表示,而且它通常将返回 void。该处理 器的返回值会被忽略。 VALIDATOR valfunction “valfunction“ 是一个之前注册的函数的名称,当一个该语言的新函数被创建时会调用该函数来验证新函 数。如果没有指定验证器函数,那么一个新函数被创建时不会被检查。验证器函数必须接受一个 oid 类 型的参数,它将是要被创建的函数的 OID,而且它通常将返回 void。 一个验证器函数通常会检查函数体中的语法正确性,但是它也能查看函数的其他属性,例如该语言能否处 理特定的参数类型。为了发出一个错误,验证器函数应该使用 ereport() 函数。验证器函数的返回值会 被忽略。 如果指定的语言名称在 sys_pltemplate 中有一项,服务器会忽略 TRUSTED 选项和支持函数的名称。 示例 创建任何标准过程语言的最好的方式是: CREATE LANGUAGE plperl; 对于 sys_pltemplate 目录不知道的一种语言,需要这样的命令序列: CREATE FUNCTION plsample_call_handler() RETURNS language_handler AS '$libdir/plsample' LANGUAGE C; 926 第 14 章 SQL 语句:COMMIT 到 CREATE LANGUAGE CREATE LANGUAGE plsample HANDLER plsample_call_handler; 兼容性 CREATE LANGUAGE 是一种 KingbaseES 扩展。 其他 使用DROP LANGUAGE 删除过程语言。 系统目录 sys_language(见 sys_language )记录着有关当前已安装的语言的信息。还有,ksql 命令\dL 列出已 安装的语言。 要以一种过程语言创建函数,用户必须具有对于该语言的 USAGE 特权。默认情况下,对于可信语言,USAGE 被授 予给 PUBLIC(即所有人)。如果需要可以将它收回。 过程语言对于单个数据库来说是本地的。但是,一种语言可以被安装在 template1 数据库中,这会导致它在所 有后续创建的数据库中自动变得可用。 如果对语言在服务器的 sys_pltemplate 中没有一项,调用处理器函数、内联处理器函数(如果有)以及验证器 函数(如果有)必须已经存在。但是当有一个那样的项时,这些函数不必已经存在。如果它们在数据库中不存在,将 自动定义它们(如果安装中实现该语言的共享库不可用可能会导致 CREATE LANGUAGE 失败)。 在 KingbaseES 版本 V7 之前,需要将处理器函数声明为返回占位符类型 opaque 而不是 language_handler。 为了支持载入旧的转储文件,CREATE LANGUAGE 将接受被声明为返回 opaque 的函数,但是它将发出一个提示并且把 该函数的声明返回类型改为 language_handler。 927 第 15 章 SQL 语句:CREATE MATERIALIZED VIEW 到 CREATE SCHEMA 15章 SQL 语句:CREATE MATERIALIZED 第 VIEW 到 CREATE SCHEMA 本章包含以下 SQL 语句: • CREATE MATERIALIZED VIEW • CREATE OPERATOR CLASS • CREATE OPERATOR • CREATE OPERATOR FAMILY • CREATE PACKAGE • CREATE PACKAGE BODY • CREATE POLICY • CREATE PROCEDURE • CREATE PUBLICATION • CREATE RESOURCE GROUP • CREATE ROLE • CREATE RULE • CREATE SCHEMA 15.1 CREATE MATERIALIZED VIEW 用途 CREATE MATERIALIZED VIEW 定义一个查询的物化视图。在该命令被发出时,查询会被执行并且被用来填充该视 图(除非使用了 WITH NO DATA),并且后来可能会用 REFRESH MATERIALIZED VIEW 进行刷新。 928 第 15 章 SQL 语句:CREATE MATERIALIZED VIEW 到 CREATE SCHEMA CREATE MATERIALIZED VIEW 类似于 CREATE TABLE AS,但是它还会记住被用来初始化该视图的查询,这样它可 以在后来被命令刷新。一个物化视图有很多和表相同的属性,但是不支持临时物化视图。 前置条件 无 语法 CREATE MATERIALIZED VIEW [ IF NOT EXISTS ] table_name [ (column_name [, ...] ) ] [ USING method ] [ WITH ( storage_parameter [= value] [, ... ] ) ] [ TABLESPACE tablespace_name ] AS query [ WITH [ NO ] DATA ] 语义 IF NOT EXISTS 如果已经存在一个同名的物化视图时不要抛出错误。这种情况下会发出一个提示。注意这不保证现有的物 化视图与即将创建的物化视图相似。 table_name 要创建的物化视图的名称(可以被模式限定)。 column_name 新物化视图中的一个列名。如果没有提供列名,会从查询的输出列名来得到。 USING method 此可选子句指定用于存储新物化视图内容的表访问方法; 该方法需要是类型 TABLE 的访问方法。如果未 指定此选项,则为新物化视图选择默认表访问方法。有关更多信息,参见 default_table_access_method 929 第 15 章 SQL 语句:CREATE MATERIALIZED VIEW 到 CREATE SCHEMA 。 WITH ( storage_parameter [= value] [, ... ] ) 这个子句为新的物化视图指定可选的存储参数。所有 CREATE TABLE 支持的参数 CREATE MATERIALIZED VIEW 也支持。详见CREATE TABLE 。 TABLESPACE tablespace_name “tablespace_name“是 要 把 新 物 化 视 图 创 建 在 其 中 的 表 空 间 的 名 称。 如 果 没 有 指 定, 查 阅 de- fault_tablespace 。 query 一个 ref:SELECT 或者 VALUES 命令。这个查询将在一个安全受限的操作中运行。特别地,对本身会创 建临时表的函数的调用将会失败。 WITH [ NO ] DATA 这个子句指定物化视图是否在创建时被填充。如果不是,该物化视图将被标记为不可扫描并且在 REFRESH MATERIALIZED VIEW 被使用前不能被查询。 示例 创建物化视图 mymatview: CREATE MATERIALIZED VIEW mymatview AS SELECT * FROM mytab; 15.2 CREATE OPERATOR CLASS 用途 CREATE OPERATOR CLASS 创建新的操作符类。一个操作符类定义一种特殊的数据类型如何被用于一个索引。操 作符类指定为该数据类型和索引方法扮演特殊角色或者“策略”的操作符。操作符类还指定当该操作符类被选择用于 一个索引列时,索引方法要使用的支持过程。操作符类所使用的所有操作符和函数必须在操作符类被创建之前被定义 好。 如果给出了一个模式名称,那么该操作符类会被创建在指定模式中。否则,它会被创建在当前模式中。同一模式 中的两个操作符类只有在被用于不同的索引方法时才可以具有相同的名称。 CREATE OPERATOR CLASS 当前不会检查操作符类定义是否包括该索引方法所要求的所有操作符和函数,也不会 检查这些操作符和函数是否构成一个一致的集合。定义一个合法的操作符类是用户的责任。 相 关 的 操 作 符 类 可 以 被 组 成 操 作 符 族。 要 把 一 个 新 的 操 作 符 类 加 入 到 一 个 现 有 的 族 中, 可 以 在 CREATE OPERATOR CLASS 中指定 FAMILY 选项。如果没有这个选项,新的类会被放到一个同名的族中(如果族不存在会 创建)。 前置条件 930 第 15 章 SQL 语句:CREATE MATERIALIZED VIEW 到 CREATE SCHEMA 定义操作符类的用户将成为其拥有者。当前,创建用户必须是超级用户(做出这种限制是因为错误的操作符类定 义会让服务器混淆甚至崩溃)。 语法 CREATE OPERATOR CLASS name [ DEFAULT ] FOR TYPE data_type USING index_method [ FAMILY family_name ] AS { OPERATOR strategy_number operator_name [ ( op_type, op_type ) ] [ FOR SEARCH | FOR ORDER BY sort_family_name ] | FUNCTION support_number [ ( op_type [ , op_type ] ) ] function_name ( argument_type [, ...] ) | STORAGE storage_type } [, ... ] 语义 name 要创建的操作符类的名称。该名称可以被模式限定。 DEFAULT 如果存在,该操作符类将成为其数据类型的默认操作符类。对一种特定的数据类型和索引方法至多有一个 默认操作符类。 data_type 这个操作符类所用于的列数据类型。 index_method 这个操作符类所用于的索引方法的名称。 family_name 931 第 15 章 SQL 语句:CREATE MATERIALIZED VIEW 到 CREATE SCHEMA 要把这个操作符类加入其中的已有操作符族的名称。如果没有指定,将使用一个同名操作符族(如果还不 存在则创建)。 strategy_number 用于一个与该操作符类相关联的操作符的索引方法策略号。 operator_name 一个与该操作符类相关联的操作符的名称(可以被模式限定)。 op_type 在一个 OPERATOR 子句中,这表示该操作符的操作数数据类型,或者用 NONE 来表示一个左一元或者右一 元操作符。在操作数数据类型与该操作符的数据类型相同的一般情况下,操作数的数据类型可以被省略。 在一个 FUNCTION 子句中,这表示该函数要支持的操作数数据类型,如果它与该函数的输入数据类型(对 于 B-树比较函数和哈希函数)或者操作符类的数据类型(对于 B-树排序支持函数和所有 GiST、SPGiST、GIN 和 BRIN 操作符类中的函数)不同。这些默认值是正确的,并且 “op_type“因此不必在 FUNCTION 子句中被指定,对于 B-树排序支持函数的情况来说,这表示跨数据类型比较。 sort_family_name 一个现有 btree 操作符族的名称(可以是模式限定的),它描述与一种排序操作符相关联的排序顺序。 如果 FOR SEARCH 和 FOR ORDER BY 都没有被指定,那么 FOR SEARCH 是默认值。 support_number 用于一个与该操作符类相关联的函数的索引方法支持过程编号。 function_name 一个用于该操作符类的索引方法支持过程的函数名称(可以是模式限定的)。 argument_type 该函数的参数数据类型。 storage_type 实际存储在索引中的数据类型。通常这和列数据类型相同,但是有些索引方法(当前有 GiST、GIN 和 BRIN)允许它们不同。除非索引方法允许使用不同的类型,STORAGE 子句必须被省略。如果 op_type 列 被指定为 anyarray,那么 storage_type 可以被声明为 anyelement 以指示索引条目是属于为每个特定 索引创建的实际数组类型的元素类型的成员。 OPERATOR 、FUNCTION 和 STORAGE 子句可以以任何顺序出现。 示例 下面的例子为数据类型 _int4(int4 数组)定义了一个 GiST 索引操作符。 CREATE OPERATOR CLASS gist__int_ops DEFAULT FOR TYPE _int4 USING gist AS OPERATOR 3 &&, 932 第 15 章 SQL 语句:CREATE MATERIALIZED VIEW 到 CREATE SCHEMA OPERATOR 6 = (anyarray, anyarray), OPERATOR 7 @>, OPERATOR 8 <@, OPERATOR 20 @@ (_int4, query_int), FUNCTION 1 g_int_consistent (internal, _int4, smallint, oid, internal), FUNCTION 2 g_int_union (internal, internal), FUNCTION 3 g_int_compress (internal), FUNCTION 4 g_int_decompress (internal), FUNCTION 5 g_int_penalty (internal, internal, internal), FUNCTION 6 g_int_picksplit (internal, internal), FUNCTION 7 g_int_same (_int4, _int4, internal); 其他 因为索引机制在使用函数之前不检查它们的权限,将一个函数或者操作符包括在一个操作符类中相当于在其上授 予公共执行权限。这对操作符类中很有用的函数来说通常不成问题。 操作符不应该用 SQL 函数定义。SQL 函数很有可能会被内联到调用查询中,这会妨碍优化器识别该查询匹配一 个索引。 在 KingbaseES V7 之前,OPERATOR 子句可以包括一个 RECHECK 选项。现在已经不再支持,因为一个索引操作符 是否为“有损的”现在是在运行时实时决定的。这允许在一个操作符可能是或者可能不是有损的情况下有效地处理。 15.3 CREATE OPERATOR 用途 CREATE OPERATOR 定义一个新的操作符 “name“。定义操作符的用户会成为该操作符的拥有者。如果给出一个模 式名,该操作符将被创建在指定的模式中。否则它会被创建在当前模式中。 操作符名称是最多 NAMEDATALEN-1(默认为 63)个字符的序列,这些字符可以是: + - * / < > = ~ ! @ # % ^ & | ` ? 对名称的选择有一些限制: • -- and /* 不能出现在操作符名称中,因为它们会被当做一段注释的开始。 • 多字符操作符名称不能以 + 或者-结束,除非该名称也包含至少一个下列字符: | | ~ ! @ # % ^ & | ` ? 例如,@-是一个被允许的操作符名称,而 *-不是。这种限制允许 KingbaseES 解析 SQL 兼容的命令而无 需记号之间的空格。 933 第 15 章 SQL 语句:CREATE MATERIALIZED VIEW 到 CREATE SCHEMA • 将 => 用作一个操作符名称已经不被推荐。在未来的发行中可能会被禁用。 • !=+, !=-, ^=+, ^=-, ||+, ||-, ^+, ^-, |+, |-这 10 个符号,将不允许被创建为自定义符号。 在输入时!= 和 ^= 都会被映射为<>,因此这两个名字总是等效的。 必须至少定义 LEFTARG 和 RIGHTARG 中的一个。对于二元操作符,两者都必须被定义。对于右一元操作符,只 应该定义 LEFTARG,而对于左一元操作符只应该定义 RIGHTARG。 function_name 函数必须在之前已经用 CREATE FUNCTION 定义好,并且必须被定义为接受正确数量的指定类型 的参数。 在 CREATE OPERATOR 的语法中,关键词 FUNCTION 和 PROCEDURE 是等效的,但不管哪种情况下被引用的函数都 必须是一个函数而不是存储过程。这里对关键词 PROCEDURE 的是用是有历史原因的,现在已经被废弃。 其他子句指定可选的操作符优化子句。它们的含义在 操作符优化信息中有详细描述。 前置条件 要创建一个操作符,必须具有参数类型和返回类型上的 USAGE 特权,以及底层函数上的 EXECUTE 特权。如果指 定了一个交换子或者求反器操作符,必须拥有这些操作符。 语法 CREATE OPERATOR name ( {FUNCTION|PROCEDURE} = function_name [, LEFTARG = left_type ] [, RIGHTARG = right_type ] [, COMMUTATOR = com_op ] [, NEGATOR = neg_op ] [, RESTRICT = res_proc ] [, JOIN = join_proc ] [, HASHES ] [, MERGES ] ) 934 第 15 章 SQL 语句:CREATE MATERIALIZED VIEW 到 CREATE SCHEMA 语义 name 要定义的操作符的名称。允许使用的字符请见上文。名称可以被模式限定,例如 CREATE OPERATOR myschema.+ (...)。如果没有被模式限定,该操作符将被创建在当前模式中。如果两个同一模式中的操 作符在不同的数据类型上操作,它们可以具有相同的名称。这被称为重载。 function_name 用来实现这个操作符的函数。 left_type 这个操作符的左操作数(如果有)的数据类型。忽略这个选项可以表示一个左一元操作符。 right_type 这个操作符的右操作数(如果有)的数据类型。忽略这个选项可以表示一个右一元操作符。 com_op 这个操作符的交换子。 neg_op 这个操作符的求反器。 res_proc 用于这个操作符的限制选择度估计函数。 join_proc 用于这个操作符的连接选择度估算函数。 HASHES 表示这个操作符可以支持哈希连接。 MERGES 表示这个操作符可以支持归并连接。 要在 “com_op“ 或者其他可选参数中给出一个模式限定的操作符名称,请使用 OPERATOR() 语法,例如: COMMUTATOR = OPERATOR(myschema.===) , 示例 下面的命令为数据类型 box 定义了一种新的操作符--面积相等: CREATE OPERATOR === ( LEFTARG = box, RIGHTARG = box, FUNCTION = area_equal_function, COMMUTATOR = ===, 935 第 15 章 SQL 语句:CREATE MATERIALIZED VIEW 到 CREATE SCHEMA NEGATOR = !==, RESTRICT = area_restriction_function, JOIN = area_join_function, HASHES, MERGES ); 其他 进一步的信息可参考 用户定义的操作符。 无法在 CREATE OPERATOR 中指定一个操作符的词法优先级,因为解析器的优先级行为是硬写在代码中的。详见 操作符优先级。 废弃的选项 SORT1、SORT2、LTCMP 以及 GTCMP 以前被用来指定与支持归并连接的操作符相关的排序操作符的名 称。现在不再需要它们了,因为相关操作符的信息可以在 B-树的操作符族中找到。如果给出了这些选项之一,它会 被忽略(除非是为了隐式设置 MERGES 为真)。 使用DROP OPERATOR 从数据库中删除用户定义的操作符。 使用ALTER OPERATOR 修改数据库中的操作符。 15.4 CREATE OPERATOR FAMILY 用途 CREATE OPERATOR FAMILY 创建一个新的操作符族。一个操作符族定义一个相关操作符类组成的集合,并且可能 还包含一些额外的、与这些操作符类兼容但对于任何个体索引的功能不是至关重要的操作符和支持函数(对索引至关 重要的操作符和函数应该被分组在相关的操作符类中,而不是“松散地”在操作符中。通常,单一数据类型操作符被 限制在操作符类中,而跨数据类型操作符可以松散地存在于一个包含用于两种数据类型的操作符类的操作符族中)。 新的操作符族初始时为空。应该通过发出后续的 CREATE OPERATOR CLASS 命令来增加包含在其中的操作符类, 还可以用可选的 ALTER OPERATOR FAMILY 命令来增加“松散的”操作符和它们对应的支持函数。 如果给出一个模式名称,该操作符族会被创建在指定的模式中。否则,它会被创建在当前模式中。只有当同一个 模式中的两个操作符族是用于不同的索引方法时,它们才能拥有相同的名字。 前置条件 定义一个操作符族的用户将成为它的拥有者。当前,创建用户必须是超级用户(做出这样的限制是因为错误的操 作符族会让服务器混淆甚至崩溃)。 语法 CREATE OPERATOR FAMILY name USING index_method 936 第 15 章 SQL 语句:CREATE MATERIALIZED VIEW 到 CREATE SCHEMA 语义 name 要创建的操作符族的名称。该名称可以被模式限定。 index_method 这个操作符族要用于的索引方法的名称。 示例 创建一个操作符族 CREATE OPERATOR FAMILY my_op_family USING btree; 兼容性 CREATE OPERATOR FAMILY 是一种 KingbaseES 扩展。在 SQL 标准中没有 CREATE OPERATOR FAMILY 语句。 15.5 CREATE PACKAGE 用途 CREATE PACKAGE 定义一个新的包规范。CREATE OR REPLACE PACKAGE 将创建一个新的包规范或者替换一个现有 的包规范。包规范中主要涵盖了各种公开资源的声明信息,它们包括:类型、变量以及子过程的声明和编译指示命 令。子过程的声明是不包括子过程的实现的,这里的声明只包括子过程的名称、参数信息以及返回值信息。 前置条件 要创建一个包规范,用户必须具有该模式下的 CREATE 权限。 语法 CREATE [ OR REPLACE ] PACKAGE package_name [ FORCE ] [ AUTHID { CURRENT_USER | DEFINER } ] { AS | IS } [ < type_declaration > ] [ < variable_declaration > ] [ < cursor_declaration > ] [ < exception_declaration > ] [ < FUNCTION function_name [ ( [ argname [ argmode ] argtype [, ...] ] ) ] { RETURNS | RETURN } rettype ; ] [ PROCEDURE procedure_name [ ( [ argname [ argmode ] argtype [, ...] ] ) ] ; ] [ ... ] END [ package_name ]; 937 第 15 章 SQL 语句:CREATE MATERIALIZED VIEW 到 CREATE SCHEMA 语义 package_name 包的名字,可以有数据库名和模式名修饰,数据库名只能是当前数据库。 FORCE FORCE 作为一个与 OR REPLACE 配合使用的选项参数,当使用 CREATE PACKAGE 语句创建一个对象类型替 换一个已有包时,FORCE 选项可以决定如何处理被替换包的依赖关系。 含有 FORCE 选项的替换创建语句 (CREATE OR REPLACE PACKAGE) 会级联删除所有对原包有依赖的对象, 并成功创建新的包。不含有 FORCE 选项的替换创建语句则会在检测到原有包处于被依赖状态时进行提示 并阻止新包成功创建。 由于 FORCE 选项会级联删除所有依赖对象,请谨慎使用。 AUTHID CURRENT_USER 调用包对象时检查当前调用者的用户权限。AUTHID CURRENT_USER 为默认值。 AUTHID DEFINER 调用包对象时检查定义者的用户权限。 type_declaration 定义类型,详见 PL/SQL 数据类型。 variable_declaration 定义变量,详见 PL/SQL 数据类型。 cursor_declaration 定义游标变量,详见 游标变量。 exception_declaration 定义异常,详见 异常处理。 function_name 要定义在包内的函数名称。 argmode 一个参数的模式:IN、OUT 或者 INOUT。如果省略,默认为 IN。注意 OUT 和 INOUT 参数不能和 RETURN / RETURNS 符号一起使用。 938 第 15 章 SQL 语句:CREATE MATERIALIZED VIEW 到 CREATE SCHEMA argname 一个参数的名称。包规范中的参数名称是没有意义的。但是你可以在定义一个包规范中的函数声明时使用 参数名来提高可读性。 argtype 该函数参数(如果有)的数据类型(可以是模式限定的)。参数类型可以是基本类型、组合类型或者域类 型,或者可以引用一个表列的类型。 根据实现语言,也可以允许指定 cstring 之类的” 伪类型”。伪类型表示实际参数类型没有被完整指定或 者不属于普通 SQL 数据类型集合。 可以写 table_name.column_name%TYPE 来引用一列的类型。使用这种特性有时可以帮助创建一个不受 表定义更改影响的函数。 rettype 返回数据类型(可能被模式限定)。返回类型可以是一种基本类型、组合类型或者域类型,也可以引用一 个表列的类型。如果该函数不会返回一个值,可以指定返回类型为 void。 可以写 table_name.column_name%TYPE 来引用一列的类型。 procedure_name 定义在包内的存储过程名称。 示例 例 1:创建一个包规范 \set SQLTERM / CREATE OR REPLACE PACKAGE pac AUTHID DEFINER AS i INT; j float NOT NULL DEFAULT 200; pi CONSTANT float := 3.14159265; cur CURSOR FOR SELECT 100; CURSOR cur2 (a INT) FOR SELECT 2; cur3 CURSOR (b INT) FOR SELECT 3; refcur REFCURSOR; FUNCTION f(i INT) RETURNS INT; FUNCTION f2(j OUT INT) RETURNS INT; PROCEDURE p(i float); PROCEDURE p2(i INT, j INT); END pac; / \set SQLTERM ; 939 第 15 章 SQL 语句:CREATE MATERIALIZED VIEW 到 CREATE SCHEMA 15.6 CREATE PACKAGE BODY 用途 CREATE PACKAGE BODY 定义一个新的包体。CREATE OR REPLACE PACKAGE BODY 将创建一个新的包体或者替换一 个现有的包体。 当数据库管理员不是包规范的属主时,也可以创建包体,这时包体的属主仍与包规范为同一属主。 如果包规范中定义了子程序,那么这个包必须有包体,否则这个包可以没有包体。包规范和包体必须在同一模式 下。包体中的子程序的定义必须与包规范中的声明一致。 包体主要有两个作用: a. 用于提供对包规范中子程序的定义; b. 允许为包编写特定的初始化代码(类似面向对象中对象的构造函数)。 前置条件 要定义一个包体,用户必须具有该模式下的 CREATE 权限。 语法 CREATE [ OR REPLACE ] PACKAGE BODY package_name { AS | IS } [ < type_declaration > ] [ < variable_declaration > ] [ < cursor_declaration > ] [ < exception_declaration > ] [ FUNCTION function_name [ ( [ argname [ argmode ] argtype [ { DEFAULT | := } default_expr ] [, ...] ] ) ] [ { RETURNS | RETURN } rettype ] { AS | IS } [ plsql_block ] ] [ PROCEDURE procedure_name [ ( [ argname [ argmode ] argtype [ { DEFAULT | := } default_expr ] [, ...] ] ) ] { AS | IS } [ plsql_block ] ] [...] [ BEGIN sequence_of_statements ] END [ package_name ]; 940 第 15 章 SQL 语句:CREATE MATERIALIZED VIEW 到 CREATE SCHEMA 语义 package_name 包的名字,可以有数据库名和模式名修饰,数据库名只能是当前数据库。 type_declaration 定义类型,详见 PL/SQL 数据类型。 variable_declaration 定义变量,详见 PL/SQL 数据类型。 cursor_declaration 定义游标变量,详见 游标变量。 exception_declaration 定义异常,详见 异常处理。 function_name 要定义在包内的函数名称。 argmode 一个参数的模式:IN、OUT 或者 INOUT。如果省略,默认为 IN。注意 OUT 和 INOUT 参数不能和 RETURN / RETURNS 符号一起使用。 argname 一个参数的名称。包声明中的参数名称是没有意义的。但是可以在定义一个包声明中的函数声明时使用参 数名来提高可读性。 argtype 该函数参数(如果有)的数据类型(可以是模式限定的)。参数类型可以是基本类型、组合类型或者域类 型,或者可以引用一个表列的类型。 根据实现语言,也可以允许指定 cstring 之类的” 伪类型”。伪类型表示实际参数类型没有被完整指定或 者不属于普通 SQL 数据类型集合。 可以写 table_name.column_name%TYPE 来引用一列的类型。使用这种特性有时可以帮助创建一个不受 表定义更改影响的函数。 default_expr 941 第 15 章 SQL 语句:CREATE MATERIALIZED VIEW 到 CREATE SCHEMA 如果参数没有被指定值时要用作默认值的表达式。该表达式的值必须能被强制转为对应参数的类型。只有 输入(包括 INOUT)参数可以具有默认值。所有跟随在一个具有默认值的参数之后的输入参数也必须有默 认值。 rettype 返回数据类型(可能被模式限定)。返回类型可以是一种基本类型、组合类型或者域类型,也可以引用一 个表列的类型。如果该函数不会返回一个值,可以指定返回类型为 void。 可以写 table_name.column_name%TYPE 来引用一列的类型。 plsql_block 包括变量、常量、游标和类型定义的 PL/SQL 语言组成的块结构。 procedure_name 要定义在包内的存储过程名称。 sequence_of_statements PL/SQL 语言组成的函数体。 示例 例 1:包体不包含初始化函数 \set SQLTERM / CREATE OR REPLACE PACKAGE pac AS i INT := 100; FUNCTION f() RETURNS INT; END; / CREATE OR REPLACE PACKAGE BODY pac AS FUNCTION f() RETURNS INT AS BEGIN RETURN pac.i; END; END; / \set SQLTERM ; 例 2:包体包含初始化函数 \set SQLTERM / CREATE OR REPLACE PACKAGE pac AS i INT := 100; FUNCTION f() RETURNS INT; END; / 942 第 15 章 SQL 语句:CREATE MATERIALIZED VIEW 到 CREATE SCHEMA CREATE OR REPLACE PACKAGE BODY pac AS FUNCTION f() RETURNS INT AS BEGIN RETURN pac.i; END; BEGIN pac.i := pac.i * 100; END pac; / \set SQLTERM ; 15.7 CREATE POLICY 用途 CREATE POLICY 为一个表定义一条行级安全性策略。注意为了应用已被创建的策略,在表上必须启用行级安全性 (使用 ALTER TABLE ... ENABLE ROW LEVEL SECURITY)。 一条策略授予权限以选择、插入、更新或者删除匹配相关策略表达式的行。现有的表行会按照 USING 中指定 的表达式进行检查,而将要通过 INSERT 或 UPDATE 创建的新行会按照 WITH CHECK 中指定的表达式进行检查。当 USING 表达式对于一个给定行返回真时,该行对用户可见,而返回假或空时该行不可见。当一个“WITH CHECK“表 达式对一行返回真时,该行会被插入或更新,而如果返回假或空时会发生一个错误。 对于 INSERT 和 UPDATE 语句,在 BEFORE 触发器被引发后并且在任何数据修改真正发生之前,WITH CHECK 表 达式会被强制。因此,一个 BEFORE ROW 触发器可以修改要被插入的数据,从而影响安全性策略检查的结果。WITH CHECK 表达式在任何其他约束之前被强制。 策略名称是针对每个表的。因此,一个策略名称可以被用于很多个不同的表并且对于不同的表呈现适合于该表的 定义。 策略可以被应用于特定的命令或者特定的角色。除非特别指定,新创建的策略的默认行为是适用于所有命令和角 色。多个策略可以应用于单个命令,更多细节请见下文。表 1 总结了不同类型的策略如何应用于特定的命令。 对同时具有 USING 和 WITH CHECK``表达式(\ ``ALL 和 UPDATE)的策略,如果没有定义 WITH CHECK 表达 式,那么 USING 表达式将被用于决定哪些行可见(普通 USING 情况)以及允许哪些新行被增加(WITH CHECK 情 况)。 如果为一个表启用了行级安全性但是没有适用的策略存在,将假定为一种“默认否定”策略,这样任何行都不可 见也不可更新。 前置条件 要为一个表创建或者修改策略,你必须是该表的拥有者。 语法 943 第 15 章 SQL 语句:CREATE MATERIALIZED VIEW 到 CREATE SCHEMA CREATE POLICY name ON table_name [ AS { PERMISSIVE | RESTRICTIVE } ] [ FOR { ALL | SELECT | INSERT | UPDATE | DELETE } ] [ TO { role_name | PUBLIC | CURRENT_USER | SESSION_USER } [, ...] ] [ USING ( using_expression ) ] [ WITH CHECK ( check_expression ) ] 语义 name 要创建的策略的名称。这必须和该表上已有的任何其他策略名称相区分。 table_name 该策略适用的表的名称(可以被模式限定)。 PERMISSIVE 指定策略被创建为宽容性策略。适用于一个给定查询的所有宽容性策略将被使用布尔“OR”操作符组合 在一起。通过创建宽容性策略,管理员可以在能被访问的记录集合中进行增加。策略默认是宽容性的。 RESTRICTIVE 指定策略被创建为限制性策略。适用于一个给定查询的所有限制性策略将被使用布尔“AND”操作符组 944 第 15 章 SQL 语句:CREATE MATERIALIZED VIEW 到 CREATE SCHEMA 合在一起。通过创建限制性策略,管理员可以减少能被访问的记录集合,因为每一条记录都必须通过所有 的限制性策略。 注意在限制性策略真正能发挥作用减少访问之前,需要至少一条宽容性策略来授予对记录的访问。如果只 有限制性策略存在,则没有记录能被访问。当宽容性和限制性策略混合存在时,只有当一个记录能通过至 少一条宽容性策略以及所有的限制性策略时,该记录才是可访问的。 command 该策略适用的命令。合法的选项是 ALL、SELECT、INSERT、UPDATE 以及 DELETE。ALL 为默认。有关这些 策略如何被应用的细节见下文。 role_name 该策略适用的角色。默认是 PUBLIC,它将把策略应用到所有的角色。 using_expression 任意的 SQL 条件表达式(返回 boolean)。该条件表达式不能包含任何聚集或者窗口函数。如果行级 安全性被启用,这个表达式将被增加到引用该表的查询。让这个表达式返回真的行将可见。让这个表达 式返回假或者空的任何行将对用户不可见(在 SELECT 中)并且将对修改不可用(在 UPDATE 或 DELETE 中)。这类行会被悄悄地禁止而不会报告错误。 check_expression 任意的 SQL 条件表达式(返回 boolean)。该条件表达式不能包含任何聚集或者窗口函数。如果行级安 全性被启用,这个表达式将被用在该表上的 INSERT 以及 UPDATE 查询中。只有让该表达式计算为真的行 才被允许。如果任何被插入的记录或者跟新后的记录导致该表达式计算为假或者空,则会抛出一个错误。 注意 “check_expression“ 是根据行的新内容而不是原始内容计算的。 1. 针对每种命令的策略 ALL 为一条策略使用 ALL 表示它将适用于所有命令,不管命令的类型如何。如果存在一条 ALL 策略以及更多 特定的策略,则 ALL 策略和那些策略会被应用。此外,ALL 策略将同时适用于一个查询的选择端和修改 端,如果只定义了一个 USING 表达式则将该 USING 表达式用于两种情况。 例如,如果发出一个 UPDATE,那么 ALL 策略将同时影响 UPDATE 能更新哪些行(应用 USING 表达式)以 及更新后的行是否被允许加入到表中(如果定义了 WITH CHECK 表达式,则应用之;否则使用 USING 表 达式)。如果一条 INSERT 或者 UPDATE 命令尝试增加行到表中,但行没有通过 ALL 策略的 WITH CHECK 表达式,则整个语句将会中断。 SELECT 对一条策略使用 SELECT 表示它将适用于 SELECT 查询,并且无论何时都要求该约束所在的关系上的 SELECT 权限。其结果是在一次 SELECT 查询期间,只有该关系中那些通过了 SELECT 策略的记录才将被 返回,并且查询要求 SELECT 权限,例如 UPDATE 也将只能看到那些 SELECT 策略允许的行。一条 SELECT 策略不能具有 WITH CHECK 表达式,因为它只适用于正在从关系中检索记录的情况。 INSERT 945 第 15 章 SQL 语句:CREATE MATERIALIZED VIEW 到 CREATE SCHEMA 为一条策略使用 INSERT 表示它适用于 INSERT 命令。没有通过这种策略的正在被插入的行会导致策略违 背错误,并且整个 INSERT 命令将会中止。一条 INSERT 策略不能具有 USING 表达式,因为它只适用于 正在向关系增加记录的情况。 注意在带有 ON CONFLICT DO UPDATE 的 INSERT 中,只有对通过 INSERT 路径追加到关系的行才会检查 INSERT 策略的 WITH CHECK 表达式。 UPDATE 为一条策略使用 UPDATE 表示它适用于 UPDATE、SELECT FOR UPDATE 和 SELECT FOR SHARE 命令,还有 INSERT 命令的辅助性的 ON CONFLICT DO UPDATE 子句。由于更新包括提取现有记录并用新修改的记录 替换它,所以更新策略同时接受 USING 表达式和 WITH CHECK 表达式。USING 表达式决定 UPDATE 命令 将能看到哪些要对其操作的记录,而 WITH CHECK 表达式定义哪些被修改的行被允许存回到关系中。 任何更新后的值无法通过 WITH CHECK 表达式的行将会导致错误,并且整个命令将被中止。如果只指定了 一个 USING 子句,那么该子句将被用于 USING 和 WITH CHECK 两种情况。 通常,更新命令还需要从被更新的关系中的列中读取数据 (例如,在 WHERE 子句或 RETURNING 子句中, 或者在 SET 子句的右侧的表达式中)。在这种情况下,还需要对更新的关系使用 SELECT 权限,以及除了 更新策略外相应的 SELECT 和 ALL 策略。因此,除了被授予通过 UPDATE 或 ALL 策略更新行的权限外, 用户还必须具有通过 SELECT 或 ALL 策略更新行的访问权。 当 INSERT 命令有一个 ON CONFLICT DO UPDATE 子句时,如果采取了 ON CONFLICT DO UPDATE 路径, 则首先根据任何更新策略的 USING 表达式检查要更新的行,然后根据 WITH CHECK 表达式检查新更新的 行。注意, 一个独立的 UPDATE 命令, 如果现有的行不能通过 USING 表达式, 将抛出一个错误 (UPDATE 路 径永远不会默默地避免)。 DELETE 为一条策略使用 DELETE 表示它适用于 DELETE 命令。只有通过这条策略的行才将能被 DELETE 命令所看 到。如果有的行不能通过该 DELETE 策略的 USING 表达式,则它们可以通过 SELECT 看到但不能被删除。 在大多数情况下,DELETE 命令还需要从它要删除的关系的列 (例如,WHERE 子句或 RETURNING 子句) 中读取数据。在这种情况下,还需要对关系使用 SELECT 权限,除了 DELETE 策略外,还将应用适当的 SELECT 或 ALL 策略。因此,除了授予用户通过 DELETE 或 ALL 策略删除行的权限外,用户还必须通过 SELECT 或 ALL 策略访问被删除的行。 DELETE 策略不能具有 WITH CHECK 表达式,因为它只适用于正在从关系中删除记录的情况,所以没有新 行需要检查。 946 第 15 章 SQL 语句:CREATE MATERIALIZED VIEW 到 CREATE SCHEMA 表 15.7.1: 应用于命令类型的策略 命令 SELECT SELECT FOR UP- SELECT/ ALL 策 INSERT/ ALL 策 略 略 USING expression WITH DELETE/ ALL 策略 CHECK USING ex- WITH CHECK USING expression pression expression pression Existing row — — — — Existing row — Existing — — DATE/SHARE ex- row INSERT INSERT... UPDATE/ALL 策略 RETURN- — New row — — — New row[a]_ New row — — — Existing & new — Existing New row — ING UPDATE rows[a]_ DELETE ON CONFLICT DO UPDATE row Existing row[a]_ — — — Existing row Existing & new — Existing New row — rows row 2. 多重策略的应用 当不同命令类型的多个策略应用于同一命令 (例如,SELECT 和 UPDATE 策略应用于 UPDATE 命令) 时,用户必须 具有两种类型的权限 (例如,从关系中选择行的权限以及更新它们的权限)。因此,使用 AND 操作符将一种类型策略 的表达式与另一种类型策略的表达式组合在一起。 当同一命令类型的多个策略应用于同一命令时,必须至少有一个允许访问关系的许可策略,并且所有限制策略必 须通过。因此,所有的许可策略表达式都使用 OR 组合,所有的限制策略表达式都使用 AND 组合,结果用 AND 表 示。如果没有允许的策略,则拒绝访问。 注意,为了组合多个策略,所有策略都被视为具有与所应用的任何其他类型的策略相同的类型。 示例,在一个同时需要 SELECT 和 UPDATE 权限的 UPDATE 命令中,如果每种类型都有多个适用的策略,它们将 被合并如下: expression from RESTRICTIVE SELECT/ALL policy 1 AND expression from RESTRICTIVE SELECT/ALL policy 2 AND ... AND ( expression from PERMISSIVE SELECT/ALL policy 1 947 第 15 章 SQL 语句:CREATE MATERIALIZED VIEW 到 CREATE SCHEMA OR expression from PERMISSIVE SELECT/ALL policy 2 OR ... ) AND expression from RESTRICTIVE UPDATE/ALL policy 1 AND expression from RESTRICTIVE UPDATE/ALL policy 2 AND ... AND ( expression from PERMISSIVE UPDATE/ALL policy 1 OR expression from PERMISSIVE UPDATE/ALL policy 2 OR ... ) 示例 创建一个策略 CREATE POLICY user_policy ON users USING (user_name = current_user); 兼容性 CREATE POLICY 是一种 KingbaseES 扩展。 其他 虽然策略将被应用于针对数据库中表的显式查询上,但当系统正在执行内部引用完整性检查或者验证约束时不会 应用它们。这意味着有间接的方法来决定一个给定的值是否存在。一个例子是向一个作为主键或者拥有唯一约束的列 中尝试插入重复值。如果插入失败则用户可以推导出该值已经存在(这个例子假设用户被策略允许插入他们看不到的 记录)。另一个例子是一个用户被允许向一个引用了其他表的表中插入,然而另一个表是隐藏表。通过用户向引用表 中插入值可以判断存在性,成功表示该值存在于被引用表中。为了解决这些问题,应该仔细地制作策略以完全阻止用 户插入、删除或者更新那些可能指示他们不能看到的值的记录,或者使用生成的值(例如代理键)来代替具有外部含 义的键。 通常,系统将在应用用户查询中出现的条件之前先强制由安全性策略施加的过滤条件,这是为了防止无意中把受 保护的数据暴露给可能不可信的用户定义函数。但是,被系统(或者系统管理员)标记为 LEAKPROOF 的函数和操作 符可以在策略表达式之前被计算,因为它们已经被假定为可信。 因为策略表达式会被直接加到用户查询上,它们将使用运行整个查询的用户的权限运行。因此,使用一条给定策 略的用户必须能够访问表达式中引用的任何表或函数,否则在尝试查询启用了行级安全性的表时,他们将简单地收到 一条没有权限的错误。但是,这不会改变视图的工作方式。就普通查询和视图来说,权限检查和视图所引用的表的策 948 第 15 章 SQL 语句:CREATE MATERIALIZED VIEW 到 CREATE SCHEMA 略将使用视图拥有者的权限以及任何适用于视图拥有者的策略。 在 行安全性策略中可以找到额外的讨论和实际的例子。 15.8 CREATE PROCEDURE 用途 CREATE PROCEDURE 定义一个新的过程。CREATE OR REPLACE PROCEDURE 将会创建一个新过程或者替换一个已有 的定义。为了能够定义过程,用户必须具有所使用的语言上的 USAGE 特权。 如果这个命令中包括了一个方案名称,则该过程将被创建在该方案中。否则过程将被创建在当前的方案中。新过 程的名称不能匹配同一方案中具有相同输入参数类型的任何现有过程或函数。但是,具有不同参数类型的过程和函数 可以共享同一个名称(这被称为重载)。 要替换一个已有过程的当前定义,请使用 CREATE OR REPLACE PROCEDURE。不能用这种方式更改过程的名称或 者参数类型(如果尝试这样做,实际上会创建一个新的、不同的过程)。 当 CREATE OR REPLACE PROCEDURE 被用来替换一个现有的过程时,该过程的拥有关系和权限保持不变。所有其 他的过程属性会被赋予这个命令中指定的或者暗示的值。必须拥有(包括成为拥有角色的成员)该过程才能替换它。 创建过程的用户将成为该过程的拥有者。 前置条件 为了能够创建一个过程,用户必须具有参数类型上的 USAGE 特权。 语法 CREATE [ OR REPLACE ] [ EDITIONABLE | NONEDITIONABLE ] PROCEDURE ProcedureName [ ( [ < ParameterList > [ , ...n ] ] ) ] [ < invoker_rights_clause > ] [ COMMENT 'String' ] { AS | IS } [ << LabelName >> ] [ DECLARE ] [ < VariableDeclaration > ] [ < CursorDeclaration > ] [ < ExceptionDeclaration > ] [ < NestfunctionDeclaration > ] BEGIN < SequenceOfStatements > END [ LabelName ]; < VariableDeclaration > ::= { PlsqlVariable < DataType > } [ ; ... n ] 949 第 15 章 SQL 语句:CREATE MATERIALIZED VIEW 到 CREATE SCHEMA CREATE [ OR REPLACE ] PROCEDURE ProcedureName ([ [, ...n]]) [ COMMENT 'String' ] { LANGUAGE lang_name | TRANSFORM { FOR TYPE type_name } [, ... ] | [] | SET configuration_parameter { TO value | = value | FROM CURRENT } | AS 'definition' | AS 'obj_file', 'link_symbol' } ... ::= { AUTHID CURRENT_USER | AUTHID DEFINER | [ EXTERNAL ] SECURITY INVOKER | [ EXTERNAL ] SECURITY DEFINER } VariableDeclaration ::= 950 第 15 章 SQL 语句:CREATE MATERIALIZED VIEW 到 CREATE SCHEMA invoker_rights_clause ::= 语义 ProcedureName 存储过程名称, 可加模式名。 VariableDeclaration 声明变量和常量,详见 数据类型与声明。 951 第 15 章 SQL 语句:CREATE MATERIALIZED VIEW 到 CREATE SCHEMA CursorDeclaration 声明显式的游标,详见 游标管理。 ExceptionDeclaration 声明异常,详见 PL/SQL 异常处理。 NestfunctionDeclaration 详见 嵌套函数。 SequenceOfStatements 表示一个语句序列。 LabelName 表示一个标签名 EDITIONABLE | NONEDITIONABLE 未设计功能,只为语法兼容。 [EXTERNAL] SECURITY INVOKER | [EXTERNAL] SECURITY DEFINER SECURITY INVOKER 表示要用调用该函数的用户的特权来执行它,这是默认值。SECURITY DEFINER 指定 要用创建函数的用户的特权来执行该函数。 为了符合 SQL,允许使用关键词 EXTERNAL。但是它是可选的,因为与 SQL 中不同,这个特性适用于所 有函数而不仅是那些外部函数。 AUTHID CURRENT_USER 同 SECURITY INVOKER。 AUTHID DEFINER 同 SECURITY DEFINER。 lang_name 用于实现该过程的语言名称。它可以是 sql、c、internal 或者一种用户定义的过程语言的名称,例如 plsql。将名称包裹在单引号内的方式已经被废弃,并且要求大小写匹配。 TRANSFORM { FOR TYPE type_name } [, ... ] } 列出对过程的调用应该应用哪些 Transform。Transform 负责在 SQL 类型和语言相关的数据类型之间进行 转换,请参考CREATE TRANSFORM 。过程语言实现通常采用硬编码的方式保存内建类型的知识,因 此它们无需在这里列出。但如果一种过程语言实现不知道如何处理一种类型并且没有提供 Transform,它 将回退到默认的行为来转换数据类型,但是这依赖于其实现。 configuration_parameter value SET 子句导致在进入该过程时指定的配置参数被设置为指定的值,并且在过程退出时恢复到之前的值。SET FROM CURRENT 把 CREATE PROCEDURE 执行时该参数的当前值保存为在进入该过程时要应用的值。 952 第 15 章 SQL 语句:CREATE MATERIALIZED VIEW 到 CREATE SCHEMA 如果对过程附加一个 SET 子句,那么在该过程中为同一个变量执行的 SET LOCAL 命令的效果就被限制于该过 程:在过程退出时还是会恢复到该配置参数的以前的值。但是,一个普通的 SET 命令(没有 LOCAL)会重载 这个 SET 子句,很像它对一个之前的 SET LOCAL 命令所做的事情:这样一个命令的效果将持续到过程退出之 后,除非当前事务被回滚。 如果对过程附加一个 SET 子句,则该过程不能执行事务控制语句(例如 COMMIT 和 ROLLBACK,具体取决于实 现的语言)。 有关允许的参数名和值的更多信息请参考SET 和《数据库参考手册》。 definition 一个定义该过程的字符串常量,其含义取决于语言。它可以是一个内部的过程名、一个对象文件的路径、 一个 SQL 命令或者以一种过程语言编写的文本。 在编写过程的定义字符串时,使用美元引用(见美元引用的字符串常量 )而不是普通的单引号语法常常 会很有帮助。如果没有美元引用,过程定义中的任何单引号或者反斜线必须以双写的方式进行转义。 obj_file, link_symbol 当 C 语言源码中的过程名与 SQL 过程的名称不同时,这种形式的 AS 子句被用于动态可装载的 C 语言 过程。字符串 “obj_file“是包含已编译好的 C 过程的共享库文件名,并且被按照LOAD 命令的方式解析。 字符串 “link_symbol“是该过程的链接符号,也就是该过程在 C 语言源代码中的名称。如果链接符号被省 略,则会被假定为与正在被定义的 SQL 过程的名称相同。 当重复的 CREATE PROCEDURE 调用引用同一个对象文件时,只会对每一个会话装载该文件一次。要卸载或 者重新载入该文件(可能是在开发期间),应该开始一个新的会话。 ParameterList 语法格式: 功能: 定义存储过程的参数。 使用说明: a. IN,OUT,INOUT 参数模式,定义了形式参数的行为。用法与不指定 LANGAGUE 时创建 的CREATE FUNCTION 一致。 953 第 15 章 SQL 语句:CREATE MATERIALIZED VIEW 到 CREATE SCHEMA b. ParameterName,表示一个形式参数,该参数在存储过程中被声明,并且可以在该存储过程体中被 引用。 c. DataType,形式参数的数据类型。可以使用的数据类型请参考”SQL 参考手册” 的” 数据类型” 部分 的内容。 d. DEFAULT 关键字或“:=”用来指示存储过程参数的默认值, 是一个合法的表达式。 跟在有默认值的参数后面的输入参数也都必须有默认值。 e. VariableDeclaration,声明变量和常量。其中变量名不允许和存储过程体中的结果集或表中的列名重 名。参照如下示例。 f. 存储过程没有“RETURNS”子句,在存储过程体中可以使用“RETURN”语句,SQL 标准规定存 储过程没有返回值,KingbaseES 的存储过程即返回一个空值(VOID)。 COMMENT 'String' 添加存储过程的注释内容,此功能仅限在 MySQL 模式下使用。 示例 例 1:把存储过程 proc1 名称改为 proc2 a. 简单存储过程示例: \set SQLTERM / CREATE OR REPLACE PROCEDURE increment1(i INTEGER) AS BEGIN RAISE NOTICE '%', i; END; / \set SQLTERM ; b. 带有 OUT 参数的存储过程示例: \set SQLTERM / CREATE OR REPLACE PROCEDURE increment2(IN i INTEGER, OUT result INTEGER) AS BEGIN result := i + 2; END; / \set SQLTERM ; c. 参数带有默认值的存储过程示例: \set SQLTERM / CREATE OR REPLACE PROCEDURE increment2(OUT result INTEGER, IN i INTEGER:=1) AS BEGIN result := i + 2; 954 第 15 章 SQL 语句:CREATE MATERIALIZED VIEW 到 CREATE SCHEMA END; / \set SQLTERM ; d. 包含注释的存储过程示例: \set SQLTERM / CREATE OR REPLACE PROCEDURE increment2(IN i INTEGER, OUT result INTEGER) COMMENT 'a procedure' AS BEGIN result := i + 2; END; / \set SQLTERM ; 其他 参见ALTER PROCEDURE , DROP PROCEDURE 15.9 CREATE PUBLICATION 用途 CREATE PUBLICATION 向当前数据库添加一个新的发布。发布的名称必须与当前数据库中任何现有发布的名称不 同。 发布本质上是一组表,其数据更改旨在通过逻辑复制进行复制。 前置条件 要创建一个发布,调用者必须拥有当前数据库的 CREATE 权限。(当然,超级用户不需要这个检查。) 语法 CREATE PUBLICATION name [ FOR TABLE [ ONLY ] table_name [ * ] [, ...] | FOR ALL TABLES ] [ WITH ( publication_parameter [= value] [, ... ] ) ] 955 第 15 章 SQL 语句:CREATE MATERIALIZED VIEW 到 CREATE SCHEMA 语义 name 新发布的名称。 FOR TABLE 指定要添加到发布的表的列表。如果在表名之前指定了 ONLY,那么只有该表被添加到发布中。如果没有 指定 ONLY,则添加表及其所有后代表(如果有的话)。可选地,可以在表名之后指定 * 以明确指示包含 后代表。 只有持久基表才能成为出版物的一部分。临时表、非日志表、外表、物化视图、常规视图和分区表不能成 为发布的一部分。要复制分区表,请将各个分区添加到发布中。 FOR ALL TABLES 将发布标记为复制数据库中所有表的更改,包括在将来创建的表。 WITH ( publication_parameter [= value ] [, ... ] ) 该子句指定发布的可选参数。支持下列参数: publish (string) 这个参数决定了哪些 DML 操作将由新的发布发布给订阅者。该值是用逗号分隔的操作列表。 允许的操作是 insert,update 和 delete。默认是发布所有的动作,所以这个选项的默认值是 'insert, update, delete'。 示例 创建一个发布,发布两个表中所有更改布: CREATE PUBLICATION mypublication FOR TABLE users, departments; 创建一个发布,发布所有表中的所有更改: 956 第 15 章 SQL 语句:CREATE MATERIALIZED VIEW 到 CREATE SCHEMA CREATE PUBLICATION alltables FOR ALL TABLES; 创建一个发布,只发布一个表中的 INSERT 操作: CREATE PUBLICATION insert_only FOR TABLE mydata WITH (publish = 'insert'); 兼容性 CREATE PUBLICATION 是一个 KingbaseES 扩展。 其他 如果既没有指定 FOR TABLE,也没有指定 FOR ALL TABLES,那么这个发布就是以一组空表开始的。这在稍后添 加表格的情况下是有用的。 创建发布不会开始复制。它只为未来的订阅者定义一个分组和过滤逻辑。 要将表添加到发布中,调用者必须拥有该表的所有权。FOR ALL TABLES 子句要求调用者是超级用户。 添加到发布 UPDATE 或 DELETE 操作的发布的表必须已经定义了 REPLICA IDENTITY。否则将在这些表上禁止这 些操作。 对于 INSERT ... ON CONFLICT 命令,发布将公布从命令实际产生的操作。因此,根据结果,它可以作为 INSERT 或 UPDATE 发布,也可以根本不发布。 COPY ... FROM 命令是作为 INSERT 操作发布的。 不发布 TRUNCATE 和 DDL 操作。 15.10 CREATE RESOURCE GROUP 用途 创建一个资源组并设置参数值。 前置条件 只有 superuser 可以创建, 最多支持 90 个资源组。 资源组功能依赖于操作系统的 cgroup,所以仅支持类 linux 操作系统。 语法 CREATE RESOURCE GROUP group_name WITH (resource_name = value); 语义 957 第 15 章 SQL 语句:CREATE MATERIALIZED VIEW 到 CREATE SCHEMA group_name 为创建的资源组名称, 一个数据库内唯一,该对象不属于某个模式下。 resource_name 为设置控制资源类型的名称,目前支持 cpu_shares 和 cpu_cfs_quota_us。 value 为资源的值,为数字类型。 15.11 CREATE ROLE 用途 CREATE ROLE 向 KingbaseES 数据库集簇增加一个新的角色。一个角色是一个实体,它可以拥有数据库对象并且 拥有数据库特权。根据一个角色如何被使用,它可以被考虑成一个“用户”、一个“组”或者两者。有关管理用户和 认证的信息可以参考 数据库角色和 客户端认证。 注意角色是定义在数据库集簇层面上的,并且因此在集簇中的所有数据库中都可用。 前置条件 要使用这个命令,你必须具有 CREATE ROLE 特权或者成为一个数据库超级用户。 语法 CREATE ROLE name [ [ WITH ] option [ ... ] ] option 可以是: SUPERUSER | NOSUPERUSER | CREATEDB | NOCREATEDB | CREATEROLE | NOCREATEROLE | INHERIT | NOINHERIT | LOGIN | NOLOGIN | REPLICATION | NOREPLICATION | BYPASSRLS | NOBYPASSRLS | CONNECTION LIMIT connlimit | [ ENCRYPTED ] PASSWORD 'password' | PASSWORD NULL | VALID UNTIL 'timestamp' | IN ROLE role_name [, ...] | IN GROUP role_name [, ...] | ROLE role_name [, ...] | ADMIN role_name [, ...] | USER role_name [, ...] | SYSID uid 958 第 15 章 SQL 语句:CREATE MATERIALIZED VIEW 到 CREATE SCHEMA option ::= 959 第 15 章 SQL 语句:CREATE MATERIALIZED VIEW 到 CREATE SCHEMA 960 第 15 章 SQL 语句:CREATE MATERIALIZED VIEW 到 CREATE SCHEMA 语义 name 新角色的名称。 SUPERUSER | NOSUPERUSER 这些子句决定新角色是否是一个“超级用户”,它可以越过数据库内的所有访问限制。超级用户状态很危 险并且只应该在确实需要时才用。要创建一个新超级用户,你必须自己是一个超级用户。如果没有指定, 默认值是 NOSUPERUSER。 CREATEDB | NOCREATEDB 这些子句定义一个角色创建数据库的能力。如果指定了 CREATEDB,被定义的角色将被允许创建新的数据 库。指定 NOCREATEDB 将否定一个角色创建数据库的能力。如果没有指定,默认值是 NOCREATEDB。 CREATEROLE | NOCREATEROLE 这些子句决定一个角色是否被允许创建新的角色(也就是执行 CREATE ROLE)。一个带有 CREATEROLE 特权的角色也能修改和删除其他角色。如果没有指定,默认值是 NOCREATEROLE。 INHERIT | NOINHERIT 如果新的角色是其他角色的成员,这些子句决定新角色是否从那些角色中“继承”特权,把新角色作为成 员的角色称为新角色的父角色。一个带有 INHERIT 属性的角色能够自动使用已经被授予给其直接或间接 父角色的任何数据库特权。如果没有 INHERIT,在另一个角色中的成员关系只会把 SET ROLE 的能力授 予给那个其他角色,只有在这样做后那个其他角色的特权才可用。如果没有指定,默认值是 INHERIT。 LOGIN | NOLOGIN 这些子句决定一个角色是否被允许登录,也就是在客户端连接期间该角色是否能被给定为初始会话认证名 称。一个具有 LOGIN 属性的角色可以被考虑为一个用户。没有这个属性的角色对于管理数据库特权很有 用,但是却不是用户这个词的通常意义。如果没有指定,默认值是 NOLOGIN,但是当 CREATE ROLE 被通 过CREATE USER 调用时默认值会是 LOGIN。 REPLICATION | NOREPLICATION 这些子句决定一个角色是否为复制角色。角色必须具有这个属性(或者成为一个超级用户)才能以复制 模式(物理复制或者逻辑复制)连接到服务器以及创建或者删除复制槽。一个具有 REPLICATION 属性的 角色是一个具有非常高特权的角色,并且只应被用于确实需要复制的角色上。如果没有指定,默认值是 NOREPLICATION。 BYPASSRLS | NOBYPASSRLS 这些子句决定是否一个角色可以绕过每一条行级安全性(RLS)策略。默认是 NOBYPASSRLS。注意 sys_dump 将默认把 row_security 设置为 OFF,以确保一个表的所有内容被转储出来。如果运行 sys_dump 的用户不具有适当的权限,将会返回一个错误。超级用户和被转储表的拥有者总是可以绕过 RLS。 CONNECTION LIMIT connlimit 961 第 15 章 SQL 语句:CREATE MATERIALIZED VIEW 到 CREATE SCHEMA 如果角色能登录,这指定该角色能建立多少并发连接。-1(默认值)表示无限制。注意这个限制仅针对于 普通连接。预备事务和后台工作者连接都不受这一限制管辖。 [ ENCRYPTED ] PASSWORD ’password’ | PASSWORD NULL 设置角色的口令(口令只对具有 LOGIN 属性的角色有用,但是不管怎样你还是可以为没有该属性的角色 定义一个口令)。如果你没有计划使用口令认证,你可以忽略这个选项。如果没有指定口令,口令将被设 置为空并且该用户的口令认证总是会失败。也可以用 PASSWORD NULL 显式地写出一个空口令。 注意: 指定一个空字符串也将把口令设置为空,但是在 KingbaseES V8R3 版本之前是不能这样做的。在 早期的版本中,是否可以使用空字符串取决于认证方法和确切的版本,而 libkci 在任何情况下都将拒绝使 用空字符串。为了避免混淆,应该避免指定空字符串。 口令总是以加密的方式存放在系统目录中。ENCRYPTED 关键词没有实际效果,它只是为了向后兼容性而存 在。加密的方法由配置参数 password_encryption 决定。如果当前的口令字符串已经是 MD5 加密或者 SCRAM 加密的格式,那么不管 password_encryption 的值是什么,口令字符串还是原样存储(因为系 统无法解密以不同格式加密的口令字符串)。这种方式允许在转储/恢复时重载加密的口令。 VALID UNTIL ’timestamp’ VALID UNTIL 机制设置一个日期和时间,在该时间点之后角色的口令将会失效。如果这个子句被忽略,那 么口令将总是有效。 IN ROLE role_name IN ROLE 子句列出一个或多个现有的角色,新角色将被立即作为新成员加入到这些角色中(注意没有选项 可以把新角色作为一个管理员加入,需要用一个单独的 GRANT 命令来完成)。 IN GROUP role_name IN GROUP 是 IN ROLE 的一种已废弃的拼写方式。 ROLE role_name ROLE 子句列出一个或者多个现有角色,它们会被自动作为成员加入到新角色中(这实际上新角色变成了 一个“组”)。 ADMIN role_name ADMIN 子句与 ROLE 相似,但是被提及的角色被使用 WITH ADMIN OPTION 加入到新角色中,让它们能够 把这个角色中的成员关系授予给其他人。 USER role_name USER 子句是 ROLE 子句的一个已废弃的拼写方式。 SYSID uid SYSID 子句会被忽略,但是会为了向后兼容,还是会接受它。 示例 962 第 15 章 SQL 语句:CREATE MATERIALIZED VIEW 到 CREATE SCHEMA 创建一个能登录但是没有口令的角色: CREATE ROLE jonathan LOGIN; 创建一个有口令的角色: CREATE USER davide WITH PASSWORD 'jw8s0F4'; (CREATE USER 和 CREATE ROLE 完全相同,除了它带有 LOGIN)。 创建一个角色,它的口令有效期截止到 2004 年底。在进入 2005 年第一秒时,该口令会失效。 CREATE ROLE miriam WITH LOGIN PASSWORD 'jw8s0F4' VALID UNTIL '2005-01-01'; 创建一个能够创建数据库并且管理角色的角色: CREATE ROLE admin WITH CREATEDB CREATEROLE; 兼容性 SQL 标准中有 CREATE ROLE 语句,但是标准只要求语法 CREATE ROLE name [ WITH ADMIN role_name ] 多个初始管理员以及 CREATE ROLE 的所有其他选项都是 KingbaseES 扩展。 SQL 标准定义了用户和角色的概念,但是它把它们看成是可区分的概念并且将定义用户的所有命令留给每一种 数据库实现来指定。在 KingbaseES 中,我们已经选择把用户和角色统一成一种单一实体类型。因此角色比起标准中 拥有更多可选的属性。 15.12 CREATE RULE 用途 CREATE RULE 定义一条应用于指定表或视图的新规则。CREATE OR REPLACE RULE 将创建一条新规则或者替换同 一个表上具有同一名称的现有规则。 KingbaseES 规则系统允许我们定义针对数据库表中插入、更新或者删除动作上的替代动作。大约来说,当在一 个给定表上执行给定命令时,一条规则会导致执行额外的命令。或者,INSTEAD 规则可以用另一个命令替换给定的命 令,或者导致一个命令根本不被执行。规则也被用来实现 SQL 视图。规则实际上是一种命令转换机制或者命令宏。 这种转换会在命令的执行开始之前进行。如果你实际上想要为每一个物理行独立地触发一个操作,你可能更需要一个 触发器而不是规则。更多有关规则系统的信息请见 规则系统。 当前,ON SELECT 规则必须是无条件 INSTEAD 规则并且其动作必须由一个单一 SELECT 命令构成。因此,一条 ON SELECT 规则实际上把表变成了一个视图,它的可见内容是由该规则的 SELECT 命令返回,而不是直接存在该表中 的内容(如果有)。但是,使用 CREATE VIEW 命令还是要比创建一个真实表并且在其上定义一条 ON SELECT 规则更 好。 963 第 15 章 SQL 语句:CREATE MATERIALIZED VIEW 到 CREATE SCHEMA 可以通过定义 ON INSERT、ON UPDATE 以及 ON DELETE 规则(或者这些规则的任意子集)来创建可更新的视 图,这些规则可以把视图上的更新动作替换为其他表上适当的更新动作。如果想要支持 INSERT RETURNING 等等, 那么一定要在每一个这类规则中放上一个合适的 RETURNING 子句。 如果你尝试为复杂视图更新使用有条件的规则,有一点是很重要的:对于你希望在该视图上允许的每一个动作, 必须有一条 INSTEAD 规则。如果该规则是有条件的,或者不是 INSTEAD,那么系统仍将拒绝尝试执行该更新动作,因 为它会认为在某些情况下它应该停止尝试在该视图的傀儡表上执行动作。如果你想处理有条件规则中的所有有用的情 况,可以增加一条无条件的 DO INSTEAD NOTHING 规则来确保系统理解它将永远不会被调用来更新傀儡表。然后让有 条件规则变成非-INSTEAD。在它们适用的情况下,它们会加到默认的 INSTEAD NOTHING 动作(但是,当前这种方法 不支持 RETURNING 查询)。 注意: 足够简单的视图自动就是可更新的(见CREATE VIEW ),它们不需要依靠用户创建的规则来变成可更新 的。但是还是可以创建一条显式规则,自动更新转换通常比显式规则效率高。 另一种值得考虑的办法是使用 INSTEAD OF 触发器(见CREATE TRIGGER )代替规则。 前置条件 要在表上创建或者修改规则,必须是表的拥有者。 语法 CREATE [ OR REPLACE ] RULE name AS ON event TO table_name [ WHERE condition ] DO [ ALSO | INSTEAD ] { NOTHING | command | ( command ; command ... ) } 其中 event 可以是以下之一: SELECT | INSERT | UPDATE | DELETE event ::= 964 第 15 章 SQL 语句:CREATE MATERIALIZED VIEW 到 CREATE SCHEMA 语义 name 要创建的规则的名称。它必须与同一个表上任何其他规则的名称相区分。同一个表上同一种事件类型的多 条规则会按照其名称的字符顺序被应用。 event 时间是 SELECT、INSERT、UPDATE 或者 DELETE 之一。注意包含 ON CONFLICT 子句的 INSERT 不能被用 在具有 INSERT 或者 UPDATE 规则的表上。那种情况下请考虑使用可更新的视图。 table_name 规则适用的表或者视图的名称(可以是模式限定的)。 condition 任意的 SQL 条件表达式(返回 boolean)。该条件表达式不能引用除 NEW 以及 OLD 之外的任何表,并且 不能包含聚集函数。 INSTEAD INSTEAD 指示该命令应该取代原始命令被执行。 ALSO ALSO 指示应该在原始命令之外执行这些命令。 如果 ALSO 和 INSTEAD 都没有被指定,默认是 ALSO。 command 组成规则动作的命令。可用的命令有 SELECT、INSERT、UPDATE、DELETE 或者 NOTIFY。 在 “condition“和 “command“中,名为 NEW 和 OLD 的表可以被用来引用被引用表中的值。在 ON INSERT 和 ON UPDATE 规则中,NEW 被用来引用被插入或者更新的新行。在 ON UPDATE 和 ON DELETE 规则中,OLD 被用来引用被更 新或者删除的现有行。 示例 在一条用于视图上 INSERT、UPDATE 或者 DELETE 的规则中,可以增加一个 RETURNING 子句来发出视图的列。 如果该规则被一个 INSERT RETURNING、UPDATE RETURNING 或者 DELETE RETURNING 命令触发,这个子句将被用来 计算输出。当规则被一个没有 RETURNING 的命令触发时,该规则的 RETURNING 子句将被忽略。当前的实现只允许 965 第 15 章 SQL 语句:CREATE MATERIALIZED VIEW 到 CREATE SCHEMA 无条件 INSTEAD 规则包含 RETURNING。此外,用于同一事件的所有规则中至多只能有一个 RETURNING 子句(这确 保了只有一个候选 RETURNING 子句被用来计算结果)。如果在任何可用规则中都没有 RETURNING 子句,视图上的 RETURNING 查询将被拒绝。 避免循环规则非常重要。例如,尽管下面的两条规则定义都被 KingbaseES 所接受,SELECT 命令将导致 KingbaseES 报告一个错误,因为会产生一条规则的递归扩展: CREATE RULE "_RETURN" AS ON SELECT TO t1 DO INSTEAD SELECT * FROM t2; CREATE RULE "_RETURN" AS ON SELECT TO t2 DO INSTEAD SELECT * FROM t1; SELECT * FROM t1; 当前,如果一个规则动作包含一个 NOTIFY 命令,该 NOTIFY 命令将被无条件执行,也就是说,即使该规则不被 应用到任何行上,也会发出 NOTIFY。例如,在 CREATE RULE notify_me AS ON UPDATE TO mytable DO ALSO NOTIFY mytable; UPDATE mytable SET name = 'foo' WHERE id = 42; 中,UPDATE 期间将发出一个 NOTIFY 事件,不管是否有行匹配条件 id = 42。这是一种实现限制,它可能会在未 来的发行中被修复。 兼容性 CREATE RULE 是一种 KingbaseES 语言扩展,整个查询重写系统也是这样。 15.13 CREATE SCHEMA 用途 CREATE SCHEMA 创建一个新模式到当前数据库中。该模式名必须与当前数据库中任何现有模式的名称不同。 一个模式本质上是一个名字空间:它包含命令对象(表、数据类型、函数以及操作符),对象可以与在其他模式 中存在的对象重名。可以通过用模式名作为一个前缀“限定”命名对象的名称来访问它们,或者通过把要求的模式包 括在搜索路径中来访问命名对象。一个指定非限定对象名的 CREATE 命令在当前模式(搜索路径中的第一个模式,由 函数 current_schema 决定)中创建对象。 CREATE SCHEMA 中可以选择包括子命令用以在新模式中创建对象。这些子命令实际被当做独立的在创建该模式后 被发出的命令一样,除非使用 AUTHORIZATION 子句,所有被创建的对象都会由该用户拥有。 966 第 15 章 SQL 语句:CREATE MATERIALIZED VIEW 到 CREATE SCHEMA 前置条件 要创建一个模式,调用用户必须拥有当前数据库的 CREATE 特权(当然,超级用户可以绕过这种检查)。 语法 CREATE SCHEMA schema_name [ AUTHORIZATION role_specification ] [ schema_element [ ... ] ] CREATE SCHEMA AUTHORIZATION role_specification [ schema_element [ ... ] ] CREATE SCHEMA IF NOT EXISTS schema_name [ AUTHORIZATION role_specification ] CREATE SCHEMA IF NOT EXISTS AUTHORIZATION role_specification 其中 role_specification 可以是: user_name | CURRENT_USER | SESSION_USER role_specification ::= 语义 schema_name 要创建的一个模式名。如果省略,user_name 将被用作模式名。该名称不能以 sys_ 开始,因为这样的名 称是用作系统模式的。 user_name 将拥有新模式的用户的角色名。如果省略,默认为执行该命令的用户。要创建由另一个角色拥有的角色, 你必须是那个角色的一个直接或者间接成员,或者是一个超级用户。 967 第 15 章 SQL 语句:CREATE MATERIALIZED VIEW 到 CREATE SCHEMA schema_element 要在该模式中创建的对象的定义 SQL 语 句。 当 前, 只 有 CREATE TABLE、CREATE VIEW、CREATE INDEX、CREATE SEQUENCE、CREATE TRIGGER 以及 GRANT 被接受为 CREATE SCHEMA 中的子句。其他 类型的对象可以在模式被创建之后用单独的命令创建。 IF NOT EXISTS 如果一个具有同名的模式已经存在,则什么也不做(但是发出一个提示)。使用这个选项时不能包括 schema_element 子命令。 示例 创建一个模式: CREATE SCHEMA myschema; 为用户 joe 创建一个模式,该模式也将被命名为 joe: CREATE SCHEMA AUTHORIZATION joe; 创建一个被用户 joe 拥有的名为 test 的模式,除非已经有一个名为 test 的模式(不管 joe 是否拥有该已经 存在的模式)。 CREATE SCHEMA IF NOT EXISTS test AUTHORIZATION joe; 创建一个模式并且在其中创建一个表和视图: CREATE SCHEMA hollywood CREATE TABLE films (title text, release date, awards text[]) CREATE VIEW winners AS SELECT title, release FROM films WHERE awards IS NOT NULL; 注意子命令不以分号结束。 下面是达到相同结果的等效的方法: CREATE SCHEMA hollywood; CREATE TABLE hollywood.films (title text, release date, awards text[]); CREATE VIEW hollywood.winners AS SELECT title, release FROM hollywood.films WHERE awards IS NOT NULL; 兼容性 SQL 标准允许在 CREATE SCHEMA 中有一个 DEFAULT CHARACTER SET 子句,以及当前 KingbaseES 接受的更多 子命令类型。 SQL 标准制定 CREATE SCHEMA 中的子命令可以以任何顺序出现。当前的 KingbaseES 实现不能处理子命令中所 有情况的向前引用。有时候可能有必要对子命令进行重排序以避免向前引用。 968 第 15 章 SQL 语句:CREATE MATERIALIZED VIEW 到 CREATE SCHEMA 根据 SQL 标准,模式的拥有者总是拥有其中的所有对象。KingbaseES 允许模式包含非模式拥有者所拥有的对 象。只有模式拥有者把其模式上的 CREATE 特权授予给了其他人或者一个超级用户选择在该模式中创建对象时才会发 生这种事情。 IF NOT EXISTS 选项是一种 KingbaseES 扩展。 969 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE 16章 SQL 语句: CREATE SEQUENCE 到 第 DELETE 本章包含以下 SQL 语句: • CREATE SEQUENCE • CREATE SERVER • CREATE STATISTICS • CREATE SUBSCRIPTION • CREATE SYNONYM • CREATE TABLE • CREATE TABLE AS • CREATE TABLESPACE • CREATE TEXT SEARCH CONFIGURATION • CREATE TEXT SEARCH DICTIONARY • CREATE TEXT SEARCH PARSER • CREATE TEXT SEARCH TEMPLATE • CREATE TRANSFORM • CREATE TRIGGER • CREATE TYPE • CREATE TYPE BODY • CREATE USER • CREATE USER MAPPING • CREATE VIEW • DEALLOCATE 970 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE • DECLARE • DELETE • DELETE RESOURCE GROUP 16.1 CREATE SEQUENCE 用途 CREATE SEQUENCE 创建一个新的序列数发生器。这涉及到用名称 “name“创建并且初始化一个新的特殊的单行 表。该发生器将由发出该命令的用户所拥有。 如果给出一个模式名称,则该序列将将被创建在指定的模式中。否则它会被创建在当前模式中。临时序列存在于 一个特殊的模式中,因此在创建临时序列时不能给出模式名。序列名称必须与同一模式中任何其他序列、表、索引、 视图或者外部表的名称不同。 在序列被创建后,可以使用函数 nextval、currval 以及 setval 来操作该序列。这些函数在 序列操作函数中有 介绍。 尽管无法直接更新一个序列,可以使用这样的查询: SELECT * FROM name; 来检查一个序列的参数以及当前状态。特别地,序列的 last_value 域显示被任意会话最后一次取得的值(当 然,在被打印时该值可能已经过时了,因为可能有其他会话正在执行 nextval 调用)。 前置条件 无 语法 CREATE [ TEMPORARY | TEMP ] SEQUENCE [ IF NOT EXISTS ] name [ INCREMENT [ BY ] increment ] [ MINVALUE minvalue | NO MINVALUE ] [ MAXVALUE maxvalue | NO MAXVALUE ] [ START [ WITH ] start ] [ CACHE cache ] [ NOCACHE ] [ [ NO ] CYCLE ] [ NOCYCLE ] [ ORDER ] [ NOORDER ] [ OWNED BY { table_name.column_name | NONE } ] 971 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE 语义 TEMPORARY | TEMP 如果被指定,只会为这个会话创建序列对象,并且在会话退出时自动删除它。当临时序列存在 时,已有的同名永久序列(在这个会话中)会变得不可见,但是可以用模式限定的名称来引用同名永久序列。 IF NOT EXISTS 如果已经存在一个同名的关系时不要抛出错误。这种情况下会发出一个提示。注意这不保证现有的 关系与即将创建的序列相似 -- 它甚至可能都不是一个序列。 name 要创建的序列的名称(可以是模式限定的)。 data_type 可选的子句 AS data_type 制定序列的数据类型。有效类型是 smallint、integer、和 bigint。默认是 bigint。数据类型决定了序列的默认最小和最大值。 increment 可选的子句 INCREMENT BY increment 指定为了创建新值会把哪个值加到当前序列值上。一个正值将会 创造一个上升序列,负值会创造一个下降序列。默认值是 1。 minvalue | NO MINVALUE 可选的子句 MINVALUE minvalue 决定一个序列能产生的最小值。如果没有提供这个子句 或者指定了 NO MINVALUE,那么会使用默认值。升序序列的默认值为 1。降序序列的默认值为数据类型的最小 值。 maxvalue | NO MAXVALUE 可选的子句 MAXVALUE maxvalue 决定该序列的最大值。如果没有提供这个子句或者指定了 NO MAXVALUE,那么将会使用默认值。升序序列的默认值是数据类型的最大值。降序序列的默认值是-1。 start 可选的子句 START WITH start 允许序列从任何地方开始。对于上升序列和下降序列来说,默认的开始值分 别是 “minvalue“和 “maxvalue“。 cache | NOCYCLE 可选的子句 CACHE cache 指定要预分配多少个序列数并且把它们放在内存中以便快速访问。最小 值为 1(一次只生成一个值,即没有缓存),默认值也是 1。 972 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE 指定 NOCACHE,即没有缓存,缓存值为 1。 CYCLE | NO CYCLE | NOCYCLE 对于上升序列和下降序列,CYCLE 选项允许序列在分别达到 “maxvalue“和 “minvalue“时 回卷。如果达到该限制,下一个产生的数字将分别是 “minvalue“和 “maxvalue“。 如果指定了 NO CYCLE,当序列到达其最大值后任何 nextval 调用将返回一个错误。如果 CYCLE 和 NO CYCLE 都没有被指定,则默认为 NO CYCLE。 NOCYCLE 等价于 NO CYCLE。 ORDER | NOORDER ORDER 与 NOORDER 只在语法层面兼容 Oracle 数据库,并没有实现相应的功能。 OWNED BY table_name.column_name | OWNED BY NONE OWNED BY 选项导致序列被与一个特定的表列关联在一起,这 样如果该列(或者整个表)被删除,该序列也将被自动删除。指定的表必须和序列具有相同的拥有者并且在同 一个模式中。默认选项 OWNED BY NONE 指定该序列不与某个列关联。 示例 创建一个称作 serial 的上升序列,从 101 开始: CREATE SEQUENCE serial START 101; 从这个序列中选取下一个数字: SELECT nextval('serial'); nextval --------101 再从这个序列中选取下一个数字: SELECT nextval('serial'); nextval --------102 在一个 INSERT 命令中使用这个序列: INSERT INTO distributors VALUES (nextval('serial'), 'nothing'); 在一次 COPY FROM 后更新新列值: BEGIN; COPY distributors FROM 'input_file'; SELECT setval('serial', max(id)) FROM distributors; END; 兼容性 973 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE CREATE SEQUENCE 符合 SQL 标准,但是下列除外: • 使用 nextval() 而不是标准的 NEXT VALUE FOR 表达式获取下一个值。 • OWNED BY 子句是一种 KingbaseES 扩展。 其他 使用 DROP SEQUENCE 移除一个序列。 序 列 是 基 于 bigint 算 法 的, 因 此 范 围 是 不 能 超 过 一 个 八 字 节 整 数 的 范 围 (-9223372036854775808 到 9223372036854775807)。 由于 nextval 和 setval 调用绝不会回滚,如果需要序数的“无间隙”分配,则不能使用序列对象。可以通过 在一个只包含一个计数器的表上使用排他锁来构建无间隙的分配,但是这种方案比序列对象开销更大,特别是当有很 多事务并发请求序数时。 如果对一个将由多个会话并发使用的序列对象使用了大于 1 的 “cache“设置,可能会得到意想不到的结果。每个 会话会在访问该序列对象时分配并且缓存后续的序列值,并且相应地增加该序列对象的 last_value。然后,在该会 话中下一次 nextval 会做 “cache“-1,并且简单地返回预分配的值而不修改序列对象。因此,任何已分配但没有在会 话中使用的数字将会在该会话结束时丢失,导致该序列中的“空洞”。 进 一 步, 尽 管 多 个 会 话 能 分 配 到 不 同 的 序 列 值, 这 些 值 可 能 会 在 所 有 会 话 都 被 考 虑 时 生 成 出 来。 例 如, “cache“的设置为 10,会话 A 可能储存值 1..10 并且返回 nextval=1,然后会话 B 可能储存值 11..20 并且在 A 生成 nextval=2 之前返回 nextval=11。因此,如果 “cache“设置为 1,可以安全地假设 nextval 值被顺序地生 成。如果 “cache“设置大于 1,就只能假定 nextval 值都是可区分的,但不能保证它们被完全地顺序生成。还有, last_value 将反映服务于任意会话的最后一个值,不管它是否已经被 nextval 返回过。 另一个考虑是,在这样一个序列上执行的 setval 将不会通知其他会话,直到它们用尽了任何已缓存的预分配 值。 16.2 CREATE SERVER 用途 CREATE SERVER 定义一个新的外部服务器。定义该服务器的用户会成为拥有者。 外部服务器通常包装了外部数据包装器用来访问一个外部数据源所需的连接信息。额外的用户相关的连接信息可 以通过用户映射的方式来指定。 服务器名称在数据库中必须唯一。 前置条件 创建服务器要求所使用的外部数据包装器上的 USAGE 特权。 语法 974 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE CREATE SERVER [ IF NOT EXISTS ] server_name [ TYPE 'server_type' ] [ VERSION 'server_version' ] FOREIGN DATA WRAPPER fdw_name [ OPTIONS ( option 'value' [, ... ] ) ] 语义 IF NOT EXISTS 如果已经存在同名的服务器,不要抛出错误。在这种情况下发出一个通知。请注意,不能保证现有 服务器与要创建的服务器类似。 server_name 要创建的外部服务器的名称。 server_type 可选的服务器类型,可能对外部数据包装器有用。 server_version 可选的服务器版本,可能对外部数据包装器有用。 fdw_name 管理该服务器的外部数据包装器的名称。 OPTIONS ( option 'value' [, ... ] ) 这个子句为服务器指定选项。这些选项通常定义该服务器的连接细节,但 是实际的名称和值取决于该服务器的外部数据包装器。option 可指定为 host(服务器名)、dbname(数据库 名)、port(端口号)。 示例 创建使用外部数据包装器 kingbase_fdw 的服务器 myserver: CREATE SERVER myserver FOREIGN DATA WRAPPER kingbase_fdw OPTIONS (host 'foo', dbname 'foodb', port '54321'); 兼容性 CREATE SERVER 符合 ISO/IEC 9075-9 (SQL/MED)。 975 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE 16.3 CREATE STATISTICS 用途 CREATE STATISTICS 将创建一个新的扩展统计对象,追踪指定表、外部表或物化视图的数据。该统计对象将在当 前数据库中创建,被发出该命令的用户所有。 如果给定了模式名(比如,CREATE STATISTICS myschema.mystat ...),那么在给定的模式中创建统计对 象。否则在当前模式中创建。统计对象的名称必须与相同模式中的任何其他统计对象不同。 前置条件 必须是表的所有者才能创建读取它的统计对象。但是,一旦创建,统计对象的所有权与基础表无关。 语法 CREATE STATISTICS [ IF NOT EXISTS ] statistics_name [ ( statistics_kind [, ... ] ) ] ON column_name, column_name [, ...] FROM table_name 语义 IF NOT EXISTS 如果具有相同名称的统计对象已经存在,不会抛出一个错误,只会发出一个提示。请注意,这里只 考虑统计对象的名称,不考虑其定义细节。 statistics_name 要创建的统计对象的名称(可以有模式限定)。 statistics_kind 在此统计对象中计算的统计种类。目前支持的种类是启用 n-distinct 统计的 ndistinct,以及启用 功能依赖性统计的 dependencies,mcv 启用最常用的值列表。如果省略该子句,则统计对象中将包含所有支持 的统计类型。 column_name 被计算的统计信息包含的表格列的名称。至少必须给出两个列名。列名的顺序无关紧要。 table_name 包含计算统计信息的列的表的名称(可以是模式限定的)。 示例 用两个功能相关的列创建表 t1,即第一列中的值的信息足以确定另一列中的值。然后,在这些列上构建函数依 赖关系统计信息: 976 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE CREATE TABLE t1 ( a int, b int ); INSERT INTO t1 SELECT i/100, i/500 FROM generate_series(1,1000000) s(i); ANALYZE t1; -- 匹配行的数量将被大大低估: EXPLAIN ANALYZE SELECT * FROM t1 WHERE (a = 1) AND (b = 0); CREATE STATISTICS s1 (dependencies) ON a, b FROM t1; ANALYZE t1; -- 现在行计数估计会更准确: EXPLAIN ANALYZE SELECT * FROM t1 WHERE (a = 1) AND (b = 0); 如果没有函数依赖性统计信息,规划器会认为两个 WHERE 条件是独立的,并且会将它们的选择性乘以一起来 返回满足条件的行,以致得到的行数被低估。通过这样的统计,规划器认识到 WHERE 条件是多余的,就不会低估行 数。 创建具有两个完全相关的列的表 t2(包含相同的数据),并在这些列上创建一个 MCV 列表: CREATE TABLE t2 ( a int, b int ); INSERT INTO t2 SELECT mod(i,100), mod(i,100) FROM generate_series(1,1000000) s(i); CREATE STATISTICS s2 (mcv) ON a, b FROM t2; ANALYZE t2; -- valid combination (found in MCV) EXPLAIN ANALYZE SELECT * FROM t2 WHERE (a = 1) AND (b = 1); -- invalid combination (not found in MCV) EXPLAIN ANALYZE SELECT * FROM t2 WHERE (a = 1) AND (b = 2); MCV 列表为计划者提供了关于表中通常出现的特定值的更详细的信息,以及未出现在表中的值的组合的选择的 上限,从而使它能够在两种情况下生成更好的估计值。 977 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE 兼容性 SQL 标准中没有 CREATE STATISTICS 命令。 16.4 CREATE SUBSCRIPTION 用途 CREATE SUBSCRIPTION 为当前数据库添加一个新的订阅。订阅名称必须与数据库中任何现有的订阅不同。 订阅表示到发布者的复制连接。因此,此命令不仅在本地目录中添加定义,还会在发布者上创建复制插槽。 在运行此命令的事务提交时,将启动逻辑复制工作器以复制新订阅的数据。 前置条件 创建复制槽时 (默认行为), CREATE SUBSCRIPTION 不能在事务块内部执行。 如果复制插槽不是作为同一命令的一部分创建的,则创建连接到相同数据库集群的订阅(例如,在同一集群中的 数据库之间进行复制或在同一个数据库中进行复制)只能成功。否则,CREATE SUBSCRIPTION 调用将挂起。要做到 这一点,单独创建复制插槽(使用函数 sys_create_logical_replication_slot 和插件名称 kboutput),并使用 参数 create_slot = false 创建订阅。这是一个实施限制,可能会在未来的版本中解除。 语法 CREATE SUBSCRIPTION subscription_name CONNECTION 'conninfo' PUBLICATION publication_name [, ...] [ WITH ( subscription_parameter [= value] [, ... ] ) ] 语义 subscription_name 新订阅的名称。 CONNECTION 'conninfo’ 连接发布者的字符串。 PUBLICATION publication_name 要订阅的发布者上的发布名称。 WITH ( subscription_parameter [ = value ] [, ... ] ) 该子句指定订阅的可选参数。支持的参数有: 978 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE copy_data (boolean) 指 定 在 复 制 启 动 后 是 否 应 复 制 正 在 订 阅 的 发 布 中 的 现 有 数 据。 默 认 值 是 true。 create_slot (boolean) 指定该命令是否要在发布者上创建复制槽。默认值是 true。 enabled (boolean) 指定订阅是否应该主动复制,或者是否应该只是设置,但尚未启动。默认值是 true。 slot_name (string) 要使用的复制插槽的名称。默认行为是使用订阅名称作为插槽的名称。 当 slot_name 设置为 NONE 时,将不会有复制槽与订阅关联。这在需要稍后手动设置复制槽的情 况下会使用。这样的订阅必须同时 enabled 并且 create_slot 设置为 false。 synchronous_commit (enum) 该参数的值会覆盖 synchronous_commit 设置。默认值是 off。 对于逻辑复制使用 off 是安全的:如果订阅者由于缺少同步而丢失事务,数据将从发布者重新发 送。 进行同步逻辑复制时,不同的设置可能是合适的。逻辑复制工作者向发布者报告写入和刷新的位 置,当使用同步复制时,发布者将等待实际刷新。这意味着,当订阅用于同步复制时,将订阅者 的 synchronous_commit 设置为 off 可能会增加发布服务器上 COMMIT 的延迟。在这种情况下, 将 synchronous_commit 设置为 local 或更高是有利的。 connect (boolean) 指定 CREATE SUBSCRIPTION 是否应该连接到发布者。将其设置为 false 将会改 变默认值 enabled、create_slot 和 copy_data 为 false。 不允许将 connect 设置为 false 的同时将 enabled、create_slot 或 copy_data 设置为 true。 因为该选项设置为 false 时不会建立连接,因此表没有被订阅,所以当启用订阅后,不会复制任 何内容。需要运行 ALTER SUBSCRIPTION ... REFRESH PUBLICATION 才能订阅表。 示例 创建一个到远程服务器的订阅,复制发布 mypublication 和 insert_only 中的表,并在提交时立即开始复制: CREATE SUBSCRIPTION mysub CONNECTION 'host=192.168.1.50 port=54321 user=foo dbname=foodb' PUBLICATION mypublication, insert_only; 创建一个到远程服务器的订阅,复制 insert_only 发布中的表,并且不开始复制直到稍后启用复制。 CREATE SUBSCRIPTION mysub CONNECTION 'host=192.168.1.50 port=54321 user=foo dbname=foodb' PUBLICATION insert_only WITH (enabled = false); 兼容性 CREATE SUBSCRIPTION 是一个 KingbaseES 扩展。 979 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE 16.5 CREATE SYNONYM 用途 CREATE SYNONYM 定义一个同义词。同义词是数据库对象的一个别名,常用于简化对象访问和提高对象访问的安 全性。在使用同义词时,数据库将它翻译成对应数据库对象的名字。与视图类似,同义词并不占用实际存储空间,只 在数据字典中保存了同义词的定义。用户可以通过访问对象的同义词,来间接访问对象。 CREATE OR REPLACE SYNONYM 与之相似,但是如果已经存在一个同名同义词,该同义词会被替换。 如果给定了一个模式名(例如 CREATE SYNONYM myschema.mysynonym ...),那么该同义词会被创建在指定的 模式中。否则,它会被创建在当前模式中。同义词的名称不能与同一模式中任何其他同义词同名。 前置条件 要创建同义词,必须拥有 CREATE SYNONYM 的系统权限。 语法 CREATE [ OR REPLACE ] [ PUBLIC ] SYNONYM syn_name FOR obj_name 语义 PUBLIC 指定创建同义词的类型,指定 PUBLIC 为公有同义词,公有同义词创建在 PUBLIC 模式下,用户创建公有 同义词时候,可以不用指定模式。创建私有同义词必须指定模式(在当前模式为 PUBLIC 的时候),模式不可 为 PUBLIC,同时不可以指定 PUBLIC 参数。 syn_name 要创建的同义词的名字(可以是模式限定的)。 obj_name 同义词引用对象(可以是模式限定的)。表、视图、物化视图、同义词、序列、存储过程、函数、类型都 可以作为同义词引用对象 示例 同义词和引用对象之间没有强依赖关系(不检查引用对象是否存在),同义词也无状态可言,一直是有效。例如 引用对象不存在: CREATE SCHEMA schm; CREATE SYNONYM schm.syn_tab FOR public.tab; --tab 不存在 SELECT * FROM schm.syn_tab; ERROR: relation "SCHM.SYN_TAB" does not exist LINE 1: SELECT * FROM schm.syn_tab; SELECT * FROM SYS_SYNONYM WHERE synname = 'SYN_TAB'; --同义词定义信息 SYNNAME | SYNNAMESPACE | SYNOWNER | REFOBJNSPNAME | REFOBJNAME ---------+--------------+----------+---------------+-----------SYN_TAB | 16385 | 10 | PUBLIC | TAB 980 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE SELECT status FROM ALL_OBJECTS WHERE object_name = 'SYN_TAB'; --查看同义词状态 STATUS -------VALID 引用对象存在,删除引用对象(可删除),同义词状态有效: CREATE TABLE public.tb(id int); INSERT INTO TB VALUES(1); CREATE SYNONYM schm.syn_tb FOR public.tb; SELECT * FROM SYS_SYNONYM WHERE synname = 'SYN_TB'; SYNNAME | SYNNAMESPACE | SYNOWNER | REFOBJNSPNAME | REFOBJNAME ---------+--------------+----------+---------------+-----------SYN_TB | 16385 | 10 | PUBLIC | TB (1 row) SELECT status FROM ALL_OBJECTS WHERE object_name = 'SYN_TB'; STATUS -------VALID SELECT * FROM schm.syn_tb; ID ---1 DROP TABLE public.tb; SELECT status FROM ALL_OBJECTS WHERE object_name = 'SYN_TB'; STATUS -------VALID SELECT * FROM schm.syn_tb; ERROR: relation "SCHM.SYN_TB" does not exist LINE 1: SELECT * FROM schm.syn_tb; 所创建的公有同义词在 PUBLIC 模式下,公有同义词可以和私有同义词同名。例如: CREATE PUBLIC SYNONYM syn_tabl FOR tabl; CREATE SYNONYM schm.syn_tabl FOR tabl; SELECT syn.synname, sp.nspname FROM SYS_SYNONYM syn, SYS_NAMESPACE sp WHERE syn.synnamespace = sp.oid; SYNNAME | NSPNAME ------------------+-----------SYN_TABL | PUBLIC SYN_TABL | SCHM 创建公有同义词不可指定模式,创建私有同义词必须指定模式(在当前模式为 PUBLIC 的时候)。例: 981 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE CREATE PUBLIC SYNONYM schm.syn_tt FOR public.tab; ERROR: PUBLIC can not be used when schema name specified for synonym name LINE 1: CREATE PUBLIC SYNONYM schm.syn_tt FOR public.tab; CREATE SYNONYM syn_tt FOR public.tab; ERROR: missing or invalid synonym identifier,the current default schema is public set SEARCH_PATH to schm,public; CREATE SYNONYM syn_tt FOR public.tab; CREATE SYNONYM 创建私有同义词不可指定为 PUBLIC。 CREATE SYNONYM public.syn_tab1 FOR public.tab1; ERROR: missing or invalid synonym identifier LINE 1: CREATE SYNONYM public.syn_tab1 FOR public.tab1; 同义词的使用,和使用引用对象一样。 CREATE TABLE public.tab1(id int); INSERT INTO public.tab1 VALUES(1); CREATE PUBLIC SYNONYM syn_tab1 FOR public.tab1; SELECT * FROM syn_tab1; ID ---1 CREATE OR REPLACE INTERNAL FUNCTION public.increment(i integer) RETURNS integer AS $$ BEGIN RETURN i + 1; END; $$ LANGUAGE plsql; CREATE SYNONYM syn_inc FOR public.increment; CALL syn_inc(3); SYN_INC --------4 兼容性 CREATE SYNONYM 是 KingbaseES 的一种语言扩展。兼容 Oracle 同义词语法。 16.6 CREATE TABLE 用途 CREATE TABLE 将在当前数据库中创建一个新的、初始为空的表。该表将由发出该命令的用户所拥有。 982 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE 如果给定了一个模式名(例如 CREATE TABLE myschema.mytable ...),那么该表被创建在指定的模式中。否 则它被创建在当前模式中。该表的名称必须与同一个模式中的任何其他表、序列、索引、视图或外部表的名称区分 开。 CREATE TABLE 也会自动地创建一个数据类型来表示对应于该表一行的组合类型。因此,表不能用同一个模式中 任何已有数据类型的名称。 可选的约束子句指定一个插入或更新操作要成功,新的或更新过的行必须满足的约束(测试)。一个约束是一个 SQL 对象,它帮助以多种方式定义表中的合法值集合。 有两种方式来定义约束:表约束和列约束。一个列约束会作为列定义的一部分定义。一个表约束定义不与一个特 定列绑定,并且它可以包含多于一个列。每一个列约束也可以被写作一个表约束,列约束只是一种当约束只影响一列 时方便书写的记号习惯。 前置条件 要能创建一个表,你必须分别具有所有列类型或 OF 子句中类型的 USAGE 特权。 语法 CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXISTS ] table_name ( [ { column_name data_type [ INVISIBLE | VISIBLE ] [ COLLATE collation ] [ column_constraint [ ... ] ] | table_constraint | LIKE source_table [ like_option ... ] } [, ... ] ] ) [ INHERITS ( parent_table [, ... ] ) ] [ PARTITION BY { RANGE | LIST | HASH } ( { column_name | ( expression ) } [ COLLATE collation ] [ opclass ] [, ... ] ) [ partition_extented_spec ] ] [ USING method ] [ WITH ( storage_parameter [= value] [, ... ] ) | WITHOUT OIDS | WITH ROWID] [ ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP } ] [ WITH ( ONCOMMIT = value ) ] [ TABLESPACE tablespace_name ] [ { ENABLE | DISABLE } [ VALIDATE | NOVALIDATE ] constraint [ ... ] ] [ ENCRYPTED [BY tablekey ]] 983 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXISTS ] table_name 984 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE OF type_name [ ( { column_name [ WITH OPTIONS ] [ column_constraint [ ... ] ] | table_constraint } [, ... ] ) ] [ PARTITION BY { RANGE | LIST | HASH } ( { column_name | ( expression ) } [ COLLATE collation ] [ opclass ] [, ... ] ) [ partition_extented_spec ] ] [ USING method ] [ WITH ( storage_parameter [= value] [, ... ] ) | WITHOUT OIDS | WITH ROWID] [ ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP } ] [ WITH ( ONCOMMIT = value ) ] [ TABLESPACE tablespace_name ] [ ENCRYPTED [BY tablekey ]] 985 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXISTS ] table_name PARTITION OF parent_table [ ( { column_name [ WITH OPTIONS ] [ column_constraint [ ... ] ] | table_constraint } [, ... ] ) ] { FOR VALUES partition_bound_spec | DEFAULT } [ PARTITION BY { RANGE | LIST | HASH } ( { column_name | ( expression ) } [ COLLATE collation ] [ opclass ] [, ... ] ) ] [ USING method ] [ WITH ( storage_parameter [= value] [, ... ] ) | WITHOUT OIDS | WITH ROWID] [ ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP } ] [ WITH ( ONCOMMIT = value ) ] [ TABLESPACE tablespace_name ] [ ENCRYPTED [BY tablekey ]] 其中 column_constraint 是: 986 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE [ CONSTRAINT constraint_name ] { NOT NULL | NULL | CHECK ( expression ) [ NO INHERIT ] | DEFAULT default_expr | GENERATED ALWAYS AS ( generation_expr ) STORED | GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY [ ( sequence_options ) ] | IDENTITY [ ( NumericOnly , NumericOnly ) ] | UNIQUE index_parameters | PRIMARY KEY index_parameters | REFERENCES reftable [ ( refcolumn ) ] [ MATCH FULL | MATCH PARTIAL | MATCH SIMPLE ] [ ON DELETE referential_action ] [ ON UPDATE referential_action ] [auto_increment] } [ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ] [ { ENABLE | DISABLE } [ VALIDATE | NOVALIDATE ] ] table_constraint 是: [ CONSTRAINT constraint_name ] { CHECK ( expression ) [ NO INHERIT ] | UNIQUE ( column_name [, ... ] ) index_parameters | PRIMARY KEY ( column_name [, ... ] ) index_parameters | EXCLUDE [ USING index_method ] ( exclude_element WITH operator [, ... ] ) index_parameters [ WHERE ( predicate ) ] | FOREIGN KEY ( column_name [, ... ] ) REFERENCES reftable [ ( refcolumn [, 987 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE ... ] ) ] [ MATCH FULL | MATCH PARTIAL | MATCH SIMPLE ] [ ON DELETE referential_action ] [ ON UPDATE referential_action ] } [ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ] [ { ENABLE | DISABLE } [ VALIDATE | NOVALIDATE ] ] like_option 是: { INCLUDING | EXCLUDING } { COMMENTS | CONSTRAINTS | DEFAULTS | GENERATED | IDENTITY | INDEXES | STATISTICS | STORAGE | ALL } 988 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE partition_bound_spec 是: IN ( partition_bound_expr [, ...] ) | FROM ( { partition_bound_expr | MINVALUE | MAXVALUE } [, ...] ) TO ( { partition_bound_expr | MINVALUE | MAXVALUE } [, ...] ) | WITH ( MODULUS numeric_literal, REMAINDER numeric_literal ) UNIQUE、PRIMARY KEY 以及 EXCLUDE 约束中的 index_parameters 是: [ INCLUDE ( column_name [, ... ] ) ] [ WITH ( storage_parameter [= value] [, ... ] ) ] [ USING INDEX TABLESPACE tablespace_name ] 989 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE 一个 EXCLUDE 约束中的 exclude_element 是: { column_name | ( expression ) } [ opclass ] [ ASC | DESC ] [ NULLS { FIRST | LAST } ] 其中 constraint 是: { CONSTRAINT constraint_name | UNIQUE ( column_name [, ... ] ) | PRIMARY KEY } 990 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE partition_extented_spec 是: [ INTERVAL ( interval_expr ) [ STORE IN ( tablespace_name [, ...]) ]] [ SUBPARTITION BY { RANGE | LIST | HASH } ( { column_name | ( expression ) } [ COLLATE collation ] [ opclass ] [, ... ] ) [ { hash_subparts_by_quantity | subpartition_template } ] ] [ ( PARTITION partition [partition_bound_spec_ex] [ TABLESPACE tablespace_name ] [ ( SUBPARTITION subpartition [subpartition_bound_spec] [ TABLESPACE tablespace_name ] [, ... ] ) | SUBPARTITIONS numeric_literal [ STORE IN ( tablespace_name [, ... ] ) ] ] [, ... ] ) | PARTITIONS numeric_literal [ STORE IN ( tablespace_name [, ... ] ) ] ] hash_subparts_by_quantity 是: SUBPARTITIONS numeric_literal [ STORE IN ( tablespace_name [, ...] ) ] subpartition_template 是: SUBPARTITION TEMPLATE ( SUBPARTITION [subpartition] [subpartition_bound_spec] [ TABLESPACE tablespace_name ] [, ...] ) 991 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE partition_bound_spec_ex 是: VALUES LESS THEN ( { partition_bound_expr | MAXVALUE } [, ...] ) | VALUES ( partition_bound_expr [, ...] | DEFAULT ) subpartition_bound_spec 是: VALUES LESS THEN ( { partition_bound_expr | MAXVALUE } [, ...] ) | VALUES ( partition_bound_expr [, ...] | DEFAULT ) 992 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE MySQL 模式语法 CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXISTS ] table_name ( [ { column_name data_type [ INVISIBLE | VISIBLE ] [ COLLATE collation ][ON UPDATE special_timestamp_ function] [ column_constraint [ ... ] ][ COMMENT 'String' ] | table_constraint | LIKE source_table [ like_option ... ] } [, ... ] ] ) [ COMMENT [=] 'String' ] [ INHERITS ( parent_table [, ... ] ) ] [ PARTITION BY { RANGE | LIST | HASH } ( { column_name | ( expression ) } [ COLLATE collation ] [ opclass ] [, ... ] ) [ partition_extented_spec ] ] [ USING method ] [ WITH ( storage_parameter [= value] [, ... ] ) | WITHOUT OIDS | WITH ROWID] [ ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP } ] [ WITH ( ONCOMMIT = value ) ] [ TABLESPACE tablespace_name ] [ { ENABLE | DISABLE } [ VALIDATE | NOVALIDATE ] constraint [ ... ] ] [ ENCRYPTED [BY tablekey ]] CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXISTS ] table_name OF type_name [ ( 993 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE { column_name [ WITH OPTIONS ][ON UPDATE special_timestamp_function] [ column_constraint [ ... ] ] | table_constraint } [, ... ] ) ] [ COMMENT [=] 'String' ] [ PARTITION BY { RANGE | LIST | HASH } ( { column_name | ( expression ) } [ COLLATE collation ] [ opclass ] [, ... ] ) [ partition_extented_spec ] ] [ USING method ] [ WITH ( storage_parameter [= value] [, ... ] ) | WITHOUT OIDS | WITH ROWID] [ ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP } ] [ WITH ( ONCOMMIT = value ) ] [ TABLESPACE tablespace_name ] [ ENCRYPTED [BY tablekey ]] 994 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXISTS ] table_name PARTITION OF parent_table [ ( { column_name [ WITH OPTIONS ] [ON UPDATE special_timestamp_function] [ column_constraint [ ... ] ] | table_constraint } [, ... ] ) ] 995 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE [ COMMENT [=] 'String' ] { FOR VALUES partition_bound_spec | DEFAULT } [ PARTITION BY { RANGE | LIST | HASH } ( { column_name | ( expression ) } [ COLLATE collation ] [ opclass ] [, ... ] ) ] [ USING method ] [ WITH ( storage_parameter [= value] [, ... ] ) | WITHOUT OIDS | WITH ROWID] [ ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP } ] [ WITH ( ONCOMMIT = value ) ] [ TABLESPACE tablespace_name ] [ ENCRYPTED [BY tablekey ]] 996 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE 其中 special_timestamp_function 是: CURRENT_TIMESTAMP | CURRENT_TIMESTAMP(precise) | LOCALTIMESTAMP | LOCALTIMESTAMP(precise) | LOCALTIME | LOCALTIME(precise)| NOW(precise) | NOW() 997 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE 语义 TEMPORARY | TEMP 如果指定,该表被创建为一个临时表。 自动清理守护进程不能访问并且因此也不能清理或分析临时表。由于这个原因,应该通过会话的 SQL 命 令执行合适的清理和分析操作。例如,如果一个临时表将要被用于复杂的查询,最好在数据加载完成后在 其上运行 ANALYZE; 如果临时表被长期使用,也需要使用者主动通过 VACUUM FREEZE 处理临时表避免因 为临时表阻碍了事务号回收造成停机。 可以选择将 GLOBAL 或 LOCAL 写在 TEMPORARY 或 TEMP 的前面。创建临时表时若不指定 GLOBAL 或 LOCAL,则默认值指定为 LOCAL。 GLOBAL KingbaseES 支持本地临时表和全局临时表。全局临时表的表定义是持久的,而表数据是临时的。 LOCAL 本地临时表的表定义和表数据都是临时的,会在会话退出后被删除。 本地临时表和全局临时表在各个会话之间数据彼此不影响;表中的数据都可以在事务结束之后删除,或者 连接退出之后删除;数据都存在在临时表空间中;临时表都不记录日志。 本地临时表和全局临时表有如下四点区别: 1. 本地临时表在临时模式下,用户不可以指定;但是全局临时表创建在用户指定模式下; 2. 本地临时表对象本身并不是一直存在,在会话退出后,本地临时表会被删除;全局临时表创建之后,一 直存在,除非显示去删除它。 3. 删除本地临时表,不受其他会话影响;但是删除全局临时表时,所有会话都不能持有全部临时表的数 据。 4. 全局临时表不支持外键约束也不支持其他表引用全局临时表作为外键约束,而本地临时表没有这个要 求。 UNLOGGED 998 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE 如果指定,该表被创建为一个不受日志记录的表。被写入到不做日志的表中的数据不会被写到预写式日志 中,这让它们比普通表快非常多。但是,它们在崩溃时是不安全的:一个不做日志的表在一次崩溃或非干 净关闭之后会被自动地截断。一个不做日志的表中的内容也不会被复制到后备服务器中。在一个不做日志 的表上创建的任何索引也会自动地不被日志记录。 IF NOT EXISTS 如果一个同名关系已经存在,不要抛出一个错误。在这种情况下会发出一个提示。注意这不保证现有的关 系是和将要被创建的表相似的东西。 table_name 要被创建的表名(可以选择用模式限定)。 OF type_name 创建一个类型化的表,它的结构取自于指定的组合类型(名字可以选择用模式限定)。一个类型化的表和 它的类型绑定在一起,例如如果类型被删除,该表也将被删除(用 DROP TYPE ... CASCADE)。 当一个类型化的表被创建时,列的数据类型由底层的组合类型决定而没有在 CREATE TABLE 命令中直接指 定。但是 CREATE TABLE 命令可以对表增加默认值和约束,并且可以指定存储参数。 column_name 要在新表中创建的一列的名称。 data_type 该列的数据类型。这可以包括数组说明符。更多关于 KingbaseES 支持的数据类型,请参考数据类型 。 INVISIBLE | VISIBLE 该列的隐含属性,关于隐含列的特征参考 Oracle 语言兼容特性中关于隐含列的描述,INVISIBLE 表示该 列在创建时指定为隐含列,相反地,如果不指定或者指定为 VISIBLE 则表示该列是非隐含列。 COLLATE collation COLLATE 子句为该列(必须是一种可排序数据类型)赋予一个排序规则。如果没有指定,将使用该列数据 类型的默认排序规则。 ON UPDATE MySQL 模式下,若表中的时间列设置了 ON UPDATE 属性,当数据行发生更新时,数据库自动设置该 列的值为当前的时间戳。 INHERITS ( parent_table [, ... ] ) 可选的 INHERITS 子句指定一个表的列表,新表将从其中自动地继承所有列。父表可以是普通表或者外部 表。 INHERITS 的使用在新的子表和它的父表之间创建一种持久的关系。对于父表的模式修改通常也会传播到 子表,并且默认情况下子表的数据会被包括在对父表的扫描中。 如果在多个父表中存在同名的列,除非父表中每一个这种列的数据类型都能匹配,否则会报告一个错误。 如果没有冲突,那么重复列会被融合来形成新表中的一个单一列。如果新表中的列名列表包含一个也是继 999 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE 承而来的列名,该数据类型必须也匹配继承的列,并且列定义会被融合成一个。如果新表显式地为列指定 了任何默认值,这个默认值将覆盖来自该列继承声明中的默认值。否则,任何父表都必须为该列指定相同 的默认值,或者会报告一个错误。 CHECK 约束本质上也采用和列相同的方式被融合:如果多个父表或者新表定义中包含相同的命名 CHECK 约束,这些约束必须全部具有相同的检查表达式,否则将报告一个错误。具有相同名称和表达式的约束将 被融合成一份拷贝。一个父表中的被标记为 NO INHERIT 的约束将不会被考虑。注意新表中一个未命名的 CHECK 约束将永远不会被融合,因为那样总是会为它选择一个唯一的名字。 列的 STORAGE 设置也会从父表复制过来。 如果父表中的列是标识列,那么该属性不会被继承。如果需要,可以将子表中的列声明为标识列。 PARTITION BY { RANGE | LIST | HASH } ( { column_name | ( expression ) } [ opclass ] [, ...] ) 可选的 PARTITION BY 子句指定了对表进行分区的策略。这样创建的表称为分区表。带括号的列或表达式 列表形成表的分区键。使用范围或哈希分区时,分区键可以包含多个列或表达式(最多 32 个,但在构建 KingbaseES 时可以更改此限制),但对于列表分区,分区键必须由单个列或表达式组成。 范围和列表分区需要一个 btree 操作符类,而哈希分区需要一个哈希操作符类。如果没有显式指定运算符 类,则使用适当类型的默认运算符类;如果不存在缺省操作符类,则会引发错误。当使用哈希分区时,使 用的操作符类必须实现支持函数 2 分区表被分成多个子表(称为分区),它们是使用单独的 CREATE TABLE 命令创建的。分区表本身是空 的。插入到表中的数据行将根据分区键中的列或表达式的值路由到分区。如果没有现有的分区与新行中的 值匹配,则会报告错误。 分区表不支持 EXCLUDE 约束,但是您可以在各个分区上定义这些约束。 可选的 partition_extented_spec 子句支持兼容 Oracle 的分区定义语法,可以在一条语句中定义单层 分区表和复合分区表。 分区自动继承分区表的全部列定义、主外键索引和约束、唯一索引和约束、NOT NULL 约束和 CHECK 约束。分区自动继承分区表的全局或者本地临时表属性。 有关表分区的更多讨论,参考 分区。 PARTITION OF parent_table { FOR VALUES partition_bound_spec | DEFAULT } 创建指定父表的分区。可以使用 FOR VALUES 创建特定值的分区,也可以使用 DEFAULT 创建默认分区。 “partition_bound_spec“必须对应于父表的分区方法和分区键,并且不能与父表的任何现有分区重叠。IN 中的表单用于列表分区,FROM 和 TO 中的表单用于范围分区, WITH 中的表单用于哈希分区。 “partition_bound_expr“是任意无变量表达式 (使子查询、窗口函数、聚合函数和集返回函数是不允许 的)。它的数据类型必须与相应分区键列的数据类型匹配。表达式在表创建时只计算一次,因此它甚至可 以包含 volatile 表达式,比如 CURRENT_TIMESTAMP。 在创建列表分区时,NULL 能够被指定来表示,允许分区键列为空。但是,对于给定的父表,不能有多个 这样的列表分区。NULL 不能指定范围分区。 在创建一个范围分区时,指定的下界 FROM 是一个包含范围,而指定的上界 TO 是一个排他界限。也就是 说,从 FROM 列表中指定的值是该分区对应分区键列的有效值,而从 TO 列表中的值则不是。注意,这个 1000 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE 语句必须根据行比较的规则来理解。例如, 给定 PARTITION BY RANGE (x,y), FROM (1, 2) TO (3, 4) 的 分区允许 x=1 绑定任意 y>=2,x=2 绑定任意非空 y,x=3 绑定任意 y<4. 特殊值 MINVALUE 和 MAXVALUE 可以在创建范围分区时使用,以指示列的值没有下限或上限。例如,使用 FROM (MINVALUE) TO (10) 定义的分区允许任何小于 10 的值,使用 FROM (10) TO (MAXVALUE) 定义的 分区允许任何大于或等于 10 的值。 当创建一个包含多个列的范围分区时,使用 MAXVALUE 作为下界的一部分,使用 MAXVALUE 作为上界的一 部分,是有意义的。例如,使用 FROM (0, MAXVALUE) TO (10, MAXVALUE) 定义的分区允许第一个分区 键列大于 0 且小于等于 10 的任何行。类似地,使用 FROM ('a', MINVALUE) TO ('b', MINVALUE) 定义 的分区允许第一个分区键列以“a”开头的任何行。 注意,如果 MINVALUE 或 MAXVALUE 被用于分区边界的一列,则必须为所有后续列使用相同的值。例如, (10, MINVALUE, 0) 不是有效的边界;应该写 (10, MINVALUE, MINVALUE)。 还要注意一些元素类型,如 timestamp,有“infinity”的概念,它只是另一个可以存储的值。这不同于 MINVALUE 和 MAXVALUE,它们不是可以存储的实际值,而是表示值是无界的。MAXVALUE 可以被认为是比 任何其他价值都大,”infinity” 和 MINVALUE 小于任何其他值,包括”minus infinity”。FROM ('infinity') TO (MAXVALUE) 不是一个空的范围;它只允许存储一个值—”infinity”。 如果指定了 DEFAULT,那么该表将被创建为父表的默认分区。此选项不适用于哈希分区表。不适合给定 父分区的任何其他分区的分区键值将被路由到默认分区。 当一个表有一个现有的默认的分区,并且添加了一个新的分区时,必须扫描这个默认的分区,以确认它没 有包含任何属于这个新分区的行。如果默认分区包含大量的行,那么速度可能会很慢。如果默认分区是一 个外表,或者它有一个约束,证明它不能包含应该放在新分区中的行,那么扫描将被跳过。 在创建哈希分区时,必须指定模数和余数。模数必须是正整数,余数必须是小于模数的非负整数。通常, 在最初设置哈希分区表时,应该选择与分区数量相等的模量,并为每个表分配相同的模量和不同的余数 (参见下面的示例)。但是,并不是要求每个分区都具有相同的模量,只是散列分区表的分区之间出现的每 个模量都是下一个较大的模量的因数。这使得分区的数量可以增量地增加,而不需要一次移动所有数据。 例如,假设有一个具有 8 个分区的散列分区表,每个分区的模量为 8,但是需要将分区数量增加到 16。您 可以分离其中一个模数-8 分区,创建两个新的模数-16 分区,覆盖键空间的相同部分 (一个余数等于已分 离分区的余数,另一个余数等于该值加上 8),然后用数据重新填充它们。然后您可以对每个模数-8 分区 重复此操作 (可能在以后的某个时间),直到没有剩余的分区。虽然在每个步骤中仍然可能涉及大量的数据 移动,但是这仍然比创建一个全新的表并一次移动所有数据要好。 分区必须具有与其所属的分区表相同的列名和类型。对分区表的列名或类型的修改将自动传播到所有分 区。每个分区都会自动继承 CHECK 约束,但是单个分区可以指定附加的 CHECK 约束;具有与父约束相同 的名称和条件的附加约束将与父约束合并。默认值可以为每个分区单独指定。 插入分区表中的行将被自动按路线发送到正确的分区。如果没有合适的分区存在,就会发生错误。 通常会影响表及其所有继承子表的 TRUNCATE 等操作将级联到所有分区,但也可以在单个分区上执行。 请注意,删除具有 DROP TABLE 的分区需要在父表上获取访问独占锁。 INTERVAL ( interval_expr ) [ STORE IN ( tablespace_name [, ...]) ] 可选的 INTERVAL 子句指定创建 Interval 分区表,Interval 分区表是一种特殊的范围分区表。当执行 IN- 1001 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE SERT 或者 UPDATE 时,由数据库根据定义的间隔参数自动创建新的分区。当插入或者更新记录的分区 键值大于等于最高分区上限时,以最高分区上限为下边界,以最高分区上限 + 间隔值倍数为下边界创建 一个新的分区。 Interval 分区表仅支持指定唯一的分区键列,类型必须是数值型或日期型。其中 interval_expr 是任何无 变量表达式(不允许子查询、窗口函数、聚合函数和集返回函数),它的数据类型必须与唯一分区键列的 数据类型相匹配。这里的类型相匹配指的是:可以在分区边界值基础上,加上间隔值(使用 + 运算符) 可以得到一个新的分区边界值,且数据类型不变,例如:date + interval = date。必须使用 PARTITION 子句指定至少一个范围分区。不能在 VALUES 子句中指定 MAXVALUE,也不能为分区键列指定 NULL 值。 使用 STORE IN 可以为 Interval 分区表指定表空间,新的分区以轮循方式使用指定的各个表空间,如果省 略 STORE IN 时,则使用分区表的表空间。 如果指定分区表为复合分区表,可选的 INTERVAL 子句指定创建 Interval 复合分区表。如果定义了子分区 模板,则新的分区将按子分区模板创建下级子分区,否则将根据子分区类型自动创建默认的子分区。 SUBPARTITION BY { RANGE | LIST | HASH } ( { column_name | ( expression ) } [ opclass ] [, ...] ) 可选的 SUBPARTITION BY 子句指定了对表进行二级分区的策略。这样创建的表称为复合分区表。带括号 的列或表达式列表形成表的子分区键。使用范围或哈希子分区时,子分区键可以包含多个列或表达式(最 多 32 个,但在构建 KingbaseES 时可以更改此限制),但对于列表子分区,子分区键必须由单个列或表 达式组成。 partition_bound_spec_ex 和 subpartition_bound_spec 必须分别与分区和子分区的分区方法和分区键 对应,而不能与其他分区和子分区重叠。VALUES 用于列表分区和子分区,VALUE LESS THAN 用于范围分 区和子分区。 VALUE LESS THAN 定义了范围分区的上边界(不包含边界值),使用分区键值与子句指定的有序值列表进 行比较,满足条件的行将被存储在分区中。使用 MAXVALUE 可以定义分区键值的最大值,该最大值总是大 于其他任何值(包括 null)。 如果在 VALUES 后指定了 NULL,表示分区允许分区键列为空。如果在 VALUES 后指定了 DEFAULT,表示 分区为默认分区。在列表分区表中仅允许存在一个 NULL 或 DEFAULT 分区,在每个复合分区表的主分区 中也仅允许存在一个这样的子分区。 PARTITIONS 和 SUBPARTITIONS 可以通过指定哈希数量方式定义多个哈希分区和子分区,numeric_literal 为正整数。数据库为每个哈希分区自动分配 table_name_pn 的分区名称,为每个哈希子分区自动分配 table_name_subpn 的分区名称。 使用 PARTITION 可以按名称指定各个分区,并为每个分区单独指定表空间。使用 TABLESPACE 可以为分 区单独指定表空间,如果省略会则使用分区表的表空间。使用 STORE IN 可以为哈希分区或者子分区指定 一个或多个表空间。表空间的数量不必等于分区的数量,表空间按顺序指定给各个哈希分区。如果分区数 大于表空间数,余下的分区使用分区表的表空间。 可选的 SUBPARTITION TEMPLATE 子句可以为复合分区表指定子分区模板。子分区模板是默认的复合分区 表分区划分方法,如果在主分区定义中指定了子分区定义,则子分区定义优先于子分区模板。 LIKE source_table [ like_option ... ] 1002 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE LIKE 指定新表将从哪一个表自动地复制所有的列名、数据类型以及它们的非空约束。 和 INHERITS 不同,新表和原始表在创建完成之后是完全分离的。对原始表的更改将不会被应用到新表, 并且不可能在原始表的扫描中包括新表的数据。 与继承不同的是,类似的复制列和约束不会与类似命名的列和约束合并。如果显式地指定了相同的名称, 或者在另一个 LIKE 子句中,错误就会被通知。 可选的 “like_option“ 子句指定所要复制的原始表的附加属性。指定 INCLUDING 复制属性,指定 EXCLUDING 省略属性。EXCLUDING 是默认的。如果为同一类型的对象制定了多个规范,则使用最后一个规 范。可用的选项有: INCLUDING COMMENTS 复制列、约束和索引的注释将被复制。默认行为是排除注释,导致新表中复制的列 和约束没有注释。 INCLUDING CONSTRAINTS CHECK 约束将被复制。列约束和表约束之间没有区别。非空约束总是复制到新 表中。 INCLUDING DEFAULTS 复制列定义的默认表达式将被复制。否则,将不复制默认表达式,从而导致新表中 复制的列具有空默认值。注意,复制调用数据库修改函数 (如 nextval) 的默认值可能会在原始表和 新表之间创建功能链接。 INCLUDING GENERATED 复制列定义的任何生成表达式都将被复制。默认情况下,新列将是常规的基本 列。 INCLUDING IDENTITY 复制列定义的任何标识规范都将被复制。为新表的每个标识列创建一个新序列,与 与旧表关联的序列分离。 INCLUDING INDEXES 原始表上的 Indexes、PRIMARY KEY、UNIQUE、和 EXCLUDE 约束将在新表上创建。 新索引和约束的名称是根据默认规则选择的,而不管原始索引和约束是如何命名的。(这种行为可以 避免新索引可能出现的重复命名错误。) INCLUDING STATISTICS 扩展的统计信息被复制到新表中。 INCLUDING STORAGE STORAGE 将复制复制列定义的设置。默认行为是排除 STORAGE 设置,使得新表中复 制的列具有类型特定的默认设置。 INCLUDING ALL INCLUDING ALL 是选择所有可用的单独选项的缩写形式。(在 INCLUDING ALL 之后选择除某 些特定选项外的所有选项,编写单独的 EXCLUDING 子句是有用的。) LIKE 子句也能被用来从视图、外部表或组合类型拷贝列定义。不适合的选项(例如来自视图的 INCLUDING INDEXES)会被忽略。 注意: LIKE 子句语法前后需要添加括号,与 MySQL 语法非完全兼容。 CONSTRAINT constraint_name 1003 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE 一个列约束或表约束的可选名称。如果该约束被违背,约束名将会出现在错误消息中,这样类似列必须为 正的约束名可以用来与客户端应用沟通有用的约束信息(指定包含空格的约束名时需要用到双引号)。如 果没有指定约束名,系统将生成一个。 NOT NULL 该列不允许包含空值。 NULL 该列允许包含空值。这是默认情况。 这个子句只是提供与非标准 SQL 数据库的兼容。在新的应用中不推荐使用。 AUTO_INCREMENT 定义表字段具有自增列属性。默认起始值为 1,步长为 1。 CHECK ( expression ) [ NO INHERIT ] CHECK 指定一个产生布尔结果的表达式,一个插入或更新操作要想成功,其中新的或被更新的行必须满足 该表达式。计算出 TRUE 或 UNKNOWN 的表达式就会成功。只要任何一个插入或更新操作的行产生了 FALSE 结果,将报告一个错误异常并且插入或更新不会修改数据库。一个被作为列约束指定的检查约束 只应该引用该列的值,而一个出现在表约束中的表达式可以引用多列。 当前,CHECK 表达式不能包含子查询,也不能引用当前行的列之外的变量。可以引用系统列 tableoid, 但不能引用其他系统列。 一个被标记为 NO INHERIT 的约束将不会传播到子表。 当一个表有多个 CHECK 约束时,检查完 NOT NULL 约束后,对于每一行会以它们名称的字母表顺序来进 行检查(V8R3 版本之前的 KingbaseES 对于 CHECK 约束不遵从任何特定的引发顺序)。 DEFAULT default_expr DEFAULT 子句为出现在其定义中的列赋予一个默认数据。该值是可以使用变量的表达式(尤其是,不允许 对其他列的交叉引用)。子查询也不被允许。默认值表达式的数据类型必须匹配列的数据类型。 默认值表达式将被用在任何没有为该列指定值的插入操作中。如果一列没有默认值,那么默认值为空值。 GENERATED ALWAYS AS ( generation_expr ) STORED 此子句将列创建为函数索引。无法写入该列,读取时将返回指定表达式的结果。 关键字 STORED 表示该列将在写时计算并存储在磁盘上。 生成表达式可以引用表中的其他列,但不能引用其他函数索引。所使用的任何函数和操作符都必须是不可 变的。不允许引用其他表。 GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY [ ( sequence_options ) ] 该子句将列创建为标识列。它将拥有一个隐式序列附加到它,并且新行中的列将自动从分配给它的序列中 获取值。 子句 ALWAYS 和 BY DEFAULT 确定在 INSERT 语句中,序列值如何优先于用户指定的值。如果指定了 ALWAYS,则只有在 INSERT 语句指定 OVERRIDING SYSTEM VALUE 时才接受用户指定的值。如果指定了 1004 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE BY DEFAULT,则用户指定的值优先。有关详细信息,请参见INSERT 。(在 COPY 命令中,无论此设置如 何,都始终使用用户指定的值。) 可选的 “sequence_options“子句可用于覆盖序列的选项。有关详细信息,请参见CREATE SEQUENCE 。 IDENTITY [ NumericOnly, NumericOnly ] 该子句将列创建为标识列。它将拥有一个隐式序列附加到它,并且新行中的列将自动从分配给它的序列中 获取值。 该语句等同于 GENERATED BY DEFAULT AS IDENTITY [ START NumericOnly INCREMENT NumericOnly ] UNIQUE (列约束) UNIQUE ( column_name [, ... ] ) [ INCLUDE ( column_name [, ...]) ] (表约束) UNIQUE 约束指定一个表中的一列或多列组成的组包含唯一的值。唯一表约束的行为与列约束的行为相 同,只是表约束能够跨越多列。 对于一个唯一约束的目的来说,空值不被认为是相等的。 每一个唯一表约束必须命名一个列的集合,并且它与该表上任何其他唯一或主键约束所命名的列集合都不 相同(否则它将是一个被列举了两次的约束)。 在为多级分区层次结构建立唯一约束时,必须在约束定义中包含目标分区表的分区键的所有列,以及它的 所有子代分区表的列。 添加唯一约束将自动在约束中使用的列或列组上创建唯一的 btree 索引。可选子句 INCLUDE 添加到索引 的一个或多个列上,在这些列上不强制唯一性。注意,虽然约束没有强制包含在列上,但它仍然依赖于它 们。因此,这些列上的某些操作 (例如 DROP COLUMN) 可能导致级联约束和索引删除。 PRIMARY KEY (列约束) PRIMARY KEY ( column_name [, ... ] ) [ INCLUDE ( column_name [, ...]) ] (表约束) PRIMARY KEY 约束指定表的一个或者多个列只能包含唯一(不重复)、非空的值。一个表上只能指定一个 主键,可以作为列约束或表约束。 主键约束所涉及的列集合应该不同于同一个表上定义的任何唯一约束的列集合(否则,该唯一约束是多余 的并且会被丢弃)。 PRIMARY KEY 强制的数据约束可以看成是 UNIQUE 和 NOT NULL 的组合,但是把一组列标识为主键也为模 式设计提供了元数据,因为主键标识其他表可以依赖这一个列集合作为行的唯一标识符。 PRIMARY KEY 约束与放在分区表上的 UNIQUE 约束相同。 添加 PRIMARY KEY 约束将自动在约束中使用的列或列组上创建唯一的 btree 索引。可选的 INCLUDE 子句 允许指定列的列表,这些列将包含在索引的非键部分中。虽然对包含的列不强制惟一性,但约束仍然依赖 于它们。因此,对所包含列的某些操作 (例如 DROP COLUMN) 可能导致级联约束和索引删除。 EXCLUDE [ USING index_method ] ( exclude_element WITH operator [, ... ] ) index_parameters [ WHERE ( predicate ) ] 1005 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE EXCLUDE 子句定一个排除约束,它保证如果任意两行在指定列或表达式上使用指定操作符进行比较,不是 所有的比较都将会返回 TRUE。如果所有指定的操作符都测试相等,这就等价于一个 UNIQUE 约束,尽管 一个普通的唯一约束将更快。但是,排除约束能够指定比简单相等更通用的约束。例如,你可以使用 && 操作符指定一个约束,要求表中没有两行包含相互覆盖的圆(见几何类型 )。 排除约束使用一个索引实现,这样每一个指定的操作符必须与用于索引访问方法 “index_method“的 一 个 适 当 的 操 作 符 类 (见 操 作 符 类 和 操 作 符 族) 相 关 联。 操 作 符 被 要 求 是 交 换 的。 每 一 个 “ex- clude_element“可以选择性地指定一个操作符类或者顺序选项,这些在CREATE INDEX 中有完整描述。 访问方法必须支持 amgettuple,目前这意味着 GIN 无法使用。尽管允许,但是在一个排除约束中使用 B-树或哈希索引没有意义,因为它无法做得比一个普通唯一索引更出色。因此在实践中访问方法将总是 GiST 或 SP-GiST。 “predicate“允许你在该表的一个子集上指定一个排除约束。在内部这会创建一个部分索引。注意在为此周 围的圆括号是必须的。 REFERENCES reftable [ ( refcolumn ) ] [ MATCH matchtype ] [ ON DELETE referential_action ] [ ON UPDATE referential_action ] (列约束) “ FOREIGN KEY ( column_name [, ... ] ) REFERENCES reftable [ ( refcolumn [, ... ] ) ] [ MATCH matchtype ] [ ON DELETE referential_action ] [ ON UPDATE referential_action ]“ (表约束) 这些子句指定一个外键约束,它要求新表的一列或一个列的组必须只包含能匹配被引用表的某个行在 被引用列上的值。如果 “refcolumn“列表被忽略,将使用 “reftable“的主键。被引用列必须是被引用表 中一个非可延迟唯一约束或主键约束的列。用户必须在被引用的表(或整个表或特定的引用列)上拥有 REFERENCES 权限。 被插入到引用列的一个值会使用给定的匹配类型与被引用表的值进行匹配。有三种匹配类型:MATCH FULL、MATCH PARTIAL 以及 MATCH SIMPLE(这是默认值)。MATCH FULL 将不允许一个多列外键中的 一列为空,除非所有外键列都是空;如果它们都是空,则不要求该行在被引用表中有一个匹配。MATCH SIMPLE 允许任意外键列为空,如果任一为空,则不要求该行在被引用表中有一个匹配。MATCH PARTIAL 现在还没有被实现(当然,NOT NULL 约束能被应用在引用列上来组织这些情况发生)。 另外,当被引用列中的数据被改变时,在这个表的列中的数据上可以执行特定的动作。ON DELETE 指 定当被引用表中一个被引用行被删除时要执行的动作。同样,ON UPDATE 指定当被引用表中一个被引 用列被更新为新值时要执行的动作。如果该行被更新,但是被引用列并没有被实际改变,不会做任何 动作。除了 NO ACTION 检查之外的引用动作不能被延迟,即便该约束被声明为可延迟的。对每一个 referential_action 子句可能有以下动作: NO ACTION 产生一个错误指示删除或更新将会导致一个外键约束违背。如果该约束被延迟,并且仍存在 引用行,这个错误将在约束检查时被产生。这是默认动作。 RESTRICT 产生一个错误指示删除或更新将会导致一个外键约束违背。这个动作与 NO ACTION 形同,但是 该检查不是可延迟的。 CASCADE 删除任何引用被删除行的行,或者把引用列的值更新为被引用列的新值。 SET NULL 将引用列设置为空。 1006 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE SET DEFAULT 设置引用列为它们的默认值(如果该默认值非空,在被引用表中必须有一行匹配该默认 值,否则该操作将会失败)。 如果被引用列被频繁地更改,最好在引用列上加上一个索引,这样与外键约束相关的引用动作能够更高效 地被执行。 DEFERRABLE | NOT DEFERRABLE 这个子句控制该约束是否能被延迟。一个不可延迟的约束将在每一次命令后立刻被检查。可延迟约束的 检查将被推迟到事务结束时进行(使用SET CONSTRAINTS 命令)。NOT DEFERRABLE 是默认值。当 前,只有 UNIQUE、PRIMARY KEY、EXCLUDE 以及 REFERENCES(外键)约束接受这个子句。NOT NULL 以 及 CHECK 约束是不可延迟的。注意在包括 ON CONFLICT DO UPDATE 子句的 INSERT 语句中,可延迟约 束不能被用作冲突裁判者。 INITIALLY IMMEDIATE | INITIALLY DEFERRED 如 果 一 个 约 束 是 可 延 迟 的, 这 个 子 句 指 定 检 查 该 约 束 的 默 认 时 间。 如 果 该 约 束 是 INITIALLY IMMEDIATE,它会 在每一个语句 之后 被检查。 这是默认 值。如 果该 约束 是 INITIALLY DEFERRED,它 只会在事务结束时被检查。约束检查时间可以用SET CONSTRAINTS 命令修改。 ENABLE VALIDATE/NOVALIDATE | DISABLE NOVALIDATE/VALIDATE 这个子句用来设置或修改约束的状态,包括 ENABLE/DISABLE 与 VALIDATE/NOVALIDATE 两个组合,共 四个状态。如果该约束是 ENABLE,数据库中输入或者更新数据要进行约束规则检查,不符合约束规则 的数据不能输入数据库,这是默认值。相反如果该约束是 DISABLE,那么输入或更新数据将不会进行约 束规则检查。一个 VALIDATE 状态的约束表示数据库内已有数据符合约束规则。如果设置或修改约束为 ENABLE 状态时并未指定有效性状态,VALIDATE 是默认值。一个 DISABLE VALIDATE 状态的约束,为了 保证有效性状态不被破坏,会将数据库表设置为只读状态,禁用对表的 DML 操作。如果为一个存在的 表增加 VALIDATE 状态的约束,将会对表内的数据做约束规则检查。一个 NOVALIDATE 状态的约束表示 数据库表内已有数据未做约束规则检查。设置或修改约束为 DISABLE 状态时,如果未指定有效性状态, NOVALIDATE 是默认值。如果为一个存在的表增加 NOVALIDATE 状态的约束,将不会对已有数据做有效性 检查(ENABLE 状态的唯一约束和主键约束依赖于索引,创建索引会检查已有数据的唯一性)。 目前这个子句只支持检查约束、唯一约束、主键和外键约束。 在分区表上创建或修改约束状态时,约束状态会级联应用到分区上的约束。分区表上的父约束与分区上的 子约束状态总是保持相同的,不可以单独修改分区表或分区上的有继承关系约束状态,但是对于分区表或 者分区上独立的约束可以单独修改约束状态。 USING method 此可选子句指定用于存储新表的内容的表访问方法;该方法需要是类型 TABLE 的访问方法。 如果未指定此选项,则为新表选择默认的表访问方法。更多信息,参考 default_table_access_method 参 数。 WITH ( storage_parameter [ = value ] [, ... ] ) 这个子句为一个表或索引指定可选的存储参数。为了向后兼容,WITH 子句可以包含 OIDS=FALSE 以指定 新表的行不应该包含 OIDs(对象标识符),OIDS=TRUE 不再被支持。 1007 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE WITHOUT OIDS 这是向后兼容的语法,用于声明一个没有 OIDS 的表,现在已经不支持创建一个有 OIDS 的表。 WITH ROWID 增加 WITH ROWID 的关键字,创建的该表的首列即为 ROWID 类型的隐含列,且名为“rowid”。 ON COMMIT 临时表在一个事务块结束时的行为由 ON COMMIT 控制。三种选项是: PRESERVE ROWS 在事务结束时不采取特殊的动作。是本地临时表采用的默认行为 DELETE ROWS 在每一个事务块结束时将删除临时表中的所有行。实质上,在每一次提交时会完 成一次自动的TRUNCATE 。在分区表上使用时,不会将其级联到其分区。这是全局临时 表的默认行为。 DROP 在当前事务块结束时将删除临时表。在分区表上使用时,此操作将删除其分区,在具有继 承子级的表上使用时,将删除依赖子级。仅本地临时表支持在当前事务块结束时将删除临 时表。为兼容 Oracle,全局临时表不支持 ON COMMIT DROP 选项。 WITH ( ONCOMMIT = value ) 这是兼容 kingbase V7 的语法,其中 value 的取值为 0~3: 0:没有 ONCOMMIT 子句,本地临时表默认为 PRESERVE ROWS,全局临时表默认为 DELETE ROWS。 1:等价于指定 PRESERVE ROWS。 2:等价于指定 DELETE ROWS。 3:等价于指定 DROP。 TABLESPACE tablespace_name “tablespace_name“是新表要创建于其中的表空间名称。如果没有指定,将参考 default_tablespace,或者 如果表是临时的则参考 temp_tablespaces。对于分区表,由于表本身不需要存储,所以指定的表空间将覆 盖 default_tablespace,作为在没有显式指定其他表空间的情况下为任何新创建的分区使用的默认表空 间。 USING INDEX TABLESPACE tablespace_name 这个子句允许选择与一个 UNIQUE、PRIMARY KEY 或者 EXCLUDE 约束相关的索引将被创建在哪个表空间 中。如果没有指定,将参考 default_tablespace,或者如果表是临时的则参考 temp_tablespaces。 ENCRYPTED [ BY tablekey ] 如果指定 ENCRYPTED,该表被创建为一个加密表,表的子表和索引数据都会被加密保存在磁盘上。加密 表的数据有更好的安全性,可以防止物理上的数据泄露。创建表时可以用 tablekey 来指定使用的秘钥, 如果没有指定会自动生成随机秘钥。 COMMENT [=] 'String' 添加表的注释内容,此功能仅限于在 MySQL 模式下使用。 1008 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE COMMENT 'String' 添加表或者列的注释内容,此功能仅限于在 MySQL 模式下使用。 示例 创建表 films 和表 distributors: CREATE TABLE films ( code char(5) CONSTRAINT firstkey PRIMARY KEY, title varchar(40) NOT NULL, did integer NOT NULL, date_prod date, kind varchar(10), len interval hour to minute ); CREATE TABLE distributors ( did integer PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY, did2 name integer IDENTITY(1,1), varchar(40) NOT NULL CHECK (name <> '') ); 创建有一个二维数组的表: CREATE TABLE array_int ( vector int[][] ); 为表 films 定义一个唯一表约束。唯一表约束能够被定义在表的一列或多列上: CREATE TABLE films ( code char(5), title varchar(40), did integer, date_prod date, kind varchar(10), len interval hour to minute, CONSTRAINT production UNIQUE(date_prod) ); 定义一个列检查约束: CREATE TABLE distributors ( did integer CHECK (did > 100), name varchar(40) ); 1009 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE 定义一个表检查约束: CREATE TABLE distributors ( did integer, name varchar(40), CONSTRAINT con1 CHECK (did > 100 AND name <> '') ); 为表 films 定义一个主键表约束: CREATE TABLE films ( code char(5), title varchar(40), did integer, date_prod date, kind varchar(10), len interval hour to minute, CONSTRAINT code_title PRIMARY KEY(code,title) ); 为表 distributors 定义一个主键约束。下面的两个例子是等价的,第一个使用表约束语法,第二个使用列约束 语法: CREATE TABLE distributors ( did integer, name varchar(40), PRIMARY KEY(did) ); CREATE TABLE distributors ( did integer PRIMARY KEY, name varchar(40) ); 为列 name 赋予一个文字常量默认值,安排列 did 的默认值是从一个序列对象中选择下一个值产生,并且让 modtime 的默认值是该行被插入的时间: CREATE TABLE distributors ( name varchar(40) DEFAULT 'Luso Films', did integer DEFAULT nextval('distributors_serial'), modtime timestamp DEFAULT current_timestamp ); 在表 distributors 上定义两个 NOT NULL 列约束,其中之一被显式给定了一个名称: 1010 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE CREATE TABLE distributors ( did integer CONSTRAINT no_null NOT NULL, name varchar(40) NOT NULL ); 为 name 列定义一个唯一约束: CREATE TABLE distributors ( did integer, name varchar(40) UNIQUE ); 同样的唯一约束用表约束指定: CREATE TABLE distributors ( did integer, name varchar(40), UNIQUE(name) ); 创建相同的表,指定表和它的唯一索引指定 70% 的填充因子: CREATE TABLE distributors ( did integer, name varchar(40), UNIQUE(name) WITH (fillfactor=70) ) WITH (fillfactor=70); 创建表 circles,带有一个排除约束阻止任意两个圆重叠: CREATE TABLE circles ( c circle, EXCLUDE USING gist (c WITH &&) ); 在表空间 diskvol1 中创建表 cinemas: CREATE TABLE cinemas ( id serial, name text, location text ) TABLESPACE diskvol1; 创建一个组合类型以及一个类型化的表: 1011 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE CREATE TYPE employee_type AS (name text, salary numeric); CREATE TABLE employees OF employee_type ( PRIMARY KEY (name), salary WITH OPTIONS DEFAULT 1000 ); 创建一个范围分区表: CREATE TABLE measurement ( logdate date not null, peaktemp int, unitsales int ) PARTITION BY RANGE (logdate); 创建在分区键中具有多个列的范围分区表: CREATE TABLE measurement_year_month ( logdate date not null, peaktemp int, unitsales int ) PARTITION BY RANGE (EXTRACT(YEAR FROM logdate), EXTRACT(MONTH FROM logdate)); 创建列表分区表: CREATE TABLE cities ( city_id bigserial not null, name text not null, population bigint ) PARTITION BY LIST (left(lower(name), 1)); 创建哈希分区表: CREATE TABLE orders ( order_id bigint not null, cust_id bigint not null, status text ) PARTITION BY HASH (order_id); 创建范围分区表的分区: CREATE TABLE measurement_y2016m07 PARTITION OF measurement ( unitsales DEFAULT 0 ) FOR VALUES FROM ('2016-07-01') TO ('2016-08-01'); 1012 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE 使用分区键中的多个列创建范围分区表的几个分区: CREATE TABLE measurement_ym_older PARTITION OF measurement_year_month FOR VALUES FROM (MINVALUE, MINVALUE) TO (2016, 11); CREATE TABLE measurement_ym_y2016m11 PARTITION OF measurement_year_month FOR VALUES FROM (2016, 11) TO (2016, 12); CREATE TABLE measurement_ym_y2016m12 PARTITION OF measurement_year_month FOR VALUES FROM (2016, 12) TO (2017, 01); CREATE TABLE measurement_ym_y2017m01 PARTITION OF measurement_year_month FOR VALUES FROM (2017, 01) TO (2017, 02); 创建列表分区表的分区: CREATE TABLE cities_ab PARTITION OF cities ( CONSTRAINT city_id_nonzero CHECK (city_id != 0) ) FOR VALUES IN ('a', 'b'); 创建本身是分区的列表分区表的分区,然后向其添加分区: CREATE TABLE cities_ab PARTITION OF cities ( CONSTRAINT city_id_nonzero CHECK (city_id != 0) ) FOR VALUES IN ('a', 'b') PARTITION BY RANGE (population); CREATE TABLE cities_ab_10000_to_100000 PARTITION OF cities_ab FOR VALUES FROM (10000) TO (100000); 创建哈希分区表的磁盘分区: CREATE TABLE orders_p1 PARTITION OF orders FOR VALUES WITH (MODULUS 4, REMAINDER 0); CREATE TABLE orders_p2 PARTITION OF orders FOR VALUES WITH (MODULUS 4, REMAINDER 1); CREATE TABLE orders_p3 PARTITION OF orders FOR VALUES WITH (MODULUS 4, REMAINDER 2); CREATE TABLE orders_p4 PARTITION OF orders FOR VALUES WITH (MODULUS 4, REMAINDER 3); 创建默认的分区: 1013 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE CREATE TABLE cities_partdef PARTITION OF cities DEFAULT; 创建范围分区表: CREATE TABLE sales ( prod_id NUMBER(6) , cust_id NUMBER , time_id DATE , channel_id CHAR(1) , promo_id NUMBER(6) , state_id varchar2(2) , quantity_sold NUMBER(3) , amount_sold NUMBER(10,2) ) PARTITION BY RANGE (time_id) ( PARTITION q1_2006 VALUES LESS THAN ('2006-04-01') , PARTITION q2_2006 VALUES LESS THAN ('2006-07-01') , PARTITION q3_2006 VALUES LESS THAN ('2006-10-01') , PARTITION q4_2006 VALUES LESS THAN ('2007-01-01') ); 创建列表分区表: CREATE TABLE sales ( prod_id NUMBER(6) , cust_id NUMBER , time_id DATE , channel_id CHAR(1) , promo_id NUMBER(6) , state_id varchar2(2) , quantity_sold NUMBER(3) , amount_sold NUMBER(10,2) ) PARTITION BY LIST (state_id) ( PARTITION northwest VALUES ('OR', 'WA') , PARTITION southwest VALUES ('AZ', 'UT', 'NM') , PARTITION northeast VALUES ('NY', 'VM', 'NJ') , PARTITION southeast VALUES ('FL', 'GA') , PARTITION northcentral VALUES ('SD', 'WI') , PARTITION southcentral VALUES ('OK', 'TX') , PARTITION defaultstate VALUES (DEFAULT) ); 创建哈希分区表: 1014 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE CREATE TABLE sales ( prod_id NUMBER(6) , cust_id NUMBER , time_id DATE , channel_id CHAR(1) , promo_id NUMBER(6) , state_id varchar2(2) , quantity_sold NUMBER(3) , amount_sold NUMBER(10,2) ) PARTITION BY HASH(channel_id) ( PARTITION p1 , PARTITION p2 , PARTITION p3 , PARTITION p4 ); 创建列表-列表复合分区表: CREATE TABLE customers ( customer_id NUMBER(6), name VARCHAR2(20), regdate date, email VARCHAR2(30), territory VARCHAR2(20), userlevel NUMBER(2) ) PARTITION BY LIST(userlevel) SUBPARTITION BY LIST(territory) ( PARTITION level1 VALUES (1, 2, 3) ( SUBPARTITION eastasia1 VALUES ('CHINA', 'JAPAN'), SUBPARTITION southeastasia1 VALUES ('THAILAND'), SUBPARTITION southasia1 VALUES ('INDIA'), SUBPARTITION centralasia1 VALUES ('KAZAKHSTAN'), SUBPARTITION westasia1 VALUES ('IRAN'), SUBPARTITION rest1 VALUES (DEFAULT) ), PARTITION level2 VALUES (4, 5, 6) ( SUBPARTITION eastasia2 VALUES ('CHINA', 'JAPAN'), SUBPARTITION southeastasia2 VALUES ('THAILAND'), SUBPARTITION southasia2 VALUES ('INDIA'), 1015 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE SUBPARTITION centralasia2 VALUES ('KAZAKHSTAN'), SUBPARTITION westasia2 VALUES ('IRAN'), SUBPARTITION rest2 VALUES (DEFAULT) ) ); CREATE TABLE customers ( customer_id NUMBER(6), name VARCHAR2(20), regdate date, email VARCHAR2(30), territory VARCHAR2(20), userlevel NUMBER(2) ) PARTITION BY LIST(userlevel) SUBPARTITION BY LIST(territory) SUBPARTITION TEMPLATE ( SUBPARTITION eastasia VALUES ('CHINA', 'JAPAN'), SUBPARTITION southeastasia VALUES ('THAILAND'), SUBPARTITION southasia VALUES ('INDIA'), SUBPARTITION centralasia VALUES ('KAZAKHSTAN'), SUBPARTITION rest VALUES (DEFAULT) ) ( PARTITION level1 VALUES (1, 2, 3), PARTITION level2 VALUES (4, 5, 6) ); 创建列表-哈希复合分区表: CREATE TABLE customers ( customer_id NUMBER(6), name VARCHAR2(20), regdate date, email VARCHAR2(30), territory VARCHAR2(20), userlevel NUMBER(2) ) PARTITION BY LIST (userlevel) SUBPARTITION BY HASH (customer_id) ( PARTITION level1 VALUES (1,2,3) 1016 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE ( SUBPARTITION level1_hash1, SUBPARTITION level1_hash2, SUBPARTITION level1_hash3, SUBPARTITION level1_hash4 ), PARTITION level2 VALUES (4,5,6) ( SUBPARTITION level2_hash1, SUBPARTITION level2_hash2, SUBPARTITION level2_hash3, SUBPARTITION level2_hash4 ) ); CREATE TABLE customers ( customer_id NUMBER(6), name VARCHAR2(20), regdate date, email VARCHAR2(30), territory VARCHAR2(20), userlevel NUMBER(2) ) PARTITION BY LIST (userlevel) SUBPARTITION BY HASH (customer_id) SUBPARTITION TEMPLATE ( SUBPARTITION hash1, SUBPARTITION hash2, SUBPARTITION hash3, SUBPARTITION hash4 ) ( PARTITION level1 VALUES (1,2,3), PARTITION level2 VALUES (4,5,6) ); 创建列表-范围复合分区表: CREATE TABLE customers ( customer_id NUMBER(6), name VARCHAR2(20), regdate date, 1017 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE email VARCHAR2(30), territory VARCHAR2(20), userlevel NUMBER(2) ) PARTITION BY LIST(userlevel) SUBPARTITION BY RANGE(regdate) ( PARTITION level1 VALUES (1, 2, 3) ( SUBPARTITION reg1_20_q1 VALUES LESS THAN('2020-04-01'), SUBPARTITION reg1_20_q2 VALUES LESS THAN('2020-07-01'), SUBPARTITION reg1_20_q3 VALUES LESS THAN('2020-10-01'), SUBPARTITION reg1_20_q4 VALUES LESS THAN('2021-01-01'), SUBPARTITION reg1_upper VALUES LESS THAN(MAXVALUE) ), PARTITION level2 VALUES (4, 5, 6) ( SUBPARTITION reg2_20_q1 VALUES LESS THAN('2020-04-01'), SUBPARTITION reg2_20_q2 VALUES LESS THAN('2020-07-01'), SUBPARTITION reg2_20_q3 VALUES LESS THAN('2020-10-01'), SUBPARTITION reg2_20_q4 VALUES LESS THAN('2021-01-01'), SUBPARTITION reg2_upper VALUES LESS THAN(MAXVALUE) ) ); CREATE TABLE customers ( customer_id NUMBER(6), name VARCHAR2(20), regdate date, email VARCHAR2(30), territory VARCHAR2(20), userlevel NUMBER(2) ) PARTITION BY LIST(userlevel) SUBPARTITION BY RANGE(regdate) SUBPARTITION TEMPLATE ( SUBPARTITION reg2_20_q1 VALUES LESS THAN('2020-04-01'), SUBPARTITION reg2_20_q2 VALUES LESS THAN('2020-07-01'), SUBPARTITION reg2_20_q3 VALUES LESS THAN('2020-10-01'), SUBPARTITION reg2_20_q4 VALUES LESS THAN('2021-01-01'), SUBPARTITION reg_upper VALUES LESS THAN(MAXVALUE) ) ( 1018 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE PARTITION level1 VALUES (1, 2, 3), PARTITION level2 VALUES (4, 5, 6) ); 创建 INTERVAL 分区表: CREATE TABLE customers ( customer_id NUMBER(6), name VARCHAR2(20), regdate date, email VARCHAR2(30), territory VARCHAR2(20), userlevel NUMBER(2) ) PARTITION BY RANGE (regdate) INTERVAL ('3 month'::interval) ( PARTITION p0 VALUES LESS THAN(TO_DATE('2020-04-01', 'YYYY-MM-DD')) ); 创建 INTERVAL 复合分区表: CREATE TABLE customers ( customer_id NUMBER(6), name VARCHAR2(20), regdate date, email VARCHAR2(30), territory VARCHAR2(20), userlevel NUMBER(2) ) PARTITION BY RANGE (regdate) INTERVAL ('3 month'::interval) SUBPARTITION BY HASH (customer_id) SUBPARTITION TEMPLATE ( SUBPARTITION hash1, SUBPARTITION hash2, SUBPARTITION hash3, SUBPARTITION hash4 ) ( PARTITION p0 VALUES LESS THAN(TO_DATE('2020-04-01', 'YYYY-MM-DD')) ); 在 MySQL 模式的数据库下,创建一个包含注释的表: 1019 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE CREATE TABLE test_comment ( id INT PRIMARY KEY COMMENT 'ID of table', name VARCHAR(20) ) COMMENT = 'a table for testing the feature of comment'; 兼容性 CREATE TABLE 命令遵从 SQL 标准,除了以下例外。 1. 临时表 尽管 CREATE TEMPORARY TABLE 的语法很像 SQL 标准的语法,但事实是并不相同。在标准中,临时表只需要 被定义一次并且会自动地存在(从空内容开始)于需要它们的每一个会话中。KingbaseES 则要求每一个会话为每一 个要用的临时表发出它自己的 CREATE TEMPORARY TABLE 命令。这允许不同的会话为不同的目的使用相同的临时表 名,而标准的方法约束一个给定临时表名的所有实例都必须具有相同的表结构。 标准中对于临时表行为的定义被广泛地忽略了。KingbaseES 在这一点上的行为和多种其他 SQL 数据库是相似 的。 SQL 标准也区分全局和本地临时表,其中一个本地临时表为每一个会话中的每一个 SQL 模块具有一个独立的内 容集合,但是它的定义仍然是多个会话共享的。因为 KingbaseES 不支持 SQL 模块,这种区别与 KingbaseES 无关。 2. 非延迟唯一性约束 但一个 UNIQUE 或 PRIMARY KEY 约束是非可延迟的,只要一个行被插入或修改,KingbaseES 就会立即检查唯一 性。SQL 标准指出只有在语句结束时才应该强制唯一性。当一个单一命令更新多个键值时,这两者是不同的。要得 到兼容标准的行为,将该约束声明为 DEFERRABLE 但是不延迟(即 INITIALLY IMMEDIATE)。注意这可能要显著地 慢于立即唯一性检查。 3. 列检查约束 SQL 标准指出 CHECK 列约束只能引用它们应用到的列,只有 CHECK 表约束能够引用多列。KingbaseES 并没有 强制这个限制,它同样处理列检查约束和表检查约束。 4. EXCLUDE 约束 EXCLUDE 约束类型是一种 KingbaseES 扩展。 5. NULL 约束 NULL “约束”(实际上是一个非约束)是一个 KingbaseES 对 SQL 标准的扩展,它也被包括(以及对称的 NOT NULL 约束)在一些其他的数据库系统中以实现兼容性。因为它是任意列的默认值,它的存在就像噪声一样。 6. 约束的命名 SQL 标准规定,表和域约束的名称必须在包含表或域的模式中是唯一的。KingbaseES 是宽松的: 它只要求约 束名称在附加到特定表或域的约束之间是唯一的。然而,这种额外的自由对于基于索引的约束并不存在 (UNIQUE、 PRIMARY KEY、和 EXCLUDE 约束),因为关联的索引与约束的名称相同,而且索引名称必须在相同模式中的所有关系 中是惟一的。 1020 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE 当前,KingbaseES 不记录 NOT NULL 约束的名称,所以它们不受唯一性限制。在将来的版本中可能会有所改 变。 7. 继承 通过 INHERITS 子句的多继承是一种 KingbaseES 的语言扩展。SQL:1999 以及之后的标准使用一种不同的语法 和不同的语义定义了单继承。SQL:1999-风格的继承还没有被 KingbaseES。 8. 零列表 KingbaseES 允许创建一个没有列的表(例如 CREATE TABLE foo();)。这是一个对于 SQL 标准的扩展,它不 允许零列表。零列表本身并不是很有用,但是不允许它们会为 ALTER TABLE DROP COLUMN 带来奇怪的特殊情况,因 此忽略这种规则限制看起来更加整洁。 9. 多个标识列 KingbaseES 允许一个表拥有多个标识列。该标准指定一个表最多只能有一个标识列。这主要是为了给模式更改 或迁移提供更大的灵活性。请注意,INSERT 命令仅支持一个适用于整个语句的覆盖子句,因此不支持具有不同行为 的多个标识列。 10. 生成列 存储的选项不是标准的,但是其他 SQL 在实践中也使用它。SQL 标准没有指定生成列的存储。 11. LIKE 子句 虽然 SQL 标准中有一个 LIKE 子句,但是 KingbaseES 接受的很多 LIKE 子句选项却不在标准中,并且有些标准 中的选项也没有被 KingbaseES 实现。 12. WITH 子句 WITH 子句是一个 KingbaseES 扩展,存储参数不在标准中。 13. 表空间 KingbaseES 的表空间概念不是标准的一部分。因此,子句 TABLESPACE 和 USING INDEX TABLESPACE 是扩展。 14. 类型化的表 类型化的表实现了 SQL 标准的一个子集。根据标准,一个类型化的表具有与底层组合类型相对应的列,以及其 他的“自引用列”。KingbaseES 不显式支持这些自引用列。 15. PARTITION BY 子句 PARTITION BY 子句是 KingbaseES 的一个扩展。 16. PARTITION OF 子句 PARTITION OF 子句 KingbaseES 的一个扩展。 其他 由于包中的类型以 package.type 的格式存储到 sys_type 中,为防止用户自定义类型(表)与包中类型相冲突, 故不支持用户自定义带‘.’的类型或者表。如果创建表名带’.’ 的普通表,如:create table ”Evil.Table”(id serial); 会 报错 ERROR: type or table name can not include ’.’。 1021 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE 16.7 CREATE TABLE AS 用途 CREATE TABLE AS 创建一个表,并且用由一个 SELECT 命令计算出来的数据填充该表。该表的列具有和 SELECT 的输出列相关的名称和数据类型(但是可以通过给出一个显式的新列名列表来覆盖这些列名)。此外,还可以通过 PARTITION BY 子句指定新建表的分区信息。 CREATE TABLE AS 和创建一个视图有些相似,但是实际上非常不同:它会创建一个新表并且只计算该查询一次用 来初始填充新表。这个新表将不会跟踪该查询源表的后续变化。相反,一个视图只要被查询,它的定义 SELECT 语句 就会被重新计算。 前置条件 你必须要有一个查询结果以使用 CREATE TABLE AS 。还必须要有 CREATE 特权。 语法 CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXISTS ] table_name [ (column_name [, ...] ) ] [ partition_by_clause ] [ USING method ] [ WITH ( storage_parameter [= value] [, ...] ) | WITHOUT OIDS ] [ ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP } ] [ TABLESPACE tablespace_name ] AS query [ WITH [ NO ] DATA ] 1022 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE partition_by_clause 是: PARTITION BY { RANGE | LIST | HASH } ( { column_name | ( expression ) } [COLLATE collation ] [ opclass ] [, ...] ) [ partition_extented_spec ] 1023 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE partition_extented_spec 是: [ INTERVAL ( interval_expr ) [ STORE IN ( tablespace_name [, ...]) ]] [ SUBPARTITION BY { RANGE | LIST | HASH } ( { column_name | ( expression ) } [ COLLATE collation ] [ opclass ] [, ...] ) [ { hash_subparts_by_quantity | subpartition_template } ] ] [ ( PARTITION partition [partition_bound_spec_ex] [ TABLESPACE tablespace_name ] [ ( SUBPARTITION subpartition [subpartition_bound_spec][ TABLESPACE tablespace_name ][, ...]) | SUBPARTITIONS numeric_literal [ STORE IN ( tablespace_name [, ...] ) ] ] [, ...] ) | PARTITIONS numeric_literal [ STORE IN ( tablespace_name [, ...] ) ] ] hash_subparts_by_quantity 是: 1024 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE SUBPARTITIONS numeric_literal [ STORE IN ( tablespace_name [, ...] ) ] subpartition_template 是: SUBPARTITION TEMPLATE ( SUBPARTITION [subpartition] [subpartition_bound_spec] [ TABLESPACE tablespace_name ][, ...] ) partition_bound_spec_ex 是: VALUES LESS THAN ( { partition_bound_expr | MAXVALUE } [, ...] ) | VALUES ( partition_bound_expr [, ...] | DEFAULT ) subpartition_bound_spec 是: VALUES LESS THAN ( { partition_bound_expr | MAXVALUE } [, ...] ) | VALUES ( partition_bound_expr [, ...] | DEFAULT ) 1025 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE 语义 GLOBAL 或者 LOCAL KingbaseES 支持本地临时表和全局临时表,详见CREATE TABLE 。 TEMPORARY 或者 TEMP 如果被指定,该表会被创建为一个临时表。详见CREATE TABLE 。 UNLOGGED 如果被指定,该表会被创建为一个不做日志的表。详见CREATE TABLE 。 IF NOT EXISTS 如果已经存在一个同名的关系时不要抛出错误。这种情况下会发出一个提示。详见CREATE TABLE 。 table_name 要创建的表的名称(可以被模式限定)。 column_name 新表中一列的名称。如果没有提供列名,会从查询的输出列名中得到。 USING method 此可选子句指定用于存储新表的内容的表访问方法; 该方法需要是类型 TABLE 的访问方法。如果未指 定此选项,则为新表选择默认的表访问方法。有关更多信息,参见 default_table_access_method 参数。 WITH ( storage_parameter [ = value ] [, ...] ) 这个子句为新表指定可选的存储参数。为了向后兼容,表的 WITH 子句还可以包含 OIDS=FALSE,以指定新表的行应该不包含 oid(对象标识符),OIDS=TRUE 不再被支持。 WITH OIDS | WITHOUT OIDS 这是向后兼容的语法,用于声明一个 WITHOUT OIDS 表,创建一个 WITH OIDS 表不再受 支持。 ON COMMIT 临时表在事务块结束时的行为可以用“ON COMMIT“控制。三个选项是: PRESERVE ROWS 在事务结束时不采取特殊的动作。这是默认行为。 DELETE ROWS 在每一个事务块结束时临时表中的所有行都将被删除。本质上,在每次提交时会完成一次自动 的TRUNCATE 。 DROP 在当前事务块结束时将删掉临时表。 TABLESPACE tablespace_name “tablespace_name“ 是要在其中创建新表的表空间名称。如果没有指定,将会查询 default_tablespace,临时表会查询 temp_tablespaces 。 query 一个SELECT 或者VALUES 命令,或者是一个运行准备好的 SELECT、TABLE 或者 VALUES 查询的EXECUTE 命令。 1026 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE WITH [ NO ] DATA 这个子句指定查询产生的数据是否应该被复制到新表中。如果不是,只有表结构会被复制。默认 是复制数据。 COLLATE collation COLLATE 子句为该列(必须是一种可排序数据类型)赋予一个排序规则。如果没有指定,将 使用该列数据类型的默认排序规则。 partition_bound_expr 任何无变量表达式(不允许子查询、窗口函数、聚合函数和集返回函数)。它的数据类型必 须与相应分区键列的数据类型相匹配。表达式在表创建时只计算一次,因此它甚至可以包含 volatile 表达式,如 CURRENT_TIMESTAMP。 numeric_literal 正整数。 示例 创建一个新表 films_recent,它只由表 films 中最近的项组成: CREATE TABLE films_recent AS SELECT * FROM films WHERE date_prod >= '2002-01-01'; 要完全地复制一个表,也可以使用 TABLE 命令的简短形式: CREATE TABLE films2 AS TABLE films; 用一个预备语句创建一个新的临时表 films_recent,它仅由表 films 中最近的项组成。新表将在提交时被删 除: PREPARE recentfilms(date) AS SELECT * FROM films WHERE date_prod > $1; CREATE TEMP TABLE films_recent ON COMMIT DROP AS EXECUTE recentfilms('2002-01-01'); 创建 students 表,并且以查询 students 表结果集作为分区表 p_students 的数据: CREATE TABLE students(id int, name text); INSERT INTO students VALUES (1,'haha'); INSERT INTO students VALUES (100,'today'); INSERT INTO students VALUES (500,'street'); INSERT INTO students VALUES (5000,'hary'); INSERT INTO students VALUES (50000,'marry'); -- create table partition_table as query CREATE TABLE p_students (a, b) PARTITION BY RANGE (a) ( PARTITION pt1 VALUES LESS THAN (100), PARTITION pt2 VALUES LESS THAN (1000), PARTITION pt3 VALUES LESS THAN (maxvalue) ) AS SELECT * FROM STUDENTS; 1027 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE SELECT 'p1' 分区名, t.* from p_students PARTITION (pt1) t; 分区名 | a | b --------+---+-----p1 | 1 | haha (1 row) SELECT 'p2' 分区名, t.* FROM p_students PARTITION (pt2) t; 分区名 | a | b --------+-----+-------p2 | 100 | today p2 | 500 | street (2 rows) SELECT 'p3' 分区名, t.* FROM p_students PARTITION (pt3) t; 分区名 | a | b --------+-------+------p3 | 5000 | hary p3 | 50000 | marry (2 rows) 兼容性 CREATE TABLE AS 符合 SQL 标准。下面的是非标准扩展: • 标准要求在子查询子句周围有圆括号,在 KingbaseES 中这些圆括号是可选的。 • 在标准中,WITH [ NO ] DATA 子句是必要的,而 KingbaseES 中是可选的。 • KingbaseES 处理临时表的方式和标准不同。详见CREATE TABLE 。 • WITH 子句是一种 KingbaseES 扩展,标准中没有存储参数。 • KingbaseES 的表空间概念是标准的一部分。因此,子句 TABLESPACE 是一种扩展。 partition_by_clause 子句仅支持兼容数据库 ORACLE 模式。 其他 这个命令在功能上类似于SELECT INTO ,但是它更好,因为不太可能被 SELECT INTO 语法的其他使用混淆。 更进一步,CREATE TABLE AS 提供了 SELECT INTO 的功能的一个超集。 16.8 CREATE TABLESPACE 用途 CREATE TABLESPACE 注册一个新的集簇范围的表空间。表空间的名称必须与数据库集簇中现有的任何表空间不 同。 1028 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE 表空间允许超级用户在文件系统上定义另一个位置,可以把包含数据库对象(例如表和索引)的数据文件放在那 里。 一个具有适当特权的用户可以把 “tablespace_name“传递给 CREATE DATABASE、CREATE TABLE、CREATE INDEX 或者 ADD CONSTRAINT 来让这些对象的数据文件存储在指定的表空间中。 警告: 表空间不能独立于定义它的集簇使用,见 表空间。表空间指定的 directory 不能位于数据库集簇目录 下。 前置条件 只有在支持符号链接的系统上才支持表空间。 CREATE TABLESPACE 不能在一个事务块内被执行。 语法 CREATE TABLESPACE tablespace_name [ OWNER { new_owner | CURRENT_USER | SESSION_USER } ] LOCATION 'directory' [ ONLINE | OFFLINE ] [ WITH ( tablespace_option = value [, ... ] ) ] 语义 tablespace_name 要创建的表空间的名称。该名称不能以 sys_ 开头,因为 sys_ 名称是为系统表空间保留的。 user_name 将拥有该表空间的用户名。如果省略,默认为执行该命令的用户。只有超级用户能创建表空间,但是它 们能把表空间的拥有权赋予给非超级用户。 directory 要被用于表空间的目录。该目录如果存在 (CREATE TABLESPACE 指定的目录不存在则会报错), 应该为空并 且必须由 KingbaseES 系统用户拥有。该目录必须用一个绝对路径指定。 1029 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE 注意:如果是主备模式,则需要在主备节点分别创建对应的目录。 tablespace_option 要设置或者重置的表空间参数。当前,唯一可用的参数是 seq_page_cost、random_page_cost 以及 effective_io_concurrency 为一个特定表空间设定其中一个值将覆盖规划器对该表空间中表页读取的 常规代价估计,常规代价估计是由同名的配置参数所建立(见 seq_page_cost、random_page_cost 、effective_io_concurrency )。如果一个表空间位于一个比其他 I/O 子系统更慢或者更快的磁盘上,这些参数就能 发挥作用。 通过指定 encryption 参数来确定表空间是否加密。通过制定 enckey 参数来指定用户的表空间密钥 此外还有和表空间模式相关的参数 online_mode、readonly_mode, 以上两个参数均为 bool 类型, 分别代表 表空间的一级模式 ONLINE/ OFFLINE 和二级模式 READONLY / READWRITE。其中创建表空间只能指 定 online_mode, readonly_mode 的设置可以在表空间创建后通过 ALTER 命令实现。如果创建过程中指定了 online_mode 参数为 true 表名创建的表空间是在线状态,此时表空间可提供任何服务。相反如果参数指定为 false,那么创建的表空间将不能提供任何的读写服务。如果不设置,默认为在线状态。备注:表空间只读或者 离线状态设置前,请先关闭参数 skip_tablespace_check(仅超级用户有修改和查看权限,默认是开启的),该 参数开启状态下不会检查当前操作是否满足表空间状态。 示例 在文件系统位置/data/dbs 创建一个表空间 dbspace,首先使用操作系统工具创建目录并设置正确的所有权: mkdir /data/dbs chown kingbase:kingbase /data/dbs 然后在 KingbaseES 内部发出表空间创建命令: CREATE TABLESPACE dbspace LOCATION '/data/dbs'; 创建由不同数据库用户拥有的表空间,使用如下命令: CREATE TABLESPACE indexspace OWNER genevieve LOCATION '/data/indexes'; 创建加密表空间,使用如下命令: CREATE TABLESPACE encrypt_tsp OWNER genevieve LOCATION '/data/encrypt_tsp' with (encryption = true, enckey = '12345678ab'); 创建表空间指定 ONLINE/OFFLINE 模式,可以使用参数进行设置: CREATE TABLESPACE tblspace_tsp1 LOCATION '/data/tblspace' WITH (ONLINE_MODE=TRUE); 也可以通过 Oracle 的兼容命令设置: CREATE TABLESPACE tblspace_tsp1 LOCATION '/data/tblspace' ONLINE; 如果两者同时设置但值不同,以 oracle 语法设置的模式的值为准,如: 1030 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE CREATE TABLESPACE tblspace_tsp1 LOCATION '/data/tblspace' OFFLINE WITH (ONLINE_MODE=TRUE); 此时表空间模式最终为离线。 兼容性 CREATE TABLESPACE 是一种 KingbaseES 扩展。 16.9 CREATE TEXT SEARCH CONFIGURATION 用途 CREATE TEXT SEARCH CONFIGURATION 创建一个新的文本搜索配置。一个文本搜索配置指定一个文本搜索解析器 (它能把字符串解析成记号),外加一些词典(可被用来决定哪些记号是搜索感兴趣的)。 如果只指定了解析器,那么新文本搜索配置最初没有从记号类型到词典的映射,并且因此将忽略所有词。后续的 ALTER TEXT SEARCH CONFIGURATION 命令必须被用来创建映射以让该配置变得可用。另一种方式是复制一个现有的 文本搜索配置。 如果给定一个模式名称,则文本搜索配置会被创建在指定的模式中。否则它将会被创建在当前模式中。 定义一个文本搜索配置的用户会成为其拥有者。 进一步的信息请参考 全文搜索。 前置条件 引用的文本搜索解析器必须已存在。 语法 CREATE TEXT SEARCH CONFIGURATION name ( PARSER = parser_name | COPY = source_config ) 语义 name 要创建的文本搜索配置的名称。该名称可以被模式限定。 parser_name 这个配置要使用的文本搜索解析器的名称。 source_config 要复制的已有文本搜索配置的名称。 1031 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE PARSER 和 COPY 选项是互斥的,因为当一个已有的配置被复制时,它的解析器选择也会被复制。 示例 CREATE TEXT SEARCH CONFIGURATION zhparsercfg (PARSER = zhparser); 兼容性 在 SQL 标准中没有 CREATE TEXT SEARCH CONFIGURATION 语句。 16.10 CREATE TEXT SEARCH DICTIONARY 用途 CREATE TEXT SEARCH DICTIONARY 创建一个新的文本搜索字典。一个文本搜索字典指定一种识别搜索感兴趣或 者不感兴趣的单词的方法。一个字典依赖于一个文本搜索模板,后者指定了实际执行该工作的函数。通常该字典提供 一些控制该模板函数细节行为的选项。 如果给出了一个模式名称,那么该文本搜索字典会被创建在指定的模式中。否则它会被创建在当前模式中。 定义文本搜索字典的用户将成为其拥有者。 前置条件 无 语法 CREATE TEXT SEARCH DICTIONARY name ( TEMPLATE = template [, option = value [, ... ]] ) 语义 name 要创建的文本搜索字典的名称。该名称可以是模式限定的。 template 将定义这个字典基本行为的文本搜索模板的名称。 option 要为此字典设置的模板相关选项的名称。 1032 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE value 用于模板相关选项的值。如果该值不是一个简单标识符或者数字,它必须被加引用(你可以按照你所希望的总 是对它加上引用)。 选项可以以任意顺序出现。 示例 下面的例子命令创建了一个基于 Snowball 的字典,它使用了非标准的停用词列表。 CREATE TEXT SEARCH DICTIONARY my_russian ( template = snowball, language = russian, stopwords = myrussian ); 兼容性 在 SQL 标准中没有 CREATE TEXT SEARCH DICTIONARY 语句。 16.11 CREATE TEXT SEARCH PARSER 用途 CREATE TEXT SEARCH PARSER 创建一个新的文本搜索解析器。一个文本搜索解析器定义把文本字符串分解成记 号并且为记号分配类型(分类)的方法。一个解析器本身并不特别有用,但是必须与一些要用于搜索的文本搜索字典 一起被绑定到一个文本搜索配置中。 如果给出了一个模式名称,那么文本搜索解析器将被创建在指定的模式中。否则它会被创建在当前模式中。 更多信息可以参考 全文搜索。 前置条件 只有超级用户才能使用 CREATE TEXT SEARCH PARSER(这是因为错误的文本搜索定义可能会让服务器混淆甚至 崩溃)。 语法 CREATE TEXT SEARCH PARSER name ( START = start_function , GETTOKEN = gettoken_function , END = end_function , LEXTYPES = lextypes_function [, HEADLINE = headline_function ] ) 1033 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE 语义 name 要创建的文本搜索解析器的名称。该名称可以是模式限定的。 start_function 用于该解析器的开始函数的名称。 gettoken_function 用于该解析器的取下一个记号的函数名称。 end_function 用于该解析器的结束函数的名称。 lextypes_function 用于该解析器的词法分析器函数(一个返回其产生的记号类型集合信息的函数)的名称。 headline_function 用于该解析器的标题函数(一个对记号集合进行综述的函数)的名称。 如有必要,函数的名称可以被模式限定。参数类型没有给出,因为函数的每个类型的参数列表无法被预先决定。 除了标题函数之外,所有函数都是必要的。 参数可以以任何顺序出现,而不是必须按照上面所展示的顺序。 示例 CREATE TEXT SEARCH PARSER jieba ( START = jieba_start, GETTOKEN = jieba_gettoken, END = jieba_end, LEXTYPES = jieba_lextype, HEADLINE = prsd_headline ); 兼容性 在 SQL 标准中没有 CREATE TEXT SEARCH PARSER 语句。 16.12 CREATE TEXT SEARCH TEMPLATE 用途 CREATE TEXT SEARCH TEMPLATE 创建一个新的文本搜索模板。文本搜索模板定义实现文本搜索字典的函数。一 个模板本身没什么用处,但是必须被实例化为一个字典来使用。字典通常指定要给予模板函数的参数。 如果给出了一个模式名,文本搜索模板会被创建在指定模式中。否则它会被创建在当前模式中。 1034 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE 进一步的信息可以参考 全文搜索。 前置条件 必须成为超级用户以使用 CREATE TEXT SEARCH TEMPLATE。做出这种限制是因为错误的模板定义会让服务器混 淆甚至崩溃。将模板与字典分隔开来的原因是模板中封装了定义字典的“不安全”方面。在定义字典时可以被设置的 参数对非特权用户是可以安全设置的,因此创建字典不需要拥有特权来操作。 语法 CREATE TEXT SEARCH TEMPLATE name ( [ INIT = init_function , ] LEXIZE = lexize_function ) 语义 name 要创建的文本搜索模板的名称。该名称可以被模式限定。 init_function 用于模板的初始化函数的名称。 lexize_function 用于模板的分词函数的名称。 如有必要,函数名称可以被模式限定。参数类型没有给出,因为每一类函数的参数列表是预先定义好的。分词函 数是必需的,但是初始化函数是可选的。 参数可以以任何顺序出现,而不是只能按照上文的顺序。 示例 CREATE TEXT SEARCH TEMPLATE intdict_template1 ( LEXIZE = dintdict_lexize, INIT = dintdict_init ); 兼容性 在 SQL 标准中没有 CREATE TEXT SEARCH TEMPLATE 语句。 16.13 CREATE TRANSFORM 用途 1035 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE CREATE TRANSFORM 定义一种新的转换。CREATE OR REPLACE TRANSFORM 将创建一种新的转换或者替换现有的定 义。 一种转换指定了如何把一种数据类型适配到一种过程语言。例如,在用 PL/Python 编写一个使用 hstore 类型 的函数时,PL/Python 没有关于如何在 Python 环境中表示 hstore 值的先验知识。语言的实现通常默认会使用文本 表示,但是在一些时候这很不方便,例如有时可能用一个联合数组或者列表更合适。 一种转换指定了两个函数: • 一个“from SQL”函数负责将类型从 SQL 环境转换到语言。这个函数将在该语言编写的一个函数的参数上调 用。 • 一个“to SQL”函数负责将类型从语言转换到 SQL 环境。这个函数将在该语言编写的一个函数的返回值上调 用。 没有必要同时提供这些函数。如果有一种没有被指定,将在必要时使用与语言相关的默认行为(为了完全阻止在 一个方向上发生转换,你也可以写一个总是报错的转换函数)。 前置条件 要创建一种转换,你必须拥有该类型并且具有该类型上的 USAGE 特权,拥有该语言上的 USAGE 特权,并且拥有 from-SQL 和 to-SQL 函数(如果指定了)及其上的 EXECUTE 特权。 语法 CREATE [ OR REPLACE ] TRANSFORM FOR type_name LANGUAGE lang_name ( FROM SQL WITH FUNCTION from_sql_function_name [ (argument_type [, ...]) ], TO SQL WITH FUNCTION to_sql_function_name [ (argument_type [, ...]) ] ); 语义 type_name 该转换的数据类型的名称。 lang_name 该转换的语言的名称。 1036 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE from_sql_function_name [(argument_type [, ...])] 将该类型从 SQL 环境转换到该语言的函数名。它必须接受 一个 internal 类型的参数并且返回类型 internal。实参将是该转换所适用的类型,并且该函数也应该被写 成认为它是那种类型(但是不允许声明一个返回 internal 但没有至少一个 internal 类型参数的 SQL 层函 数)。实际的返回值将与语言的实现相关。如果没有指定参数列表,则函数名在该模式中必须唯一。 to_sql_function_name [(argument_type [, ...])] 将该类型从语言转换到 SQL 环境的函数名。它必须接受一个 internal 类型的参数并且返回该转换所适用的类型。实参值将与语言的实现相关。如果没有指定参数列表,则 函数名在该模式中必须唯一。 示例 要为类型 hstore 和语言 plpythonu 创建一种转换,先搞定该类型和语言: CREATE TYPE hstore ...; CREATE LANGUAGE plpythonu ...; 然后创建需要的函数: CREATE FUNCTION hstore_to_plpython(val internal) RETURNS internal LANGUAGE C STRICT IMMUTABLE AS ...; CREATE FUNCTION plpython_to_hstore(val internal) RETURNS hstore LANGUAGE C STRICT IMMUTABLE AS ...; 最后创建转换把它们连接起来: CREATE TRANSFORM FOR hstore LANGUAGE plpythonu ( FROM SQL WITH FUNCTION hstore_to_plpython(internal), TO SQL WITH FUNCTION plpython_to_hstore(internal) ); 实际上,这些命令将被包裹在扩展中。 contrib 小节包含了一些提供转换的扩展,它们可以作为实际的例子。要为类型 hstore 和语言 plpythonu 创建 一种转换,先搞定该类型和语言: CREATE TYPE hstore ...; CREATE LANGUAGE plpythonu ...; 然后创建需要的函数: CREATE FUNCTION hstore_to_plpython(val internal) RETURNS internal LANGUAGE C STRICT IMMUTABLE AS ...; 1037 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE CREATE FUNCTION plpython_to_hstore(val internal) RETURNS hstore LANGUAGE C STRICT IMMUTABLE AS ...; 最后创建转换把它们连接起来: CREATE TRANSFORM FOR hstore LANGUAGE plpythonu ( FROM SQL WITH FUNCTION hstore_to_plpython(internal), TO SQL WITH FUNCTION plpython_to_hstore(internal) ); 实际上,这些命令将被包裹在扩展中。 contrib 小节包含了一些提供转换的扩展,它们可以作为实际的例子。 兼容性 这种形式的 CREATE TRANSFORM 是一种 KingbaseES 扩展。在 SQL 标准中有一个 CREATE TRANSFORM 命令,但 是它是用于把数据类型适配到客户端语言。该用法不受 KingbaseES 支持。 16.14 CREATE TRIGGER 用途 CREATE TRIGGER 创建一个新触发器。该触发器将被关联到指定的表、视图或者外部表并且在表上发生特定操作 时将执行指定的函数 “function_name“。 该触发器可以被指定为在一行上尝试该操作之前触发(在约束被检查并且 INSERT、UPDATE 或者 DELETE 被尝试 之前);也可以在该操作完成之后触发(在约束被检查并且 INSERT、UPDATE 或者 DELETE 完成之后);或者取代该 操作(在对一个视图插入、更新或删除的情况中)。如果该触发器在事件之前触发或者取代事件,该触发器可以跳过 对当前行的操作或者改变正在被插入的行(只对 INSERT 以及 UPDATE 操作)。如果该触发器在事件之后触发,所有 更改(包括其他触发器的效果)对该触发器“可见”。 一个被标记为 FOR EACH ROW 的触发器会对该操作修改的每一行都调用一次。例如,一个影响 10 行的 DELETE 将导致在目标关系上的任何 ON DELETE 触发器被独立调用 10 次,也就是为每一个被删除的行调用一次。与此相反, 一个被标记为 FOR EACH STATEMENT 的触发器只会为任何给定的操作执行一次,不管该操作修改多少行(特别地, 一个修改零行的操作将仍会导致任何可用的 FOR EACH STATEMENT 触发器被执行)。 被指定为要触发 INSTEAD OF 触发器事件的触发器必须被标记为 FOR EACH ROW,并且只能被定义在视图上。一 个视图上的 BEFORE 和 AFTER 触发器必须被标记为 FOR EACH STATEMENT。 此外,触发器可以被定义成为 TRUNCATE 触发,但只能是 FOR EACH STATEMENT。 下面的表格总结了哪些触发器类型可以被用在表、视图和外部表上: 1038 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE 表 16.14.1: 触发器类型 何时 事件 行级 语句级 BEFORE INSERT/UPDATE/DELETE 表和外部表 表、视图和外部表 TRUNCATE — 表 INSERT/UPDATE/DELETE 表和外部表 表、视图和外部表 TRUNCATE — 表 INSERT/UPDATE/DELETE 视图 — TRUNCATE — — AFTER INSTEAD OF 还有,一个触发器定义可以指定一个布尔的 WHEN 条件,它将被测试来看看该触发器是否应该被触发。在行级触 发器中,WHEN 条件可以检查该行的列的新旧值。语句级触发器也可以有 WHEN 条件,尽管该特性对于它们不是很有 用(因为条件不能引用表中的任何值)。 如果有多个同种触发器被定义为相同事件触发,它们将按照名称的字母表顺序被触发。 当 CONSTRAINT 选项被指定,这个命令会创建一个约束触发器。这和一个常规触发器相同,但是触发该触发器的 时机可以使用SET CONSTRAINTS 调整。约束触发器必须是表上的 AFTER ROW 触发器。它们可以在导致触发器事 件的语句末尾被引发或者在包含该语句的事务末尾被引发。在后一种情况中,它们被称作是被延迟。一个待处理的延 迟触发器的引发也可以使用 SET CONSTRAINTS 立即强制发生。当约束触发器实现的约束被违背时,约束触发器应该 抛出一个异常。 REFERENCING 选项启用对传递关系的收集,传递关系是包括被当前 SQL 语句插入、删除或者修改的行的行集 合。这个特性让触发器能看到该语句做的事情的全局视图,而不是一次只看到一行。仅对非约束触发器的 AFTER 触 发器允许这个选项。此外,如果触发器是一个 UPDATE 触发器,则它不能指定 “column_name“列表。OLD TABLE 仅 可以被指定一次,并且只能为在 UPDATE 或 DELETE 事件上引发的触发器指定,它创建的传递关系包含有该语句更新 或删除的所有行的前映像。类似地,NEW TABLE 仅可以被指定一次,并且只能为在 UPDATE 或 INSERT 事件上引发的 触发器指定,它创建的传递关系包含有该语句更新或插入的所有行的后映像。 SELECT 不修改任何行,因此你无法创建 SELECT 触发器。规则和视图可以为需要 SELECT 触发器的问题提供可 行的解决方案。 触发事件可以是多个数据操作的组合,即一个触发器可能既是 INSERT 触发器,又是 DELETE 或 UPDATE 触 发器。当一个触发器可以为多个 DML 语句触发时,在这种触发器体内部可以使用三个谓词:INSERTING、DELETING 和 UPDATING 来确定当前执行的是何种操作。 1039 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE 谓词 状态 INSERTING 当触发语句为 INSERT 时为真,否则为假 DELETING 当触发语句为 DELETE 时为真,否则为假 UPDATING[(< 列 未指定列名时,当触发语句为 UPDATE 时为真,否则为假;指定某一列名时,当触发语句为 名 >)] 对该列的 UPDATE 时为真,否则为假。 关于触发器的更多信息请见 触发器。 前置条件 要在一个表上创建一个触发器,用户必须具有该表上的 TRIGGER 特权。用户还必须具有在触发器函数上的 EXECUTE 特权。 语法 第一种语法: create_trigger ::= CREATE [ OR REPLACE ] [ EDITIONABLE | NONEDITIONABLE ] TRIGGER plsql_trigger_source plsql_trigger_source ::= [ schema. ]trigger_name { simple_dml_trigger | instead_of_dml_trigger } ( simple_dml_trigger ::= , instead_of_dml_trigger ::= ) simple_dml_trigger ::= { BEFORE | AFTER } dml_event_clause [ referencing_clause ] [ FOR EACH ROW ] [ WHEN ( condition ) ] trigger_body 1040 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE ( dml_event_clause ::= , referencing_clause ::= , trigger_body ::= ) instead_of_dml_trigger ::= INSTEAD OF { DELETE | INSERT | UPDATE } [ OR { DELETE | INSERT | UPDATE } ]... ON [ schema. ] noneditioning_view [ referencing_clause ] [ FOR EACH ROW ] trigger_body ( referencing_clause ::= , trigger_body ::= ) dml_event_clause ::= { DELETE | INSERT | UPDATE [ OF column [, column ]... ] } [ OR { DELETE | INSERT | UPDATE [ OF column [, column]... ] }... ON [ schema.] { table | view } 1041 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE referencing_clause ::= REFERENCING { OLD [ AS ] old | NEW [ AS ] new }.. trigger_body ::= { plsql_block | CALL routine_clause } routine_clause ::= [ schema. ] [ type. ] { procedure | method } ( ) ( plsql_block ::= ) 1042 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE 第二种语法: CREATE [ CONSTRAINT ] TRIGGER [ schema. ] name { BEFORE | AFTER | INSTEAD OF } { event [ OR ... ] } ON table_name [ FROM referenced_table_name ] [ NOT DEFERRABLE | [ DEFERRABLE ] [ INITIALLY IMMEDIATE | INITIALLY DEFERRED ] ] [ REFERENCING { { OLD | NEW } TABLE [ AS ] transition_relation_name } [ ... ] ] [ FOR [ EACH ] { ROW | STATEMENT } ] [ WHEN ( condition ) ] EXECUTE { FUNCTION | PROCEDURE } function_name ( arguments ) 图 16.14.1: 这里的 event 可以是下列之一: INSERT UPDATE [ OF column_name [, ... ] ] DELETE TRUNCATE 1043 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE 语义 第一种语法的语义: create_trigger OR REPLACE 如果存在,则重新创建触发器,并重新编译它。 在重新定义触发器之前被授予权限的用户仍然可以访问该过程,而无需重新授予权限。 [ EDITIONABLE | NONEDITIONABLE ] 仅兼容语法。 plsql_trigger_source schema 指定模式名,仅语法兼容。 trigger 要创建的触发器的名称。 simple_dml_trigger 创建一个简单的 DML 触发器(在“DML 触发器”中描述)。 BEFORE 使数据库在运行触发事件之前触发触发器。对于行触发器,触发器会在每个受影响的行 发生更改之前触发。 BEFORE 的限制 不能在视图上指定 BEFORE 触发器,除非它是一个编辑视图。 在 BEFORE 语句触发器中,触发器主体不能读取:NEW 或:OLD。(在 BEFORE 行触发器 中,触发器主体可以读写:OLD 和:NEW 字段。) 1044 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE AFTER 使数据库在运行触发事件后触发触发器。对于行触发器,触发器会在每个受影响的行发 生更改后触发。 对 AFTER 的限制 不能在视图上指定 AFTER 触发器,除非它是一个编辑视图。 在 AFTER 语句触发器中,触发器主体不能读取:NEW 或:OLD。(在 AFTER 行触发器 中,触发器主体可以读取但不能写入:OLD 和:NEW 字段。) FOR EACH ROW 将触发器创建为行触发器。 数据库为受触发语句影响并满足 WHEN 条件中定义的可选触发器约束的每一行触发一个 行触发器。 如果省略此子句,则触发器是语句触发器。只有在满足可选触发器约束的情况下发出触 发语句时,数据库才会触发语句级触发器。 WHEN (condition) 指定数据库为触发语句影响的每一行计算的 SQL 条件。如果针对受影响的行, condition 的值是 TRUE,则 trigger_body 针对该行运行;否则,trigger_body 不 会针对该行运行。无论 condition 的值如何,触发语句都会运行。 condition 可以包含相关名称(请参阅referencing_clause ::= )。 在 condition 下,最好不要在相关名称 NEW、OLD 之前放置冒号 (:)(在此上下文 中,它不是绑定变量的占位符)。 另请参阅: 《KingbaseES 数据库 SQL 语言参考手册 》,了解有关 SQL condition 的内容。 WHEN(条件)的限制 如果指定此子句,那么还必须指定 FOR EACH ROW 。 condition 不能包含子查询或 PL/SQL 表达式(例如,用户定义函数的调用)。 trigger_body 数据库运行可以触发触发器的 PL/SQL 块或 CALL 子程序。CALL 子程序是不带参数 的 PL/SQL 存储过程。 instead_of_dml_trigger 创建一个 INSTEAD OF DML 触发器(在 INSTEAD OF DML 触发器中描述)。 对 INSTEAD OF 的限制 INSTEAD OF 触发器可以读取:OLD 和:NEW 值,但不能更改它们。 DELETE 1045 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE 如果触发器是在非编辑视图上创建的,那么只要 DELETE 语句从定义了非编辑视图的表 中删除一行,DELETE 就会导致数据库触发触发器。 INSERT 如果触发器是在非编辑视图上创建的,那么只要 INSERT 语句将行添加到定义非编辑视 图的表中,INSERT 就会使数据库触发触发器。 UPDATE 如果触发器是在非编辑视图上创建的,那么只要 UPDATE 语句更改定义了非编辑视图的 表的列中的值,UPDATE 就会导致数据库触发触发器。 另请参阅: 《KingbaseES SQL 语言参考手册 》中 CREATE VIEW 的 AS 子查询子句,用于防止 对视图进行插入、更新或删除的构造列表。 noneditioning_view noneditioning_view 是要在其上创建触发器的非编辑视图的名称。 FOR EACH ROW INSTEAD OF 触发器始终是行触发器,因此仅用于标识。 trigger_body 数据库运行以触发触发器的 PL/SQL 块或 CALL 子程序。CALL 子程序是不带参数的 PL/SQL 存储过程。 dml_event_clause 指定 simple_dml_trigger 的触发语句。数据库在现有用户事务中触发触发器。 DELETE 每当 DELETE 语句从表或定义视图的表中删除一行时,使数据库触发触发器。 INSERT 每当 INSERT 语句将行添加到表或定义视图的表时,使数据库触发触发器。 UPDATE [ OF column [, column ] ] 每当 UPDATE 语句更改指定列中的值时,使数据库触发触发器。默认值:只要 UPDATE 语句更改表的任何列或定义视图的表中的值,数据库就会触发触发器。 如果指定列,则不能在触发器主体中更改其值。 schema 包含要在其上创建触发器的数据库对象的模式的名称。默认值:当前模式。 table 要在其上创建触发器的表的名称。 1046 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE view 要在其上创建触发器的视图的名称。 referencing_clause 指定相关名称,它引用当前行的旧值、新值。默认值:OLD、NEW。 如果触发器与名为 OLD、NEW 的表相关联,则使用此子句指定不同的相关名称以避免表名称 和相关名称之间的混淆。 对 reference_clause 的限制 如果 trigger_body 是 call routine_clause ,则引用子句无效。 routine_clause 触发器引用的程序为不带参数的存储过程或不带参数的 object type static 方法。 schema 指定模式名。 type 指定 object type 类型名。 procedure 指定不带参数的存储过程名。 method 指定不带参数的 object type static 方法。 第二种语法的语义: name 给新触发器的名称。这必须与同一个表上的任何其他触发器不同。 BEFORE | AFTER | INSTEAD OF 决定触发器函数是要在事件之前、之后被调用还是会取代该事件。一个约束触发器也能被指定 为 AFTER。 event INSERT、UPDATE、DELETE 或者 TRUNCATE 之一,这指定了将要引发该触发器的事件。多个事件 可以用 OR 指定,要求转换表的时候除外。 对于 UPDATE 事件,可以使用下面的语法指定一个列的列表: UPDATE OF column_name1 [, column_name2 ... ] 只有当至少一个被指定的列出现在 UPDATE 命令的更新目标中时,该触发器才会触发;或者, 指定的列之一是生成的列,该列依赖于 UPDATE 的目标列。 1047 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE INSTEAD OF UPDATE 事件不允许列的列表。在请求转换表时,也不能指定列的列表。 schema 指定模式名,仅语法兼容。 table_name 要使用该触发器的表、视图或外部表的名称(可能被模式限定)。 referenced_table_name 约束引用的另一个表的(可能是模式限定的)名称。此选项用于外键约束,不推荐用于一般用 途。这只能为约束触发器指定。 DEFERRABLE | NOT DEFERRABLE | INITIALLY IMMEDIATE | INITIALLY DEFERRED 该触发器的默认时机。这些约束选项的细节可参考 PLSQL CREATE TABLE 文档。这只能为 约束触发器指定。 REFERENCING 该关键字紧接在声明一个或者两个关系名称之前,这些关系名称提供对触发语句的转换表的访 问。 OLD TABLE | NEW TABLE 这个子句指示接下来的关系名是用于前转换表还是后转换表。 transition_relation_name 在该触发器中这个转换表要使用的(未限定)名称。 FOR EACH ROW | FOR EACH STATEMENT 这指定是否应该为受触发事件影响的每一行触发一次触发函数,或者每个 SQL 语句只触发 一次。如果两者都没有被指定,则 FOR EACH STATEMENT 是默认值。约束触发器只能指定 FOR EACH ROW。 condition 一个决定该触发器函数是否将被实际执行的布尔表达式。如果指定了 WHEN,只有 condition 返回 true 时才会调用该函数。在 FOR EACH ROW 触发器中,WHEN 条件可以分别写 OLD. column_name 或者 NEW.column_name 来引用列的新旧行值。当然,INSERT 触发器不能引用 OLD 并且 DELETE 触发器不能引用 NEW。 INSTEAD OF 触发器不支持 WHEN 条件。 当前,WHEN 表达式不能包含子查询。 注意对于约束触发器,对于 WHEN 条件的计算不会被延迟,而是直接在行更新操作被执行之后 立刻发生。如果该条件计算得不到真,那么该触发器就不会被放在延迟执行的队列中。 function_name 1048 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE 一个用户提供的函数,它被声明为不用参数并且返回类型 trigger,当触发器引发时会执行该 函数。 一个用户提供的无参数存储过程。 在 CREATE TRIGGER 的语法中,关键词 FUNCTION 和 PROCEDURE 是等效的,这里,关键词 PROCEDURE 的使用是有历史原因的并且已经被废弃。 arguments 一个可选的逗号分隔的参数列表,它在该触发器被执行时会被提供给该函数。参数是字符串常 量。简单的名称和数字常量也可以被写在这里,但是它们将全部被转换成字符串。请检查该触 发器函数的实现语言的描述来找出在函数内部如何访问这些参数,这可能与普通函数参数不 同。 示例 例 1:只要表 accounts 的一行即将要被更新时会执行函数 check_account_update: CREATE TRIGGER check_update BEFORE UPDATE ON accounts FOR EACH ROW EXECUTE FUNCTION check_account_update(); 例 2:下面的例子与上面一个例子相同,但是只在 UPDATE 命令指定要更新 balance 列时才执行该函数: CREATE TRIGGER check_update BEFORE UPDATE OF balance ON accounts FOR EACH ROW EXECUTE FUNCTION check_account_update(); 例 3:这种形式只有列 balance 具有真正被改变的值时才执行该函数: CREATE TRIGGER check_update BEFORE UPDATE ON accounts FOR EACH ROW WHEN (OLD.balance IS DISTINCT FROM NEW.balance) EXECUTE FUNCTION check_account_update(); 例 4:调用一个函数来记录 accounts 的更新,但是只在有东西被改变时才调用: CREATE TRIGGER log_update AFTER UPDATE ON accounts FOR EACH ROW WHEN (OLD.* IS DISTINCT FROM NEW.*) EXECUTE FUNCTION log_account_update(); 例 5:为每一个要插入到视图底层表中的行执行函数 view_insert_row: 1049 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE CREATE TRIGGER view_insert INSTEAD OF INSERT ON my_view FOR EACH ROW EXECUTE FUNCTION view_insert_row(); 例 6:为每个语句执行函数 check_transfer_balances_to_zero 以确认 transfer 的行不会有净值增加: CREATE TRIGGER transfer_insert AFTER INSERT ON transfer REFERENCING NEW TABLE AS inserted FOR EACH STATEMENT EXECUTE FUNCTION check_transfer_balances_to_zero(); 例 7:为每一行执行函数 check_matching_pairs 以确认(同一个语句)同时对匹配对做了更改: CREATE TRIGGER paired_items_update AFTER UPDATE ON paired_items REFERENCING NEW TABLE AS newtab OLD TABLE AS oldtab FOR EACH ROW EXECUTE FUNCTION check_matching_pairs(); 例 8:为每一个要插入到视图底层表中的行执行 PLSQL BLOCK: \set SQLTERM / CREATE TRIGGER view_insert INSTEAD OF INSERT ON my_view FOR EACH ROW AS BEGIN RAISE NOTICE 'execute view_insert pl_block'; END; / 例 9:为每一个要插入到视图底层表中的行执行 PLSQL BLOCK: \set SQLTERM / CREATE TRIGGER view_insert INSTEAD OF INSERT ON my_view FOR EACH ROW AS BEGIN RAISE NOTICE 'execute view_insert pl_block'; END; / 例 10:创建一个无参数存储过程后,再创建触发器调用该存储过程 1050 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE \set SQLTERM / CREATE TABLE test_trg_table(id int); / CREATE OR REPLACE PROCEDURE PRO1 AS BEGIN RAISE NOTICE 'execute pro1'; END; / CREATE OR REPLACE TRIGGER test_trg BEFORE INSERT ON test_trg_table FOR EACH ROW CALL PRO1() / INSERT INTO test_trg values(1); / 例 11:为当前触发器影响行取别名 \set SQLTERM ; drop table if exists t1; create table t1(id int); insert into t1 values(10); \set SQLTERM / CREATE or replace TRIGGER tg_test_10 before update On t1 referencing NEW as new_alias old as "old_alias" for each row when (new_alias.id = 20 and "old_alias".id = 10) declare a int; begin raise notice '%', :new_alias.id; raise notice '%', :old_alias.id; :new_alias.id := 100; end; / \set SQLTERM ; update t1 set id = 20 where id = 10; select * from t1; drop table t1; 兼容性 该部分不是必有的,如有对 SQL 标准的扩展等兼容性产生影响在这里描述。 其他 1051 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE 当一个列相关的触发器(使用 UPDATE OF column_name 语法定义的触发器)的列被列为 UPDATE 命令的 SET 列 表目标时,它会被触发。即便该触发器没有被引发,一个列的值也可能改变,因为 BEFORE UPDATE 触发器对行内容 所作的改变不会被考虑。相反,一个诸如 UPDATE ... SET x = x ... 的命令将引发一个位于列 x 上的触发器,即 便该列的值没有改变。 在一个 BEFORE 触发器中,WHEN 条件正好在函数被或者将被执行之前被计算,因此使用 WHEN 与在触发器函数 的开始测试同一个条件没有实质上的区别。特别注意该条件看到的 NEW 行是当前值,虽然可能已被早前的触发器所 修改。还有,一个 BEFORE 触发器的 WHEN 条件不允许检查 NEW 行的系统列(例如 ctid),因为那些列还没有被设 置。 在一个 AFTER 触发器中,WHEN 条件正好在行更新发生之后被计算,并且它决定一个事件是否要被放入队列以便 在语句的末尾引发该触发器。因此当一个 AFTER 触发器的 WHEN 条件不返回真时,没有必要把一个事件放入队列或 者在语句末尾重新取得该行。如果触发器只需要为一些行被引发,就能够显著地加快修改很多行的语句的速度。 在一些情况下,单一的 SQL 命令可能会引发多种触发器。例如,一个带有 ON CONFLICT DO UPDATE 子句的 INSERT 可能同时导致插入和更新操作,因此它将根据需要引发这两种触发器。提供给触发器的传递关系与它们的事 件类型有关,因此 INSERT 触发器将只看到被插入的行,而 UPDATE 触发器将只看到被更新的行。 由外键强制动作导致的行更新或删除(例如 ON UPDATE CASCADE 或 ON DELETE SET NULL)被当做导致它们的 SQL 命令的一部分。受影响的表上的相关触发器将被引发,这样就提供了另一种方法让 SQL 命令引发不直接匹配其 类型的触发器。在简单的情况中,请求传递关系的触发器将在一个传递关系中看到由原始 SQL 命令在其表中做出的 所有改变。但是,有些情况中一个请求传递关系的 AFTER ROW 触发器的存在将导致由单个 SQL 命令触发的外键强制 动作被分成多步,每一步都有其自己的传递关系。在这种情况下,没创建一个传递关系集合都会引发存在的所有语句 级触发器,确保那些触发器能够在一个传递关系中看到每个受影响的行一次,并且只看到一次。 只有当视图上的动作被一个行级 INSTEAD OF 触发器处理时才会引发视图上的语句级触发器。如果动作被一个 INSTEAD 规则处理,那么该语句发出的任何语句都会代替提及该视图的原始语句执行,这样将被引发的触发器是替换 语句中提及的表上的那些触发器。类似地,如果视图是自动可更新的,则该动作将被处理为把该语句自动重写成在视 图基表上的一个动作,这样基表的语句级触发器就是要被引发的。 在分区表上创建一个行级触发器将导致在它所有的现有分区上创建相同的触发器,并且以后创建或者挂接的任何 分区也将包含一个相同的触发器。分区表上的触发器只能是 AFTER。 修改分区表或者带有继承子表的表会引发挂接到显式提及表的语句级触发器,但不会引发其分区或子表的语句级 触发器。相反,行级触发器会在受影响的分区或子表上引发,即便它们在查询中没有被明确提及。如果一个语句级触 发器用 REFERENCING 子句定义有传递关系,则来自所有受影响分区或子表中的行的前后映像都是可见的。在继承子 表的情况中,行映像仅包括该触发器所附属的表中存在的列。当前,不能在分区或继承子表上定义带有传递关系的行 级触发器。 在 KingbaseES V7 以前的版本中,必须要声明触发器函数为返回占位符类型 opaque 而不是 trigger。要支持 载入旧的转储文件,CREATE TRIGGER 将接受一个被声明为返回 opaque 的函数,但是它会发出一个通知并且会把该 函数的声明返回类型改为 trigger。 1052 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE 16.15 CREATE TYPE 用途 CREATE TYPE 在当前数据库中注册一种新的数据类型。定义数据类型的用户将成为它的拥有者。 如果给定一个模式名,那么该类型将被创建在指定的模式中。否则它会被创建在当前模式中。类型名称必须与同 一个模式中任何现有的类型或者域相区别(因为表具有相关的数据类型,类型名称也必须与同一个模式中任何现有表 的名字不同)。 如上面的语法所示,有八种形式的 CREATE TYPE。它们分别创建组合类型、枚举类型、SET 类型、范围类型、 基础类型、shell 类型、嵌套表类型、可变数组类型和对象类型。下文将依次讨论这些形式。 1. 组合类型 第一种形式的 CREATE TYPE 创建组合类型。组合类型由一个属性名和数据类型的列表指定。如果属 性的数据类型是可排序的,也可以指定该属性的排序规则。组合类型本质上和表的行类型相同,但是 如果只想定义一种类型,使用 CREATE TYPE 避免了创建一个实际的表。单独的组合类型也是很有用 的,例如可以作为函数的参数或者返回类型。 为了能够创建组合类型,必须拥有在其所有属性类型上的 USAGE 特权。 2. 枚举类型 如枚举类型 中所述,第二种形式的 CREATE TYPE 创建枚举类型。枚举类型需要一个带引号的标签构 成的列表,每一个标签长度必须不超过 NAMEDATALEN 字节(在标准的 KingbaseES 编译中是 64 字 节)。可以创建具有零个标签的枚举类型,但是在使用ALTER TYPE 添加至少一个标签之前,不能 使用这种类型来保存值。 3. 范围类型 如范围类型 中所述,第三种形式的 CREATE TYPE 创建范围类型。 范围类型的 “subtype“可以是任何带有一个相关的 B 树操作符类(用来决定该范围类型值的顺序) 的类型。通常,子类型的默认 B 树操作符类被用来决定顺序。要使用一种非默认操作符类,可以用 “subtype_opclass“指定它的名字。如果子类型是可排序的并且希望在该范围的顺序中使用一种非默认 的排序规则,可以用 “collation“选项来指定。 可选的 “canonical“函数必须接受一个所定义的范围类型的参数,并且返回同样类型的一个值。在适用 时,它被用来把范围值转换成一种规范的形式。更多信息请见定义新的范围类型 。创建一个 “canonical“函数有点棘手,因为必须在声明范围类型之前定义它。要这样做,必须首先创建一种 shell 类型, 它是一种没有属性只有名称和拥有者的占位符类型。这可以通过发出不带额外参数的命令 CREATE TYPE name 来完成。然后可以使用该 shell 类型作为参数和结果来声明该函数,并且最终用同样的名 称来声明范围类型。这会自动用一种合法的范围类型替换 shell 类型项。 可选的 “subtype_diff“函数必须接受两个 “subtype“类型的值作为参数,并且返回一个 double precision 值表示两个给定值之间的差别。虽然这是可选的,但是提供这个函数会让该范围类型列上 GiST 索引效率更高。详见定义新的范围类型 。 4. SET 类型 1053 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE 如SET 类型 中所述,第四种形式的 CREATE TYPE 创建 SET 类型。SET 类型需要一个带引号的标签 构成的列表,每一个标签长度必须不超过 NAMEDATALEN 字节(在标准的 KingbaseES 编译中是 64 字 节)。可以创建具有 0 到 64 个标签的 SET 类型,但是在使用ALTER TYPE 添加至少一个标签之 前,不能使用这种类型来保存值。 5. 基础类型 第四种形式的 CREATE TYPE 创建一种新的基本类型(标量类型)。为了创建一种新的基本类型,你 必须是一个超级用户(做这种限制的原因是一种错误的类型定义可能让服务器混淆甚至崩溃)。 参 数 可 以 以 任 意 顺 序 出 现 (而 不 仅 是 按 照 上 面 所 示 的 顺 序), 并 且 大 部 分 是 可 选 的。 在 定 义 类 型 前, 必 须 注 册 两 个 或 者 更 多 函 数 (使 用 CREATE FUNCTION)。 支 持 函 数 “in- put_function“以及 “output_function“ 是必需的,而函数 “receive_function“、“send_function“、 “type_modifier_input_function“、“type_modifier_output_function“和 “analyze_function“ 是可选 的。通常来说这些函数必须是用 C 或者另外一种低层语言编写的。 “input_function“将类型的外部文本表达转换成为该类型定义的操作符和函数所使用的内部表达。 “output_function“ 执行反向的转换。输入函数可以被声明为有一个 cstring 类型的参数,或者有三 个类型分别为 cstring、oid、integer 的参数。第一个参数是以 C 字符串存在的输入文本,第二个 参数是该类型自身的 OID(对于数组类型则是其元素类型的 OID),第三个参数是目标列的 typmod (如果知道,不知道则将传递 -1)。输入函数必须返回一个该数据类型本身的值。通常,一个输入函 数应该被声明为 STRICT。如果不是这样,在读到一个 NULL 输入值时,调用它时第一个参数会是 NULL。在这种情况下,该函数必须仍然返回 NULL,除非它发生了错误(这种情况主要是想支持域 输入函数,它们可能需要拒绝 NULL 输入)。输出函数必须被声明为有一个新数据类型的参数。输出 函数必须返回类型 cstring。对于 NULL 值不会调用输出函数。 T 可选的 “receive_function“ 会把类型的外部二进制表达转换成内部表达。如果没有提供这个函数, 该类型不能参与到二进制输入中。二进制表达转换成内部形式代价更低,然而却更容易移植(例如, 标准的整数数据类型使用网络字节序作为外部二进制表达,而内部表达是机器本地的字节序)。接收 函数应该执行足够的检查以确保该值是有效的。接收函数可以被声明为有一个 internal 类型的参 数,或者有三个类型分别为 internal、oid、integer 的参数。第一个参数是一个指向 StringInfo 缓冲区的指针,其中保存着接收到的字节串。其余可选的参数和文本输入函数的相同。接收函数必 须返回一个该数据类型本身的值。通常,一个接收函数应该被声明为 STRICT。如果不是这样,在 读到一个 NULL 输入值时,调用它时第一个参数会是 NULL。在这种情况下,该函数必须仍然返回 NULL,除非它发生了错误(这种情况主要是想支持域接收函数,它们可能需要拒绝 NULL 输入)。 类似地,可选的 “send_function“将内部表达转换成外部二进制表达。如果没有提供这个函数,该类 型将不能参与到二进制输出中。发送函数必须被声明为有一个新数据类型的参数。发送函数必须返回 类型 bytea。对于 NULL 值不会调用发送函数。 到这里你应该在疑惑输入和输出函数是如何能被声明为具有新类型的结果或参数的?因为必须在创 建新类型之前创建这两个函数。这个问题的答案是,新类型应该首先被定义为一种 shell type,它是 一种占位符类型,除了名称和拥有者之外它没有其他属性。这可以通过不带额外参数的命令 CREATE TYPE name 做到。然后用 C 写的 I/O 函数可以被定义为引用这种 shell type。最后,用带有完整定 义的 CREATE TYPE 把该 shell type 替换为一个完全的、合法的类型定义,之后新类型就可以正常使用 了。 1054 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE 如果该类型支持修饰符(附加在类型声明上的可选约束,例如 char(5) 或者 numeric(30,2)), 则需要可选的 “type_modifier_input_function“ 以及 “type_modifier_output_function“。KingbaseES 允许用户定义的类型有一个或者多个简单常量或者标识符作为修饰符。但是,为了存储在 系统目录中,该信息必须能被打包到一个非负整数值中。所声明的修饰符会被以 cstring 数组的形 式传递给 “type_modifier_input_function“。它必须检查该值的合法性(如果值错误就抛出一个错 误),如果值正确,要返回一个非负 integer 值,它将被存储在“typmod”列中。如果类型没有 “type_modifier_input_function“ 则类型修饰符将被拒绝。“type_modifier_output_function“ 把内 部的整数 typmod 值转换回正确的形式用于用户显示。它必须返回一个 cstring 值,该值就是追加 到类型名称后的字符串。例如 numeric 的函数可能会返回 (30,2)。如果默认的显示格式就是只把存 储的 typmod 整数值放在圆括号内,则允许省略 “type_modifier_output_function“。 可选的 “analyze_function“ 为该数据类型的列执行与类型相关的统计信息收集。默认情况下,如果该 类型有一个默认的 B-树操作符类,ANALYZE 将尝试用类型的“equals”和“less-than”操作符来收集 统计信息。这种行为对于非标量类型并不合适,因此可以通过指定一个自定义分析函数来覆盖这种行 为。分析函数必须被声明为有一个类型为 internal 的参数,并且返回一个 boolean 结果。分析函 数的详细 API 请见 src/include/commands/vacuum.h。 虽然只有 I/O 函数和其他为该类型创建的函数才知道新类型的内部表达的细节,但是内部表达的一些 属性必须被向 KingbaseES 声明。其中最重要的是 “internallength“。基本数据类型可以是定长的(这 种情况下 “internallength“是一个正整数)或者是变长的(把 “internallength“设置为 VARIABLE,在内 部通过把 typlen 设置为 -1 表示)。所有变长类型的内部表达都必须以一个 4 字节整数开始,它给 出了这个值的总长度。 可选的标志 PASSEDBYVALUE 表示这种数据类型的值需要被传值而不是传引用。传值的类型必须是定 长的,并且它们的内部表达不能超过 Datum 类型(某些机器上是 4 字节,其他机器上是 8 字节)的 尺寸。 “alignment“参数指定数据类型的存储对齐要求。允许的值等同于以 1、2、4 或 8 字节边界对齐。注 意变长类型的 alignment 参数必须至少为 4,因为它们需要包含一个 int4 作为它们的第一个组成部 分。 “storage“参数允许为变长数据类型选择存储策略(对定长类型只允许 plain)。plain 指定该类型 的数据将总是被存储在线内并且不会被压缩。extended 指定系统将首先尝试压缩一个长的数据值, 并且将在数据仍然太长的情况下把值移出主表行。external 允许值被移出主表,但是系统将不会尝 试对它进行压缩。main 允许压缩,但是不鼓励把值移出主表(如果没有其他办法让行的大小变得合 适,具有这种存储策略的数据项仍将被移出主表,但比起 extended 以及 external 项来,这种存储 策略的数据项会被优先考虑保留在主表中)。 如 用户定义的类型 TOAST 所述,除 plain 之外所有的 “storage“值都暗示该数据类型的函数能处理 被 TOAST 过的值。指定的值仅仅是决定一种可 TOAST 数据类型的列的默认 TOAST 存储策略,用 户可以使用 ALTER TABLE SET STORAGE 为列选取其他策略。 “like_type“参数提供了另一种方法来指定一种数据类型的基本表达属性:从某种现有的类型中拷贝。 “internallength“、“passedbyvalue“、“alignment“和 “storage“的值会从指定的类型中复制而来(也可 以通过在 LIKE 子句中指定这些属性的值来覆盖复制过来的值,但是通常并不这么做)。当新类型的 低层实现是以一种现有的类型为“载体”时,用这种方式指定表达特别有用。 1055 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE “category“和 “preferred“参数可以被用来帮助控制在混淆的情况下应用哪一种隐式造型。每一种数据 类型都属于一个用单个 ASCII 字符命名的分类,并且每一种类型可以是其所属分类中的“首选”。 当有助于解决重载函数或操作符时,解析器将优先造型到首选类型(但是只能从同类的其他类型造 型)。更多细节请见 类型转换。对于没有隐式造型到任意其他类型或者从任意其他类型造型的类型, 让这些设置保持默认即可。但是,对于一组具有隐式造型的相关类型,把它们都标记为属于同一个类 别并且选择一种或两种“最常用”的类型作为该类别的首选通常是很有用的。在把一种用户定义的类 型增加到一个现有的内建类别(例如数字或者字符串类型)中时,“category“参数特别有用。但是, 也可以创建新的全部是用户定义类型的类别。对这样的类别,可选择除大写字母之外的任何 ASCII 字 符。 如果用户希望该数据类型的列被默认为某种非空值,可以指定一个默认值。默认值可以用 DEFAULT 关键词指定(这样一个默认值可以被附加到一个特定列的显式 DEFAULT 子句覆盖)。 要指定一种类型是数组,用 ELEMENT 关键词指定该数组元素的类型。例如,要定义一个 4 字节整数 的数组(int4),应指定 ELEMENT = int4。更多有关数组类型的细节请见下文。 要指定在这种类型数组的外部表达中分隔值的定界符,可以把 “delimiter“设置为一个特定字符。默认 的定界符是逗号(,)。注意定界符是与数组元素类型相关的,而不是数组类型本身相关。 如果可选的布尔参数 “collatable“为真,这种类型的列定义和表达式可能通过使用 COLLATE 子句携带 有排序规则信息。在该类型上操作的函数的实现负责真正利用这些信息,仅把类型标记为可排序的并 不会让它们自动地去使用这类信息。 6. shell 类型 shell 类型仅仅是一种用于后面要定义的类型的占位符,通过发出一个不带除类型名之外其他参数的 CREATE TYPE 命令可以创建这种类型。在创建范围类型和基础类型时,需要 shell 类型作为一种向 前引用。 7. 嵌套表类型 如 集合类型中所述,第六种形式的 CREATE TYPE 用于创建嵌套表类型。其中 datatype 支持基本数 据类型、用户自定义数据数据类型和集合类型。NOT NULL 指定嵌套表内元素的值不能为空。 8. 可变数组类型 如 集合类型中所述,第七种形式的 CREATE TYPE 用于创建可变数组类型。其中 datatype 支持基 本数据类型、用户自定义数据数据类型和集合类型。size_limit 指定元素个数的最大限制值。NOT NULL 指定可变数组内元素得值不能为空。 9. 对象类型 如对象类型 中所述,第八种形式的 CREATE TYPE 用于创建一个对象类型。 对象类型在使用上与组合类型基本一致。不同于组合类型,对象类型在创建时可以创建类型声明和类 型体 ( CREATE TYPE BODY ),在创建对象类型声明时除了指定与组合类型相同的属性 (列) 外, 还可以声明静态函数(存储过程)、成员函数(存储过程)、构造函数三种内部方法。并在相应的类 型体内分别为声明的内部方法创建完整的方法定义。 对象类型在创建时总会创建一个默认的构造函数,默认构造函数的参数列表与对象类型的列成员一 致,默认构造函数会将作为参数传入的列成员构造成对应的对象返回,当默认构造函数与用户自定义 1056 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE 构造函数参数相同时,将优先调用用户自定义的构造函数。 前置条件 为了能够创建组合类型,必须拥有在其所有属性类型上的 USAGE 特权。创建范围类型,必须在声明范围之前进 行定义。要创建一种新的数据类型,你必须是一个超级用户。 语法 CREATE TYPE name AS ( [ attribute_name data_type [ COLLATE collation ] [, ... ] ] ) CREATE TYPE name AS ENUM ( [ 'label' [, ... ] ] ) CREATE TYPE name AS RANGE ( SUBTYPE = subtype [ , SUBTYPE_OPCLASS = subtype_operator_class ] [ , COLLATION = collation ] [ , CANONICAL = canonical_function ] [ , SUBTYPE_DIFF = subtype_diff_function ] ) 1057 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE CREATE TYPE name AS SET ( [ 'label' [, ... ] ] ) CREATE TYPE name ( INPUT = input_function, OUTPUT = output_function [ , RECEIVE = receive_function ] [ , SEND = send_function ] [ , TYPMOD_IN = type_modifier_input_function ] [ , TYPMOD_OUT = type_modifier_output_function ] [ , ANALYZE = analyze_function ] [ , INTERNALLENGTH = { internallength | VARIABLE } ] [ , PASSEDBYVALUE ] [ , ALIGNMENT = alignment ] [ , STORAGE = storage ] [ , LIKE = like_type ] [ , CATEGORY = category ] [ , PREFERRED = preferred ] [ , DEFAULT = default ] [ , ELEMENT = element ] [ , DELIMITER = delimiter ] [ , COLLATABLE = collatable ] ) 1058 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE CREATE TYPE name CREATE TYPE name AS TABLE OF datatype [NOT NULL] 1059 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE CREATE TYPE name AS VARRAY(size_limit) OF datatype [NOT NULL] CREATE [ OR REPLACE ] TYPE name [ FORCE ] [ AUTHID { CURRENT_USER | DEFINER } ] { AS | IS } OBJECT ( attribute_name data_type [, ... ] {[NOT] {FINAL | INSTANTIABLE}}... [, subprogram_spec [, ... ] ] [, constructor_spec [, ... ] ] [, map_order_function_spec [, ... ] ] ) [ [NOT] { FINAL | INSTANTIABLE } ]... 这里 subprogram_spec 是以下之一: { STATIC | MEMBER } FUNCTION function_name [ ( [ argname [ argmode ] argtype [ { DEFAULT | := } default_expr ] [, ...] ] ) ] { RETURNS | RETURN } rettype ] 1060 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE { STATIC | MEMBER } PROCEDURE procedure_name [ ( [ argname [ argmode ] argtype [ { DEFAULT | := } default_expr ] [, ...] ] ) ] constructor_spec 是: [ FINAL ] [ INSTANTIABLE ] CONSTRUCTOR FUNCTION name [ ( [ SELF IN OUT name ] [, argname [ argmode ] argtype [ { DEFAULT | := } default_expr ] [, ...] ] ) ] { RETURNS | RETURN } SELF AS RESULT map_order_function_spec 是: ORDER MEMBER FUNCTION name [ ( [ argname [ argmode ] argtype [ { DEFAULT | := } default_expr ] [, ...] ] ) ] { RETURNS | RETURN } rettype ] 语义 name 要创建的类型的名称(可以被模式限定)。 attribute_name 组合类型的一个属性(列)的名称。 data_type 要成为组合类型的一个列的现有数据类型的名称。 collation 要关联到组合类型的一列或者范围类型的现有排序规则的名称。 label 一个字符串,它表达与枚举类型或 SET 类型的一个值相关的文本标签。 subtype 范围类型的元素类型的名称,范围类型表示的范围属于该类型。 subtype_operator_class 用于 subtype 的 B 树操作符类的名称。 1061 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE canonical_function 范围类型的规范化函数的名称。 subtype_diff_function 用于 subtype 的差函数的名称。 input_function 将数据从类型的外部文本形式转换为内部形式的函数名。 output_function 将数据从类型的内部形式转换为外部文本形式的函数名。 receive_function 将数据从类型的外部二进制形式转换成内部形式的函数名。 send_function 将数据从类型的内部形式转换为外部二进制形式的函数名。 type_modifier_input_function 将类型的修饰符数组转换为内部形式的函数名。 type_modifier_output_function 将类型的修饰符的内部形式转换为外部文本形式的函数名。 analyze_function 为该数据类型执行统计分析的函数名。 internallength 一个数字常量,它指定新类型的内部表达的字节长度。默认的假设是它是变长的。 alignment 该数据类型的存储对齐需求。如果被指定,它必须是 char、int2、int4 或者 double。默认是 int4。 storage 该数据类型的存储策略。如果被指定,必须是 plain、external、extended 或者 main。默认是 plain。 like_type 与新类型具有相同表达的现有数据类型的名称。会从这个类型中复制 “internallength“、“passedbyvalue“、“alignment“以及 “storage“的值(除非在这个 CREATE TYPE 命令的其他地方用显式说明覆盖)。 category 这种类型的分类码(一个 ASCII 字符)。默认是“用户定义类型”的'U'。为了创建自定义分类,你也可 以选择其他 ASCII 字符。 preferred 如果这种类型是其类型分类中的优先类型则为真,否则为假。默认为假。在一个现有类型分类中创建一 种新的优先类型要非常小心,因为这可能会导致行为上令人惊奇的改变。 default 数据类型的默认值。如果被省略,默认值是空。 element 被创建的类型是一个数组,这指定了数组元素的类型。 delimiter 在由这种类型组成的数组中值之间的定界符。 collatable 如果这个类型的操作可以使用排序规则信息,则为真。默认为假。 FORCE FORCE 作为一个与 OR REPLACE 配合使用的选项参数,当使用 CREATE TYPE 语句创建一个对象类型替换一个 已有类型时,FORCE 选项可以决定如何处理被替换类型的依赖关系。 含有 FORCE 选项的替换创建语句 (CREATE OR REPLACE TYPE) 会级联删除所有对原类型有依赖的对象,并成功 创建新的对象类型。不含有 FORCE 选项的替换创建语句则会在检测到原有类型处于被依赖状态时进行提示并阻 止新类型成功创建。 只有对象类型的创建语句支持 FORCE 选项,由于 FORCE 选项会级联删除所有依赖对象,请谨慎使用。 AUTHID { CURRENT_USER | DEFINER } • AUTHID CURRENT_USER 表示在调用该类型内部方法时,使用调用方法的用户的权限来执行。这是默认值。 • AUTHID DEFINER 指定要用类型的属主的权限来执行该类型的内部方法。 STATIC 标志该对象类型的内部函数(存储过程)为一个静态函数(存储过程)。 1062 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE MEMBER 标志该对象类型的内部函数(存储过程)为一个成员函数(存储过程)。 CONSTRUCTOR FUNCTION 标志该方法作为该对象类型的构造函数被创建。 [NOT] FINAL [NOT] INSTANTIABLE [NOT] FINAL FINAL 子句决定是否可以以此类型为基类型创建其他子类型。目前仅兼容语法。 [NOT] INSTANTIABLE INSTANTIABLE 子句决定是否可以为此类型构造实例对象。目前仅兼容语法。 示例 这个例子创建了一种组合类型并且将其用在了一个函数定义中: CREATE TYPE compfoo AS (f1 int, f2 text); CREATE FUNCTION getfoo() RETURNS SETOF compfoo AS $$ SELECT fooid, fooname FROM foo $$ LANGUAGE SQL; 这个例子创建了一个枚举类型并且将其用在一个表定义中: CREATE TYPE bug_status AS ENUM ('new', 'open', 'closed'); CREATE TABLE bug ( id serial, description text, status bug_status ); 这个例子创建了一个范围类型: CREATE TYPE float8_range AS RANGE (subtype = float8, subtype_diff = float8mi); 这个例子创建了一个枚举类型并且将其用在一个表定义中: CREATE TYPE rainbow AS SET ('R', 'O', 'Y', 'G', 'B', 'P'); CREATE TABLE colors (col rainbow) 创建一个 INT 类型的嵌套表,并且元素的值不能 NULL: CREATE TYPE int_table AS TABLE OF INT NOT NULL; 创建一个最大长度为 10 的 INT 类型的可变数组: 1063 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE CREATE TYPE int_varray AS VARRAY(10) OF INT; 这个例子创建了基本数据类型 box 然后将它用在一个表定义中: CREATE TYPE box; CREATE FUNCTION my_box_in_function(cstring) RETURNS box AS ... ; CREATE FUNCTION my_box_out_function(box) RETURNS cstring AS ... ; CREATE TYPE box ( INTERNALLENGTH = 16, INPUT = my_box_in_function, OUTPUT = my_box_out_function ); CREATE TABLE myboxes ( id integer, description box ); 如果 box 的内部结构是四个 float4 元素的一个数组,我们可能会使用: CREATE TYPE box ( INTERNALLENGTH = 16, INPUT = my_box_in_function, OUTPUT = my_box_out_function, ELEMENT = float4 ); 这将允许用下标来访问一个 box 值的组件编号。否则该类型的行为和前面的一样。 这个例子创建了一个大对象类型并且将它用在了一个表定义中: CREATE TYPE bigobj ( INPUT = lo_filein, OUTPUT = lo_fileout, INTERNALLENGTH = VARIABLE ); CREATE TABLE big_objs ( id integer, obj bigobj ); 创建一个对象类型声明: CREATE OR REPLACE TYPE objtype FORCE AUTHID CURRENT_USER AS OBJECT( f1 INT, 1064 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE f2 TEXT, MEMBER FUNCTION memfunc(i INT) RETURN INT, STATIC PROCEDURE staproc(), CONSTRUCTOR FUNCTION objtype(self inout objtype) RETURN SELF AS RESULT ); 更多例子(包括配套的输入和输出函数)请见 用户定义的类型。 兼容性 创建组合类型的第一种形式的 CREATE TYPE 命令符合 SQL 标准。其他的形式都是 KingbaseES 扩展。SQL 标准 中的 CREATE TYPE 语句也定义了其他 KingbaseES 中没有实现的形式。 创建一个具有零个属性的组合类型的能力是一种 KingbaseES 对 SQL 标准的衍生(类似于 CREATE TABLE 中相 同的情况)。 其他 由于一旦数据类型被创建,对该数据类型的使用就没有限制,创建一种基本类型或者范围类型就等同于在类型定 义中提到的函数上授予公共执行权限。对于在类型定义中有用的函数来说这通常不是问题。但是如果设计一种类型时 要求在转换到外部形式或者从外部形式转换时使用“秘密”信息,你就应该三思而后行。 在 KingbaseESV7 版本之前,自动生成的数组类型的名称总是正好为元素类型的名称外加一个前置的下划线字符 (_)。因此类型名称的长度限制比其他名称还要少一个字符。虽然现在这仍然是通常情况,但如果名称达到最大长 度或者与其他下划线开头的用户类型名称冲突,数组类型的名称也可以不同于这种规则。因此依靠这种习惯编写代码 现在已经不适用了。现在,可以使用 sys_type.typarray 来定位与给定类型相关的数组类型。 建议避免使用以下划线开始的类型名和表名。虽然服务器会改变生成的数组类型名称以避免与用户给定的名称冲 突,仍然有混淆的风险,特别是对旧的客户端软件来说,它们可能会假定以下划线开始的类型名总是表示数组。 在 KingbaseES V7 版本之前,shell-type 的创建语法 CREATE TYPE name 不存在。创建一种新基本类型的方法是 先创建它的输入函数。在这种方法中,KingbaseES 将首先把新数据类型的名称看做是输入函数的返回类型。在这种 情况下 shell type 会被隐式地创建,并且能在剩余的 I/O 函数的定义中引用。这种方法现在仍然有效,但是已经被 弃用并且可能会在未来的某个发行中被禁止。还有,为了避免由于函数定义中的打字错误导致 shell type 弄乱系统目 录,当输入函数用 C 编写时,将只能用这种方法创建一种 shell type。 在 KingbaseES V7 以前的版本中,常常为了完全避免创建 shell type 而把函数对该类型名的向前引用用占位 符伪类型 opaque 替换。在 V7 以前,cstring 参数和结果也必须被声明为 opaque。为了支持载入旧的转储文件, CREATE TYPE 将接受使用 opaque 声明的 I/O 函数,但是它将发出一个提示并且把函数的声明改成使用正确的类型。 静 态 函 数 (存 储 过 程) 不 能 创 建 含 有 名 为 SELF 的 参 数, 在 调 用 时 需 要 以 类 型 名 做 前 缀 修 饰, 如 type_name.method()。 成员函数(存储过程)的第一个参数必须是名为 SELF 且类型为当前对象类型的参数,若未显式创建 SELF 参 数,那么该参数会被隐式创建为 IN 参数。在调用成员函数(存储过程)时需要以类型定义的具体对象名做前缀修 饰,如 object_expression.method()。且不需要为 SELF 参数传值,成员函数(存储过程)会自动接收对其进行修饰 的对象作为 SELF 参数传入。 成员函数(存储过程)的 SELF 参数可以是 IN 参数或者 IN OUT 参数。 1065 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE 一个对象类型可以创建多个构造函数,所有构造函数都必须与类型同名。与成员方法一样,自定义构造函数的第 一个参数必须是 SELF 参数,若 SELF 参数未被显式创建,也会被隐式创建。不同于成员方法的是,自定义构造函数 的 SELF 参数只能是 IN OUT 参数。 16.16 CREATE TYPE BODY 用途 CREATE TYPE BODY 完善一个对象类型的所有内部函数(存储过程)的定义。CREATE OR REPLACE TYPE BODY 将 完善一个新的或者替换一个已有的对象类型的所有子函数(存储过程)的定义。 在 CREATE TYPE BODY 语句中,必须一次性为所有对象类型声明中声明的内部函数(存储过程)的定义进行完 善,否则 CREATE TYPE BODY 语句无法执行成功。 前置条件 如果给定一个模式名,那么该类型体将被创建在指定的模式中。否则它会被创建在当前模式中。类型体名称必须 与对应模式中对应的对象类型声明相同。 语法 CREATE [ OR REPLACE ] TYPE BODY name { AS | IS } [ { STATIC | MEMBER } FUNCTION function_name [ ( [ argname [ argmode ] argtype [ { DEFAULT | := } default_expr ] [, ...] ] ) ] { RETURNS | RETURN } rettype { AS | IS } plsql_block ] [ { STATIC | MEMBER } PROCEDURE procedure_name [ ( [ argname [ argmode ] argtype [ { DEFAULT | := } default_expr ] [, ...] ] ) ] { AS | IS } plsql_block ] [ CONSTRUCTOR FUNCTION name [ ( [ SELF IN OUT name ] [, argname [ argmode ] argtype [ { DEFAULT | := } default_expr ] [, ...] ] ) ] { RETURNS | RETURN } SELF AS RESULT { AS | IS } [ variable_declaration ] [ cursor_declaration ] [ type_declaration ] [ exception_declaration ] [ nestfunction_declaration ] BEGIN sequence_of_statement RETURN ; END; ] 1066 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE [ ... ] END; 语义 name 对象类型的名称(可以被模式限定)。 STATIC 对象类型内部函数(存储过程)的类型为 STATIC。 MEMBER 对象类型内部函数(存储过程)的类型为 MEMBER。 function_name 对象类型的内部函数的名称。 argmode 函数(存储过程)的参数的模式:IN、OUT 或者 INOUT。如果省略,默认为 IN。 argname 函数(存储过程)的参数的名称。 argtype 该函数参数(如果有)的数据类型(可以是模式限定的)。参数类型可以是基本类型、对象类型或者域类 型,或者可以引用一个表列的类型。 根据实现语言,也可以允许指定 cstring 之类的” 伪类型”。伪类型表示实际参数类型没有被完整指定或者不属 于普通 SQL 数据类型集合。 可以写 table_name.column_name%TYPE 来引用一列的类型。使用这种特性有时可以帮助创建一个不受表定 义更改影响的函数。 default_expr 如果参数没有被指定值时要用作默认值的表达式。该表达式的值必须能被强制转为对应参数的类型。 只有输入(包括 INOUT)参数可以具有默认值。所有跟随在一个具有默认值的参数之后的输入参数也必须有默 认值。CREATE TYPE BODY 语句中的内部函数(存储过程)定义中参数的默认值必须保持与 CREATE TYPE 语句 中内部函数(存储过程)声明时指定的默认值相同(如果有的话)。 rettype 返回数据类型(可能被模式限定)。返回类型可以是一种基本类型、对象类型或者域类型,也可以引用一个 表列的类型。如果该函数不会返回一个值,可以指定返回类型为 void。 可以写 table_name.column_name%TYPE 来引用一列的类型。 plsql_block 包括变量、常量、游标和类型的定义以及 PL/SQL 语句组成的块结构。 procedure_name 对象类型的内部存储过程的名称。 示例 创建一个完整的对象类型: CREATE OR REPLACE TYPE objtype FORCE AUTHID CURRENT_USER AS OBJECT( f1 int, f2 varchar2(10), 1067 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE MEMBER FUNCTION memfunc(i int) RETURN INT, STATIC PROCEDURE staproc, CONSTRUCTOR FUNCTION objtype(self in out objtype) RETURN SELF AS RESULT ); \set SQLTERM / CREATE OR REPLACE TYPE BODY objtype AS MEMBER FUNCTION memfunc(i int) RETURN INT AS BEGIN RAISE NOTICE 'self.f1 is %', self.f1; RAISE NOTICE 'self.f2 is %', f2; RETURN i; END; STATIC PROCEDURE staproc AS BEGIN RAISE NOTICE 'this is a static procedure in object type'; END; CONSTRUCTOR FUNCTION objtype(self in out objtype) RETURN SELF AS RESULT AS BEGIN f1 := 1; self.f2 := 'a'; RETURN ; END; END; / \set SQLTERM ; 对象类型成员函数及构造函数的使用: CREATE TABLE tb1(i objtype); INSERT INTO tb1 VALUES(objtype()); -- 自定义构造函数 INSERT INTO tb1 VALUES(objtype(2, 'b')); -- 默认构造函数 SELECT * FROM tb1; i ------(1,a) (2,b) (2 rows) SELECT t.i.memfunc(1) FROM tb1 t; NOTICE: self.f1 is 1 NOTICE: self.f2 is a NOTICE: self.f1 is 2 1068 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE NOTICE: self.f2 is b objtype.memfunc ----------------1 1 (2 rows) 对象类型静态存储过程的使用: CALL objtype.staproc(); NOTICE: this is a static procedure in object type CALL 其他 静 态 函 数 (存 储 过 程) 不 能 创 建 含 有 名 为 SELF 的 参 数, 在 调 用 时 需 要 以 类 型 名 做 前 缀 修 饰, 如 type_name.method()。 成员函数(存储过程)的第一个参数必须是名为 SELF 且类型为当前对象类型的参数,若未显式创建 SELF 参 数,那么该参数会被隐式创建为 IN 参数。在调用成员函数(存储过程)时需要以类型定义的具体对象名做前缀修 饰,如 object_expression.method()。且不需要为 SELF 参数传值,成员函数(存储过程)会自动接收对其进行修饰 的对象作为 SELF 参数传入。 成员函数(存储过程)的 SELF 参数可以是 IN 参数或者 IN OUT 参数。 一个对象类型可以创建多个构造函数,所有构造函数都必须与类型同名。与成员方法一样,自定义构造函数的第 一个参数必须是 SELF 参数,若 SELF 参数未被显式创建,也会被隐式创建。 不同于成员方法的是,自定义构造函数的 SELF 参数只能是 IN OUT 参数。 不同于普通函数,自定义构造函数的 RETURN 子句不能带有任何表达式,构造函数总会自动把 SELF 参数作为返 回值进行返回。 16.17 CREATE USER 用途 CREATE USER 现在是CREATE ROLE 的一个别名。唯一的区别是 “CREATE USER“中 LOGIN 被作为默认值, 而 NOLOGIN 是 “CREATE ROLE“的默认值。 前置条件 必须具有 CREATE ROLE 特权或者成为一个数据库超级用户。 语法 CREATE USER name [ [ WITH ] option [ ... ] ] 1069 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE 这里 option 可以是: SUPERUSER | NOSUPERUSER | CREATEDB | NOCREATEDB | CREATEROLE | NOCREATEROLE | INHERIT | NOINHERIT | LOGIN | NOLOGIN | ACCOUNT { LOCK | UNLOCK } | REPLICATION | NOREPLICATION | BYPASSRLS | NOBYPASSRLS | CONNECTION LIMIT connlimit | CONNECTION INTERVALS 'time1 TO time2' | [ ENCRYPTED ] PASSWORD 'password' | VALID UNTIL 'timestamp' | IN ROLE role_name [, ...] | IN GROUP role_name [, ...] | ROLE role_name [, ...] | ADMIN role_name [, ...] | USER role_name [, ...] | SYSID uid 1070 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE 1071 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE 语义 参见CREATE ROLE 示例 参见CREATE ROLE 16.18 CREATE USER MAPPING 用途 CREATE USER MAPPING 定义一个用户到一个外部服务器的新映射。一个用户映射通常会包含连接信息,外部数 据包装器会使用连接信息和外部服务器中包含的信息一起来访问一个外部数据源。 前置条件 一个外部服务器的拥有者可以为任何服务器任何用户创建用户映射。还有,如果一个用户被授予了服务器上的 USAGE 特权,该用户可以为他们自己的用户名创建用户映射。 语法 CREATE USER MAPPING [IF NOT EXISTS] FOR { user_name | USER | CURRENT_USER | PUBLIC } SERVER server_name [ OPTIONS ( option 'value' [ , ... ] ) ] 语义 IF NOT EXISTS 如果给定用户到给定外部服务器的映射已经存在,则不要抛出错误。在这种情况下发出通知。请注 意,不能保证现有的用户映射与要创建的映射完全相同。 user_name 要映射到外部服务器的一个现有用户的名称。CURRENT_USER 和 USER 匹配当前用户的名称。当 PUBLIC 被指定时,一个所谓的公共映射会被创建,当没有特定用户的映射可用时将会使用它。 server_name 将为其创建用户映射的现有服务器的名称。 1072 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE OPTIONS ( option 'value' [, ... ] ) 这个子句指定用户映射的选项。这些选项通常定义该映射实际的用户名和 口令。选项名必须唯一。允许的选项名和值与该服务器的外部数据包装器有关。 示例 为用户 bob、服务器 foo 创建一个用户映射: CREATE USER MAPPING FOR bob SERVER foo OPTIONS (user 'bob', password 'secret'); 兼容性 CREATE USER MAPPING 符合 ISO/IEC 9075-9 (SQL/MED)。 16.19 CREATE VIEW 用途 CREATE VIEW 定义一个查询的视图。该视图不会被物理上物质化。相反,在每一次有查询引用该视图时,视图的 查询都会被运行。 CREATE OR REPLACE VIEW 与之相似,但是如果已经存在一个同名视图,该视图会被替换。当原视图被其他对象 依赖,在被替换前,将依赖对象更新为无效状态。如果依赖原视图的对象不是视图,在更新其状态时会出错;如果依 赖原视图的对象是视图,则将该对象更新为无效状态。 如果给定了一个模式名(例如 CREATE VIEW myschema.myview ...),那么该视图会被创建在指定的模式中。 否则,它会被创建在当前模式中。临时视图存在于一个特殊模式中,因此创建临时视图时不能给定一个模式名。视图 的名称不能与同一模式中任何其他视图、表、序列、索引或外部表同名。 前置条件 如果给定了一个模式名,那么该视图会被创建在指定的模式中。否则,它会被创建在当前模式中。临时视图存在 于一个特殊模式中,因此创建临时视图时不能给定一个模式名。 语法 CREATE [ OR REPLACE ] [ TEMP | TEMPORARY ] [ RECURSIVE ] [ FORCE ] VIEW name [ ( column_name [, ...] ) ] [ WITH ( view_option_name [= view_option_value] [, ... ] ) ] AS query [ WITH [ CASCADED | LOCAL ] CHECK OPTION | READ ONLY ] 1073 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE 语义 TEMPORARY 或者 TEMP 如果被指定,视图被创建为一个临时视图。在当前会话结束时会自动删掉临时视图。当临时视 图存在时,具有相同名称的已有永久视图对当前会话不可见,除非用模式限定的名称引用它们。 如果视图引用的任何表是临时的,视图将被创建为临时视图(不管有没有指定 TEMPORARY)。 RECURSIVE 创建一个递归视图。 语法 CREATE RECURSIVE VIEW [ schema . ] view_name (column_names) AS SELECT ...; 等效于 CREATE VIEW [ schema . ] view_name AS WITH RECURSIVE view_name (column_names) AS (SELECT ...) SELECT column_names FROM view_name; 1074 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE 对于一个递归视图必须指定一个视图列名列表。 FORCE 创建一个 FORCE 视图。 语法 CREATE FORCE VIEW [ schema . ] view_name (column_names) AS SELECT ...; 创建一个 FORCE 视图,无论视图依赖检查是否成功都能创建视图。依赖检查 (编译) 成功,那么创建为一个有 效视图,否则为一个无效视图。 name 要创建的视图的名字(可以是模式限定的)。 column_name 要用于视图列的名称列表,可选。如果没有给出,列名会根据查询推导。 WITH ( view_option_name [= view_option_value] [, ... ] ) 这个子句为视图指定一些可选的参数,支持下列参数: check_option (string) 这个参数可以是 local 或者 cascaded,并且它等效于指定 WITH [ CASCADED | LOCAL ] CHECK OPTION(见下文)。可以使用ALTER VIEW 在一个现有视图上修改这个选项。 security_barrier (boolean) 如果希望视图提供行级安全性,应该使用这个参数。详见 规则和权限。 query 提供视图的行和列的一个SELECT 或者VALUES 命令。 WITH [ CASCADED | LOCAL ] CHECK OPTION 这个选项控制自动可更新视图的行为。这个选项被指定时,将检查该 视图上的 INSERT 和 UPDATE 命令以确保新行满足视图的定义条件(也就是,将检查新行来确保通过视图能看到 它们)。如果新行不满足条件,更新将被拒绝。如果没有指定 CHECK OPTION,会允许该视图上的 INSERT 和 UPDATE 命令创建通过该视图不可见的行。支持下列检查选项: LOCAL 只根据直接定义在该视图本身的条件检查新行。任何定义在底层基视图上的条件都不会被检查(除非它 们也指定了 CHECK OPTION)。 CASCADED 会根据该视图和所有底层基视图上的条件检查新行。如果 CHECK OPTION 被指定,并且没有指定 LOCAL 和 CASCADED,则会假定为 CASCADED。 CHECK OPTION 不应该和 RECURSIVE 视图一起使用。 1075 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE 注意,只有在自动可更新的、没有 INSTEAD OF 触发器或者 INSTEAD 规则的视图上才支持 CHECK OPTION。如 果一个自动可更新的视图被定义在一个具有 INSTEAD OF 触发器的基视图之上,那么 LOCAL CHECK OPTION 可 以被用来检查该自动可更新的视图之上的条件,但具有 INSTEAD OF 触发器的基视图上的条件不会被检查(一 个级联检查选项将不会级联到一个触发器可更新的视图,并且任何直接定义在一个触发器可更新视图上的检查 选项将被忽略)。如果该视图或者任何基础关系具有导致 INSERT 或 UPDATE 命令被重写的 INSTEAD 规则,那 么在被重写的查询中将忽略所有检查选项,包括任何来自于定义在带有 INSTEAD 规则的关系之上的自动可更新 视图的检查。 READ ONLY 创建视图指定 WITH READ ONLY, 则不允许通过视图进行 DML 操作。 示例 创建一个由所有喜剧电影组成的视图: CREATE VIEW comedies AS SELECT * FROM films WHERE kind = 'Comedy'; 创建的视图包含创建时 film 表中的列。尽管 “ *“被用来创建该视图,后来被加入到该表中的列不会成为该视图 的组成部分。 创建带有 LOCAL CHECK OPTION 的视图: CREATE VIEW universal_comedies AS SELECT * FROM comedies WHERE classification = 'U' WITH LOCAL CHECK OPTION; 这将创建一个基于 comedies 视图的视图,只显示 kind = 'Comedy'和 classification = 'U'的电影。如果新 行没有 classification = 'U',在该视图中的任何 INSERT 或 UPDATE 尝试将被拒绝,但是电影的 kind 将不会被 检查。 用 CASCADED CHECK OPTION 创建一个视图: CREATE VIEW sys_comedies AS SELECT * FROM comedies WHERE classification = 'PG' WITH CASCADED CHECK OPTION; 这将创建一个检查新行的 kind 和 classification 的视图。 创建一个由可更新列和不可更新列混合而成的视图: CREATE VIEW comedies AS SELECT f.*, 1076 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE country_code_to_name(f.country_code) AS country, (SELECT avg(r.rating) FROM user_ratings r WHERE r.film_id = f.id) AS avg_rating FROM films f WHERE f.kind = 'Comedy'; 这个 视图 将支 持 INSERT、UPDATE 以及 DELETE。所 有来 自于 films 表的 列 都将 是可 更新 的,而 计算 列 country 和“avg_rating“将是只读的。 创建一个由数字 1 到 100 组成的递归视图: CREATE RECURSIVE VIEW public.nums_1_100 (n) AS VALUES (1) UNION ALL SELECT n+1 FROM nums_1_100 WHERE n < 100; 注意在这个 CREATE 中尽管递归的视图名称是方案限定的,但它内部的自引用不是方案限定的。这是因为隐式创 建的 CTE 的名称不能是方案限定的。 兼容性 CREATE OR REPLACE VIEW 是一种 KingbaseES 的语言扩展。临时视图的概念也是这样。WITH ( ... ) 子句也是 一种扩展。 其他 1. 使用DROP VIEW 语句删除视图。 要小心视图列的名称和类型将会按照你想要的方式指定。例如: CREATE VIEW vista AS SELECT 'Hello World'; 是不好的形式,因为列名默认为?column?,而且列的数据类型默认为 text,这可能不是用户想要 的。视图结果中一个字符串更好的风格类似于这样: CREATE VIEW vista AS SELECT text 'Hello World' AS hello; 对视图中引用的表的访问由视图拥有者的权限决定。在某些情况下,这可以被用来提供安全但是受限 的底层表访问。但是,并非所有视图都对篡改是安全的,详见 规则和权限。在视图中调用的函数会被 同样对待,就好像是直接在使用该视图的查询中调用它们一样。因此,一个视图的用户必须具有调用 视图所使用的全部函数的权限。 当 CREATE OR REPLACE VIEW 被用在一个现有视图上时,只有该视图的定义 SELECT 规则被改变。 其他包括拥有关系、权限和非 SELECT 规则在内的视图属性不会被更改。要替换视图,你必须拥有 它(包括作为拥有角色的一个成员)。 2. 可更新视图 1077 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE 简单视图是自动可更新的:系统将允许在这类视图上以在常规表上相同的方式使用 INSERT、UPDATE 以及 DELETE 语句。如果一个视图满足以下条件,它就是自动可更新的: • 在该视图的 FROM 列表中刚好只有一项,并且它必须是一个表或者另一个可更新视图。 • 视图定义的顶层不能包含 WITH、DISTINCT、GROUP BY、HAVING、LIMIT 或者 OFFSET 子句。 • 视图定义的顶层不能包含集合操作(UNION、INTERSECT 或者 EXCEPT)。 • 视图的选择列表不能包含任何聚集、窗口函数或者集合返回函数。 一个自动可更新的视图可以混合可更新列以及不可更新列。如果一个列是对底层基本关系中一个可更 新列的简单引用,则它是可更新的。否则该列是只读的,并且在一个 INSERT 或者 UPDATE 语句尝试 对它赋值时会报出一个错误。 如果视图是自动可更新的,系统将把视图上的任何 INSERT、UPDATE 或者 DELETE 语句转换成在底层 基本关系上的对应语句。带有 ON CONFLICT UPDATE 子句的 INSERT 语句已经被完全支持。 如果一个自动可更新视图包含一个 WHERE 条件,该条件会限制基本关系的哪些行可以被该视图上的 UPDATE 以及 DELETE 语句修改。但是,一个允许被 UPDATE 修改的行可能让该行不再满足 WHERE 条 件,并且因此也不再能从视图中可见。类似地,一个 INSERT 命令可能插入不满足 WHERE 条件的基本 关系行,并且因此从视图中也看不到这些行(ON CONFLICT UPDATE 可能会类似地影响无法通过该视 图见到的现有行)。CHECK OPTION 可以被用来阻止 INSERT 和 UPDATE 命令创建这类从视图中无法看 到的行。 如果一个自动可更新视图被标记了 security_barrier 属性,那么所有该属性的 WHERE 条件(以及 任何使用标记为 LEAKPROOF 的操作符的条件)将在该视图使用者的任何条件之前计算。详见 规则 和权限。由于它们不会通过用户的 WHERE 条件,所以,最终不会返回的行可能仍会结束被锁定的状 态。可以用 EXPLAIN 来查看哪些条件被应用在关系层面(并且因此不锁定行)以及哪些不会被应用 在关系层面。 一个更加复杂的不满足所有这些条件的视图默认是只读的:系统将不允许在该视图上的插入、更新或 者删除。可以通过在该视图上创建一个 INSTEAD OF 触发器来获得可更新视图的效果,该触发器必须 把该视图上的尝试的插入等转换成其他表上合适的动作。更多信息请见CREATE TRIGGER 。另一 种可能性是创建规则(见CREATE RULE ),但是实际中触发器更容易理解和正确使用。 注意在视图上执行插入、更新或删除的用户必须具有该视图上相应的插入、更新或删除特权。此外, 视图的拥有者必须拥有底层基本关系上的相关特权,但是执行更新的用户并不需要底层基本关系上的 任何权限(见 规则和权限)。 16.20 DEALLOCATE 用途 DEALLOCATE 被用来释放一个之前准备好的 SQL 语句。如果不显式地释放一个预备语句,会话结束时会释放它。 更多关于预备语句的信息请见PREPARE 。 前置条件 1078 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE 无 语法 DEALLOCATE [ PREPARE ] { name | ALL } 语义 PREPARE 这个关键词会被忽略。 name 要释放的预备语句的名称。 ALL 释放所有预备语句。 示例 DEALLOCATE ALL; 兼容性 SQL 标准包括一个 DEALLOCATE 语句,但是只用于嵌入式 SQL。 16.21 DECLARE 用途 DECLARE 允许用户创建游标,游标可以被用来在大型查询暂停时检索少量的行。游标被创建后,可以用FETCH 从中取得行。 注意: 这个页面描述在 SQL 命令层面上游标的用法。如果想要在 PL/SQL 函数中使用游标,其规则是不同的。 前置条件 无 语法 DECLARE name [ BINARY ] [ INSENSITIVE ] [ [ NO ] SCROLL ] CURSOR [ { WITH | WITHOUT } HOLD ] FOR query 1079 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE 语义 name 要创建的游标的名称。 BINARY 让游标返回二进制数据而不是返回文本格式数据。 INSENSITIVE 指示从游标中检索数据的过程不受游标创建之后在其底层表上发生的更新的影响。在 KingbaseES 中, 这是默认的行为。因此这个关键词没有实际效果,仅仅被用于兼容 SQL 标准。 SCROLL | NO SCROLL SCROLL 指定游标可以用非顺序(例如,反向)的方式从中检索行。根据查询的执行计划的复杂 度,指定 SCROLL 可能导致查询执行时间上的性能损失。NO SCROLL 指定游标不能以非顺序的方式从中检索行。 默认是允许在某些情况下滚动,但这和指定 SCROLL 不完全相同。 WITH HOLD | WITHOUT HOLD WITH HOLD 指定该游标在创建它的事务提交之后还能被继续使用。WITHOUT HOLD 指定该 游标不能在创建它的事务之外使用。如果两者都没有指定,则默认为 WITHOUT HOLD。 query 用于提供该游标返回的行的SELECT 或者VALUES 命令。 关键词 BINARY 、INSENSITIVE 和 SCROLL 可以以任意顺序出现。 示例 声明一个游标: DECLARE liahona CURSOR FOR SELECT * FROM films; 更多游标的例子请见FETCH 。 兼容性 SQL 标准认为游标是否默认对底层数据的并发更新敏感是与实现相关的。在 KingbaseES 中,默认游标对此是不 敏感的,并且可以通过指定 FOR UPDATE 让它变得对此敏感。其他产品的行为可能有所不同。 SQL 标准只允许在嵌入式 SQL 和模块中使用游标。KingbaseES 允许以交互的方式使用游标。 二进制游标是一种 KingbaseES 扩展。 其他 普通游标以文本格式返回数据,这和 SELECT 产生的数据一样。BINARY 选项指定游标应该以二进制格式返回数 据。这减少了服务器和客户端的转换负担,但程序员需要付出更多工作来处理与平台相关的二进制数据格式。例如, 1080 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE 如果一个查询从一个整数列中返回一个值一,用一个默认游标将得到一个字符串 1,而使用一个二进制游标将得到该 值的四字节内部表示(big-endian 大端字节顺序)。 使用二进制游标时应该小心。很多应用(包括 ksql)还没有准备好处理二进制游标,它们仍然期待数据以文本格 式到来。 注意: 当客户端应用使用“扩展查询”协议发出一个 FETCH 命令,绑定协议消息会指定使用文本还是二进制格式检 索数据。这种选择会覆盖定义游标时指定的方式。因此在使用扩展查询协议时,这样一个二进制游标的概念实际是被 废弃的—任何游标都可以被视作文本或者二进制。 除非指定了 WITH HOLD,这个命令创建的游标只能在当前事务中使用。因此,没有 WITH HOLD 的 DECLARE 在 事务块外是没有用的:游标只会生存到该语句结束。因此如果这种命令在事务块之外被使用,KingbaseES 会报告一 个错误。定义事务块需要使用BEGIN 和COMMIT (或者ROLLBACK )。 如果指定了 WITH HOLD 并且创建游标的事务成功提交,在同一个会话中的后续事务中还能够继续访问该游标 (但是如果创建事务被中止,游标会被移除)。一个用 WITH HOLD 创建的游标可以用一个显式的 CLOSE 命令关闭, 或者会话结束时它也会被关闭。在当前的实现中,由一个被保持游标表示的行会被复制到一个临时文件或者内存区域 中,这样它们才会在后续事务中保持可用。 当查询包括 FOR UPDATE 或 FOR SHARE 时,不能指定 WITH HOLD。 在定义一个将被反向取元组的游标时,应该指定 SCROLL 选项。这是 SQL 标准所要求的。但是,为了和早期版 本兼容,如果游标的查询计划足够简单到支持它不需要额外的开销,KingbaseES 会允许在没有 SCROLL 的情况下反向 取元组。但是,建议应用开发者不要依赖于从没有用 SCROLL 创建的游标中反向取元组。如果指定了 NO SCROLL,那 么任何情况下都不允许反向取元组。 当查询包括 FOR UPDATE 或 FOR SHARE 时,也不允许反向取元组。因此在这种情况下不能指定 SCROLL。 警告: 如果可滚动和 WITH HOLD 游标调用了任何不稳定的函数(见 函数易变性分类),它们可能给出预 期之外的结果。当重新取得一个之前取得过的行时,那些函数会被重新执行,这可能导致得到与第一次不同的结 果。对这类情况的一种变通方法是,声明游标为 WITH HOLD 并且在从其中读取任何行之前提交事务。这将强制 该游标的整个输出被物化在临时存储中,这样针对每一行只会执行一次不稳定函数。 如果游标的查询包括 FOR UPDATE 或者 FOR SHARE,那么被返回的行会在它们第一次被取得时被锁定,这和带 有这些选项的常规SELECT 命令一样。此外,被返回的行将是最新的版本,因此这些选项提供了被 SQL 标准称为 “敏感游标”的等效体(把 INSENSITIVE 与 FOR UPDATE 或者 FOR SHARE 一起指定是错误)。 警告: 如果游标要和 UPDATE ... WHERE CURRENT OF 或者 DELETE ... WHERE CURRENT OF 一起使用,通 常推荐使用 FOR UPDATE。使用 FOR UPDATE 可以阻止其他会话在行被取得和被更新之间修改行。如果没有 FOR UPDATE,当行在游标创建后被更改后,一个后续的 WHERE CURRENT OF 命令将不会产生效果。 另一个使用 FOR UPDATE 的原因是,如果没有它,当游标查询不符合 SQL 标准的“简单可更新”规则 时,后续的 WHERE CURRENT OF 可能会失败(特别地,该游标必须只引用一个表并且没有使用分组或者 ORDER 1081 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE BY)。不是简单可更新的游标可能成功也可能不成功,这取决于计划选择的细节。因此在最坏的情况下,应用可 能会在测试时成功但是在生产中失败。 不把 FOR UPDATE 和 WHERE CURRENT OF 一起用的主要原因是,需要游标时可滚动的或者对于后续更新不敏 感(也就是说,继续显示旧的数据)。如果这是你的需求,应密切关注安上述警示。 SQL 标准只对嵌入式 SQL 中的游标做出了规定。KingbaseES 服务器没有为游标实现 OPEN 语句。当游标被声明 时就被认为已经被打开。但是,ESQL(KingbaseES 的嵌入式 SQL 预处理器)支持标准 SQL 游标习惯,包括那些 DECLARE 和 OPEN 语句。 你可以通过查询 sys_cursors 系统视图可以看到所有可用的游标。 16.22 DELETE 用途 DELETE 从指定表中删除满足 WHERE 子句的行。如果 WHERE 子句没有出现,效果将会是删除表中的所有行。结果 是一个合法的空表。 提示: TRUNCATE 提供移除表中所有行的快速机制。 有两种方式可以使用数据库中其他表中包含的信息来删除一个表的行:使用子选择或者在 USING 子句中指定额 外的表。哪种技术更合适取决于特定的环境。 可选的 RETURNING 子句导致 DELETE``基于实际被删除的每一行计算并且返回值。任何使用被删除表列或者 ``USING 中提到的其他表的列的表达式都可以被计算。RETURNING 列表的语法和 SELECT 的输出列表语法相同。 前置条件 要从表中删除行,你必须具有其上的 DELETE 特权,以及 USING 子句中任何表以及其值在 “condition“中被读取 的表上的 SELECT 特权。 语法 [ WITH [ RECURSIVE ] with_query [, ...] ] DELETE FROM [ ONLY ] table_name [part_extension_clause] [ * ] [ [ AS ] alias ] | sub_query [alias] [ USING using_list ] [ WHERE condition | WHERE CURRENT OF cursor_name ] [ RETURNING * | output_expression [ [ AS ] output_name ] [, ...] ] 1082 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE Part_extension_clause: { PARTITION (patition) | PARTITION FOR (partition_key_value [, partition_key_value]…) | SUBPARTITION (subpartition) | SUBPARTITION FOR (subpartition_key_value [, subpartition_key_value]…) } 1083 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE 语义 with_query WITH 子句允许你指定一个或者多个子查询,在 DELETE 查询中可以用子查询的名字来引用它们。详见 WITH 查询和SELECT 。 table_name 要从其中删除行的表名(可以是模式限定的)。如果在表名前指定 ONLY,只会从提到的表中删除匹配的 行。如果没有指定 ONLY,还会删除该表的任何继承表中的匹配行。可选地,可以在表名后面指定 * 来显式指定 要包括继承表。 part_extension_clause 支持通过 partitionsubpartition 关键字指定分区名或者子分区名,实现对分区和子分区直接 进行 delete 操作。其中 PARTITION FOR(partition_key_value) 指定分区键值,PARTITION (partition)指 定分区名,这里的分区名是指 oralce 语法创建分区表时指定的分区名,而不是分区对象在系统表 sys_class 中 存储的对象名。 alias 目标表的一个别名。提供别名时,它会完全隐藏该表的真实名称。例如,对于 DELETE FROM foo AS f, DELETE 语句的剩余部分都会用 f 而不是 foo 来引用该表。 sub_query • 当子查询作为 DELETE 目标时,DELETE 的目标是子查询中的基表; • 子查询投影列中不包含聚集函数(avg,count,max,min,sum 等),distinct 等; • 不支持 group by,having,start with,connect by 子句; • 如果查询表达式是带有连接的查询,那么对于基表以外的表,连接列上必须是主键或者带有 unique 约束; • 子查询不支持 Union/Intersect/Except/Minus 等集合查询。 using_list 一个表表达式的列表,它允许在 WHERE 条件中出现来自其他表的列。这和 SELECT 语句的`FROM 子句 中指定的表列表相似。例如,可以指定表的别名。除非想要进行自连接,否则不要在 “using_list“ 再写上目标 表。 condition 一个返回 boolean 类型值的表达式。只有让这个表达式返回 true 的行才将被删除。 1084 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE cursor_name 要在 WHERE CURRENT OF 情况中使用的游标的名称。最近一次从这个游标中取出的行将被删除。该游 标必须是 DELETE 的目标表上的非分组查询。注意不能在使用 WHERE CURRENT OF 的同时指定一个布尔条件。 有关将游标用于 WHERE CURRENT OF 的更多信息请见DECLARE 。 output_expression 在每一行被删除后,会被 DELETE 计算并且返回的表达式。该表达式可以使用 “table_name“ 以 及 USING 中的表的任何列。写成 * 可以返回所有列。 output_name 被返回列的名称。 示例 删除所有电影,但音乐剧除外: DELETE FROM films WHERE kind <> 'Musical'; 清空表 films: DELETE FROM films; 删除已完成的任务,返回被删除行的明细: DELETE FROM tasks WHERE status = 'DONE' RETURNING *; 删除 tasks 中游标 c_tasks 当前位于其上的行: DELETE FROM tasks WHERE CURRENT OF c_tasks; 兼容性 这个命令符合 SQL 标准,但是 USING 和 RETURNING 子句是 KingbaseES 扩展,在 DELETE 中使用 WITH 也是扩 展。 其他 1. 输出 在成功完成时,一个 DELETE 命令会返回以下形式的命令标签: DELETE count “count“是被删除行的数目。注意如果有一个 BEFORE DELETE 触发器抑制删除,那么该数目可能小于匹配 “condition“ 的行数。如果 “count“为 0,表示查询没有删除行(这并非一种错误)。 如果 DELETE 命令包含 RETURNING 子句,则结果会与包含有 RETURNING 列表中定义的列和值的 SELECT 语句结 果相似,这些结果是在被该命令删除的行上计算得来。 2. 注解 通过在 USING 子句中指定其他的表,KingbaseES 允许在 WHERE 条件中引用其他表的列。例如,要删除有一个给 定制片人制作的所有电影,可以这样做: 1085 第 16 章 SQL 语句: CREATE SEQUENCE 到 DELETE DELETE FROM films USING producers WHERE producer_id = producers.id AND producers.name = 'foo'; 这里实际发生的事情是在 films 和 producers 之间进行连接,然后删除所有成功连接的 films 行。这种语法不 属于标准。更标准的方式是: DELETE FROM films WHERE producer_id IN (SELECT id FROM producers WHERE name = 'foo'); 在一些情况下,连接形式比子查询形式更容易书写或者执行更快。 16.23 DELETE RESOURCE GROUP 用途 删除一个资源组。 前置条件 资源组功能依赖于操作系统的 cgroup,所以仅支持类 linux 操作系统。 语法 DROP RESOURCE GROUP group_name; 语义 group_name 为创建的资源组名称, 一个数据库内唯一,该对象不属于某个模式下。 示例: drop resource group rgroup1; 1086 第 17 章 SQL 语句: DISCARD 到 DROP LANGUAGE 第 17章 SQL 语句: DISCARD 到 DROP LANGUAGE 本章包含以下 SQL 语句: • DISCARD • DO • DROP ACCESS METHOD • DROP AGGREGATE • DROP CAST • DROP COLLATION • DROP CONTEXT • DROP CONVERSION • DROP DATABASE • DROP DATABASE LINK • DROP DIRECTORY • DROP DOMAIN • DROP EXTENSION • DROP EVENT TRIGGER • DROP FOREIGN DATA WRAPPER • DROP FOREIGN TABLE • DROP FUNCTION • DROP GROUP • DROP INDEX • DROP LANGUAGE 1087 第 17 章 SQL 语句: DISCARD 到 DROP LANGUAGE 17.1 DISCARD 用途 DISCARD —抛弃会话状态 DISCARD 释放与一个数据库会话相关的内部资源。这个命令有助于部分或者完全重置该会话的状态。有几个子命 令来释放不同类型的资源。DISCARD ALL 变体把所有其他形式都包含在内,并且还会重置额外的状态。 前置条件 无 语法 DISCARD { ALL | PLANS | SEQUENCES | TEMPORARY | TEMP } 语义 PLANS 释放所有已缓存的查询计划,强制在下一次使用相关预备语句时重新做计划。 SEQUENCES 丢弃所有已缓存的序列相关的状态,包括 “currval()“/lastval() 信息以及任何还未被 nextval() 返回 的预分配的序列值(预分配序列值的描述请见CREATE SEQUENCE ); TEMPORARY | TEMP 删除当前会话中创建的所有临时表。 ALL 释放与当前会话相关的所有临时资源并且把会话重置为初始状态。当前这和执行以下语句序列的效果相同: CLOSE ALL; SET SESSION AUTHORIZATION DEFAULT; RESET ALL; DEALLOCATE ALL; UNLISTEN *; SELECT sys_advisory_unlock_all(); DISCARD PLANS; DISCARD TEMP; DISCARD SEQUENCES; 1088 第 17 章 SQL 语句: DISCARD 到 DROP LANGUAGE 示例 DISCARD SEQUENCES; 兼容性 DISCARD 是一种 KingbaseES 扩展。 其他 DISCARD ALL 不能在事务块内执行。 17.2 DO 用途 DO —执行一个匿名代码块 DO 执行一个匿名代码块,或者换句话说执行一个以一种过程语言编写的瞬时匿名函数。 代码块就好像是一个没有参数并且返回 void 的函数的函数体。它会被在一次时间内解析并且执行。 可选的 LANGUAGE 子句可以卸载代码块之前或者之后。 前置条件 要使用的过程语言必须已经用 CREATE LANGUAGE 安装在当前数据库中。默认已经安装了 plsql,但是其他语言 没有被安装。 用户必须拥有该过程语言的 USAGE 特权,如果该语言是不可信的则必须是一个超级用户。这和创建一个该语言 的函数对特权的要求相同。 语法 DO [ LANGUAGE lang_name ] code 语义 code 要被执行的过程语言代码。就像在 “CREATE FUNCTION“中一样,必须把它指定为一个字符串。推荐使用一 个美元引用的文本。 lang_name 编写该代码的过程语言的名称。如果省略,默认为 plsql。 示例 把模式 public 中所有视图上的所有特权授予给角色 webuser: 1089 第 17 章 SQL 语句: DISCARD 到 DROP LANGUAGE DO $$DECLARE r record; BEGIN FOR r IN SELECT table_schema, table_name FROM information_schema.tables WHERE table_type = 'VIEW' AND table_schema = 'public' LOOP EXECUTE 'GRANT ALL ON ' || quote_ident(r.table_schema) || '.' || quote_ident(r.table_name) || ' TO webuser'; END LOOP; END$$; 兼容性 SQL 标准中没有 DO 语句。 17.3 DROP ACCESS METHOD 用途 DROP ACCESS METHOD —移除一种访问方法 DROP ACCESS METHOD 移除一种现有的访问方法。 前置条件 只有超级用户能够删除访问方法。 语法 DROP ACCESS METHOD [ IF EXISTS ] name [ CASCADE | RESTRICT ] 语义 IF EXISTS 如果该访问方法不存在,则不会抛出错误。这种情况下会发出一个提示。 name 一种现有的访问方法的名称。 CASCADE 自动删除依赖于该访问方法的对象(例如操作符类、操作符族以及索引),并且接着删除所有依赖于那些对 象的对象。 RESTRICT 如果有任何对象依赖于该访问方法,则拒绝删除它。这是默认设置。 1090 第 17 章 SQL 语句: DISCARD 到 DROP LANGUAGE 示例 删除访问方法 heptree: DROP ACCESS METHOD heptree; 兼容性 DROP ACCESS METHOD 是一种 KingbaseES 扩展。 17.4 DROP AGGREGATE 用途 DROP AGGREGATE —移除一个聚集函数 DROP AGGREGATE 移除一个现有的聚集函数。 前置条件 要执行这个命令,当前用户必须是该聚集函数的拥有者。 语法 DROP AGGREGATE [ IF EXISTS ] name ( aggregate_signature ) [, ...] [ CASCADE | RESTRICT ] 这里 aggregate_signature 是: * | [ argmode ] [ argname ] argtype [ , ... ] | [ [ argmode ] [ argname ] argtype [ , ... ] ] ORDER BY [ argmode ] [ argname ] argtype [ , ... ] aggregate_signature ::= 1091 第 17 章 SQL 语句: DISCARD 到 DROP LANGUAGE 语义 IF EXISTS 如果该聚集不存在则不要抛出一个错误,而是发出一个提示。 name 一个现有聚集函数的名称(可以是模式限定的)。 argmode 一个参数的模式:IN 或 VARIADIC。如果被忽略,默认值是 IN。 argname 一个参数的名称。注意“DROP AGGREGATE“并不真正关心参数名称,因为决定聚集函数的身份时只需要 参数数据类型。 argtype 该聚集函数所操作的一个输入数据类型。要引用一个零参数的聚集函数,写 “*“来替代参数说明列表。要引 用一个有序集聚集函数,在直接和聚集参数说明之间写上 ORDER BY。 CASCADE 自动删除依赖于该聚集函数的对象(例如使用它的视图),然后删除所有依赖于那些对象的对象。 RESTRICT 如果有任何对象依赖于该聚集函数,则拒绝删除它。这是默认值。 示例 要为类型 integer 移除聚集函数 myavg: DROP AGGREGATE myavg(integer); 要移除假想集聚集函数 myrank,该函数接收一个排序列的任意列表和直接参数的一个匹配的列表: DROP AGGREGATE myrank(VARIADIC "any" ORDER BY VARIADIC "any"); 要在一个命令中删除多个聚合函数: DROP AGGREGATE myavg(integer), myavg(bigint); 兼容性 在 SQL 标准中没有 DROP AGGREGATE 语句。 其他 ALTER AGGREGATE 下描述了另一种引用有序集聚集的语法。 1092 第 17 章 SQL 语句: DISCARD 到 DROP LANGUAGE 17.5 DROP CAST 用途 DROP CAST —移除一个造型 DROP CAST 移除一个之前定义好的造型。 前置条件 要能删除一个造型,你必须拥有源数据类型或目标数据类型。这也是创建一个造型所要求的特权。 语法 DROP CAST [ IF EXISTS ] (source_type AS target_type) [ CASCADE | RESTRICT ] 语义 IF EXISTS 如果该造型不存在则不要抛出一个错误,而是发出一个提示。 source_type 该造型的源数据类型的名称。 target_type 该造型的目标数据类型的名称。 CASCADE 这个关键词没有任何效果,因为在造型上没有依赖性。 RESTRICT 这个关键词没有任何效果,因为在造型上没有依赖性。 示例 要移除从类型 text 到类型 int 的造型: DROP CAST (text AS int); 兼容性 DROP CAST 命令符合 SQL 标准。 17.6 DROP COLLATION 用途 DROP COLLATION —移除一个排序规则 DROP COLLATION 移除一个之前定义好的排序规则。 1093 第 17 章 SQL 语句: DISCARD 到 DROP LANGUAGE 前置条件 要能删除一个排序规则,你必须拥有它。 语法 DROP COLLATION [ IF EXISTS ] name [ CASCADE | RESTRICT ] 语义 IF EXISTS 如果该排序规则不存在则不要抛出一个错误,而是发出一个提示。 name 排序规则的名称。排序规则名称可以是模式限定的。 CASCADE 自动删除依赖于该排序规则的对象,然后删除所有依赖于那些对象的对象。 RESTRICT 如果有任何对象依赖于该排序规则,则拒绝删除它。这是默认值。 示例 要删除名为 german 的排序规则: DROP COLLATION german; 兼容性 除了 IF EXISTS 选项之外,DROP COLLATION 命令符合 SQL 标准。该选项是一个 KingbaseES 扩展。 17.7 DROP CONTEXT 用途 DROP CONTEXT 删除 context(userenv 不可以删除)。该信息将从 sys_context 表中删除。 删除 context 不会使该 context 下设置的 key-value 失效。但是,当用户下次尝试设置该 context 时,该 context 将无效。即其删除的是字典对象,实例对象并不会删除。 前置条件 具有对象的删除权限。 语法 1094 第 17 章 SQL 语句: DISCARD 到 DROP LANGUAGE DROP CONTEXT namespace 语义 namespace 指定要删除的 context 名称。不能删除内置上下文 userenv。 示例 要删除名字为 context_test 的 context: drop context context_test; 17.8 DROP CONVERSION 用途 DROP CONVERSION —移除一个转换 DROP CONVERSION 移除一个之前定义好的转换。 前置条件 要能删除一个转换,你必须拥有该转换。 语法 DROP CONVERSION [ IF EXISTS ] name [ CASCADE | RESTRICT ] 语义 IF EXISTS 如果该转换不存在则不要抛出一个错误,而是发出一个提示。 name 转换的名称。转换名称可以是模式限定的。 CASCADE 这个关键词没有任何效果,因为在转换上没有依赖性。 RESTRICT 这个关键词没有任何效果,因为在转换上没有依赖性。 1095 第 17 章 SQL 语句: DISCARD 到 DROP LANGUAGE 示例 要删除名为 myname 的转换: DROP CONVERSION myname; 兼容性 在 SQL 标准中没有 DROP CONVERSION 语句,但是有一个 DROP TRANSLATION 语句。还有对应的 CREATE TRANSLATION 语句,它与 KingbaseES 中的 CREATE CONVERSION 句相似。 17.9 DROP DATABASE 用途 DROP DATABASE 移除一个数据库。它会移除该数据库的系统目录项并且删除包含数据的文件目录。它只能由数据 库拥有者执行。还有,当你或者任何其他人已经连接到目标数据库时,它不能被执行(连接到 kingbase 或者任何其 他数据库来发出这个命令)。 DROP DATABASE 不能被撤销。请小心使用! 前置条件 你必须拥有该数据库以使用 DROP DATABASE 。 语法 DROP DATABASE [ IF EXISTS ] name 语义 IF EXISTS 如果该数据库不存在则不要抛出一个错误,而是发出一个提示。 name 要移除的数据库的名称。 示例 删除数据库 mydatabase DROP DATABASE mydatabase; 兼容性 SQL 标准中没有 DROP DATABASE 语句。 1096 第 17 章 SQL 语句: DISCARD 到 DROP LANGUAGE 其他 DROP DATABASE 不能在一个事务块内执行。 在连接到目标数据库时,这个命令不能被执行。因此,使用程序 dropdb 会更方便,它是这个命令的一个包装 器。 17.10 DROP DATABASE LINK 用途 DROP DATABASE LINK 移除一个 database link。database link 可以被拥有者和 DBA 删除, 删除 database link 对 象之后,所有的用户会话中的对象都会被清除。 如果 database link 正在被其他用户使用,则无法删除此 database link。 暂不支持 PUBLIC 关键字。 前置条件 要执行这个命令必须拥有该 database link 的权限。 语法 DROP DATABASE LINK dblink_name 语义 dblink_name 要删除的 DATABASE LINK 名,可以包含模式名。 示例 删除 mydblink DROP DATABASE LINK mydblink; 17.11 DROP DIRECTORY 用途 DROP DIRECTORY 移除一个目录。 前置条件 只有 superuser 可以移除目录。 1097 第 17 章 SQL 语句: DISCARD 到 DROP LANGUAGE 语法 DROP DIRECTORY [ IF EXISTS ] (public.)dir_name 语义 IF EXISTS 如果该目录不存在则不要抛出一个错误,而是发出一个提示。 dir_name 一个现有目录的名称(默认为 public 模式,可以指定为 public 模式,指定其他模式报错)。 示例 要移除目录: DROP DIRECTORY dir_name; 兼容性 除了 IF EXISTS 选项,这个命令符合 SQL 标准。该选项是一个 KingbaseES 扩展。 17.12 DROP DOMAIN 用途 DROP DOMAIN —移除一个域 DROP DOMAIN 移除一个域。 前置条件 只有域的拥有者才能移除它。 语法 DROP DOMAIN [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ] 1098 第 17 章 SQL 语句: DISCARD 到 DROP LANGUAGE 语义 IF EXISTS 如果该域不存在则不要抛出一个错误,而是发出一个提示。 name 一个现有域的名称(可以是模式限定的)。 CASCADE 自动删除依赖于该域的对象(例如表列),然后删除所有依赖于那些对象的对象。 RESTRICT 如果有任何对象依赖于该域,则拒绝删除它。这是默认值。 示例 要移除域 box: DROP DOMAIN box; 兼容性 除了 IF EXISTS 选项,这个命令符合 SQL 标准。该选项是一个 KingbaseES 扩展。 17.13 DROP EVENT TRIGGER 用途 DROP EVENT TRIGGER —移除一个事件触发器 前置条件 要执行这个命令,当前用户必须是事件触发器的拥有者。 语法 DROP EVENT TRIGGER [ IF EXISTS ] name [ CASCADE | RESTRICT ] 语义 IF EXISTS 如果该事件触发器不存在则不要抛出一个错误,而是发出一个提示。 name 要移除的事件触发器的名称。 CASCADE 自动删除依赖于该触发器的对象,然后删除所有依赖于那些对象的对象。 RESTRICT 如果有任何对象依赖于该触发器,则拒绝删除它。这是默认值。 1099 第 17 章 SQL 语句: DISCARD 到 DROP LANGUAGE 示例 销毁触发器 snitch: DROP EVENT TRIGGER snitch; 兼容性 在 SQL 标准中没有 DROP EVENT TRIGGER 语句。 17.14 DROP EXTENSION 用途 DROP EXTENSION —移除一个扩展 DROP EXTENSION 从数据库移除扩展。删除一个扩展会导致其组成对象也被删除。 前置条件 你必须拥有该扩展才能使用 DROP EXTENSION。 语法 END [ WORK | TRANSACTION ] [ AND [ NO ] CHAIN ] 语义 IF EXISTS 如果该扩展不存在则不要抛出一个错误,而是发出一个提示。 name 一个已安装扩展的名称。 CASCADE 自动删除依赖于该扩展的对象,然后删除所有依赖于那些对象的对象。 RESTRICT 如果有任何对象依赖于该扩展(而不是它自己拥有的成员对象和其他被列在同一个 DROP 命令中的扩 展),则拒绝删除它。这是默认值。 示例 要从当前数据库移除扩展 hstore: DROP EXTENSION hstore; 1100 第 17 章 SQL 语句: DISCARD 到 DROP LANGUAGE 如果 hstore 的任何对象在该数据库库中正在使用,例如有一个表的列是 hstore 类型,这个命令都将会失败。 加上 CASCADE 选项可以强制把这些依赖对象也移除。 兼容性 DROP EXTENSION 是一个 KingbaseES 扩展。 17.15 DROP FOREIGN DATA WRAPPER 用途 DROP FOREIGN DATA WRAPPER —移除一个外部数据包装器 DROP FOREIGN DATA WRAPPER 移除一个已有的外部数据包装器。 前置条件 要执行这个命令,当前用户必须是该外部数据包装器的拥有者。 语法 DROP FOREIGN DATA WRAPPER [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ] 语义 IF EXISTS 如果该外部数据包装器不存在则不要抛出一个错误,而是发出一个提示。 name 一个现有外部数据包装器的名称。 CASCADE 自动删除依赖于该外部数据包装器的对象(例如服务器),然后删除所有依赖于那些对象的对象。 RESTRICT 如果有任何对象依赖于该外部数据包装器,则拒绝删除它。这是默认值。 示例 删除外部数据包装器 dbi: DROP FOREIGN DATA WRAPPER dbi; 兼容性 DROP FOREIGN DATA WRAPPER 符合 ISO/IEC 9075-9 (SQL/MED)。IF EXISTS 子句是一个 KingbaseES 扩展。 1101 第 17 章 SQL 语句: DISCARD 到 DROP LANGUAGE 17.16 DROP FOREIGN TABLE 用途 DROP FOREIGN TABLE —移除一个外部表 DROP FOREIGN TABLE 移除一个外部表。 前置条件 只有一个外部表的拥有者才能移除它。 语法 DROP FOREIGN TABLE [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ] 语义 IF EXISTS 如果该外部表不存在则不要抛出一个错误,而是发出一个提示。 name 要删除的外部表的名称(可以是模式限定的)。 CASCADE 自动删除依赖于该外部表的对象(例如视图),然后删除所有依赖于那些对象的对象。 RESTRICT 如果有任何对象依赖于该外部表,则拒绝删除它。这是默认值。 示例 要销毁两个外部表 films 和 distributors: DROP FOREIGN TABLE films, distributors; 兼容性 这个命令符合 ISO/ IEC 9075-9 (SQL/ MED),但是该标准只允许每个命令中删除一个外部表并且没有 IF EXISTS 选项。该选项是一个 KingbaseES 扩展。 17.17 DROP FUNCTION 用途 1102 第 17 章 SQL 语句: DISCARD 到 DROP LANGUAGE DROP FUNCTION 移除一个已有函数的定义。该函数的参数类型必须被指定,因为多个不同的函数可能会具有相同 的函数名和不同的参数列表。 前置条件 要执行这个命令用户必须是该函数的拥有者。 语法 DROP FUNCTION [ IF EXISTS ] name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ] [, ...] [ CASCADE | RESTRICT ] 语义 IF EXISTS 如果该函数不存在则不要抛出一个错误,而是发出一个提示。 name 一个现有函数的名称(可以是模式限定的)。如果未指定参数列表,则该名称在其模式中必须是唯一的。 argmode 一个参数的模式:IN、OUT、INOUT 或者 VARIADIC。如果被忽略,则默认为 IN。注意 DROP FUNCTION 并 不真正关心 OUT 参数,因为决定函数的身份时只需要输入参数。因此列出 IN、INOUT 和 VARIADIC 参数足以。 argname 一个参数的名称。注意 DROP FUNCTION 并不真正关心参数名称,因为决定函数的身份时只需要参数的数据 类型。 argtype 如果函数有参数,这是函数参数的数据类型(可以是模式限定的)。 CASCADE 自动删除依赖于该函数的对象(例如操作符和触发器),然后删除所有依赖于那些对象的对象。 RESTRICT 如果有任何对象依赖于该函数,则拒绝删除它。这是默认值。 示例 这个命令移除平方根函数: DROP FUNCTION sqrt(integer); 在一个命令中删除多个函数: 1103 第 17 章 SQL 语句: DISCARD 到 DROP LANGUAGE DROP FUNCTION sqrt(integer), sqrt(bigint); 如果函数名称在其模式中是唯一的,则可以在不带参数列表的情况下引用它: DROP FUNCTION update_employee_salaries; 请注意,这与 DROP FUNCTION update_employee_salaries(); 不同,后者引用一个零个参数的函数,而第一个变体才可以引用具有任意数量参数的函数,包括零,只要该名称 是唯一的。 兼容性 该命令符合 SQL 标准,使用这些 KingbaseES 扩展: • 该标准只允许每个命令删除一个函数。 • IF EXISTS 选项 • 能够指定参数模式和名称 17.18 DROP GROUP 用途 DROP GROUP —移除一个数据库角色 DROP GROUP 现在是DROP ROLE 的一个别名。 前置条件 参见DROP ROLE 语法 DROP GROUP [ IF EXISTS ] name [, ...] 语义 1104 第 17 章 SQL 语句: DISCARD 到 DROP LANGUAGE IF EXISTS 如果该角色不存在则不要抛出一个错误,而是发出一个提示。 name 要移除的角色的名称。 示例 DROP GROUP regress_priv_group1; 兼容性 在 SQL 标准中没有 DROP GROUP 语句。 17.19 DROP INDEX 用途 DROP INDEX 从数据库系统中移除一个已有的索引。 前置条件 要执行这个命令你必须是该索引的拥有者。 语法 DROP INDEX [ CONCURRENTLY ] [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ] 语义 CONCURRENTLY 删除索引并且不阻塞在索引基表上的并发选择、插入、更新和删除操作。一个普通的 DROP INDEX 会 要求该表上的排他锁,这样会阻塞其他访问直至索引删除完成。通过这个选项,该命令会等待直至冲突事务完 成。 在使用这个选项时有一些需要注意的事情。只能指定一个索引名称,并且不支持 CASCADE 选项(因此,一个支 持 UNIQUE 或者 PRIMARY KEY 约束的索引不能以这种方式删除)。还有,常规的 DROP INDEX 命令可以在一个 事务块内执行,而 DROP INDEX CONCURRENTLY 不能。 IF EXISTS 如果该索引不存在则不要抛出一个错误,而是发出一个提示。 name 要移除的索引的名称(可以是模式限定的)。 CASCADE 自动删除依赖于该索引的对象,然后删除所有依赖于那些对象的对象。 1105 第 17 章 SQL 语句: DISCARD 到 DROP LANGUAGE RESTRICT 如果有任何对象依赖于该索引,则拒绝删除它。这是默认值。 示例 这个命令将移除索引 title_idx: DROP INDEX title_idx; 兼容性 DROP INDEX 是一个 KingbaseES 语言扩展。在 SQL 标准中没有关于索引的规定。 17.20 DROP LANGUAGE 用途 DROP LANGUAGE —移除一个过程语言 DROP LANGUAGE 移除一个之前注册的过程语言的定义。 前置条件 你必须是一个超级用户或者该语言的拥有者才能使用 “DROP LANGUAGE“。 语法 DROP [ PROCEDURAL ] LANGUAGE [ IF EXISTS ] name [ CASCADE | RESTRICT ] 语义 IF EXISTS 如果该语言不存在则不要抛出一个错误,而是发出一个提示。 name 一个已有过程语言的名称。为了向前兼容,这个名称可以用单引号包围。 CASCADE 自动删除依赖于该语言的对象(例如该语言中的函数),然后删除所有依赖于那些对象的对象。 RESTRICT 如果有任何对象依赖于该语言,则拒绝删除它。这是默认值。 示例 这个命令移除过程语言 plsample: DROP LANGUAGE plsample; 1106 第 17 章 SQL 语句: DISCARD 到 DROP LANGUAGE 兼容性 在 SQL 标准中没有 DROP LANGUAGE 语句。 1107 第 18 章 SQL 语句: DROP MATERIALIZED VIEW 到 DROP SYNONYM 18章 SQL 语句: DROP MATERIALIZED 第 VIEW 到 DROP SYNONYM 本章包含以下 SQL 语句: • DROP MATERIALIZED VIEW • DROP OPERATOR • DROP OPERATOR CLASS • DROP OPERATOR FAMILY • DROP OWNED • DROP PACKAGE • DROP PACKAGE BODY • DROP POLICY • DROP PROCEDURE • DROP PUBLICATION • DROP ROLE • DROP ROUTINE • DROP RULE • DROP SCHEMA • DROP SEQUENCE • DROP SERVER • DROP STATISTICS • DROP SUBSCRIPTION • DROP SYNONYM 1108 第 18 章 SQL 语句: DROP MATERIALIZED VIEW 到 DROP SYNONYM 18.1 DROP MATERIALIZED VIEW 用途 DROP MATERIALIZED VIEW 删除一个现有的物化视图。 前置条件 要执行这个命令你必须是该物化视图的拥有者。 语法 DROP MATERIALIZED VIEW [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ] 语义 IF EXISTS 如果该物化视图不存在则不要抛出一个错误,而是发出一个提示。 name 要移除的物化视图的名称(可以是模式限定的)。 CASCADE 自动删除依赖于该物化视图的对象(例如其他物化视图或常规视图),然后删除所有依赖于那些对象的对 象。 RESTRICT 如果有任何对象依赖于该物化视图,则拒绝删除它。这是默认值。 示例 这个命令将移除名为 order_summary 的物化视图: DROP MATERIALIZED VIEW order_summary; 兼容性 DROP MATERIALIZED VIEW 是一个 KingbaseES 扩展。 18.2 DROP OPERATOR 用途 DROP OPERATOR 从数据库系统中删除一个现有的操作符。 前置条件 要执行这个命令,你必须是该操作符的拥有者。 1109 第 18 章 SQL 语句: DROP MATERIALIZED VIEW 到 DROP SYNONYM 语法 DROP OPERATOR [ IF EXISTS ] name ( { left_type | NONE } , { right_type | NONE } ) [, ...] [ CASCADE | RESTRICT ] 语义 IF EXISTS 如果该操作符不存在则不要抛出一个错误,而是发出一个提示。 name 一个现有的操作符的名称(可以是模式限定的)。 left_type 该操作符左操作数的数据类型,如果没有左操作数就写 NONE。 right_type 该操作符右操作数的数据类型,如果没有右操作数就写 NONE。 CASCADE 自动删除依赖于该操作符的对象(例如使用它的视图),然后删除所有依赖于那些对象的对象。 RESTRICT 如果有任何对象依赖于该操作符,则拒绝删除它。这是默认值。 示例 为类型 integer 移除幂操作符: DROP OPERATOR ^ (integer, integer); 为类型 bit 移除左一元按位补操作符: DROP OPERATOR ~ (none, bit); 为类型 bigint 移除右一元阶乘操作符: DROP OPERATOR ! (bigint, none); 在一条命令中删除多个操作符: DROP OPERATOR ~ (none, bit), ! (bigint, none); 兼容性 SQL 标准中没有 DROP OPERATOR 语句。 1110 第 18 章 SQL 语句: DROP MATERIALIZED VIEW 到 DROP SYNONYM 18.3 DROP OPERATOR CLASS 用途 DROP OPERATOR CLASS —删除一个操作符类 DROP OPERATOR CLASS 不会删除任何被该类引用的操作符或者函数。如果有索引依赖于该操作符类,你将需要 指定 CASCADE 来完成删除。 前置条件 要执行这个命令,你必须是该操作符类的拥有者。 语法 DROP OPERATOR CLASS [ IF EXISTS ] name USING index_method [ CASCADE | RESTRICT ] 语义 IF EXISTS 如果该操作符类不存在则不要抛出一个错误,而是发出一个提示。 name 一个现有的操作符类的名称(可以是模式限定的)。 index_method 该操作符类适用的索引访问方法的名称。 CASCADE 自动删除依赖于该操作符类的对象(例如索引),然后删除所有依赖于那些对象的对象。 RESTRICT 如果有任何对象依赖于该操作符类,则拒绝删除它。这是默认值。 示例 移除 B-树操作符类 widget_ops: DROP OPERATOR CLASS widget_ops USING btree; 如果有任何使用该操作符类的索引存在,这个命令都不会成功。增加 CASCADE 可以把这类索引与该操作符类一 起删除。 兼容性 SQL 标准中没有 DROP OPERATOR CLASS 语句。 其他 DROP OPERATOR CLASS 将不会删除包含该类的操作符族,即使该族中已经没有任何成员(特别是由 CREATE OPERATOR CLASS 隐式创建的族)。一个空操作符族是无害的,但是为了整洁你可能希望用 DROP OPERATOR AMILY 移除该操作符族,或者一开始就使用 DROP OPERATOR FAMILY 会更好。 1111 第 18 章 SQL 语句: DROP MATERIALIZED VIEW 到 DROP SYNONYM 18.4 DROP OPERATOR FAMILY 用途 DROP OPERATOR FAMILY —删除一个操作符族 DROP OPERATOR FAMILY 包括删除该族所包含的任何操作符类,但是它不会删除该族所引用的任何操作符或函 数。如果有任何依赖于该族中操作符类的索引存在,你将需要指定 CASCADE 来完成删除。 前置条件 要执行这个命令,你必须是该操作符族的拥有者。 语法 DROP OPERATOR FAMILY [ IF EXISTS ] name USING index_method [ CASCADE | RESTRICT ] 语义 IF EXISTS 如果该操作符族不存在则不要抛出一个错误,而是发出一个提示。 name 一个现有操作符族的名称(可以是模式限定的)。 index_method 该操作符族适用的索引访问方法的名称。 CASCADE 自动删除依赖于该操作符族的对象,然后删除所有依赖于那些对象的对象。 RESTRICT 如果有任何对象依赖于该操作符族,则拒绝删除它。这是默认值。 示例 移除 B-树操作符族 float_ops: DROP OPERATOR FAMILY float_ops USING btree; 如果有任何使用该族中操作符类的索引存在,这个命令都不会成功。增加 CASCADE 可以把这类索引与该操作符 族一起删除。 兼容性 SQL 标准中没有 DROP OPERATOR FAMILY 语句。 1112 第 18 章 SQL 语句: DROP MATERIALIZED VIEW 到 DROP SYNONYM 18.5 DROP OWNED 用途 DROP OWNED —移除一个数据库角色拥有的数据库对象 DROP OWNED 删除当前数据库中被指定角色之一拥有的所有对象。任何已被授予给给定角色在当前数据库中对象 上以及在共享对象(数据库、表空间)上的特权也将会被收回。 前置条件 无 语法 DROP OWNED BY { name | CURRENT_USER | SESSION_USER } [, ...] [ CASCADE | RESTRICT ] 语义 name 其对象将被删除并且其特权将被收回的角色的名称。 CASCADE 自动删除依赖于受影响对象的对象,然后删除所有依赖于那些对象的对象。 RESTRICT 如果有任何其他数据库对象依赖于一个受影响的对象,则拒绝删除一个角色所拥有的对象。这是默认 值。 示例 DROP OWNED BY user1; 兼容性 DROP OWNED 命令是一个 KingbaseES 扩展。 其他 DROP OWNED 常常被用来为移除一个或者多个角色做准备。因为 DROP OWNED 只影响当前数据库中的对象,通常 需要在包含将被移除角色所拥有的对象的每一个数据库中都执行这个命令。 使用 CASCADE 选项可能导致这个命令递归去删除由其他用户所拥有的对象。 1113 第 18 章 SQL 语句: DROP MATERIALIZED VIEW 到 DROP SYNONYM REASSIGN OWNED 命令是另一种选择,它可以把一个或多个角色所拥有的所有数据库对象重新授予给其他角 色。但是,REASSIGN OWNED 不处理其他对象的特权。角色所拥有的数据库、表空间将不会被移除。 更多讨论请见 删除角色。 18.6 DROP PACKAGE 用途 删除包。需要注意,在执行该命令删除一个包的时候,会同时删除包规范和包体。无法单独删除一个包规范,若 只想删除一个包体,可通过 DROP PACKAGE BODY 命令,详见DROP PACKAGE BODY 。 用户必须是包的属主或包所在模式的属主或非受限数据库管理员。 前置条件 用户要具有包所在模式下的 USAGE 权限。 语法 DROP PACKAGE [ IF EXISTS ] package_names [ CASCADE | RESTRICT ] 语义 package_names 包的名字,当需要同时删除多个包时,包名之间用, 隔开。可以有数据库名和模式名修饰,但数据库 名只能是当前数据库。 IF EXIST 要删除的包不存在时,不会出现错误信息。 CASCADE 自动删除依赖于该过程的对象,然后接着删除依赖于那些对象的对象(见 依赖跟踪)。 RESTRICT 如果有任何对象依赖于该过程,则拒绝删除它。这是默认选项。 示例 DROP PACKAGE pkg; DROP PACKAGE IF EXISTS test.public.pkg, pkg2; 1114 第 18 章 SQL 语句: DROP MATERIALIZED VIEW 到 DROP SYNONYM 18.7 DROP PACKAGE BODY 用途 删除包体。需要注意,在执行该命令删除一个包体的时候,不会删除包规范。无法单独删除一个包规范,若想删 除包含包规范在内的一整个包,可通过 DROP PACKAGE 命令,详见DROP PACKAGE 。 前置条件 用户必须是包的属主或包所在模式的属主或非受限数据库管理员。 用户要具有包所在模式下的 USAGE 权限。 语法 DROP PACKAGE BODY [ IF EXISTS ] package_names; 语义 package_names 包的名字,当需要同时删除多个包体时,包名之间用, 隔开。可以有数据库名和模式名修饰,但数据 库名只能是当前数据库。 IF EXIST 要删除的包体不存在时,不会出现错误信息。 示例 DROP PACKAGE BODY pkg; DROP PACKAGE BODY IF EXISTS test.public.pkg, pkg2; 18.8 DROP POLICY 用途 DROP POLICY —从一个表移除一条行级安全性策略 DROP POLICY 从该表移除指定的策略。注意如果从一个移除了最后一条策略并且该表的行级安全性仍被 ALTER TABLE 启用,则默认的否定策略将被使用。不管该表的策略存在与否,ALTER TABLE ... DISABLE ROW LEVEL SECURITY 都可以被用来禁用一个表的行级安全性。 前置条件 无 1115 第 18 章 SQL 语句: DROP MATERIALIZED VIEW 到 DROP SYNONYM 语法 DROP POLICY [ IF EXISTS ] name ON table_name [ CASCADE | RESTRICT ] 语义 IF EXISTS 如果该策略不存在也不抛出一个错误。这种情况下会发出一个提示。 name 要删除的策略的名称。 table_name 该策略所在的表的名称(可以被模式限定)。 CASCADE 这些关键词不会产生效果,因为它们不依赖于策略。 RESTRICT 这些关键词不会产生效果,因为它们不依赖于策略。 示例 要在名为 my_table 上删除策略 p1: DROP POLICY p1 ON my_table; 兼容性 DROP POLICY 是一种 KingbaseES 扩展。 18.9 DROP PROCEDURE 用途 DROP PROCEDURE 移除一个现有过程的定义。 前置条件 为了执行这个命令,用户必须是该过程的拥有者。该过程的参数类型必须指定,因为可能存在多个不同的过程具 有相同名称和不同参数列表。 语法 DROP PROCEDURE [ IF EXISTS ] name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ] [, ...] [ CASCADE | RESTRICT ] 1116 第 18 章 SQL 语句: DROP MATERIALIZED VIEW 到 DROP SYNONYM 语义 IF EXISTS 如果该过程不存在也不抛出一个错误。这种情况下会发出一个提示。 name 现有过程的名称(可以是被方案限定的)。如果没有指定参数列表,则该名称在其所属的方案中必须是唯一 的。 argmode 参数的模式:IN 或者 VARIADIC。如果省略,默认为 IN。 argname 参数的名称。注意,其实 DROP PROCEDURE 并不在意参数名称,因为只需要参数的数据类型来确定过程的 身份。 argtype 该过程如果有参数,参数的数据类型(可以是被方案限定的)。 CASCADE 自动删除依赖于该过程的对象,然后接着删除依赖于那些对象的对象(见 依赖跟踪)。 RESTRICT 如果有任何对象依赖于该过程,则拒绝删除它。这是默认选项。 示例 DROP PROCEDURE do_db_maintenance(); 兼容性 这个命令符合 SQL 标准,但是 KingbaseES 做了这些扩展: • 标准仅允许每个命令删除一个过程。 • IF EXISTS 选项 • 指定参数模式和名称的能力 18.10 DROP PUBLICATION 用途 1117 第 18 章 SQL 语句: DROP MATERIALIZED VIEW 到 DROP SYNONYM DROP PUBLICATION —删除一个发布 DROP PUBLICATION 从数据库中删除一个现有的发布。 前置条件 发布只能被它自己的所有者或超级用户删除。 语法 DROP PUBLICATION [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ] 语义 IF EXISTS 如果发布不存在,不要抛出一个错误。在这种情况下发出一个提示。 name 现有发布的名称。 CASCADE 这些关键词没有任何作用,因为发布没有依赖关系。 RESTRICT 这些关键词没有任何作用,因为发布没有依赖关系。 示例 删除一个发布: DROP PUBLICATION mypublication; 兼容性 DROP PUBLICATION 是一个 KingbaseES 扩展。 18.11 DROP ROLE 用途 DROP ROLE 移除指定的角色。 没有必要移除涉及该角色的角色成员关系。DROP ROLE 会自动收回目标角色在其他角色中的成员关系,以及其他 角色在目标角色中的成员关系。其他角色不会被删除也不会被影响。 1118 第 18 章 SQL 语句: DROP MATERIALIZED VIEW 到 DROP SYNONYM 前置条件 如果一个角色仍然被集簇中任何数据库中引用,它就不能被移除。如果尝试移除将会抛出一个错误。在删除该角 色前,你必须删除(或者重新授予所有权)它所拥有的所有对象并且收回该已经授予给该角色的在其他对象上的特 权。REASSIGN OWNED 和DROP OWNED 命令可以用于这个目的。更多讨论请见 删除角色。要删除一个超级用 户角色,你必须自己就是一个超级用户。要删除一个非超级用户角色,你必须具有 CREATEROLE 特权。 语法 DROP ROLE [ IF EXISTS ] name [, ...] 语义 IF EXISTS 如果该角色不存在则不要抛出一个错误,而是发出一个提示。 name 要移除的角色的名称。 示例 要删除一个角色: DROP ROLE jonathan; 兼容性 SQL 标准定义了 DROP ROLE,但是它只允许一次删除一个角色并且它指定了和 KingbaseES 不同的特权需求。 其他 KingbaseES 包括一个程序 dropuser 具有和这个命令完全相同的功能(事实上它会调用这个命令),但是该程序 可以从 shell 运行。 18.12 DROP ROUTINE 用途 DROP ROUTINE —删除一个例程 DROP ROUTINE 删除一个现有例程的定义,它可以是一个聚集函数、一个普通函数或者过程。有关参数的描述、 更多的示例以及进一步的细节请参考DROP AGGREGATE 、DROP FUNCTION 以及DROP PROCEDURE 。 前置条件 1119 第 18 章 SQL 语句: DROP MATERIALIZED VIEW 到 DROP SYNONYM 无 语法 DROP ROUTINE [ IF EXISTS ] name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ] [, ...] [ CASCADE | RESTRICT ] 语义 IF EXISTS 如果该聚集不存在则不要抛出一个错误,而是发出一个提示。 name 一个现有聚集函数的名称(可以是模式限定的)。 argmode 一个参数的模式:IN 或 VARIADIC。如果被忽略,默认值是 IN。 argname 一个参数的名称。注意“DROP AGGREGATE“并不真正关心参数名称,因为决定聚集函数的身份时只需要 参数数据类型。 argtype 该聚集函数所操作的一个输入数据类型。要引用一个零参数的聚集函数,写 “*“来替代参数说明列表。要引 用一个有序集聚集函数,在直接和聚集参数说明之间写上 ORDER BY。 CASCADE 自动删除依赖于该聚集函数的对象(例如使用它的视图),然后删除所有依赖于那些对象的对象。 RESTRICT 如果有任何对象依赖于该聚集函数,则拒绝删除它。这是默认值。 示例 要为类型 integer 移除聚集函数 myavg: DROP AGGREGATE myavg(integer); 要移除假想集聚集函数 myrank,该函数接收一个排序列的任意列表和直接参数的一个匹配的列表: DROP AGGREGATE myrank(VARIADIC "any" ORDER BY VARIADIC "any"); 要在一个命令中删除多个聚合函数: 1120 第 18 章 SQL 语句: DROP MATERIALIZED VIEW 到 DROP SYNONYM DROP AGGREGATE myavg(integer), myavg(bigint); 兼容性 在 SQL 标准中没有 DROP AGGREGATE 语句。 其他 ALTER AGGREGATE 下描述了另一种引用有序集聚集的语法。 18.13 DROP RULE 用途 DROP RULE —移除一个重写规则 DROP RULE 删除一个重写规则。 前置条件 无 语法 DROP RULE [ IF EXISTS ] name ON table_name [ CASCADE | RESTRICT ] 语义 IF EXISTS 如果该规则不存在则不要抛出一个错误,而是发出一个提示。 name 要删除的规则的名称。 table_name 该规则适用的表或视图的名称(可以是模式限定的)。 CASCADE 自动删除依赖于该规则的对象,然后删除所有依赖于那些对象的对象。 RESTRICT 如果有任何对象依赖于该规则,则拒绝删除它。这是默认值。 示例 要删除重写规则 newrule: 1121 第 18 章 SQL 语句: DROP MATERIALIZED VIEW 到 DROP SYNONYM DROP RULE newrule ON mytable; 兼容性 DROP RULE 是一个 KingbaseES 语言扩展,整个查询重写系统也是这样。 18.14 DROP SCHEMA 用途 DROP SCHEMA —移除一个模式 DROP SCHEMA 从数据库中移除模式。 前置条件 一个模式只能由其拥有者或一个超级用户删除。注意即使拥有者不拥有该模式中的某些对象,也能删除该模式 (以及所有含有的对象)。 语法 DROP SCHEMA [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ] 语义 IF EXISTS 如果该模式不存在则不要抛出一个错误,而是发出一个提示。 name 一个模式的名称。 CASCADE 自动删除包含在该模式中的对象(表、函数等),然后删除所有依赖于那些对象的对象。 RESTRICT 如果该模式含有任何对象,则拒绝删除它。这是默认值。 示例 要从数据库中移除模式 mystuff 及其中所包含的对象: DROP SCHEMA mystuff CASCADE; 1122 第 18 章 SQL 语句: DROP MATERIALIZED VIEW 到 DROP SYNONYM 兼容性 DROP SCHEMA 完全符合 SQL 标准,但是该标准只允许在每个命令中删除一个模式并且没有 IF EXISTS 选项。该 选项是一个 KingbaseES 扩展。 其他 使用 CASCADE 选项可能会使这条命令移除除指定模式之外其他模式中的对象。 18.15 DROP SEQUENCE 用途 DROP SEQUENCE 移除序数生成器。 前置条件 一个序列只能被其拥有者或超级用户删除。 语法 DROP SEQUENCE [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ] 语义 IF EXISTS 如果该序列不存在则不要抛出一个错误,而是发出一个提示。 name 一个序列的名称(可以是模式限定的)。 CASCADE 自动删除依赖于该序列的对象,然后删除所有依赖于那些对象的对象。 RESTRICT 如果有任何对象依赖于该序列,则拒绝删除它。这是默认值。 示例 要移除序列 serial: DROP SEQUENCE serial; 1123 第 18 章 SQL 语句: DROP MATERIALIZED VIEW 到 DROP SYNONYM 兼容性 DROP SEQUENCE 符合 SQL 标准,但是该标准只允许每个命令中删除一个序列并且没有 IF EXISTS 选项。该选项 是一个 KingbaseES 扩展。 18.16 DROP SERVER 用途 DROP SERVER —移除一个外部服务器描述符 DROP SERVER 移除一个现有的外部服务器描述符。 前置条件 要执行这个命令,当前用户必须是该服务器的拥有者。 语法 DROP SERVER [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ] 语义 IF EXISTS 如果该服务器不存在则不要抛出一个错误,而是发出一个提示。 name 一个现有服务器的名称。 CASCADE 自动删除依赖于该服务器的对象(例如用户映射),然后删除所有依赖于那些对象的对象。 RESTRICT 如果有任何对象依赖于该服务器,则拒绝删除它。这是默认值。 示例 如果一个服务器 foo 存在则删除它: DROP SERVER IF EXISTS foo; 兼容性 DROP SERVER 符合 ISO/IEC 9075-9(SQL/MED)。IF EXISTS 子句是一个 KingbaseES 扩展。 1124 第 18 章 SQL 语句: DROP MATERIALIZED VIEW 到 DROP SYNONYM 18.17 DROP STATISTICS 用途 DROP STATISTICS —删除扩展统计 DROP STATISTICS 删除数据库中的统计对象。 前置条件 只有统计对象的所有者、模式的所有者或超级用户可以删除统计对象。 语法 DROP STATISTICS [ IF EXISTS ] name [, ...] 语义 IF EXISTS name 要删除的统计对象的名称(可以有模式修饰)。 示例 删除不同模式中的两个统计对象,如果不存在时不会失败: DROP STATISTICS IF EXISTS accounting.users_uid_creation, public.grants_user_role; 兼容性 SQL 标准中没有 DROP STATISTICS 命令。 18.18 DROP SUBSCRIPTION 用途 DROP SUBSCRIPTION —删除一个订阅 DROP SUBSCRIPTION 删除数据库集群中的一个订阅。 如果订阅与复制槽相关联,就不能在事务块内部执行 DROP SUBSCRIPTION。(可以使用 ALTER SUBSCRIPTION 取 消关联复制槽。) 1125 第 18 章 SQL 语句: DROP MATERIALIZED VIEW 到 DROP SYNONYM 前置条件 只有超级用户才可以删除订阅。 语法 DROP SUBSCRIPTION [ IF EXISTS ] name [ CASCADE | RESTRICT ] 语义 name 要删除的订阅的名称。 CASCADE 这个关键词没有任何作用,因为订阅没有依赖关系。 RESTRICT 这个关键词没有任何作用,因为订阅没有依赖关系。 示例 删除一个订阅: DROP SUBSCRIPTION mysub; 兼容性 DROP SUBSCRIPTION 是一个 KingbaseES 扩展。 其他 当删除与远程主机(正常状态)上的复制槽相关联的订阅时,DROP SUBSCRIPTION``将连接到远程主机,并尝试 删除该复制槽,作为其操作的一部分。这是必要的,以便释放远程主机上为订阅分配的资源。如果失败,因为远程主 机不可访问,或者因为远程复制槽不能被删除,或者复制槽不存在或从不存在,则\ ``DROP SUBSCRIPTION 命令将 失败。要在这种情况下继续,请执行“ALTER SUBSCRIPTION ... SET (slot_name = NONE)“来解除复制槽与订 阅的关联。之后,“DROP SUBSCRIPTION“将不再尝试对远程主机执行任何操作。请注意,如果远程复制槽仍然存 在,则应手动删除该插槽;否则将继续保留 WAL,最终可能导致磁盘空间不足。 如果订阅与复制槽相关联,那么不能在事务块内部执行 DROP SUBSCRIPTION。 18.19 DROP SYNONYM 用途 DROP SYNONYM 删除一个现有的同义词。 1126 第 18 章 SQL 语句: DROP MATERIALIZED VIEW 到 DROP SYNONYM 前置条件 要执行这个命令必须拥有该同义词的权限。 语法 DROP [ PUBLIC ] SYNONYM [ IF EXISTS ] syn_name [, ...] [ FORCE ] 语义 IF EXISTS 当该同义词不存在时不发出错误信息,而是发出一个提示。 syn_name 要移除的同义词的名称(可以是模式限定的)。 FORCE 没有实际意义。 示例 例 1:删除名为 syntab 的私有同义词: DROP SYNONYM syntab; 例 2:删除名为 syntb 的公有同义词: DROP PUBLIC SYNONYM syntb; 1127 第 19 章 SQL 语句: DROP TABLE 到 LOAD 第 19章 SQL 语句: DROP TABLE 到 LOAD 本章包含以下 SQL 语句: • DROP TABLE • DROP TABLESPACE • DROP TRANSFORM • DROP TEXT SEARCH CONFIGURATION • DROP TEXT SEARCH DICTIONARY • DROP TEXT SEARCH PARSER • DROP TEXT SEARCH TEMPLATE • DROP TRIGGER • DROP TYPE • DROP TYPE BODY • DROP USER • DROP USER MAPPING • DROP VIEW • END • EXECUTE • EXPLAIN PLAN • FETCH • FLASHBACK TABLE • GRANT • INSERT • INSERT ALL FIRST 1128 第 19 章 SQL 语句: DROP TABLE 到 LOAD • INSERT(MySQL 模式) • INSERT ON DUPLICATE(MySQL 模式) • LISTEN • LOCK • LOAD 19.1 DROP TABLE 用途 DROP TABLE 从数据库移除表。要清空一个表中的行但是不销毁该表,可以使用DELETE 或者TRUNCATE 。 DROP TABLE 总是移除目标表的任何索引、规则、触发器和约束。但是,要删除一个被视图或者另一个表的外键 约束所引用的表,必须指定 CASCADE 或 CASCADE CONSTRAINTS。(CASCADE 将会把依赖的视图也完全移除,但是对 于外键它将只移除外键约束,而完全不会移除其他表。CASCADE CONSTRAINTS 不移除依赖的视图,仅改变视图状态 为无效,但是对于外键它将只移除外键约束,而完全不会移除其他表。)。 DROP TABLE 若是开启了 GUC 参数:kdb_flashback.db_recyclebin=on 且未指定 PURGE 选项,则删除的表及 其关联的索引、规则、触发器、约束等将被放到 SYS_RECYCLEBIN 系统表中。在需要时可以将回收站中的表闪回 到删除之前的状态。 前置条件 只有表拥有者、模式拥有者和超级用户能删除一个表。 语法 DROP TABLE [ IF EXISTS ] name [, ...] [ CASCADE | CASCADE CONSTRAINTS | RESTRICT ] [ PURGE ] 语义 IF EXISTS 如果该表不存在则不要抛出一个错误,而是发出一个提示。 name 要删除的表的名称(可以是模式限定的)。 CASCADE 自动删除依赖于该表的对象(例如视图),然后删除所有依赖于那些对象的对象。 1129 第 19 章 SQL 语句: DROP TABLE 到 LOAD CASCADE CONSTRAINTS 与 CASCADE 的唯一区别是,指定 CASCADE CONSTRAINTS 时,不移除依赖的视图,仅 改变视图状态为无效。 RESTRICT 如果有任何对象依赖于该表,则拒绝删除它。这是默认值。 PURGE 删除的表将不能被闪回,即使开启了回收站参数。 示例 要销毁两个表 films 和 distributors: DROP TABLE films, distributors; 兼容性 这个命令符合 SQL 标准,但是该标准只允许每个命令删除一个表并且没有 “IF EXISTS“选项。该选项是一个 KingbaseES 扩展。 19.2 DROP TABLESPACE 用途 DROP TABLESPACE 从系统中移除一个表空间。 前置条件 一个表空间只能被其拥有者或超级用户删除。在一个表空间能被删除前,其中必须没有任何数据库对象。即使当 前数据库中没有对象正在使用该表空间,也可能有其他数据库的对象存在于其中。还有,如果该表空间被列在任何活 动会话的 temp_tablespaces 设置中,DROP 也可能会失败,因为可能有临时文件存在其中。 语法 DROP TABLESPACE [ IF EXISTS ] name 语义 IF EXISTS 如果该表空间不存在则不要抛出一个错误,而是发出一个提示。 name 一个表空间的名称。 示例 要从系统移除表空间 mystuff: 1130 第 19 章 SQL 语句: DROP TABLE 到 LOAD DROP TABLESPACE mystuff; 兼容性 DROP TABLESPACE 是一个 KingbaseES 扩展。 其他 DROP TABLESPACE 不能在一个事务块内执行。 19.3 DROP TRANSFORM 用途 DROP TRANSFORM —移除转换 DROP TRANSFORM 移除一个之前定义的转换。 前置条件 为了删除一种转换,你必须拥有该类型和语言。这些同样也是创建转换所需要的特权。 语法 DROP TRANSFORM [ IF EXISTS ] FOR type_name LANGUAGE lang_name [ CASCADE | RESTRICT ] 语义 IF EXISTS 如果该转换不存在也不要抛出一个错误。这种情况下会发出一个提示。 type_name 该转换的数据类型的名称。 lang_name 该转换的语言的名称。 CASCADE 自动删除依赖于该转换的对象,然后删除所有依赖于那些对象的对象。 RESTRICT 如果有任何对象依赖于该转换,则拒绝删除它。这是默认行为。 示例 要删除用于类型 hstore 和语言 plpythonu 的转换: DROP TRANSFORM FOR hstore LANGUAGE plpythonu; 1131 第 19 章 SQL 语句: DROP TABLE 到 LOAD 兼容性 这种形式的 DROP TRANSFORM 是一种 KingbaseES 扩展。详见CREATE TRANSFORM 。 19.4 DROP TEXT SEARCH CONFIGURATION 用途 DROP TEXT SEARCH CONFIGURATION —移除一个文本搜索配置 前置条件 要执行这个命令,你必须是该配置的拥有者 语法 DROP TEXT SEARCH CONFIGURATION [ IF EXISTS ] name [ CASCADE | RESTRICT ] 语义 IF EXISTS 如果该文本搜索配置不存在则不要抛出一个错误,而是发出一个提示。 name 一个现有文本搜索配置的名称(可以是模式限定的)。 CASCADE 自动删除依赖于该文本搜索配置的对象,然后删除所有依赖于那些对象的对象。 RESTRICT 如果有任何对象依赖于该文本搜索配置,则拒绝删除它。这是默认值。 示例 移除文本搜索配置 my_english: DROP TEXT SEARCH CONFIGURATION my_english; 如果有任何在 to_tsvector 调用中引用该配置的索引存在,这个命令都不会成功。增加 CASCADE 可以把这类索 引与该文本搜索配置一起删除。 兼容性 SQL 标准中没有 DROP TEXT SEARCH CONFIGURATION 语句。 1132 第 19 章 SQL 语句: DROP TABLE 到 LOAD 19.5 DROP TEXT SEARCH DICTIONARY 用途 DROP TEXT SEARCH DICTIONARY —移除一个文本搜索字典 前置条件 要执行这个命令,你必须是该字典的拥有者。 语法 DROP TEXT SEARCH DICTIONARY [ IF EXISTS ] name [ CASCADE | RESTRICT ] 语义 IF EXISTS 如果该文本搜索字典不存在则不要抛出一个错误,而是发出一个提示。 name 一个现有文本搜索字典的名称(可以是模式限定的)。 CASCADE 自动删除依赖于该文本搜索字典的对象,然后删除所有依赖于那些对象的对象。 RESTRICT 如果有任何对象依赖于该文本搜索字典,则拒绝删除它。这是默认值。 示例 移除文本搜索字典 english: DROP TEXT SEARCH DICTIONARY english; 如果有任何使用该字典的文本搜索配置存在,这个命令都不会成功。增加 CASCADE 可以把这类配置与字典一起 删除。 兼容性 SQL 标准中没有 DROP TEXT SEARCH DICTIONARY 语句。 19.6 DROP TEXT SEARCH PARSER 用途 DROP TEXT SEARCH PARSER —移除一个文本搜索解析器 1133 第 19 章 SQL 语句: DROP TABLE 到 LOAD 前置条件 你必须作为一个超级用户来使用这个命令。 语法 DROP TEXT SEARCH PARSER [ IF EXISTS ] name [ CASCADE | RESTRICT ] 语义 IF EXISTS 如果该文本搜索解析器不存在则不要抛出一个错误,而是发出一个提示。 name 一个现有文本搜索解析器的名称(可以是模式限定的)。 CASCADE 自动删除依赖于该文本搜索解析器的对象,然后删除所有依赖于那些对象的对象。 RESTRICT 如果有任何对象依赖于该文本搜索解析器,则拒绝删除它。这是默认值。 示例 移除文本搜索解析器 my_parser: DROP TEXT SEARCH PARSER my_parser; 如果有任何使用该解析器的文本搜索配置存在,这个命令都不会成功。增加 CASCADE 可以把这类配置与解析器 一起删除。 兼容性 SQL 标准中没有 DROP TEXT SEARCH PARSER 语句。 19.7 DROP TEXT SEARCH TEMPLATE 用途 DROP TEXT SEARCH TEMPLATE —移除一个文本搜索模板 前置条件 你必须作为一个超级用户来使用这个命令。 语法 1134 第 19 章 SQL 语句: DROP TABLE 到 LOAD DROP TEXT SEARCH TEMPLATE [ IF EXISTS ] name [ CASCADE | RESTRICT ] 语义 IF EXISTS 如果该文本搜索模板不存在则不要抛出一个错误,而是发出一个提示。 name 一个现有文本搜索模板的名称(可以是模式限定的)。 CASCADE 自动删除依赖于该文本搜索模板的对象,然后删除所有依赖于那些对象的对象。 RESTRICT 如果有任何对象依赖于该文本搜索模板,则拒绝删除它。这是默认值。 示例 移除文本搜索模板 thesaurus: DROP TEXT SEARCH TEMPLATE thesaurus; 如果有任何使用该模板的文本搜索字典存在,这个命令都不会成功。增加 CASCADE 可以把这类字典与模板一起 删除。 兼容性 SQL 标准中没有 DROP TEXT SEARCH TEMPLATE 语句。 19.8 DROP TRIGGER 用途 DROP TRIGGER 移除一个现有的触发器定义。 前置条件 要执行这个命令,当前用户必须是触发器基表的拥有者。 语法 DROP TRIGGER [ IF EXISTS ] name ON table_name [ CASCADE | RESTRICT ] DROP TRIGGER name 1135 第 19 章 SQL 语句: DROP TABLE 到 LOAD 语义 IF EXISTS 如果该触发器不存在则不要抛出一个错误,而是发出一个提示。 name 要移除的触发器的名称。 table_name 定义了该触发器的表的名称(可以是模式限定的)。 CASCADE 自动删除依赖于该触发器的对象,然后删除所有依赖于那些对象的对象。 RESTRICT 如果有任何对象依赖于该触发器,则拒绝删除它。这是默认值。 示例 销毁表 films 上的触发器 if_dist_exists: DROP TRIGGER if_dist_exists ON films; 销毁表 films 上的触发器 if_dist_exists,且 if_dist_exists 名唯一: DROP TRIGGER if_dist_exists; 兼容性 在 SQL 标准中,不同表上也不能有同名的触发器,但 KingbaseES 存在同名触发器。因此当触发器名不唯一时, 使用 DROP TRIGGER name 命令 KingbaseES 会报错。 19.9 DROP TYPE 用途 DROP TYPE 移除一种用户定义的数据类型。 前置条件 只有一个类型的拥有者才能移除它。 语法 1136 第 19 章 SQL 语句: DROP TABLE 到 LOAD DROP TYPE [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT | FORCE | VALIDATE ] 语义 IF EXISTS 如果该类型不存在则不要抛出一个错误,而是发出一个提示。 name 要移除的数据类型的名称(可以是模式限定的)。 CASCADE 自动删除依赖于该类型的对象(例如表列、函数、操作符),然后删除所有依赖于那些对象的对象。 RESTRICT 如果有任何对象依赖于该类型,则拒绝删除它。这是默认值。 FORCE 同 CASCADE 。 VALIDATE 同 RESTRICT。 示例 要移除数据类型 box: DROP TYPE box; 兼容性 这个命令类似于 SQL 标准中的对应命令,但 IF EXISTS 子句是一个 KingbaseES 扩展。但要注意 KingbaseES 中 CREATE TYPE 命令的很大部分以及数据类型扩展机制都与 SQL 标准不同。 19.10 DROP TYPE BODY 用途 DROP TYPE BODY 移除一个对象类型的所有内部函数(存储过程)的定义。 前置条件 1137 第 19 章 SQL 语句: DROP TABLE 到 LOAD 只有对象类型的拥有者才能移除它。。 语法 DROP TYPE BODY [ IF EXISTS ] name [, ...] 语义 IF EXISTS 如果该类型体不存在则不要抛出一个错误,而是发出一个提示。 name 要移除的对象类型体的名称(可以是模式限定的)。 示例 要移除对象类型体 objtype: DROP TYPE BODY objtype; 19.11 DROP USER 用途 DROP USER —移除一个数据库用户 前置条件 请参考DROP ROLE。 语法 DROP USER [ IF EXISTS ] name [, ...] 语义 1138 第 19 章 SQL 语句: DROP TABLE 到 LOAD 请参考DROP ROLE 。 示例 删除用户 testuser DROP USER testuser; 19.12 DROP USER MAPPING 用途 DROP USER MAPPING —移除一个用于外部服务器的用户映射 DROP USER MAPPING 从外部服务器移除一个已有的用户映射。 一个外部服务器的拥有者可以为该服务器的任何用户删除用户映射。如果该服务器上的 USAGE 特权被授予了一 个用户,它也能删除用于它们自己的用户名的用户映射。 前置条件 无 语法 语义 IF EXISTS 如果该用户映射不存在则不要抛出一个错误,而是发出一个提示。 user_name 该映射的用户名。CURRENT_USER``和\ ``USER 匹配当前用户的名称。“PUBLIC“被用来匹配系统中所有 现存和未来的用户名。 server_name 用户映射的服务器名。 示例 删除一个用户映射 bob(服务器 foo),如果它存在: DROP USER MAPPING IF EXISTS FOR bob SERVER foo; 兼容性 DROP USER MAPPING 符合 ISO/IEC 9075-9 (SQL/MED)。IF EXISTS 子句是一个 KingbaseES 扩展。 1139 第 19 章 SQL 语句: DROP TABLE 到 LOAD 19.13 DROP VIEW 用途 DROP VIEW 删除一个现有的视图。 前置条件 要执行这个命令你必须是该视图的拥有者。 语法 DROP VIEW [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ] 语义 IF EXISTS 如果该视图不存在则不要抛出一个错误,而是发出一个提示。 name 要移除的视图的名称(可以是模式限定的)。 CASCADE 自动删除依赖于该视图的对象(例如其他视图),然后删除所有依赖于那些对象的对象。 RESTRICT 如果有任何对象依赖于该视图,则拒绝删除它。这是默认值。 示例 这个命令将移除名为 kinds 的视图: DROP VIEW kinds; 兼容性 这个命令符合 SQL 标准,但是该标准只允许在每个命令中删除一个视图并且没有 IF EXISTS 选项。该选项是一 个 KingbaseES 扩展。 19.14 END 用途 1140 第 19 章 SQL 语句: DROP TABLE 到 LOAD END —提交当前事务 END 提交当前事务。所有该事务做的更改便得对他人可见并且被保证发生崩溃时仍然是持久的。这个命令是一种 KingbaseES 扩展,它等效于COMMIT 。 前置条件 无 语法 END [ WORK | TRANSACTION ] [ AND [ NO ] CHAIN ] 语义 WORK TRANSACTION 可选关键词,它们没有效果。 AND CHAIN 如果指定了 AND CHAIN,则立即启动具有与刚刚完成的事务相同的事务特征的新事务 (参见SET TRANSACTION )。否则,不会启动任何新事务。 示例 要提交当前事务并且让所有更改持久化: END; 兼容性 END 是一种 KingbaseES 扩展,它提供和COMMIT 等效的功能,后者在 SQL 标准中指定。 其他 使用ROLLBACK 可以中止一个事务。 当不在一个事务中时发出 END 没有危害,但是会产生一个警告消息。 19.15 EXECUTE 用途 EXECUTE —执行一个预备语句 1141 第 19 章 SQL 语句: DROP TABLE 到 LOAD EXECUTE 被用来执行一个之前准备好的语句。 如果创建预备语句的 PREPARE 语句指定了一些参数,必须向 EXECUTE 语句传递一组兼容的参数,否则会发生错 误。注意(与函数不同)预备语句无法基于其参数的类型或者数量重载。在一个数据库会话中,预备语句的名称必须 唯一。 更多创建和使用预备语句的信息请见PREPARE 。 前置条件 由于预备语句只在会话期间存在,该预备语句必须在当前会话中由一个更早执行的 PREPARE 语句所创建。 语法 EXECUTE name [ ( parameter [, ...] ) ] 语义 name 要执行的预备语句的名称。 parameter 给预备语句的参数的实际值。这必须是一个能得到与该参数数据类型(在预备语句创建时决定)兼容的 值的表达式。 示例 为一个 INSERT 语句创建一个预备语句,然后执行它: PREPARE fooplan (int, text, bool, numeric) AS INSERT INTO foo VALUES($1, $2, $3, $4); EXECUTE fooplan(1, 'Hunter Valley', 't', 200.00); 为一个 SELECT 语句创建一个预备语句,然后执行它: PREPARE usrrptplan (int) AS SELECT * FROM users u, logs l WHERE u.usrid=$1 AND u.usrid=l.usrid AND l.date = $2; EXECUTE usrrptplan(1, current_date); 在本例中,没有指定第二个参数的数据类型,因此,它是从使用 $2 的上下文中推断出来的。 兼容性 SQL 标准包括了一个 EXECUTE 语句,但是只被用于嵌入式 SQL。这个版本的 EXECUTE 语句也用了一种有点不 同的语法。 1142 第 19 章 SQL 语句: DROP TABLE 到 LOAD 其他 EXECUTE 返回的命令标签是预备语句的命令标签而不是 “EXECUTE“。 19.16 EXPLAIN PLAN 用途 这个命令显示 KingbaseES 计划器为提供的语句所生成的执行计划。该执行计划会显示将怎样扫描语句中引用的 表—普通的顺序扫描、索引扫描等等—以及在引用多个表时使用何种连接算法来把来自每个输入表的行连接在一起。 显示中最重要的部分是估计出的语句执行代价,它是计划器对于该语句要运行多久的猜测(以任意的代价单位度 量,但是习惯上表示取磁盘页面的次数)。事实上会显示两个数字:在第一行能被返回前的启动代价,以及返回所有 行的总代价。对于大部分查询来说总代价是最重要的,但是在一些情景中(如 EXISTS 中的子查询),计划器将选择 更小的启动代价来代替最小的总代价(因为因为执行器将在得到一行后停止)。此外,如果你用一个 LIMIT 子句限 制返回行的数量,计划器会在终端代价之间做出适当的插值来估计到底哪个计划是真正代价最低的。 ANALYZE 选项导致该语句被实际执行,而不仅仅是被计划。那么实际的运行时间统计会被显示出来,包括在每个 计划结点上花费的总时间(以毫秒计)以及它实际返回的行数。这对观察计划器的估计是否与实际相近很有用。 注意: 记住当使用了 ANALYZE 选项时语句会被实际执行。尽管 EXPLAIN 将丢弃 SELECT 所返回的任何输出,照例该 语句的其他副作用还是会发生。如果你希望在 INSERT、UPDATE、DELETE、CREATE TABLE AS 或者 EXECUTE 上使用 EXPLAIN ANALYZE 而不希望它们影响你的数据,可以使用下面的方法: BEGIN; EXPLAIN ANALYZE ...; ROLLBACK; 只有 ANALYZE 和 VERBOSE 选项能被指定,并且必须按照上述的顺序,不要把选项列表放在圆括号内。在 KingbaseES V8R2 之前,只支持没有圆括号的语法。我们期望所有新的选项将只在圆括号语法中支持。 前置条件 无 语法 EXPLAIN [ ( option [, ...] ) ] statement EXPLAIN [ ANALYZE ] [ VERBOSE ] statement 这里 option 可以是: ANALYZE [ boolean ] VERBOSE [ boolean ] COSTS [ boolean ] 1143 第 19 章 SQL 语句: DROP TABLE 到 LOAD SETTINGS [ boolean ] BUFFERS [ boolean ] TIMING [ boolean ] SUMMARY [ boolean ] FORMAT { TEXT | XML | JSON | YAML } 语义 ANALYZE 执行命令并且显示实际的运行时间和其他统计信息。这个参数默认被设置为 FALSE。 VERBOSE 显示关于计划的额外信息。特别是:计划树中每个结点的输出列列表、模式限定的表和函数名、总是把表达 式中的变量标上它们的范围表别名,以及总是打印统计信息被显示的每个触发器的名称。这个参数默认被设置 为 FALSE。 COSTS 包括每一个计划结点的估计启动和总代价,以及估计的行数和每行的宽度。这个参数默认被设置为 TRUE。 SETTINGS 包括关于配置参数的信息。具体来说,包括与内置默认值不同的值影响查询规划的选项。该参数默认为 FALSE。 BUFFERS 包括缓冲区使用的信息。特别是:共享块命中、读取、标记为脏和写入的次数、本地块命中、读取、标记为 脏和写入的次数、以及临时块读取和写入的次数。一次命中表示避免了一次读取,因为需要的块已经在缓存中 找到了。共享块包含着来自于常规表和索引的数据,本地块包含着来自于临时表和索引的数据,而临时块包含 着在排序、哈希、物化计划结点和类似情况中使用的短期工作数据。脏块的数量表示被这个查询改变的之前未 被修改块的数量,而写入块的数量表示这个后台在查询处理期间从缓存中替换出去的脏块的数量。为一个较高 层结点显示的块数包括它的所有子结点所用到的块数。在文本格式中,只会打印非零值。只有当 ANALYZE 也被 启用时,这个参数才能使用。它的默认被设置为 FALSE。 TIMING 在输出中包括实际启动时间以及在每个结点中花掉的时间。反复读取系统时钟的负荷在某些系统上会显著地 拖慢查询,因此在只需要实际的行计数而不是实际时间时,把这个参数设置为 FALSE 可能会有用。即便用这个 选项关闭结点层的计时,整个语句的运行时间也总是会被度量。只有当 ANALYZE 也被启用时,这个参数才能使 用。它的默认被设置为 TRUE。 SUMMARY 在查询计划之后包含摘要信息(例如,总计的时间信息)。当使用 ANALYZE 时默认包含摘要信息,但默认 情况下不包含摘要信息,但可以使用此选项启用摘要信息。使用 EXPLAIN EXECUTE 中的计划时间包括从缓存中 获取计划所需的时间以及重新计划所需的时间(如有必要)。 FORMAT 指定输出格式,可以是 TEXT、XML、JSON 或者 YAML。非文本输出包含和文本输出格式相同的信息,但 是更容易被程序解析。这个参数默认被设置为 TEXT。 boolean 指定被选中的选项是否应该被打开或关闭。可以写 TRUE、ON 或 1 来启用选项,写 FALSE、OFF 或 0 禁用 它。“boolean“值也能被忽略,在这种情况下会假定值为 TRUE。 statement 你想查看其执行计划的任何 SELECT、INSERT、UPDATE、DELETE、VALUES、EXECUTE、DECLARE、CREATE TABLE AS 或者 CREATE MATERIALIZED VIEW AS 语句。 示例 有一个具有单个 integer 列和 10000 行的表,要显示在其上的一个简单查询的计划: 1144 第 19 章 SQL 语句: DROP TABLE 到 LOAD EXPLAIN SELECT * FROM foo; QUERY PLAN --------------------------------------------------------Seq Scan on foo (cost=0.00..155.00 rows=10000 width=4) (1 row) 这里有同样一个查询的 JSON 输出格式: EXPLAIN (FORMAT JSON) SELECT * FROM foo; QUERY PLAN -------------------------------[ + { + "Plan": { + "Node Type": "Seq Scan",+ "Relation Name": "foo", + "Alias": "foo", + "Startup Cost": 0.00, + "Total Cost": 155.00, + "Plan Rows": 10000, + "Plan Width": 4 + } + } + ] (1 row) 如果有一个索引,并且我们使用了一个带有可索引 WHERE 条件的查询,EXPLAIN 可能会显示一个不同的计划: EXPLAIN SELECT * FROM foo WHERE i = 4; QUERY PLAN -------------------------------------------------------------Index Scan using fi on foo (cost=0.00..5.98 rows=1 width=4) Index Cond: (i = 4) (2 rows) 这里是同一查询的 YAML 格式: EXPLAIN (FORMAT YAML) SELECT * FROM foo WHERE i='4'; QUERY PLAN ------------------------------- Plan: Node Type: "Index Scan" + + Scan Direction: "Forward"+ Index Name: "fi" + 1145 第 19 章 SQL 语句: DROP TABLE 到 LOAD Relation Name: "foo" + Alias: "foo" + Startup Cost: 0.00 + Total Cost: 5.98 + Plan Rows: 1 + Plan Width: 4 + Index Cond: "(i = 4)" (1 row) XML 格式我们留给读者做练习。 这里是去掉了代价估计的同样一个计划: EXPLAIN (COSTS FALSE) SELECT * FROM foo WHERE i = 4; QUERY PLAN ---------------------------Index Scan using fi on foo Index Cond: (i = 4) (2 rows) 这里是一个使用聚集函数的查询的查询计划例子: EXPLAIN SELECT sum(i) FROM foo WHERE i < 10; QUERY PLAN --------------------------------------------------------------------Aggregate -> (cost=23.93..23.93 rows=1 width=4) Index Scan using fi on foo (cost=0.00..23.92 rows=6 width=4) Index Cond: (i < 10) (3 rows) 这里是一个使用 EXPLAIN EXECUTE 显示预备查询的执行计划的例子: PREPARE query(int, int) AS SELECT sum(bar) FROM test WHERE id > $1 AND id < $2 GROUP BY foo; EXPLAIN ANALYZE EXECUTE query(100, 200); QUERY PLAN -------------------------------------------------------------------------HashAggregate (cost=9.54..9.54 rows=1 width=8) (actual time=0.156..0.161 rows=11 loops=1) Group Key: foo -> Index Scan using test_pkey on test (cost=0.29..9.29 rows=50 width=8) ( actual time=0.039..0.091 rows=99 loops=1) 1146 第 19 章 SQL 语句: DROP TABLE 到 LOAD Index Cond: ((id > $1) AND (id < $2)) Planning time: 0.197 ms Execution time: 0.225 ms (6 rows) 当然,这里显示的有关数字取决于表涉及到的实际内容。还要注意这些数字甚至选中的查询策略,可能在 KingbaseES 的不同版本之间变化,因为计划器可能被改进。此外,ANALYZE 命令使用随机采样来估计数据统计。因此, 在一次新的 ANALYZE 运行之后,代价估计可能会改变,即便是表中数据的实际分布没有改变也是如此。 其他 1. 命令输出 这个命令的结果是为 “statement“选中的计划的文本描述,可能还标注了执行统计信息。 2. 注意 为了允许 KingbaseES 查询计划器在优化查询时能做出合理的知情决策,查询中用到的所有表的 sys_statistic 数 据应该能保持为最新。通常这个工作会由 autovacuum daemon 负责自动完成。但是如果一个表最近在内容上有大量 的改变,我们可能需要做一次手动的ANALYZE 而不是等待 autovacuum 捕捉这些改变。 为了执行计划中每个结点的运行时间开销,当前的 “EXPLAIN ANALYZE“实现为查询执行增加了 profiling overhead 。这样,在一个查询上运行 EXPLAIN ANALYZE 有时候比正常执行该查询要慢很多。开销的量取决于该查询的性 质,以及使用的平台。最坏的情况会发生在那些自身执行时间很短的结点上,以及在那些具有相对较慢的有关时间的 操作系统调用的机器上。 19.17 FETCH 用途 FETCH —使用游标从查询中检索行 FETCH 从之前创建的一个游标中检索行。 游标具有一个相关联的位置,FETCH 会用到该位置。游标位置可能会位于查询结果的第一行之前、结果中任意行 之上或者结果的最后一行之后。在被创建时,游标被定位在第一行之前。在取出一些行后,该游标被定位在最近被取 出的行上。如果 “FETCH“运行超过了可用行的末尾,则该游标会被定位在最后一行之后(如果向后取,则是第一行 之前)。FETCH ALL 或者 FETCH BACKWARD ALL 将总是让游标被定位于最后一行之后或者第一行之前。 NEXT、PRIOR、FIRST、LAST、ABSOLUTE、RELATIVE 形式会在适当移动游标后取出一行。如果没有这样一行,将 返回一个空结果,并且视情况将游标定位在第一行之前或者最后一行之后。 使用 FORWARD 和 BACKWARD 的形式会在向前移动或者向后移动的方向上检索指定数量的行,然后将游标定位在 最后返回的行上(如果 “count“超过可用的行数,则定位在所有行之后或者之前)。 RELATIVE 0、FORWARD 0 以及 “BACKWARD 0“都会请求检索当前行但不移动游标,也就是重新取最近被取出 的行。只要游标没有被定位在第一行之前或者最后一行之后,这种操作都会成功,否则不会返回任何行。 1147 第 19 章 SQL 语句: DROP TABLE 到 LOAD 注意: 这个页面描述在 SQL 命令层面上对游标的使用。如果想要在 PL/SQL 函数中使用游标,规则会有所不同。 如果成功完成,FETCH 命令返回一个下面形式的命令标签: FETCH count “count“是取得的行数(可能为零)。注意在 ksql 中,命令标签将不会实际显示,因为 ksql 会显示被取得的行。 前置条件 无 语法 FETCH [ direction [ FROM | IN ] ] cursor_name 其中 direction 可以为空或者以下之一: NEXT PRIOR FIRST LAST ABSOLUTE count RELATIVE count count ALL FORWARD FORWARD count FORWARD ALL BACKWARD BACKWARD count BACKWARD ALL 1148 第 19 章 SQL 语句: DROP TABLE 到 LOAD 语义 direction “direction“ 定义获取方向以及要取得的行数。它可以是下列之一: NEXT 取出下一行。如果省略 “direction“,这将是默认值。 PRIOR 取出当前位置之前的一行。 FIRST 取出该查询的第一行(和 ABSOLUTE 1 相同)。 LAST 取出该查询的最后一行(和 ABSOLUTE -1 相同)。 ABSOLUTE count 取出该查询的第 “count“个行,如果 “count“为负则是从尾部开始取出第 abs(count) 个行。 如果 “count“超出范围,将定位在第一行之前或者最后一行之后。特别地,ABSOLUTE 0 会定位在第一行之 前。 1149 第 19 章 SQL 语句: DROP TABLE 到 LOAD RELATIVE count 取出第 “count“个后继行,如果 “count“为负则是取出前面的第 abs(count) 个行。RELATIVE 0 重新取出当前行(如果有)。 count 取出接下来的 “count“行(和 FORWARD count 相同)。 ALL 取出所有剩余的行(和 FORWARD ALL 相同)。 FORWARD 取出下一行(和 NEXT 相同)。 FORWARD count 取出接下来的 “count“行。FORWARD 0 重新取出当前行。 FORWARD ALL 取出所有剩下的行。 BACKWARD 取出当前行前面的一行(和 PRIOR 相同)。 BACKWARD count 取出前面的 “count“行(反向扫描)。 BACKWARD 0 会重新取出当前行。 BACKWARD ALL 取出所有当前位置之前的行(反向扫描)。 count “count“是一个可能带有符号的整数常量,它决定要取得的位置或者行数。对于 FORWARD 和 BACKWARD 情况, 指定一个负的 “count“等效于改变 FORWARD 和 BACKWARD 的意义。 cursor_name 一个已打开游标的名称。 示例 下面的例子用一个游标遍历一个表: BEGIN WORK; -- 建立一个游标: DECLARE liahona SCROLL CURSOR FOR SELECT * FROM films; -- 在游标 liahona 中取出前 5 行: FETCH FORWARD 5 FROM liahona; code | title | did | date_prod | kind | len -------+-------------------------+-----+------------+----------+------BL101 | The Third Man | 101 | 1949-12-23 | Drama | 01:44 BL102 | The African Queen | 101 | 1951-08-11 | Romantic | 01:43 JL201 | Une Femme est une Femme | 102 | 1961-03-12 | Romantic | 01:25 P_301 | Vertigo | 103 | 1958-11-14 | Action | 02:08 P_302 | Becket | 103 | 1964-02-03 | Drama | 02:28 -- 取出前面一行: FETCH PRIOR FROM liahona; code | title | did | date_prod | kind | len -------+---------+-----+------------+--------+------P_301 | Vertigo | 103 | 1958-11-14 | Action | 02:08 1150 第 19 章 SQL 语句: DROP TABLE 到 LOAD -- 关闭游标并且结束事务: CLOSE liahona; COMMIT WORK; 兼容性 SQL 标准只定义 FETCH 在嵌入式 SQL 中使用。这里描述的 FETCH 变体返回数据时就好像数据是一个 SELECT 结果,而不是被放在主变量中。除这一点之外,FETCH 完全向上兼容于 SQL 标准。 涉及 FORWARD 和 BACKWARD 的 “FETCH“形式,以及形式 FETCH count 和 FETCH ALL(其中 FORWARD 是隐式 的)都是 KingbaseES 扩展。 SQL 标准只允许 FROM 在游标名之前。使用 “IN“的选项或者完全省去它们是一种扩展。 其他 如果想要使用 FETCH 的任意变体而不使用带有正计数的 “FETCH NEXT“或者 FETCH FORWARD,应该用 SCROLL 声明游标。对于简单查询,KingbaseES 将允许从不带 “SCROLL“游标中反向取得行,但最好不要依赖这种 行为。如果游标被声明为带有 SCROLL,则不允许反向取得。 用 ABSOLUTE 取行并不比用相对移动快多少:不管则样,底层实现都必须遍历所有的中间行。用负绝对值获取 的情况更糟:必须读到查询尾部来找到最后一行,并且接着从那里反向开始遍历。但是,回卷到查询的开始(正如 FETCH ABSOLUTE 0)是很快的。 DECLARE 被用来定义游标。使用MOVE 可改变游标位置而不检索数据。 19.18 FLASHBACK TABLE 用途 FLASHBACK —闪回一个回收站中的表或者将该表闪回至一个历史的快照时刻 前置条件 回收站功能默认关闭,只有开启了参数才能将表放置到回收站中,参数名称:kdb_flashback.db_recyclebin,参 数为 bool 类型,参数级别为 pgc_sighup。开启了回收站参数后,如果不允许一个删除的表进回收站,需要在 DROP 语句后面加上 PUGREX 选项。FLASHBACK 支持将一个已经删除到回收站中的表及相关对象闪回到删除之前状态。 如果在当前 SCHEMA 下已经存在同名的表,则闪回失败,需要使用 RENAME TO 选项指定一个新的表名。成功闪 回一个表后,回收站视图 recyclebin 和回收站系统表 sys_recyclebin 中对象将被清除。 闪回表至历史时刻,基于闪回查询将被操作表的数据还原到指定的快照时刻,该操作基于 AS OF 闪回查询和当 前快照数据的差异进行还原。闪回表至历史时刻可以通过时间戳 (timestamp)、csn 两种方式进行指定。闪回表的过 程中默认关闭触发器行为,如果期望开启的话请通过 ENABLE TRIGGERS 语句进行。 更多信息请见《kes-vs-oracle 》中的闪回技术。 语法 1151 第 19 章 SQL 语句: DROP TABLE 到 LOAD FLASHBACK TABLE table_name TO { [ BEFREO DROP [ RENAME TO newname ] ] | [ { TIMESTAMP | CSN | SCN } asof_item [ { ENABLE | DISABLE } TRIGGERS ] ]} 语义 table_name 指定需要闪回的表名,如果不存在则报错。 newname 如果需要闪回的表在当前 SCHEMA 已经存在一个同名的表,则闪回该表时报错,需要通过 RENAME TO 选项指定新的表名。 asof_item 闪回表到指定的历史时刻,可以通过指定时间戳 (timestamp)、csn 两种方式进行。asof_item 即通过时 间戳 (timestamp) 或者 csn 进行闪回历史时刻时,指定的一个历史快照时刻的表达式。 示例 一个 FLASHBACK 命令: FLASHBACK TABLE table_name TO BEFORE DROP; 这个命令将在回收站中的 table_name 闪回到删除之前的状态: FLASHBACK TABLE table_name TO BEFORE DROP RENAME TO newname; 将回收站中的表闪回到一个新的表名: 提示: 要将删除的表放到回收站需要开启参数 kdb_flashback.db_recyclebin=on。 兼容性 FLASHBACK 这个命令是一个 KingbaseES 扩展。 其他 单独删除的一个子表、临时表、分区都不支持闪回,删除的表和相关对象不再允许操作。 1152 第 19 章 SQL 语句: DROP TABLE 到 LOAD 19.19 GRANT 用途 GRANT —定义访问特权 GRANT 命令由两种基本的变体:一种授予在一个数据库对象(表、列、视图、外部表、序列、数据库、外部数据 包装器、外部服务器、函数、过程、包、过程语言、模式或表空间)上的特权,另一个授予一个角色中的成员关系。 这些变体在很多方面都相似,但是也有很多不同,所以还是得分别描述它们。 1. 在数据库对象上 GRANT 这种 GRANT 命令的变体将一个数据库对象上的指定特权交给一个或多个角色。如果有一些已经被授予,这些特 权会被加入到它们之中。 关键词 PUBLIC 指示特权要被授予给所有角色,包括那些可能稍后会被创建的角色。PUBLIC 可以被认为是一个 被隐式定义的总是包含所有角色的组。任何特定角色都将具有直接授予给它的特权、授予给它作为成员所在的任何角 色的特权以及被授予给 PUBLIC 的特权。 如果指定了 WITH GRANT OPTION,特权的接收者可以接着把它授予给其他人。如果没有授权选项,接收者就不 能这样做。授权选项不能被授予给 PUBLIC。 没有必要把权限授予给一个对象的拥有者(通常就是创建该对象的用户),因为拥有者默认具有所有的特权(但 是拥有者可能为了安全选择撤回一些它们自己的特权)。 删除一个对象或者以任何方式修改其定义的权力是不被当作一个可授予特权的,它被固化在拥有者中,并且不能 被授予和撤回(但是,相似地效果可以通过授予或者撤回在拥有该对象的角色中的成员关系来实现,见下文)。拥有 者也隐式地拥有该对象的所有授权选项。 函数语法适用于普通函数、聚合函数和窗口函数,但不适用于过程;这里使用过程。或者,使用 ROUTINE 来引 用函数、聚合函数、窗口函数或过程,而不考虑其精确类型。 有一个选项可以在一个或多个模式中对所有相同类型的对象授予特权。目前仅对表、序列、函数和过程支持此功 能。ALL TABLES 也会影响视图和外部表,就像特定对象 GRANT 命令一样。ALL FUNCTIONS 也影响聚合和窗口函数, 但不影响过程,这与特定对象的 GRANT 命令一样。使用 ALL ROUTINES,包括过程。 2. 角色上的 GRANT GRANT 命令的这种变体把一个角色中的成员关系授予一个或者多个其他角色。一个角色中的成员关系是有意义 的,因为它会把授予给一个角色的特权带给该角色的每一个成员。 如果指定了 WITH ADMIN OPTION,成员接着可以把该角色中的成员关系授予给其他用户,也可以撤回该角 色中的成员关系。如果没有管理选项,普通用户就不能做这些工作。一个角色不被认为持有自身的 WITH ADMIN OPTION,但是它可以从一个会话用户匹配该角色的数据库会话中授予或撤回自身中的成员关系。数据库超级用户能 够授予或撤回任何角色中任何人的成员关系。和特权的情况不同,一个角色中的成员关系不能被授予 PUBLIC。还要 注意这种形式的命令不允许噪声词 GROUP。 前置条件 1. 在数据库对象上 GRANT 授权者需 WITH GRANT OPTION 授权选项,如果没有授权选项,无法完成授权。 1153 第 19 章 SQL 语句: DROP TABLE 到 LOAD 2. 角色上的 GRANT 授权者需 WITH ADMIN OPTION 管理选项。具有 CREATE ROLE 特权的角色能够授予或者撤回任何非超级用户角色 中的成员关系。 语法 GRANT { { SELECT | INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES | TRIGGER } [, ...] | ALL [ PRIVILEGES ] } ON { [ TABLE ] table_name [, ...] | ALL TABLES IN SCHEMA schema_name [, ...] } TO role_specification [, ...] [ WITH GRANT OPTION ] GRANT { { SELECT | INSERT | UPDATE | REFERENCES } ( column_name [, ...] ) [, ...] | ALL [ PRIVILEGES ] ( column_name [, ...] ) } ON [ TABLE ] table_name [, ...] TO role_specification [, ...] [ WITH GRANT OPTION ] 1154 第 19 章 SQL 语句: DROP TABLE 到 LOAD GRANT { { USAGE | SELECT | UPDATE } [, ...] | ALL [ PRIVILEGES ] } ON { SEQUENCE sequence_name [, ...] | ALL SEQUENCES IN SCHEMA schema_name [, ...] } TO role_specification [, ...] [ WITH GRANT OPTION ] 1155 第 19 章 SQL 语句: DROP TABLE 到 LOAD GRANT { { CREATE | CONNECT | TEMPORARY | TEMP } [, ...] | ALL [ PRIVILEGES ] } ON DATABASE database_name [, ...] TO role_specification [, ...] [ WITH GRANT OPTION ] 1156 第 19 章 SQL 语句: DROP TABLE 到 LOAD GRANT { USAGE | ALL [ PRIVILEGES ] } ON DOMAIN domain_name [, ...] TO role_specification [, ...] [ WITH GRANT OPTION ] GRANT { USAGE | ALL [ PRIVILEGES ] } ON FOREIGN DATA WRAPPER fdw_name [, ...] TO role_specification [, ...] [ WITH GRANT OPTION ] GRANT { USAGE | ALL [ PRIVILEGES ] } ON FOREIGN SERVER server_name [, ...] TO role_specification [, ...] [ WITH GRANT OPTION ] 1157 第 19 章 SQL 语句: DROP TABLE 到 LOAD GRANT { EXECUTE | ALL [ PRIVILEGES ] } ON { { FUNCTION | PROCEDURE | ROUTINE | PACKAGE } routine_name [ ( [ [ argmode ] [arg_name ] arg_type [, ...] ] ) ] [, ...] | ALL { FUNCTIONS | PROCEDURES | ROUTINES } IN SCHEMA schema_name [, ...] } TO role_specification [, ...] [ WITH GRANT OPTION ] 1158 第 19 章 SQL 语句: DROP TABLE 到 LOAD GRANT { USAGE | ALL [ PRIVILEGES ] } ON LANGUAGE lang_name [, ...] TO role_specification [, ...] [ WITH GRANT OPTION ] GRANT { { SELECT | UPDATE } [, ...] | ALL [ PRIVILEGES ] } ON LARGE OBJECT loid [, ...] TO role_specification [, ...] [ WITH GRANT OPTION ] 1159 第 19 章 SQL 语句: DROP TABLE 到 LOAD GRANT { { CREATE | USAGE } [, ...] | ALL [ PRIVILEGES ] } ON SCHEMA schema_name [, ...] TO role_specification [, ...] [ WITH GRANT OPTION ] GRANT { CREATE | ALL [ PRIVILEGES ] } ON TABLESPACE tablespace_name [, ...] TO role_specification [, ...] [ WITH GRANT OPTION ] 1160 第 19 章 SQL 语句: DROP TABLE 到 LOAD GRANT { USAGE | ALL [ PRIVILEGES ] } ON TYPE type_name [, ...] TO role_specification [, ...] [ WITH GRANT OPTION ] 其中 role_specification 可以是: [ GROUP ] role_name | PUBLIC | CURRENT_USER | SESSION_USER GRANT role_name [, ...] TO role_name [, ...] [ WITH ADMIN OPTION ] 语义 1161 第 19 章 SQL 语句: DROP TABLE 到 LOAD 可能的特权是: SELECT INSERT UPDATE DELETE TRUNCATE REFERENCES TRIGGER CREATE CONNECT TEMPORARY EXECUTE USAGE 权限中定义的特权的特定类型。 TEMP 替代拼写 TEMPORARY。 ALL PRIVILEGES 授予对象类型的所有可用特权。在 KingbaseES 中,PRIVILEGES 关键词是可选的,但是在严格的 SQL 中是要求它的。 示例 把表 films 上的插入特权授予给所有用户: GRANT INSERT ON films TO PUBLIC; 把视图 kinds 上的所有可用特权授予给用户 manuel: GRANT ALL PRIVILEGES ON kinds TO manuel; 注意虽然上述语句被一个超级用户或者 kinds 的拥有者执行时确实会授予所有特权,但是当由其他人执行时将 只会授予那些执行者拥有授权选项的权限。 把角色 admins 中的成员关系授予给用户 joe: GRANT admins TO joe; 兼容性 根据 SQL 标准,ALL PRIVILEGES 中的 PRIVILEGES 关键词是必须的。SQL 标准不支持在每个命令中设置超过 一个对象上的特权。 KingbaseES 允许一个对象拥有者撤回它们拥有的普通特权:例如,一个表拥有者可以通过撤回其自身拥有的 INSERT、UPDATE、DELETE 和 TRUNCATE 特权让该表对它们自己只读。根据 SQL 标准这是不可能发生的。原因在于 KingbaseES 认为拥有者的特权是由拥有者授予给它们自己的,因此它们也能够撤回它们。在 SQL 标准中,拥有者的 特权是有一个假设的实体“_SYSTEM”所授予。由于不是“_SYSTEM”,拥有者就不能撤回这些权力。 根据 SQL 标准,授权选项可以被授予给 PUBLIC,KingbaseES 只支持把授权选项授予给角色。 SQL 标准提供了其他对象类型上的 USAGE 特权:字符集、排序规则、翻译。 在 SQL 标准中,序列只有一个 USAGE 特权,它控制 NEXT VALUE FOR 表达式的使用,该表达式等效于 KingbaseES 中的函数 nextval。序列的特权 SELECT 和 UPDATE 是 KingbaseES 扩展。应用序列的 USAGE 特权到 currval 函数也是一个 KingbaseES 扩展(该函数本身也是)。 数据库、表空间、模式和语言上的特权都是 KingbaseES 扩展。 其他 REVOKE 命令被用来撤回访问特权。 1162 第 19 章 SQL 语句: DROP TABLE 到 LOAD 从 KingbaseES V7 开始,用户和组的概念已经被统一到一种单一类型的实体(被称为一个角色)。因此不再需 要使用关键词 GROUP 来标识一个被授权者是一个用户或者一个组。在该命令中仍然允许 GROUP,但是它只是一个噪 音词而已。 如果一个用户持有特定列或者其所在的整个表的特权,该用户可以在该列上执行 SELECT、INSERT 等命令。在表 层面上授予特权然后对一列撤回该特权将不会按照你希望的运作:表级别的授权不会受到列级别操作的影响。 当一个对象的非拥有者尝试 GRANT 该对象上的特权,如果该用户在该对象上什么特权都不拥有,该命令将立刻 失败。只要有一些特权可用,该命令将继续,但是它将只授予那些用户具有授权选项的特权。如果不持有授权选项, GRANT ALL PRIVILEGES 形式将发出一个警告消息。而如果不持有命令中特别提到的任何特权的授权选项,其他形式 将会发出一个警告(原则上这些语句也适用于对象拥有者,但是由于拥有者总是被视为持有所有授权选项,因此这种 情况不会发生)。 需要注意的是,数据库超级用户可以访问所有对象而不管对象特权的设置。这可与 Unix 系统中的 root 权力相 提并论。对于 root 来说,除非绝对必要,使用一个超级用户来操作是不明智的。 如果一个超级用户选择发出一个 GRANT 或者 REVOKE 命令,该命令将被执行,好像它是由被影响对象的拥有者 发出的一样。特别地,通过这样一个命令授予的特权将好像是由对象拥有者授予的一样(对于角色成员关系,该成员 关系好像是由该角色本身授予的一样)。 GRANT 以及 REVOKE 也可以由一个不是受影响对象拥有者的角色完成,但是该角色是拥有该对象的角色的一个成 员,或者是在该对象上持有特权的 WITH GRANT OPTION 的角色的一个成员。在这种情况下,特权将被记录为由实际 拥有该对象的角色授予或者是由持有特权的 WITH GRANT OPTION 的角色授予。例如,如果表 t1 被角色 g1 拥有, u1 是它的一个成员,那么 u1 可以把 t1 上的特权授予给 u2,但是那些特权将好像是直接由 g1 授予的。角色 g1 的任何其他成员可以稍后撤回它们。 如果执行 GRANT 的角色间接地通过多于一条角色成员关系路径持有所需的特权,将不会指定哪一个包含它的角 色将被记录为完成了该授权。在这样的情况中,最好使用 SET ROLE 来成为你想用其做 GRANT 的特定角色。 授予一个表上的权限不会自动地扩展权限给该表使用的任何序列,包括绑定在 SERIAL 列上的序列。序列上的权 限必须被独立设置。 参考 权限获得更多关于特定特权类型的信息,以及如何检查对象的特权。 19.20 INSERT 用途 INSERT 将新行插入到一个表中。我们可以插入一个或者更多由值表达式指定的行,或者插入来自一个查询的零 行或者更多行。 目标列的名称可以以任意顺序列出。如果没有给出列名列表,则有两种确定目标列的可能性。第一种是以被声明 的顺序列出该表的所有列。另一种可能性是,如果 VALUES 子句或者 “query“只提供 “N“个列,则以被声明的顺序列 出该表的前 “N“列。VALUES 子句或者 “query“提供的值会被从左至右关联到这些显式或者隐式给出的目标列。 每一个没有出现在显式或者隐式列列表中的列都将被默认填充,如果为该列声明过默认值则用默认值填充,否则 用空值填充。 1163 第 19 章 SQL 语句: DROP TABLE 到 LOAD 如果任意列的表达式不是正确的数据类型,将会尝试自动类型转换。 ON CONFLICT 可以用来指定发生唯一约束或者排除约束违背错误时的替换动作(见下文的 CONFLICT 子句)。 可选的 RETURNING 子句让 INSERT 根据实际被插入(如果使用了 ON CONFLICT DO UPDATE 子句,可能是被更 新)的每一行来计算和返回值。这主要用来获取由默认值提供的值,例如一个序列号。但是,允许在其中包括使用该 表列的任何表达式。RETURNING 列表的语法与 SELECT 的输出列表的相同。只有被成功地插入或者更新的行才将被返 回。例如,如果一行被锁定但由于不满足 ON CONFLICT DO UPDATE ... WHERE clause “condition“没有被更新,该行 将不被返回。 前置条件 为了向表中插入,你必须具有其上的 INSERT 特权。如果存在 ON CONFLICT DO UPDATE 子句,还要求该表上的 UPDATE 特权。 如 果 一 个 列 列 表 被 指 定, 你 只 需 要 其 中 的 列 上 的 INSERT``特 权。 类 似 地, 在 指 定 了\ ``ON CONFLICT DO UPDATE 时,你只需要被列出要更新的列上的 UPDATE 特权。但是,ON CONFLICT DO UPDATE 还要求其值被 ON CONFLICT DO UPDATE 表达式或者 “condition“使用的列上的 SELECT 特权。 使用 RETURNING 子句需要 RETURNING 中提到的所有列的 SELECT 权限。如果使用 “query“子句从查询中插入行, 则当然需要对查询中使用的任何表或列具有 SELECT 权限。 语法 [ WITH [ RECURSIVE ] with_query [, ...] ] INSERT INTO table_name [part_extension_clause] [ [ AS ] alias ] | sub_query [alias] [ ( column_name [, ...] ) ] [ OVERRIDING { SYSTEM | USER} VALUE ] { DEFAULT VALUES | VALUES ( { expression | DEFAULT } [, ...] ) [, ...] | query | VALUES record | SET { column_name = { expression | DEFAULT } | ( column_name [, ...] ) = [ ROW ] ( { expression | DEFAULT } [, ...] ) | ( column_name [, ...] ) = ( sub-SELECT ) } [, ...] } [ ON CONFLICT [ conflict_target ] conflict_action ] [ RETURNING * | output_expression [ [ AS ] output_name ] [, ...] ] 1164 第 19 章 SQL 语句: DROP TABLE 到 LOAD 其中 conflict_target 可以是以下之一: ( { index_column_name | ( index_expression ) } [ COLLATE collation ] [ opclass ] [, ...] ) [ WHERE index_predicate ] ON CONSTRAINT constraint_name 1165 第 19 章 SQL 语句: DROP TABLE 到 LOAD 并且 conflict_action 是以下之一: DO NOTHING DO UPDATE SET { column_name = { expression | DEFAULT } | ( column_name [, ...] ) = [ ROW ] ( { expression | DEFAULT } [, ...] ) | ( column_name [, ...] ) = ( sub-SELECT ) } [, ...] [ WHERE condition ] 1166 第 19 章 SQL 语句: DROP TABLE 到 LOAD Part_extension_clause: { PARTITION (patition) | PARTITION FOR (partition_key_value [, partition_key_value]…) | SUBPARTITION (subpartition) | SUBPARTITION FOR (subpartition_key_value [, subpartition_key_value]…) } 1167 第 19 章 SQL 语句: DROP TABLE 到 LOAD 语义 1. 插入 with_query WITH 子句允许指定一个或者更多子查询,在 INSERT 查询中可以用名称引用这些子查询。详见 WITH 查 询以及SELECT 。 “query“ (SELECT 语句)也可以包含一个 WITH 子句。在这种情况下 “query“中可以引用两组 “with_query“, 但是第二个优先级更高(因为它被嵌套更近)。 table_name 一个已有表的名称(可以被模式限定)。 part_extension_clause 支持通过 partitionsubpartition 关键字指定分区名或者子分区名,实现对分区和子分区直接 进行 insert 操作。其中 PARTITION FOR(partition_key_value) 指定分区键值,PARTITION (partition)指 定分区名,这里的分区名是指 oralce 语法创建分区表时指定的分区名,而不是分区对象在系统表 sys_class 中 存储的对象名。 alias “table_name“ 的替补名称。当提供了一个别名时,它会完全隐藏掉表的实际名称。当 ON CONFLICT DO UPDATE 的目标是一个被排除的表时这特别有用,因为那将被当作表示要被插入行的特殊表的名 称。 sub_query • 插入的 values 列与子查询投影列要对应; • 子查询是多表时,插入的基表必须是 key-preserved table; • 子查询投影列中不能有非基表列; • 子查询中不能包含以下内容: 聚集函数(avg,count,max,min,sum 等); 分析函数;Distinct 语 句;Union/Intersect/Except/Minus 等集合查询。 column_name 名为 “table_name“的表中的一个列的名称,可以用表名 (可以被模式名限定) 做限定。如有必要,列名 还可以用一个子域名 (子域名需要和表名、模式名一同用小括号包围起来进行限定) 或者数组下标限定(指向一 个组合列的某些列中插入会让其他域为空)。 OVERRIDING SYSTEM VALUE 如果没有这个子句,为定义为 GENERATED ALWAYS 的标识列指定一个明确的值(不是 DEFAULT)就是一种错误。这个子句推翻了这种限制。 OVERRIDING USER VALUE 如果指定这个子句,则会忽略提供给定义为 GENERATED BY DEFAULT 的标识列的值,并且 应用默认的由序列生成的值。 例如,当在表之间拷贝值时,这个子句有能派上用场。INSERT INTO tbl2 OVERRIDING USER VALUE SELECT * FROM tbl1 将从 tbl1 中拷贝所有在 tbl2 中不是标识列的列,而 tbl2 中标识列的值将由与 tbl2 关联的序列 产生。 DEFAULT VALUES 所有列都将被其默认值填充(例如这种形式下不允许 OVERRIDING 子句)。 expression 要赋予给相应列的表达式或者值。 DEFAULT 相应的列将被其默认值填充。 1168 第 19 章 SQL 语句: DROP TABLE 到 LOAD query 提供要被插入行的查询(SELECT 语句)。其语法描述请参考SELECT 语句。 output_expression 在每一行被插入或更新后由 INSERT 命令计算并且返回的表达式。该表达式可以使用 “table_name“ 指定的表中的任何列。写成 * 可返回被插入或更新行的所有列。 output_name 要用于被返回列的名称。 record record 变量名,变量类型是自定义 RECORD 或%ROWTYPE。INSERT 语句插入行数据为 record 变量值。 对于行数据的每列,record 的成员必须与表对应列类型兼容。如果表列有 NOT NULL 约束,对应的 record 成 员不能有 NULL 值。record 成员个数必须都前面 table 列数相同,且类型兼容。否则报错。 SET 子句 KingbaseES 兼容 MySQL 的 Insert Into Set 语法,可以像使用 Update 中的 Set 子句一样,分别为每列设 置要插入的值。 2. ON CONFLICT 子句 可选的 ON CONFLICT 子句为出现唯一性违背或排除约束违背错误时提供另一种可供选择的动作。对于每一个要 插入的行,不管是插入进行下去还是由 “conflict_target“ 指定的一个仲裁者约束或者索引被违背,都会采取可供选择 的 “conflict_action“。ON CONFLICT DO NOTHING 简单地把避免插入行。ON CONFLICT DO UPDATE 则会更新与要插入 的行冲突的已有行。 “conflict_target“可以执行唯一索引推断。在执行推断时,它由一个或者多个 “index_column_name“ 列或者 “index_expression“ 表达式以及一个可选的 “index_predicate“构成。所有刚好包含 “conflict_target“指定的列/表达式 的 “table_name“唯一索引(不管顺序)都会被推断为(选择为)仲裁者索引。如果指定了 “index_predicate“,它必 须满足仲裁者索引(也是推断过程的一个进一步的要求)。注意这意味着如果有一个满足其他条件的非部分唯一索引 (没有谓词的唯一索引)可用,它将被推断为仲裁者(并且会被 ON CONFLICT 使用)。如果推断尝试不成功,则会 发生一个错误。 ON CONFLICT DO UPDATE 保证一个原子的 INSERT 或者 UPDATE 结果。在没有无关错误的前提下,这两种结果之 一可以得到保证,即使在很高的并发度也能保证。这也可以被称作 UPSERT —“UPDATE 或 INSERT”。 conflict_target 通过选择仲裁者索引来指定哪些行与 ON CONFLICT 在其上采取可替代动作的行相冲突。要么 执行唯一索引推断,要么显式命名一个约束。对于 ON CONFLICT DO NOTHING 来说,它对于指定一个 “conflict_target“是可选的。在被省略时,与所有有效约束(以及唯一索引)的冲突都会被处理。对于 ON CONFLICT DO UPDATE,必须提供一个 “conflict_target“。 conflict_action “conflict_action“指定一个可替换的 ON CONFLICT 动作。它可以是 DO NOTHING,也可以是一个 指定在冲突情况下要被执行的 UPDATE 动作细节的 DO UPDATE 子句。ON CONFLICT DO UPDATE 中的 SET 和 WHERE 子句能够使用该表的名称(或者别名)访问现有的行,并且可以用特殊的被排除表访问要插入的行。这 个动作要求被排除列所在目标表的任何列上的 SELECT 特权。 注意所有行级 BEFORE INSERT 触发器的效果都会反映在被排除值中,因为那些效果可能会让该行避免被插入。 index_column_name 一个 “table_name“列的名称。它被用来推断仲裁者索引。它遵循 CREATE INDEX 格式。这要求 “index_column_name“ 上的 SELECT 特权。 index_expression 和 “index_column_name“类似,但是被用来推断出现在索引定义中的 “table_name“列(非简单 列)上的表达式。遵循 CREATE INDEX 格式。这要求任何出现在 “index_expression“中的列上的 SELECT 特权。 collation 指定时,强制相应的 “index_column_name“或 “index_expression“ 使用一种特定的排序规则以便在推断 期间能被匹配上。通常会被省略,因为排序规则通常不会影响约束违背的发生。遵循 CREATE INDEX 格式。 1169 第 19 章 SQL 语句: DROP TABLE 到 LOAD opclass 指定时,强制相应的 “index_column_name“或 “index_expression“ 使用特定的操作符类以便在推断期间能 被匹配上。通常会被省略,因为相等语义在一种类型的操作符类之间都是等价的,或者因为足以信任已定义的 唯一索引具有适当的相等定义。遵循 CREATE INDEX 格式。 index_predicate 用于允许推断部分唯一索引。任何满足该谓词(不一定需要真的是部分索引)的索引都能被推 断。遵循 CREATE INDEX 格式。这要求任何出现在 “index_predicate“中的列上的 SELECT 特权。 constraint_name 用名称显式地指定一个仲裁者约束,而不是推断一个约束或者索引。 condition 一个能返回 boolean 值的表达式。只有让这个表达式返回 true 的行才将被更新,但是在采用 ON CONFLICT DO UPDATE 动作时所有的行都会被锁定。注意 “condition“会被最后计算,即一个冲突被标识为要更 新的候选对象之后。 注意不支持把排除约束作为 ON CONFLICT DO UPDATE 的仲裁者。在所有的情况中,只支持 NOT DEFERRABLE 约 束和唯一索引作为仲裁者。 带有 ON CONFLICT DO UPDATE 子句的 INSERT 是一种“确定性的”语句。这表明不允许该命令影响任何单个现 有行超过一次,如果发生则会发生一个基数违背错误。要插入的行不应该在仲裁者索引或约束所限制的属性上相重 复。 注意,当前不支持用分区表上的 INSERT 的 ON CONFLICT DO UPDATE 子句更新冲突行的分区键,因为那样会让 行移动到新的分区中。 提示: 使用唯一索引推断通常比使用 ON CONFLICT ON CONSTRAINT “constraint_name“直接提名一个约束更好。当 底层索引被以重叠方式替换成另一个或多或少等效的索引时,推断将能继续正确地工作,例如在删除要被替换的索引 之前使用 CREATE UNIQUE INDEX ... CONCURRENTLY。 对于 VALUES record 语句,有下面限制条件: a. INSERT .. VALUES record 只能在 PLSQL 中使用。 b. Record 变量只允许出现在: 1)NSERT 语句的 VALUES 子句中。 2)RETURNING 子句的 INTO 子句中。 c. Record 变量不允许在 SELECT 列表、WHERE 子句、GROUP BY 子句或 ORDER BY 子句。 d. 如果 INSERT 语句 VALUES 子句包含一个 record 变量,不允许出现其他变量或值。 e. 如果 RETURNING INTO 子句包含一个 record 变量,不允许出现其他变量或值。 f. record 成员个数必须都前面 table 列数相同,且类型兼容。否则报错。 g. 不支持: 1)嵌套的 record 类型。 2)返回 record 类型的函数。 3)EXECUTE IMMEDIATE 的 INSERT, UPDATE 语句的 record 1170 第 19 章 SQL 语句: DROP TABLE 到 LOAD 示例 向 films 中插入一行: INSERT INTO films VALUES ('UA502', 'Bananas', 105, '1971-07-13', 'Comedy', '82 minutes'); 在这个例子中,len 列被省略并且因此会具有默认值: INSERT INTO films (code, title, did, date_prod, kind) VALUES ('T_601', 'Yojimbo', 106, '1961-06-16', 'Drama'); 这个例子为日期列使用 DEFAULT 子句而不是指定一个值: INSERT INTO films VALUES ('UA502', 'Bananas', 105, DEFAULT, 'Comedy', '82 minutes'); INSERT INTO films (code, title, did, date_prod, kind) VALUES ('T_601', 'Yojimbo', 106, DEFAULT, 'Drama'); 插入一个完全由默认值构成的行: INSERT INTO films DEFAULT VALUES; 用多行 VALUES 语法插入多个行: INSERT INTO films (code, title, did, date_prod, kind) VALUES ('B6717', 'Tampopo', 110, '1985-02-10', 'Comedy'), ('HG120', 'The Dinner Game', 140, DEFAULT, 'Comedy'); 这个例子从表 tmp_films 中获得一些行插入到表 “films“中,两个表具有相同的列布局: INSERT INTO films SELECT * FROM tmp_films WHERE date_prod < '2004-05-07'; 这个例子插入数组列: -- 为 noughts-and-crosses 游戏创建一个空的 3x3 棋盘 INSERT INTO tictactoe (game, board[1:3][1:3]) VALUES (1, '{{" "," "," "},{" "," "," "},{" "," "," "}}'); -- 实际上可以不用上面例子中的下标 INSERT INTO tictactoe (game, board) VALUES (2, '{{X," "," "},{" ",O," "},{" ",X," "}}'); 向表 distributors 中插入一行,返回由 “DEFAULT“子句生成的序号: INSERT INTO distributors (did, dname) VALUES (DEFAULT, 'XYZ Widgets') RETURNING did; 1171 第 19 章 SQL 语句: DROP TABLE 到 LOAD 增加为 Acme Corporation 管理账户的销售人员的销量,并且把整个被更新的行以及当前时间记录到一个日志表 中: WITH upd AS ( UPDATE employees SET sales_count = sales_count + 1 WHERE id = (SELECT sales_person FROM accounts WHERE name = 'Acme Corporation') RETURNING * ) INSERT INTO employees_log SELECT *, current_timestamp FROM upd; 酌情插入或者更新新的 distributor。假设已经定义了一个唯一索引来约束出现在 did 列中的值。注意,特殊的 “excluded“表被用来引用原来要插入的值: INSERT INTO distributors (did, dname) VALUES (5, 'Gizmo Transglobal'), (6, 'Associated Computing, Inc') ON CONFLICT (did) DO UPDATE SET dname = EXCLUDED.dname; 插入一个 distributor,或者在一个被排除的行(具有一个匹配约束的列或者会让行级前(或者后)插入触发器引 发的列的行)存在时不处理要插入的行。例子假设已经定义了一个唯一触发器来约束出现在 did 列中的值: INSERT INTO distributors (did, dname) VALUES (7, 'Redline GmbH') ON CONFLICT (did) DO NOTHING; 酌情插入或者更新新的 distributor。例子假设已经定义了一个唯一触发器来约束出现在 did 列中的值。WHERE 子 句被用来限制实际被更新的行(但是,任何没有被更新的已有行仍将被锁定): -- 根据一个特定的 ZIP 编码更新 distributors INSERT INTO distributors AS d (did, dname) VALUES (8, 'Anvil Distribution') ON CONFLICT (did) DO UPDATE SET dname = EXCLUDED.dname || ' (formerly ' || d.dname || ')' WHERE d.zipcode <> '21201'; -- 直接在语句中命名一个约束(使用相关的索引来判断是否做 -- DO NOTHING 动作) INSERT INTO distributors (did, dname) VALUES (9, 'Antwerp Design') ON CONFLICT ON CONSTRAINT distributors_pkey DO NOTHING; 如果可能就插入新的 distributor, 否 则 DO NOTHING。 例 子 假 设 已 经 定 义 了 一 个 唯 一 索 引, 它 约 束 让 is_active``布尔列为\ ``true 的行子集上 did 列中的值: -- 这个语句可能推断出一个在 "did" 上带有谓词 "WHERE is_active" -- 的部分唯一索引,但是它可能也只是使用了 "did" 上的一个常规唯一约束 INSERT INTO distributors (did, dname) VALUES (10, 'Conrad International') ON CONFLICT (did) WHERE is_active DO NOTHING; 插入表数据为 record 变量值: 1172 第 19 章 SQL 语句: DROP TABLE 到 LOAD CREATE TABLE t1(id INT, name VARCHAR(20)); DECLARE TYPE myrecord IS RECORD(id INT, name VARCHAR(20)); r1 myrecord; BEGIN r1.id := 1; r1.name := 'new'; INSERT INTO t1 VALUES r1; END; / 兼容性 INSERT 符合 SQL 标准,但是 RETURNING 子句是一种 KingbaseES 扩展,在 INSERT 中使用 WITH 也是,用 ON CONFLICT 指定一个替代动作也是扩展。还有,标准不允许省略列名列表但不通过 VALUES 子句或者 “query“填充所有 列的情况。 SQL 标准指定只有存在一个总是会生成值的标识列时才能指定 OVERRIDING SYSTEM VALUE。而 KingbaseES 在 任何情况下都允许这个子句,并且在不适用时会忽略它。 “query“子句可能的限制在SELECT 有介绍。 其他 1. 输出 成功完成时,INSERT 命令会返回以下形式的命令标签: INSERT oid count “count“是被插入或更新的行数。“oid“通常是 0(使用 OID 声明目标表,如果 “count“为 1;否则,使用 WITH OIDS 和 0 声明目标表,但是不再支持使用 oid 创建表。否则为 0,那么它通常是分配给插入行的 OID,但是不再支 持使用 WITH OIDS 创建表)。 如果 INSERT 命令包含 RETURNING 子句,其结果会类似于包含 RETURNING 列表中定义的列和值的 “SELECT“语 句,这些结果是由该命令在被插入或更新行上计算得到。 2. 说明 如果指定的表是一个分区表,每一行都会被路由到合适的分区并且插入其中。如果指定的表是一个分区,如果输 入行之一违背该分区的约束则将发生错误。 19.21 INSERT ALL FIRST 用途 INSERT ALL | FIRST —在一个多个满足条件的表中创建新行 1173 第 19 章 SQL 语句: DROP TABLE 到 LOAD INSERT ALL 将新行插入到满足条件的多个表中。我们可以插入一个或者更多由值表达式指定的行,或者插入来 自一个查询的零行或者更多行。 INSERT FIRST 将新行插入到第一个满足条件的表中。我们可以插入一个或者更多由值表达式指定的行,或者插 入来自一个查询的零行或者更多行。 目标列的名称可以以任意顺序列出。如果没有给出列名列表,则有两种确定目标列的可能性。第一种是以被声明 的顺序列出该表的所有列。另一种可能性是,如果 VALUES 子句或者 “query“只提供 “N“个列,则以被声明的顺序列 出该表的前 *“N“* 列。VALUES 子句或者 *“query“* 提供的值会被从左至右关联到这些显式或者隐式给出的目标列。 每一个没有出现在显式或者隐式列列表中的列都将被默认填充,如果为该列声明过默认值则用默认值填充,否则 用空值填充。 如果任意列的表达式不是正确的数据类型,将会尝试自动类型转换。 前置条件 为了向表中插入,你必须具有其上的 INSERT 特权。 如果一个列列表被指定,你只需要其中的列上的“INSERT“特权。 语法 INSERT ALL 可以使用条件表达式,或者不适用条件表达式,INSERT FIRST 必须和 WHEN 条件表达式结合 使用。 其中无条件表达式语法如下: INSERT ALL into_clause [into_clause].. subquery; into_clause ::= INTO [schema.]{table_name|view_name} [t_alias][(column_name [,column_name]..)] [values_clause] INSERT ALL | FIRST 使用条件表达式语法如下: 1174 第 19 章 SQL 语句: DROP TABLE 到 LOAD INSERT {ALL|FIRST} condition_clause [condition_clause].. condition_else_clause subquery; into_clause ::= INTO [schema.]{table_name|view_name} [t_alias][(column_name [,column_name]..)] [values_clause] condition_clause ::= WHEN condition_expr THEN into_clause [into_clause].. condition_else_clause ::= [ELSE into_clause [into_clause]..] values_clause ::= VALUES ({expre|default}[,{expre|default}]..) 1175 第 19 章 SQL 语句: DROP TABLE 到 LOAD 语义 只插入新行时可以使用的参数。 table_name 一个已有表的名称(可以被模式限定)。 condition_expr 一个条件表达式,可以大于、小于、等于、true、false 等。 column_name 名为 “table_name“的表中的一个列的名称,可以用表名 (可以被模式名限定) 做限定。如有必要,列名 还可以用一个子域名 (子域名需要和表名、模式名一同用小括号包围起来进行限定) 或者数组下标限定(指向一 个组合列的某些列中插入会让其他域为空)。 DEFAULT VALUES 所有列都将被其默认值填充。 expression 要赋予给相应列的表达式或者值。 DEFAULT 相应的列将被其默认值填充。 query 提供要被插入行的查询(SELECT 语句)。其语法描述请参考SELECT 语句。 成功完成时,INSERT 命令会返回以下形式的命令标签: INSERT oid count “count“是被插入的行数。 “oid“通常是 0(使用 OID 声明目标表,如果 “count“为 1;否则,使用 WITH OIDS 和 0 声明目标表,但是不再 支持使用 oid 创建表否则为 0,那么它通常是分配给插入行的 OID,但是不再支持使用 WITH OIDS 创建表)。 示例 向 films 和 films1 中分别插入一行: INSERT ALL INTO films VALUES ('UA502', 'Bananas', 105, '1971-07-13', 'Comedy', '82 minutes') INTO films1 VALUES ('UA502', 'Bananas', 105, '1971-07-13', 'Comedy', '82 minutes') SELECT * FROM dual; 在这个例子中,filmslen 列被省略并且因此会具有默认值: INSERT ALL INTO films (code, title, did, date_prod, kind) VALUES ('T_601', 'Yojimbo', 106, '1961-06-16', 'Drama') INTO films1 (code, title, did, date_prod, kind, len) 1176 第 19 章 SQL 语句: DROP TABLE 到 LOAD VALUES ('UA502', 'Bananas', 105, '1971-07-13', 'Comedy', '82 minutes') SELECT * FROM dual; 这个例子为日期列使用 DEFAULT 子句而不是指定一个值: INSERT ALL INTO films VALUES ('UA502', 'Bananas', 105, DEFAULT, 'Comedy', '82 minutes') INTO films1 (code, title, did, date_prod, kind) VALUES ('T_601', 'Yojimbo', 106, DEFAULT, 'Drama') SELECT * FROM dual; 向 films 和 films1 中插入数据,每行数据若都满足表的插入条件,则只插入第一个表: 这个例子从表 tmp_films 中获得一些行插入到表 “films 和 films1“中,最终只有表 films 插入了所有的数据,三 个表具有相同的列布局: INSERT FIRST WHEN date_prod < '2004-05-07' THEN INTO films WHEN date_prod < '2004-04-07' THEN INTO films1 SELECT * FROM tmp_films WHERE date_prod < '2004-05-07'; 这个例子满足条件插入 films, 不满足插入 films1,: INSERT FIRST WHEN date_prod < '2004-05-07' THEN INTO films ELSE INTO films1 SELECT * FROM tmp_films WHERE date_prod < '2004-05-07'; 兼容性 INSERT ALL|FIRST 是为了兼容 ORACLE 功能特性,目前只兼容了基础的功能。像 INSERT ALL | FIRST 通 过 PARTITION、SUBPARTITION 指定插入分区和子分区,插入物化视图,通过 @dblink 插入外部表等功能都不支 持。 其他 如果指定的表是一个分区表,每一行都会被路由到合适的分区并且插入其中。如果指定的表是一个分区,如果输 入行之一违背该分区的约束则将发生错误。 如果指定的视图是一个物化视图将报错 19.22 INSERT(MySQL 模式) 用途 本小节仅针对于 MySQL 模式下特有属性,其他具体细节可参考INSERT 。 1177 第 19 章 SQL 语句: DROP TABLE 到 LOAD INSERT 将新行插入到一个表中。我们可以插入一个或者更多由值表达式指定的行,或者插入来自一个查询的零 行或者更多行。 语法 [ WITH [ RECURSIVE ] with_query [, ...] ] INSERT [INTO] table_name[()] [part_extension_clause] [ [ AS ] alias ] | sub_query [alias] [ ( column_name [, ...] ) ] [ OVERRIDING { SYSTEM | USER} VALUE ] { DEFAULT VALUES | {VALUES| VALUE} ( { expression | DEFAULT } [, ...] ) [, ...] | query | VALUES record | SET { column_name = { expression | DEFAULT } | ( column_name [, ...] ) = [ ROW ] ( { expression | DEFAULT } [, ...] ) | ( column_name [, ...] ) = ( sub-SELECT ) } [, ...] } [ ON CONFLICT [ conflict_target ] conflict_action ] [ RETURNING * | output_expression [ [ AS ] output_name ] [, ...] ] 1178 第 19 章 SQL 语句: DROP TABLE 到 LOAD 示例 1、支持 into 可选、value、values row。 insert test4 values(1,'SongJiang'); insert test4 value(2,'LuZhiSheng'); insert test4 values row(3,'GuDaSao'); 2、支持 as 子句不依赖 on duplicate 子句。 1179 第 19 章 SQL 语句: DROP TABLE 到 LOAD insert into test4 values(1,'SongJiang') as t; insert into test4 value(2,'LuZhiSheng') as t; 3、支持表名后的括号可选。 insert into test4() values(1,'SongJiang'); insert into test4() value(),(); insert into test4() values row(2,'LuZhiSheng'),row(3,'GuDaSao'); 19.23 INSERT ON DUPLICATE(MySQL 模式) 用途 INSERT ON DUPLICATE KEY UPDATE 功能和 KingbaseES 的 ON CONFLICT 相似。如果在 INSERT 语句 后面指定了 ON DUPLICATE KEY UPDATE, 并且插入当前的元组后会导致 UNIQUE KEY 或 PRIMARY KEY 中 出现了重复的值,则在出现 UNIQUE KEY 重复的已存在元组执行 UPDATE 操作;如果插入的元组与已存在元组不 存在 UNIQUE KEY 重复问题,则插入新的元组。 前置条件 KingbaseES 数据库初始化为 MySQL 模式。 为了向表中插入,你必须具有其上的 INSERT 特权。 如果一个列被指定,你只需要其中的列上的“INSERT“特权。 语法 INSERT INTO table_name[(col_name_list)] VALUES(value_list)[,(value_list)...] [AS row_alias[col_name_alias]] ON DUPLICATE KEY UPDATE expression[RETURNING col_name_list]; 1180 第 19 章 SQL 语句: DROP TABLE 到 LOAD INSERT INTO table_name {SELECT ... | TABLE table_name| VALUES ROW({ expression | DEFAULT } [, ...])[,...]} ON DUPLICATE KEY UPDATE expression[RETURNING col_name_list]; INSERT INTO table_name SET col_name = value[,col_name=value...] ON DUPLICATE KEY UPDATE expression [RETURNING col_name_list]; 语义 语法中关键词的含义。 table_name 一个已有表的名称(可以被模式限定)。 col_name 期望插入值的目标列。 col_name_list 期望插入值的目标列的集合。 col_name_alias 期望插入值的目标列的别名。 row_alias 期望插入值的目标列集合的别名。 value 目标列插入的数据。 value_list 期望插入的数据集。 expression 插入的新元组与已存在元组冲突时,要赋予相应列的表达式或者值。 成功完成时,INSERT 命令会返回以下形式的命令标签: 1181 第 19 章 SQL 语句: DROP TABLE 到 LOAD INSERT oid count “count“是被插入的行数。 “oid“通常是 0(使用 OID 声明目标表,如果 “count“为 1;否则,使用 WITH OIDS 和 0 声明目标表,但是不再 支持使用 oid 创建表否则为 0,那么它通常是分配给插入行的 OID,但是不再支持使用 WITH OIDS 创建表)。 示例 -- 创建含有 UNIQUE KEY 表 CREATE TABLE t2( a INT UNIQUE, b INT, c INT ); INSERT INTO t2 VALUES(1,1,1); -- 定义 row_alias INSERT INTO t2 VALUES(1,1,1) AS new ON DUPLICATE KEY UPDATE a = new.b + new.c; SELECT * FROM t2; a | b | c ---+---+--2 | 1 | 1 -- 定义 row_alias(col_name_alias) INSERT INTO t2 VALUES(2,1,1) AS new(m,n,p) ON DUPLICATE KEY UPDATE a = new.m + new.p; SELECT * FROM t2; a | b | c ---+---+--3 | 1 | 1 -- 创建多个 UNIQUE/PRIMARY KEY 表 CREATE TABLE t1( a INT PRIMARY KEY, b INT UNIQUE, c INT DEFAULT 1 ); -- 插入非重复元组, 不执行 UPDATE 操作 INSERT INTO t1 VALUES(1,1,1) ON DUPLICATE KEY UPDATE c = 2; SELECT * FROM t1; a | b | c ---+---+--1 | 1 | 1 1182 第 19 章 SQL 语句: DROP TABLE 到 LOAD -- 插入 UNIQUE KEY 重复的元组,执行 UPDATE 操作 INSERT INTO t1 VALUES(1,2,3) ON DUPLICATE KEY UPDATE b = 3; SELECT * FROM t1; a | b | c ---+---+--1 | 3 | 1 -- RETURNING col_name_list INSERT INTO t1 VALUES(1,2,3) ON DUPLICATE KEY UPDATE b = 5 RETURNING a,b,c; a | b | c ---+---+--1 | 5 | 5 SELECT * FROM t1; a | b | c ---+---+--1 | 5 | 5 INSERT INTO t1 SET a = 1, b = 2, c = 2 ON DUPLICATE KEY UPDATE a = 2, b = 2, c = 2; SELECT * FROM t1; a | b | c ---+---+--2 | 2 | 2 注意: 如果表定义存在多个 UNIQUE KEY 时,对它们的唯一性检查是 OR 的关系。如下描述例子,待插入的新元 组 (1,1,3),首先 a 列值为 1, 通过 UNIQUE KEY 判断与旧元组 (1,2,3) 重复,然后执行 UPDATE 操作,将旧元组 (1,2,3) 的 b 列值设置为 3, 这时 b 列的 UNIQUE KEY 检查到已存在该值,所以 INSERT 失败。 -- t1 的定义 test2=# \d t1 Table "public.t1" Column | Type | Collation | Nullable | Default --------+---------+-----------+----------+--------a | integer | | not null | b | integer | | | c | integer | | | 1 Indexes: "t1_pkey" PRIMARY KEY, btree (a) "t1_b_key" UNIQUE CONSTRAINT, btree (b) SELECT * FROM t1; a | b | c 1183 第 19 章 SQL 语句: DROP TABLE 到 LOAD ---+---+--1 | 2 | 3 2 | 3 | 4 -- 插入重复的元组 INSERT INTO t1 VALUES(1,1,3) ON DUPLICATE KEY UPDATE b = 3; ERROR: duplicate key value violates unique constraint "t1_b_key" DETAIL: Key (b)=(3) already exists. -- MySQL 模式 INSERT 语句中,可使用一条插入语句插入多行默认空值或 DEFAULT。 insert into test4 values(),(); insert into test4 value(),(); insert into test4 values row(),row(); 兼容性 INSERT ON DUPLICATE 是为了兼容 MySQL 功能特性,如果插入的元组和已存在的元组冲突,那么 MySQL 返回的影响行数是待插入的元组数与更新元组数和,KingbaseES 返回的影响行数是被更新的元组数与新插入元组数 的和。 其他 如果指定的表是一个分区表,每一行都会被路由到合适的分区并且插入其中。如果指定的表是一个分区,如果输 入行之一违背该分区的约束则将发生错误。 19.24 LISTEN 用途 LISTEN —监听一个通知 LISTEN 在名为 “channel“的通知频道上将当前会话注册为一个监听者。如果当前会话已经被注册为这个通知频道 的一个监听者,则什么也不会发生。 只要命令 NOTIFY channel 被调用(不管是在这个会话还是在另一个连接到同一数据库的会话中),所有当前正 在该通知频道上监听的会话都会被通知,并且每一个会话将会接着通知连接到它的客户端应用。 可以使用 UNLISTEN 命令在一个给定通知频道上反注册一个会话。当会话结束时,它的监听注册会被自动清除。 一个客户端应用检测通知事件的必用方法取决于它使用的 KingbaseES 应用编程接口。如果使用 libkci 库,应用 会将 LISTEN 作为一个普通 SQL 命令发出,并且接着必须周期性地调用函数 KCIGetNextNotification 来查看是否 接收到通知事件。其他诸如 libkbtcl 的接口提供了更高层次上的处理通知事件的方法。事实上,通过使用 libkbtcl 应 用程序员甚至不必直接发出 LISTEN 或 UNLISTEN。更多细节可参阅所使用的接口的文档。 NOTIFY 包含了使用 LISTEN 和 NOTIFY 的更广泛的讨论。 1184 第 19 章 SQL 语句: DROP TABLE 到 LOAD 前置条件 无 语法 LISTEN channel 语义 channel 一个通知频道的名称(任意标识符)。 示例 从 ksql 中配置并执行一个监听/通知序列 LISTEN virtual; NOTIFY virtual; Asynchronous notification "virtual" received from server process with PID 8448. 兼容性 在 SQL 标准中没有 LISTEN 语句。 其他 LISTEN 在事务提交时生效。如果在一个后来被回滚的事务中执行了 LISTEN 或 UNLISTEN,被监听的通知频道集 合不会变化。 一个已经执行了 LISTEN 的事务不能为两阶段提交做准备。 19.25 LOAD 用途 LOAD —载入一个共享库文件 这个命令把一个共享库文件载入到 KingbaseES 服务器的地址空间中。如果该文件已经被载入,这个命令什么 也不会做。只要调用包含 C 函数的共享库文件中的一个函数,这些共享库文件就会被自动载入。因此,一次显式的 LOAD 通常只在载入一个通过“钩子”修改服务器行为而不是提供一组函数的库时需要。 库文件名通常只是一个裸文件名,在服务器的库搜索路径(由 dynamic_library_path 设置)中寻找。或者,它 可以作为完整的路径名称给出。无论哪种情况,平台的标准共享库文件扩展名都可以省略。 前置条件 1185 第 19 章 SQL 语句: DROP TABLE 到 LOAD 非超级用户只能把 LOAD 应用在位于 “$libdir/plugins/“中的库文件—指定的*“filename“* 必须正好以该字符串开 始(确保在那里只安装了“安全的”库是数据库管理员的责任)。 语法 LOAD 'filename' 语义 filename 要加载的库库文件名或者路径 示例 LOAD 'sys_hint_plan'; 兼容性 LOAD 是一种 KingbaseES 扩展。 19.26 LOCK 用途 LOCK TABLE 获得一个表级锁,必要时会等待任何冲突锁被释放。如果指定了 NOWAIT,LOCK TABLE 不会等待以 获得想要的锁:如果它不能立刻得到,该命令会被中止并且发出一个错误。一旦获取到,该锁会被在当前事务中一直 持有(没有 UNLOCK TABLE 命令,锁总是在事务结束时被释放)。 当一个视图被锁定时,出现在该视图定义查询中的所有关系也将被使用同样的锁模式递归地锁住。 在为引用表的命令自动获取锁时,KingbaseES 总是尽可能使用最不严格的锁模式。提供 LOCK TABLE 是用于 想要更严格的锁定的情况。例如,假设一个应用运行一个 READ COMMITTED 隔离级别的事务,并且需要确保一个表 中的数据在该事务的期间保持稳定。要实现这个目的,必须在查询之前在表上获得 SHARE 锁模式。这将阻止并发 的数据更改并且确保该表的后续读操作会看到已提交数据的一个稳定视图,因为 SHARE 锁模式与写入者所要求的 ROW EXCLUSIVE 锁有冲突,并且你的 LOCK TABLE name IN SHARE MODE 语句将等待,直到任何并发持有 ROW EXCLUSIVE 模式锁的持有者提交或者回滚。因此,一旦得到锁,就不会有未提交的写入还没有解决。更进一步,在释 放该锁之前,任何人都不能开始。 要在运行在 REPEATABLE READ 或 SERIALIZABLE 隔离级别的事务中得到类似的效果,你必须在执行任何 SELECT 或者数据修改语句之前执行 LOCK TABLE 语句。一个 REPEATABLE READ 或者 SERIALIZABLE 事务的数据视图将在它 的第一个 SELECT 或者数据修改语句开始时被冻结。在该事务中稍后的一个 LOCK TABLE 仍将阻止并发写—但它不会 确保该事务读到的东西对应于最新的已提交值。 如果一个此类事务正要修改表中的数据,那么它应该使用 SHARE ROW EXCLUSIVE 锁模式来取代 SHARE 模式。这 会保证一次只有一个此类事务运行。如果不用这种模式,死锁就可能出现:两个事务可能都要求 SHARE 模式,并且都 1186 第 19 章 SQL 语句: DROP TABLE 到 LOAD 不能获得 ROW EXCLUSIVE 模式来真正地执行它们的更新(注意一个事务所拥有的锁不会冲突,因此一个事务可以在 它持有 SHARE``模式时获得\ ``ROW EXCLUSIVE 模式—但是如果有其他人持有 SHARE 模式时则不能)。为了避免死 锁,确保所有的事务在同样的对象上以相同的顺序获得锁,并且如果在一个对象上涉及多种锁模式,事务应该总是首 先获得最严格的那种模式。 前置条件 无 语法 LOCK [ TABLE ] [ ONLY ] name [ * ] [, ...] [ IN lockmode MODE ] [ NOWAIT ] 其中 lockmode 可以是以下之一: ACCESS SHARE | ROW SHARE | ROW EXCLUSIVE | SHARE UPDATE EXCLUSIVE | SHARE | SHARE ROW EXCLUSIVE | EXCLUSIVE | ACCESS EXCLUSIVE 语义 name 要锁定的一个现有表的名称(可以是模式限定的)。如果在表名前指定了 ONLY,只有该表会被锁定。如果没有 指定了 ONLY,该表和它所有的后代表(如果有)都会被锁定。可选地,在表名后指定 * 来显式地表示把后代表 1187 第 19 章 SQL 语句: DROP TABLE 到 LOAD 包括在内。 命令 LOCK TABLE a, b; 等效于 LOCK TABLE a; LOCK TABLE b;。这些表会被按照在 LOCK TABLE 中指定的顺 序一个一个被锁定。 lockmode 锁模式指定这个锁和哪些锁冲突。 如果没有指定锁模式,那儿将使用最严格的模式 ACCESS EXCLUSIVE。 NOWAIT 指定 LOCK TABLE 不等待任何冲突锁被释放:如果所指定的锁不能立即获得,那么事务就会中止。 示例 在将要向一个外键表中执行插入时在主键表上获得一个 SHARE 锁: BEGIN WORK; LOCK TABLE films IN SHARE MODE; SELECT id FROM films WHERE name = 'Star Wars: Episode I - The Phantom Menace'; -- 如果记录没有被返回就做 ROLLBACK INSERT INTO films_user_comments VALUES (_id_, 'GREAT! I was waiting for it for so long!'); COMMIT WORK; 在将要执行一次删除操作前在主键表上取一个 “SHARE ROW EXCLUSIVE“锁: BEGIN WORK; LOCK TABLE films IN SHARE ROW EXCLUSIVE MODE; DELETE FROM films_user_comments WHERE id IN (SELECT id FROM films WHERE rating < 5); DELETE FROM films WHERE rating < 5; COMMIT WORK; 兼容性 在 SQL 标准中没有 LOCK TABLE,SQL 标准中使用 SET TRANSACTION 指定事务上的并发层次。KingbaseES 也 支持这样做,详见SET TRANSACTION 。 除 ACCESS SHARE、ACCESS EXCLUSIVE 和 SHARE UPDATE EXCLUSIVE 锁模式之外,KingbaseES 锁模式和 LOCK TABLE 语法与 Oracle 中的兼容。 其他 LOCK TABLE ... IN ACCESS SHARE MODE 要求目标表上的 SELECT 特权。LOCK TABLE ... IN ROW EXCLUSIVE MODE 要求目标表上的 INSERT、UPDATE、DELETE 或 TRUNCATE 特权。所有其他形式的 LOCK 要求表级 UPDATE、 DELETE 或 TRUNCATE 特权。 在该视图上执行锁定的用户必须具有该视图上相应的特权。此外视图的拥有者必须拥有底层基关系上的相关特 权,但是执行锁定的用户不需要底层基关系上的任何权限。 1188 第 19 章 SQL 语句: DROP TABLE 到 LOAD LOCK TABLE 在一个事务块外部没有用处:锁将只保持到语句完成。因此如果在一个事务块外部使用了 LOCK, KingbaseES 会报告一个错误。使用BEGIN 和COMMIT (或者ROLLBACK )定义一个事务块。 LOCK TABLE 只处理表级锁,因此涉及到 ROW 的模式名称在这里都是不当的。这些模式名称应该通常被解读为用 户在被锁定表中获取行级锁的意向。还有,ROW EXCLUSIVE 模式是一个可共享的表锁。记住就 LOCK TABLE 而言,所 有的锁模式都具有相同的语义,只有模式的冲突规则有所不同。 1189 第 20 章 SQL 语句: MERGE 到 VALUES 第 20章 SQL 语句: MERGE 到 VALUES 本章包含以下 SQL 语句: • MERGE • MOVE • NOTIFY • PREPARE • PREPARE TRANSACTION • PURGE TABLE • REASSIGN OWNED • REFRESH MATERIALIZED VIEW • REINDEX • REPLACE INTO • RELEASE SAVEPOINT • RESET • REVOKE • ROLLBACK • ROLLBACK PREPARED • ROLLBACK TO SAVEPOINT • SAVEPOINT • SECURITY LABEL • SELECT • SELECT INTO • SET 1190 第 20 章 SQL 语句: MERGE 到 VALUES • SET CONSTRAINTS • SET ROLE • SET SESSION AUTHORIZATION • SET TRANSACTION • SHOW • START TRANSACTION • TRUNCATE • UNLISTEN • UPDATE • UPDATE(MySQL 模式) • VACUUM • VALUES 20.1 MERGE 用途 MERGE -- 根据连接条件对目标表执行插入或修改操作 MERGE 在一次扫描过程中根据连接条件对目标表执行插入或修改操作。 使用 MERGE 语法可合并 UPDATE 和 INSERT 语句。通过 MERGE 语句,根据一张表(或视图)的连接条 件对另外一张表(或视图)进行查询,连接条件匹配上的执行 UPDATE(可能含有 DELETE),无法匹配的执行 INSERT。其中数据表包括:普通表、分区表。 MERGE 语法仅需要一次全表扫描就完成了全部工作,执行效率要高于 INSERT + UPDATE。 MERGE 也是一个 DML 语句,和其它的 DML 语句一样需要通过 ROLLBACK 和 COMMIT 语句结束事务。 前置条件 如果 MERGE action 中指定了 UPDATE/INSERT 子句,则要求用户拥有该表的 UPDATE/INSERT 权限,如 果在 UPDATE 子句中指定了 DELETE action ,则还需要具有该表的 DELETE 权限。 语法 MERGE INTO [ schema. ] { target_table } [part_extension_clause] [ [ AS ] target_table_alias ] | sub_query [ target_table_alias ] USING { [ schema. ] { source_table } [part_extension_clause] [ [ AS ] source_table_alias ] ON ( condition_expression ) [ merge_update_clause ] [ merge_insert_clause ]; 1191 第 20 章 SQL 语句: MERGE 到 VALUES merge_update_clause: WHEN MATCHED THEN UPDATE SET column = { expr | DEFAULT }[, column = { expr | DEFAULT } ]... [ where_clause ] [ delete_clause ] delete_clause: [DELETE where_clause] merge_insert_clause: WHEN NOT MATCHED THEN INSERT [ ( column [, column ]...) ] VALUES ({ expr | DEFAULT }[, { expr | DEFAULT } ]...) [ where_clause ] where_clause: WHERE condition merge_update_clause ::= 1192 第 20 章 SQL 语句: MERGE 到 VALUES delete_clause ::= merge_insert_clause ::= where_clause ::= Part_extension_clause: { PARTITION (patition) | PARTITION FOR (partition_key_value [, partition_key_value]…) | SUBPARTITION (subpartition) | SUBPARTITION FOR (subpartition_key_value [, subpartition_key_value]…) } 1193 第 20 章 SQL 语句: MERGE 到 VALUES 语义 target_table MERGE 目标,它可以是表、水平分区表或可更新视图。不可以是继承的表和垂直分区表。 target_table_alias MERGE 目标的别名。 part_extension_clause 支持通过 partitionsubpartition 关键字指定分区名或者子分区名,实现对分区和子分区直 接进行 merge into 操作。其中 PARTITION FOR(partition_key_value) 指定分区键值,PARTITION (partition)指定分区名,这里的分区名是指 oralce 语法创建分区表时指定的分区名,而不是分区对象在系统表 sys_class 中存储的对象名。 sub_query • merge into 子查询时,子查询只支持单表。 • 只可以对子查询的投影列进行操作。 • 子查询中不能包含聚集函数(avg,count,max,min,sum 等),分析函数,distinct 等。 source_table MERGE 源,可以是表、视图、SQL/MED、子查询、join table 以及函数等等。 source_table_alias MERGE 源的别名。 condition_expression 指 定 目 标 表 与 源 表 之 间 进 行 联 接 的 联 接 条 件。 如 果 该 条 件 为 真, 且 指 定 了 WHEN MATCHED THEN UPDATE 子句,则对匹配到的目标表的该元组执行更新操作;否则,如果该条件为假 且指定了 WHEN NOT MATCHED THEN INSERT 子句,则对目标表执行插入操作。 merge_update_clause 当目标表和源表的 ON 条件为真时,执行该子句,即更新目标表数据。该更新操作会触发目 标表上面的触发器。更新的列不能是 ON 条件中被引用的列,更新时可以通过 WHERE 条件指明要更新的行, 条件中既可以包含源表的列,也可以包含目标表的列,当指明 WHERE 条件且条件为假时,则不更新。 delete_clause DELETE 子句只删除目标表和源表的 ON 条件为真、并且是更新后的符合删除条件的记录, DELETE 子句不影响 INSERT 项插入的行。删除条件作用在更新后的记录上,既可以和源表相关,也可以和 目标表相关,或者都相关。如果 ON 条件为真,但是不符合更新条件,并没有更新数据,那么 DELETE 将不 会删除任何数据。 1194 第 20 章 SQL 语句: MERGE 到 VALUES merge_insert_clause 当目标表和源表的 ON 条件为假时,执行该语句。可指定插入条件,插入时的 WHERE 条件 只能引用源表中的列。VALUES 后面也只能引用源表中的列,不能包含目标表的列。 可选的参数可以被写成任何顺序,不用按照上面说明的顺序。 示例 例 1: create table test1(a int, b int); insert into test1 values(1, 1); insert into test1 values(2, 2); insert into test1 values(3, 3); create table test2(x int, y int); insert into test2 values(1, 1); insert into test2 values(3, 3); insert into test2 values(5, 5); merge into test2 using test1 on (test1.a = test2.x) when matched then update set y = y * -1 where test1.a > 1 when not matched then insert values(test1.a, test1.b); 执行结果: x | y ---+---1 | 1 5 | 5 2 | 2 3 | -3 (4 rows) 例 2:MERGE 中使用 DELETE 语句: create table t1(id int, a int, b int, c varchar(100)); create table t2(id int, a int, b int, c varchar(100)); insert into t1 values(1, 1, 1, '1'); insert into t1 values(2, 2, 2, '2'); insert into t1 values(3, 3, 3, '3'); insert into t1 values(4, 4, 4, '4'); insert into t2 values(2, 22, 22, '2'); insert into t2 values(4, 44, 44, '4'); merge into t2 using t1 on (t1.id = t2.id) when matched then update set t2.a = t2.a * -1, t2.b = t2.b * -1 delete where t1.id = t2.id 1195 第 20 章 SQL 语句: MERGE 到 VALUES when not matched then insert values(t1.id, t1.a, t1.b, t1.c); 执行结果: id | a | b | c ----+---+---+--1 | 1 | 1 | 1 3 | 3 | 3 | 3 (2 行记录) 兼容性 MERGE 语句不兼容 SQL 标准。 其他 1. 如果源表中有多行与目标表中的一行匹配,并且同时指定了 WHEN MATCHED THEN UPDATE 子句,则报 错,因为同一元组不能被重复更新。 2. 对于 set_list 来说,不能指定 ON 条件子句中用于联接条件的目标表中的列。 3. 在 value_list 的值表达式中不能引用目标表中的列。 4. 如果目标表上有约束或目标视图的定义中有 WITH CHECK OPTION,则对目标表所做的更新要满足基表上的 约束条件或视图定义的校验条件。 5. 需要有对源表的 SELECT 权限,对目标表的 UPDATE/INSERT 权限,如果 UPDATE 子句有 DELETE,还 需要有 DELETE 权限。 20.2 MOVE 用途 MOVE —定位一个游标 MOVE 的工作完全像 “FETCH“命令,但是它只定位游标并且不返回行。用于 MOVE 命令的参数和 FETCH 命令的 一样,可参考FETCH 。 成功完成时,MOVE 命令返回的命令标签形式是 MOVE count “count“是一个具有同样参数的 FETCH 命令会返回的行数(可能为零)。 前置条件 无 语法 1196 第 20 章 SQL 语句: MERGE 到 VALUES MOVE [ direction [ FROM | IN ] ] cursor_name 其中 direction 可以为空或者以下之一: NEXT PRIOR FIRST LAST ABSOLUTE count RELATIVE count count ALL FORWARD FORWARD count FORWARD ALL BACKWARD BACKWARD count BACKWARD ALL direction ::= 语义 用于 MOVE 命令的参数和 FETCH 命令的一样,可参考FETCH 。 1197 第 20 章 SQL 语句: MERGE 到 VALUES 示例 BEGIN WORK; DECLARE liahona CURSOR FOR SELECT * FROM films; -- 跳过前 5 行: MOVE FORWARD 5 IN liahona; MOVE 5 -- 从游标 liahona 中取第 6 行: FETCH 1 FROM liahona; code | title | did | date_prod | kind | len -------+--------+-----+------------+--------+------P_303 | 48 Hrs | 103 | 1982-10-22 | Action | 01:37 (1 row) -- 关闭游标 liahona 并且结束事务: CLOSE liahona; COMMIT WORK; 兼容性 在 SQL 标准中没有 MOVE 语句。 20.3 NOTIFY 用途 NOTIFY —生成一个通知 NOTIFY 命令发送一个通知事件以及一个可选的“载荷”字符串给每个正在监听的客户端应用,这些应用之前都 在当前数据库中为指定的频道名执行过 LISTEN channel。通知对所有用户都可见。 NOTIFY 为访问同一个 KingbaseES 数据库的进程集合提供了一种简单的进程间通讯机制。伴随着通知可以发送 一个载荷字符串,通过使用数据库中的表从通知者向监听者传递额外的数据,也可以构建用于传输结构化数据的高层 机制。 由一个通知事件传递给客户端的信息包括通知频道名称、发出通知的会话的服务器进程 PID 以及载荷字符串, 如果载荷字符串没有被指定则它为空字符串。 将在一个给定数据库以及其他数据库中使用的频道名称由数据库设计者定义。通常,频道名称与数据库中某个表 的名称相同,并且通知事件其实就意味着:“我改变了这个表,来看看改了什么吧”。但是 NOTIFY 和 LISTEN 命令 并未强制这样的关联。例如,一个数据库设计者可以使用几个不同的频道名称来标志一个表上的不同种类的改变。另 外,载荷字符串可以被用于多种不同的情况。 当 NOTIFY 被用来标志对一个特定表的改变时,一种有用的编程技巧是把“NOTIFY“放在一个由表更新触发的语 句触发器中。在这种方式中,每当表被改变时都将自动发生通知,并且应用程序员不可能会忘记发出通知。 1198 第 20 章 SQL 语句: MERGE 到 VALUES NOTIFY 以一些重要的方式与 SQL 事务互动。首先,如果一个 NOTIFY 在一个事务内执行,在事务被提交之前, 该通知事件都不会被递送。这是合适的,因为如果该事务被中止,所有其中的命令都将不会产生效果,包括 NOTIFY 在内。但如果期望通知事件被立即递送,那这种行为就会令人不安。其次,如果一个监听会话收到了一个通知信号而 它正在一个事务中,在该事务完成(提交或者中止)之前,该通知事件将不会被递送给它连接的客户端。同样,原因 在于如果一个通知在一个事务内被递送且该事务后来被中止,我们会希望该通知能以某种方式被撤销 但是服务器一旦把通知发送给客户端就无法“收回它”。因此通知事件只能在事务之间递送。其中的要点是把 NOTIFY 用作实时信号的应用应该让它们事务尽可能短小。 如果从同一个事务多次用相同的载荷字符串对同一个频道名称发送通知,数据库服务器能决定只递送一个单一的 通知。另一方面,带有不同载荷字符串的通知将总是作为不同的通知被递送。类似地,来自不同事务的通知将不会被 折叠成一个通知。除了丢弃后来生成的重复通知实例之外,NOTIFY 保证来自同一个事务的通知按照它们被发送的顺 序被递送。还可以保证的是,来自不同事务的消息会按照其事务被提交的顺序递送。 一个执行 NOTIFY 的客户端自己也同时在监听同一个通知频道是很常见的事。在这种情况下,和所有其他监听会 话一样,它会取回一个通知事件。根据应用的逻辑,这可能导致无用的工作,例如从自己刚刚写入的一个表中读出相 同的更新。可以通过关注发出通知的服务器进程 PID(在通知事件消息中提供)与自己的会话 PID(可以从 libkci 得 到)是否相同来避免这种额外的工作。当两者相同时,该通知事件就是当前会话自己发出的,所以可以忽略。 前置条件 无 语法 NOTIFY channel [ , payload ] 语义 channel 要对其发信号的通知频道的名称(任意标识符)。 payload 要通过通知进行沟通的“载荷”字符串。这必须是一个简单的字符串。在默认配置下,该字符串不能超过 8000 字节(如果需要发送二进制数据或者更多信息,最好是把它放在一个数据库表中并且发送该记录的键)。 示例 从 ksql 配置和执行一个监听/通知序列: LISTEN virtual; NOTIFY virtual; Asynchronous notification "virtual" received from server process with PID 8448. NOTIFY virtual, 'This is the payload'; Asynchronous notification "virtual" with payload "This is the payload" received from server process with PID 8448. 1199 第 20 章 SQL 语句: MERGE 到 VALUES LISTEN foo; SELECT sys_notify('fo' || 'o', 'pay' || 'load'); Asynchronous notification "foo" with payload "payload" received from server process with PID 14728. 兼容性 在 SQL 标准中没有 NOTIFY 语句。 其他 有一个队列保持着已经发送但是还没有被所有监听会话处理的通知。如果该队列被占满,调用 NOTIFY 的事务将 在提交时失败。该队列非常大(标准安装中是 8GB)并且应该足以应付几乎每一种用例。但是,如果一个会话执行 了 NOTIFY 并且接着长时间进入一个事务,不会发生清理操作。一旦该队列使用过半,你将在日志文件中看到警告, 它指出哪个会话阻止了清理。在这种情况中,应该确保这个会话结束它的当前事务,这样清理才能够进行下去。 函数 sys_notification_queue_usage 返回队列中当前被待处理通知所占据的比例。详见 系统信息函数和操作 符。 一个已经执行了 NOTIFY 的事务不能为两阶段提交做准备。 要发送一个通知,你也能使用函数 sys_notify(text, text)。该函数采用频道名称作为第一个参数,而载荷则 作为第二个参数。如果你需要使用非常量的频道名称和载荷,这个函数比 NOTIFY 命令更容易使用。 20.4 PREPARE 用途 PREPARE —为执行准备一个语句 SELECT INTO 创建一个新表并且用一个查询计算得到的数据填充它。这些数据不会像普通的 “SELECT“那样被 返回给客户端。新表的列具有和 SELECT 的输出列相关的名称和数据类型。 PREPARE 创建一个预备语句。预备语句是一种服务器端对象,它可以被用来优化性能。当 PREPARE 语句被执行 时,指定的语句会被解析、分析并且重写。当后续发出一个 EXECUTE 命令时,该预备语句会被规划并且执行。这种 工作的划分避免了重复性的解析分析工作,但是允许执行计划依赖所提供的特定参数值。 预备语句可以接受参数:在执行时会被替换到语句中的值。在创建预备语句时,可以用位置引用参数,如 $1、 $2 等。也可以选择性地指定参数数据类型的一个列表。当一个参数的数据类型没有被指定或者被声明为 unknown 时,其类型会从该参数被第一次引用的环境中推知(如果可能)。在执行该语句时,在 EXECUTE 语句中为这些参数 指定实际值。更多有关于此的信息可参考EXECUTE 。 预备语句只在当前数据库会话期间存在。当会话结束时,预备语句会消失,因此在重新使用之前必须重新建立 它。这也意味着一个预备语句不能被多个数据库客户端同时使用。但是,每一个客户端可以创建它们自己的预备语句 来使用。预备语句可以用DEALLOCATE 命令手工清除。 1200 第 20 章 SQL 语句: MERGE 到 VALUES 当一个会话要执行大量类似语句时,预备语句可能会有最大性能优势。如果该语句很复杂(难于规划或重写), 例如,如果查询涉及很多表的连接或者要求应用多个规则,性能差异将会特别明显。如果语句相对比较容易规划和重 写,但是执行起来开销相对较大,那么预备语句的性能优势就不那么显著了。 前置条件 无 语法 PREPARE name [ ( data_type [, ...] ) ] AS statement 语义 name 给这个特定预备语句的任意名称。它在一个会话中必须唯一并且后续将被用来执行或者清除一个之前准备好的 语句。 data_type 预备语句一个参数的数据类型。如果一个特定参数的数据类型没有被指定或者被指定为 unknown,将从 该参数被第一次引用的环境中推得。要在预备语句本身中引用参数,可以使用 “$1“、$2 等。 statement 任何 SELECT、INSERT、UPDATE、DELETE 或者 VALUES 语句。 示例 为一个 INSERT 语句创建一个预备语句,然后执行它: PREPARE fooplan (int, text, bool, numeric) AS INSERT INTO foo VALUES($1, $2, $3, $4); EXECUTE fooplan(1, 'Hunter Valley', 't', 200.00); 为一个 SELECT 语句创建一个预备语句,然后执行它: PREPARE usrrptplan (int) AS SELECT * FROM users u, logs l WHERE u.usrid=$1 AND u.usrid=l.usrid AND l.date = $2; EXECUTE usrrptplan(1, current_date); 在本例中,没有指定第二个参数的数据类型,因此,它是从使用 $2 的上下文中推断出来的。 兼容性 SQL 标准包括一个 PREPARE 语句,但是它只用于嵌入式 SQL。这个版本的 PREPARE 语句也使用了一种有些不 同的语法。 其他 1201 第 20 章 SQL 语句: MERGE 到 VALUES 可以使用 generic plan 或 custom plan 来执行准备好的语句。通用计划在所有执行中是相同的,而使用调用中给 定的参数值为特定执行生成自定义计划。使用通用计划可以避免计划开销,但在某些情况下,自定义计划执行起来更 有效,因为计划人员可以利用参数值的知识。(当然,如果准备好的语句没有参数,那么这是没有意义的,通常使用 的是通用计划。) 默认情况下 (也就是说,当 plan_cache_mode 被设置为 auto),服务器将自动选择对一个有参数的准备好的语 句使用通用计划还是自定义计划。当前的规则是,前五个执行是使用定制计划完成的,并计算这些计划的平均估计成 本。然后创建一个通用计划,并将其估计成本与平均定制计划成本进行比较。如果通用计划的成本并不比平均定制计 划成本高得多,从而使重复的重新计划看起来更可取,那么随后的执行将使用通用计划。 通过将 plan_cache_mode 设置为 force_generic_plan 或 force_custom_plan,可以覆盖此启发式,迫使服 务器使用通用计划或自定义计划。这个设置主要是有用的,如果通用计划的成本估计由于某种原因很差,允许选择 它,即使它的实际成本比定制计划的成本要高得多。 要检查 KingbaseES 为一个预备语句使用的查询计划,可以使用 EXPLAIN ,例如: EXPLAIN EXECUTE stmt_name(parameter_values); 如果使用的是一个通用计划,它将包含参数符号 $n,而一个定制计划则会把提供的参数值替换进去。 更多关于查询规划以及 KingbaseES 为此所收集的统计信息的内容,请见ANALYZE 文档。 尽管预备语句主要是为了避免重复对语句进行解析分析以及规划,但是只要上一次使用该预备语句后该语句中用 到的数据库对象发生了定义性(DDL)改变,KingbaseES 将会对该语句强制进行重新分析和重新规划。还有,如果 search_path 的值发生变化,也将使用新的 search_path 重新解析该语句(后一种行为是从 KingbaseES V8R2 开始 的新行为)。这些规则让预备语句的使用在语义上几乎等效于反复提交相同的查询文本,但是能在性能上获利(如果 没有对象定义被改变,特别是如果最优计划保持不变时)。该语义等价性不完美的一个例子是:如果语句用一个未限 定的名称引用表,并且之后在 search_path 中更靠前的模式中创建了一个新的同名表,则不会发生自动的重解析, 因为该语句使用的对象没有被改变。但是,如果某些其他更改造成了重解析,后续使用中都会引用新表。 可以通过查询 sys_prepared_statements 系统视图来看到会话中所有可用的预备语句。 20.5 PREPARE TRANSACTION 用途 PREPARE TRANSACTION —为两阶段提交准备当前事务 PREPARE TRANSACTION 为两阶段提交准备当前事务。在这个命令之后,该事务不再与当前会话关联。相反,它 的状态被完全存储在磁盘上,并且有很高的可能性它会被提交成功(即便在请求提交前发生数据库崩溃)。 一旦被准备好,事务稍后就可以分别用COMMIT PREPARED 或者ROLLBACK PREPARED 提交或者回滚。 可以从任何会话而不仅仅是执行原始事务的会话中发出这些命令。 从发出命令的会话的角度来看,PREPARE TRANSACTION 不像 ROLLBACK 命令:在执行它之后,就没有活跃的当前 事务,并且该预备事务的效果也不再可见(如果该事务被提交,效果将重新变得可见)。 如果由于任何原因 PREPARE TRANSACTION 命令失败,它会变成一个 ROLLBACK:当前事务会被取消。 1202 第 20 章 SQL 语句: MERGE 到 VALUES 前置条件 PREPARE TRANSACTION 并不是设计为在应用或者交互式会话中使用。它的目的是允许一个外部事务管理器在 多个数据库或者其他事务性来源之间执行原子的全局事务。除非你在编写一个事务管理器,否则你可能不会用到 PREPARE TRANSACTION。 这个命令必须在一个事务块中使用。事务块用BEGIN 开始。 当前在已经执行过任何涉及到临时表、创建带 WITH HOLD 的游标或者执行 LISTEN、UNLISTEN 或 NOTIFY 的事 务中,不允许 PREPARE 该事务。这些特性与当前会话绑定得太过紧密,所以对一个要被准备的事务来说没有什么用 处。 语法 PREPARE TRANSACTION transaction_id 语义 transaction_id 一个任意的事务标识符,COMMIT PREPARED 或者 ROLLBACK PREPARED 以后将用这个标识符来标识 这个事务。该标识符必须写成一个字符串,并且长度必须小于 200 字节。它也不能与任何当前已经准备好的事 务的标识符相同。 示例 为两阶段提交准备当前事务,使用 foobar 作为事务标识符: PREPARE TRANSACTION 'foobar'; 兼容性 PREPARE TRANSACTION 是一种 KingbaseES 扩展。其意图是用于外部事务管理系统,其中有些已经被标准涵盖 (例如 X/Open XA),但是那些系统的 SQL 方面未被标准化。 其他 如果用 SET(不带 LOCAL 选项)修改过事务的任何运行时参数,这些效果会持续到 PREPARE TRANSACTION 之后,并且将不会被后续的任何 COMMIT PREPARED 或 “ROLLBACK PREPARED“所影响。因此,在这一方面 PREPARE TRANSACTION 的行为更像 COMMIT 而不是 ROLLBACK。 所有当前可用的准备好事务被列在 sys_prepared_xacts 系统视图中。 警告: 让一个事务处于准备好状态太久是不明智的。这将会干扰 VACUUM 回收存储的能力,并且在极限情况 下可能导致数据库关闭以阻止事务 ID 回卷(见 防止事务 ID 回卷失败)。还要记住,该事务会继续持有它已经 持有的锁。该特性的设计用法是,只要一个外部事务管理器已经验证其他数据库也准备好了要提交,一个准备好 的事务将被正常地提交或者回滚。 1203 第 20 章 SQL 语句: MERGE 到 VALUES 如果没有建立一个外部事务管理器来跟踪准备好的事务并且确保它们被迅速地结束,最好禁用准备好事务特 性(设置 max_prepared_transactions 为零)。这将防止意外地创建准备好事务,不然该事务有可能被忘记并且 最终导致问题。 20.6 PURGE TABLE 用途 PURGE TABLE 分为删除回收站中指定的一个表和清空回收站。清理回收站时,回收站视图 recyclebin 和回收 站系统表 sys_recyclebin 中对象将被清除。删除回收站中指定的一个表时,将删除表及其相关联对象,例如表的 index、constraint、trigger、policy、rule 等。清空回收站将删除回收站中所有的表及关联对象。 PUGRE RECYCLEBIN 清空回收站,不属于当前 schema 的表也将清空。 前置条件 PUGRE TABLE 删除回收站中一个指定的 table。要执行这个命令你必须是该表的拥有者,如果指定的表不属于当 前 search_path,则还需要指定 schema。 语法 删除回收站中指定的一个表 PURGE TABLE table_name; 清空回收站中所有的表 PURGE RECYCLEBIN; 语义 table_name 指定需要删除的表。 示例 这个命令将删除回收站中名为 kinds 的表及其关联对象: PURGE TABLE kinds; 这个命令将清空回收站中所有的对象: 1204 第 20 章 SQL 语句: MERGE 到 VALUES PURGE RECYCLEBIN; 兼容性 PUGRE TABLE 语句是一个 KingbaseES 扩展。 其他 无。 20.7 REASSIGN OWNED 用途 REASSIGN OWNED —更改一个数据库角色拥有的数据库对象的拥有关系 REASSIGN OWNED 指示系统把 “old_role“拥有的任何数据库对象的拥有关系更改为 “new_role“。 前置条件 REASSIGN OWNED 同时要求源角色和目标角色上的资格。 语法 REASSIGN OWNED BY { old_role | CURRENT_USER | SESSION_USER } [, ...] TO { new_role | CURRENT_USER | SESSION_USER } 语义 old_role 一个角色的名称。这个角色在当前数据库中所拥有的所有对象以及所有共享对象(数据库、表空间)的所 有权都将被重新赋予给 “new_role“。 new_role 将作为受影响对象的新拥有者的角色名称。 示例 移除曾经拥有过对象的角色的方法是: 1205 第 20 章 SQL 语句: MERGE 到 VALUES REASSIGN OWNED BY doomed_role TO successor_role; DROP OWNED BY doomed_role; -- 在集簇中的每一个数据库中重复上述命令 DROP ROLE doomed_role; 兼容性 REASSIGN OWNED 命令是一种 KingbaseES 扩展。 其他 REASSIGN OWNED 经常被用来为移除一个或者多个角色做准备。因为 REASSIGN OWNED 不影响其他数据库中的对 象,通常需要在包含有被删除的角色所拥有的对象的每一个数据库中都执行这个命令。 DROP OWNED 命令可以简单地删掉一个或者多个角色所拥有的所有数据库对象。 REASSIGN OWNED 命令不会影响授予给*old_role``* 的在它们不拥有的对象上的任何特权。同样,它也不会影 响用 \ ``ALTER DEFAULT PRIVILEGES 创建的默认特权。DROP OWNED 可以回收那些特权。 更多讨论请见 删除角色。 20.8 REFRESH MATERIALIZED VIEW 用途 REFRESH MATERIALIZED VIEW —替换一个物化视图的内容 REFRESH MATERIALIZED VIEW 完全替换一个物化视图的内容。旧的内容会被抛弃。如果指定了 “WITH DATA“ (或者作为默认值),支持查询将被执行以提供新的数据,并且会让物化视图将处于可扫描的状态。如果指定了 “WITH NO DATA“,则不会生成新数据并且会让物化视图处于一种不可扫描的状态。 前置条件 CONCURRENTLY 和 WITH NO DATA 不能被一起指定。 语法 REFRESH MATERIALIZED VIEW [ CONCURRENTLY ] name [ WITH [ NO ] DATA ] 语义 1206 第 20 章 SQL 语句: MERGE 到 VALUES CONCURRENTLY 对物化视图的刷新不阻塞在该物化视图上的并发选择。如果没有这个选项,一次影响很多行的刷新将 使用更少的资源并且更快结束,但是可能会阻塞其他尝试从物化视图中读取的连接。这个选项在只有少量行被 影响的情况下可能会更快。 只有当物化视图上有至少一个 UNIQUE 索引(只用列名并且包括所有行)时,才允许这个选项。也就是说,该 索引不能建立在任何表达式上或者包括 WHERE 子句。 当物化视图还未被填充时,这个选项不能被使用。 即使带有这个选项,对于任意一个物化视图一次也只能运行一个 “REFRESH“。 name 要刷新的物化视图的名称(可以被模式限定)。 示例 这个命令将使用物化视图 order_summary 定义中的查询来替换该物化视图的内容,并且让它处于一种可扫描的 状态: REFRESH MATERIALIZED VIEW order_summary; 这个命令将释放与物化视图 annual_statistics_basis 相关的存储并且让它变成一种不可扫描的状态: REFRESH MATERIALIZED VIEW annual_statistics_basis WITH NO DATA; 兼容性 REFRESH MATERIALIZED VIEW 是一种 KingbaseES 扩展 其他 虽然用于未来的CLUSTER 操作的默认索引会被保持,REFRESH MATERIALIZED VIEW 不会基于这个属性排序产 生的行。如果希望数据在产生时排序,必须在支持查询中使用 “ORDER BY“子句。 20.9 REINDEX 用途 REINDEX —重建索引 REINDEX 使用索引的表里存储的数据重建一个索引,并且替换该索引的旧拷贝。有一些场景需要使用 REINDEX: • 一个索引已经损坏,并且不再包含合法数据。尽管理论上这不会发生,实际上索引会因为软件缺陷或硬件失效 损坏。REINDEX 提供了一种恢复方法。 • 一个索引变得“臃肿”,其中包含很多空的或者近乎为空的页面。KingbaseES 中的 B-树索引在特定的非常规 访问模式下可能会发生这种情况。“REINDEX“提供了一种方法来减少索引的空间消耗,即制造一个新版本的索 引,其中没有死亡页面。详见 日常重建索引。 • 修改了一个索引的存储参数(例如填充因子),并且希望确保这种修改完全生效。 1207 第 20 章 SQL 语句: MERGE 到 VALUES • 如果 CONCURRENTLY 选项的索引构建失败,该索引被保留为“invalid”。这样的索引是无用的,但是可以方便 地使用 REINDEX 来重建它们。注意,只有 REINDEX INDEX 能够在无效索引上执行并发构建。 前置条件 无 语法 REINDEX [ ( VERBOSE ) ] { INDEX | TABLE | SCHEMA | DATABASE | SYSTEM } [ CONCURRENTLY ] name 语义 INDEX 重新创建指定的索引。 TABLE 重新创建指定表的所有索引。如果该表有一个二级“TOAST”表,它也会被重索引。 SCHEMA 重建指定方案的所有索引。如果这个方案中的一个表有次级的“TOAST”表,它也会被重建索引。共享系统 目录上的索引也会被处理。这种形式的 REINDEX 不能在事务块内执行。 DATABASE 重新创建当前数据库内的所有索引。共享的系统目录上的索引也会被处理。这种形式的 REINDEX 不能在一 个事务块内执行。 SYSTEM 重新创建当前数据库中在系统目录上的所有索引。共享系统目录上的索引也被包括在内。用户表上的索引则 不会被处理。这种形式的 REINDEX 不能在一个事务块内执行。 name 要被重索引的特定索引、表或者数据库的名字。索引和表名可以被模式限定。当前,REINDEX DATABASE 和 REINDEX SYSTEM 只能重索引当前数据库,因此它们的参数必须匹配当前数据库的名称。 CONCURRENTLY 当使用此选项时,KingbaseES 将重新构建索引,而不采取任何锁来防止表上的并发插入、更新或删 除; 而标准的索引重新构建将锁定表上的写操作 (而不是读操作),直到完成为止。在使用这个选项时需要注意几 个注意事项参见同时重建索引 _ . VERBOSE 在每个索引被重建时打印进度报告。 示例 重建单个索引: 1208 第 20 章 SQL 语句: MERGE 到 VALUES REINDEX INDEX my_index; 重建表 my_table 上的所有索引: REINDEX TABLE my_table; 重建一个特定数据库中的所有索引,且不假设系统索引已经可用: $ export KINGBASE_OPTIONS="-P" $ ksql broken_db ... broken_db=> REINDEX DATABASE broken_db; broken_db=> \q 重新建立表的索引,在重新建立索引的过程中不阻塞对相关关系的读写操作: REINDEX TABLE CONCURRENTLY my_broken_table; 兼容性 在 SQL 标准中没有 REINDEX 命令。 其他 如果怀疑一个用户表上的索引损坏,可以使用 REINDEX INDEX 或者 “REINDEX TABLE“简单地重建该索引或者 表上的所有索引。 如果你需要从一个系统表上的索引损坏中恢复,就更困难一些。在这种情况下,对系统来说重要的是没有使用过 任何可疑的索引本身(实际上,这种场景中,你可能会发现服务器进程会在启动时立刻崩溃,这是因为对于损坏的索 引的依赖)。要安全地恢复,服务器必须用 “-P“选项启动,这将阻止它使用索引来进行系统目录查找。 这样做的一种方法是关闭服务器,并且启动一个单用户的 KingbaseES 服务器,在其命令行中包括-P 选项。然 后,可以发出 “REINDEX DATABASE“、REINDEX SYSTEM、REINDEX TABLE 或者 REINDEX INDEX,具体使用哪个 命令取决于你想要重构多少东西。如果有疑问,可以使用 “REINDEX SYSTEM“来选择重建数据库中的所有系统索 引。然后退出单用户服务器会话并且重启常规的服务器。更多关于如何与单用户服务器接口交互的内容请见 kingbase 参考页。 在另一种方法中,可以开始一个常规的服务器会话,在其命令行选项中包括-P。这样做的方法与客户端有关,但 是在所有基于 libkci 的客户端中都可以在开始客户端之前设置 KINGBASE_OPTIONS 环境变量为-P。注意虽然这种方法 不要求用锁排斥其他客户端,在修复完成之前避免其他用户连接到受损的数据库才是更加明智的。 REINDEX 类似于删除索引并且重建索引,在其中索引内容会被从头开始建立。但是,锁定方面的考虑却相当不 同。REINDEX 会用锁排斥写,但不会排斥在索引的父表上的读。它也会在被处理的索引上取得一个排他锁,该锁将 会阻塞对该索引的使用尝试。相反,DROP INDEX 会暂时在附表上取得一个排他锁,阻塞写和读。后续的 CREATE INDEX 会排斥写但不排斥读,由于该索引不存在,所以不会有读取它的尝试,这意味着不会有阻塞但是读操作可能被 强制成昂贵的顺序扫描。 重索引单独一个索引或者表要求用户是该索引或表的拥有者。对方案或数据库重建索引要求是该方案或者数据库 的拥有者。注意因此非超级用户有时无法重建其他用户拥有的表上的索引。但是,作为一种特例,当一个非超级用户 1209 第 20 章 SQL 语句: MERGE 到 VALUES 发出 REINDEX DATABASE、REINDEX SCHEMA 或者 REINDEX SYSTEM 时,共享目录上的索引将被跳过,除非该用户拥 有该目录(通常不会是这样)。当然,超级用户总是可以重建所有的索引。 不支持重建分区表的索引或者分区索引。但是可以单独为每个分区重建索引。重建索引可能会干扰数据库的正常 操作。通常 KingbaseES 会锁定一个表,这个表的索引是根据写操作重新构建的,并且只扫描一次表就可以执行整个 索引构建。其他事务仍然可以读取表,但是如果它们试图插入、更新或删除表中的行,它们将阻塞这些行,直到完成 索引重建。如果系统是一个实时的生产数据库,这可能会产生严重的影响。非常大的表可能需要花费很多小时来建立 索引,甚至对于更小的表,重新构建索引可能会将编写者锁定在生产系统无法接受的长时间内。 KingbaseES 支持最小化写锁的重建索引。该方法调用 CONCURRENTLY 的 REINDEX 选项。当使用这个选项时, KingbaseES 必须为每个需要重建的索引执行两次表扫描,并等待可能使用该索引的所有现有事务的终止。与标准的 索引重建相比,此方法需要更多的总工作,而且完成所需的时间要长得多,因为它需要等待可能修改索引的未完成事 务。但是,由于它允许在重新构建索引时继续正常操作,所以此方法对于在生产环境中重新构建索引非常有用。的当 然,由索引重新生成的额外 CPU、内存和 I/O 负载可能会减慢其他操作。 在并发重索引中执行以下步骤。每个步骤都在一个单独的事务中运行。如果有多个索引需要重新构建,那么每个 步骤在进入下一个步骤之前循环遍历所有索引。 1. 一个新的临时索引定义被添加到目录 sys_index。此定义将用于替换旧索引。会话级别的 SHARE UPDATE EXCLUSIVE 锁对正在重编索引的索引及其关联表执行锁,以防止在处理时进行任何模式修改。 2. 为每个新索引完成构建索引的第一次遍历。一旦建立了索引,它的标志 sys_index.indisready 被切换为 “true”,以使它为插入做好准备,使它在执行构建的事务完成后对其他会话可见。此步骤在每个索引的单独 事务中完成。 3. 然后执行第二个遍历来添加在第一个遍历运行时添加的元组。此步骤也在每个索引的单独事务中完成。 4. 所有引用索引的约束都被更改为引用新的索引定义,索引的名称也被更改。此时,sys_index.indisvalid 是 转向“true”新指数和“false”, 缓存失效导致所有会话引用旧的索引失效。 5. 旧的索引由 sys_index.indisready 切换到“false”以防止任何新的元组插入,在等待可能引用旧索引的查询 完成之后。 6. 旧的索引被删除。索引和表的 SHARE UPDATE EXCLUSIVE 会话锁被释放。 如果在重新构建索引时出现问题,例如惟一索引中的唯一性冲突,则 REINDEX 命令将失败,但会留下一个“invalid”的新索引附加于已存在的索引。出于查询的目的,这个索引将被忽略,因为它可能是不完整的; 但是,它仍然 会消耗更新开销。ksql“d“命令将报告这样一个索引:INVALID: kingbase=# \d tab Table "public.tab" Column | Type | Modifiers --------+---------+----------col | integer | Indexes: "idx" btree (col) "idx_ccnew" btree (col) INVALID 在这种情况下,建议的恢复方法是删除无效的索引,然后再次尝试并发地执行 REINDEX CONCURRENTLY。在处理 1210 第 20 章 SQL 语句: MERGE 到 VALUES 过程中创建的并发索引的名称以后缀 ccnew,或 ccold(如果它是我们未能删除的旧索引定义) 结尾。可以使用 DROP INDEX 删除无效索引,包括无效的 toast 索引。 常规索引构建允许同一表上的其他常规索引构建同时发生,但是一次只能在一个表上发生一个并发索引构建。在 这两种情况下,不允许同时对表进行其他类型的模式修改。另一个区别是常规的 REINDEX TABLE 或 REINDEX INDEX 命令可以在一个事务块中执行,但是 REINDEX CONCURRENTLY 不能执行。 REINDEX SYSTEM 不支持 “CONCURRENTLY“,因为系统目录不能并发重索引。 此外,排除约束的索引不能并发地重新建立索引。如果在此命令中直接命名这样的索引,则会引发错误。如果具 有排它约束索引的表或数据库被并发地重新索引,那么这些索引将被跳过。(可以在不使用 CONCURRENTLY 选项的情 况下重新索引这些索引。) 20.10 REPLACE INTO 用途 REPLACE 功能与 INSERT 相似。向表里插入元组,只有一点除外,如果表中的一个已存在的元组与一个用于 PRIMARY KEY 或一个 UNIQUE 索引的新记录具有相同的值,则在新元组被插入之前,所有重复的旧元组被删除。 前置条件 KingbaseES 数据库初始化为 MySQL 模式。 为了向表中插入,你必须具有其上的 INSERT 特权。 如果一个列被指定,你只需要其中的列上的“INSERT“特权。 语法 REPLACE [INTO] tbl_name[(col_name_list)] VALUES (value_list)[,(value_list)...] [RETURNING col_name_list] REPLACE [INTO] tbl_name SET col_name = value[,col_name=value...] [RETURNING col_name_list] REPLACE [INTO] tbl_name [(col_name [, col_name] ...)] {SELECT ... | TABLE tbl_name} [RETURNING col_name_ list] 1211 第 20 章 SQL 语句: MERGE 到 VALUES 语义 语法中关键词的含义。 tbl_name 一个已有表的名称(可以被模式限定)。 value_list 期望插入的数据集。 value 目标列插入的数据。 col_name_list 期望插入值的目标列的集合。 成功完成时,INSERT 命令会返回以下形式的命令标签: INSERT oid count “count“是被插入的行数。 “oid“通常是 0(使用 OID 声明目标表,如果 “count“为 1;否则,使用 WITH OIDS 和 0 声明目标表,但是不再 支持使用 oid 创建表否则为 0,那么它通常是分配给插入行的 OID,但是不再支持使用 WITH OIDS 创建表)。 示例 -- 创建多个 UNIQUE/PRIMARY KEY 表 CREATE TABLE t1( a INT PRIMARY KEY, b INT UNIQUE, c INT DEFAULT 1 ); -- 插入非重复的元组 REPLACE INTO t1 VALUES(1,1,1); REPLACE INTO t1 SET a = 2, b = 2; 1212 第 20 章 SQL 语句: MERGE 到 VALUES SELECT * FROM t1; a | b | c ---+---+--1 | 1 | 1 2 | 2 | 1 -- 插入重复的元组 REPLACE INTO t1 VALUES(1,2,3); SELECT * FROM t1; a | b | c ---+---+--1 | 2 | 3 -- 子查询作为目标数据 REPLACE INTO t1 SELECT * FROM t1; SELECT * FROM t1; a | b | c ---+---+--1 | 2 | 3 -- RETURNING col_name_list REPLACE INTO t1 VALUES(3,3,3) RETURNING a,b,c; row --------(3,3,3) 注意: 如果表含有多个 UNIQUE/PRIMARY KEY 并且新元组中不同 UNIQUE/PRIMARY KEY 的值分别与多个 旧元组相对应的 UNIQUE KEY 相同,首先删除表中所有重复的元组,然后将新元组插入。例如上面的例子中,待插 入的新元组 TUPLE_NEW(1,2,3) 中的 a 列值为 1 和表中元组 TUPLE_OLD_1(1,1,1) 重复,b 列值为 2 和表中元 组 TUPLE_OLD_2(2,2,2) 重复,所以将重复的元组删除 (1,1,1)(2,2,2),然后插入新的元组 (1,2,3), 最后的结果集为 (1,2,3)。 兼容性 REPLACE INTO 是兼容 MySQL 的特性,在 MySQL 数据库中,如果 REPLACE INTO 插入的新元组和表中已 存在的元组数据完全相同时,只返回存在数据冲突的行数 (不会进行实际的插入新元组操作),否则返回插入的元组行 数与删除的元组行数和。但是在 KingbaseES 数据库中该功能返回影响行数为插入的新元组数与删除的元组数的和。 其他 如果指定的表是一个分区表,每一行都会被路由到合适的分区并且插入其中。如果指定的表是一个分区,如果输 1213 第 20 章 SQL 语句: MERGE 到 VALUES 入行之一违背该分区的约束则将发生错误。 20.11 RELEASE SAVEPOINT 用途 RELEASE SAVEPOINT —销毁一个之前定义的保存点 RELEASE SAVEPOINT 销毁在当前事务中之前定义的一个保存点。 销毁一个保存点会使得它不能再作为一个回滚点,但是它没有其他用户可见的行为。它不会撤销在该保存点被建 立之后执行的命令的效果(要这样做,可见ROLLBACK TO SAVEPOINT )。当不再需要一个保存点时销毁它允许 系统在事务结束之前回收一些资源。 RELEASE SAVEPOINT 也会销毁所有在该保存点建立之后建立的保存点。 前置条件 指定一个不是之前定义的保存点名称是错误。 当事务处于中止状态时不能释放保存点。 如果多个保存点具有相同的名称,只有最近被定义的那个会被释放。 语法 RELEASE [ SAVEPOINT ] savepoint_name 语义 savepoint_name 要销毁的保存点的名称。 示例 建立并且销毁一个保存点: BEGIN; INSERT INTO table1 VALUES (3); SAVEPOINT my_savepoint; INSERT INTO table1 VALUES (4); RELEASE SAVEPOINT my_savepoint; COMMIT; 上述事务将插入 3 和 4。 1214 第 20 章 SQL 语句: MERGE 到 VALUES 兼容性 这个命令符合 SQL 标准。该标准指定关键词 “SAVEPOINT“是强制需要的,但 KingbaseES 允许省略。 20.12 RESET 用途 RESET —把一个运行时参数的值恢复到默认值 RESET 把运行时参数恢复到它们的默认值。RESET 是 SET configuration_parameter TO DEFAULT 的另一种写法。详见SET 。 前置条件 无 语法 RESET configuration_parameter RESET ALL 语义 configuration_parameter 一个可设置的运行时参数名称。可用的参数记录在《数据库参考手册》以及SET 参考页 中。 ALL 把所有可设置的运行时参数重置为默认值。 示例 把 timezone 配置变量设置为默认值: RESET timezone; 兼容性 RESET 是一种 KingbaseES 扩展。 其他 1215 第 20 章 SQL 语句: MERGE 到 VALUES 默认值被定义为如果在当前会话中没有发出过 SET,参数必须具有的值。这个值的实际来源可能是一个编译在内 部的默认值、配置文件、命令行选项、或者针对每个数据库或者每个用户的默认设置。这和把它定义成“在会话开始 时该参数得到的值”有细微的差别,因为如果该值来自于配置文件,它将被重置为现在配置文件所指定的任何东西。 详见《数据库参考手册》。 RESET 的事务行为和 SET 相同:它的效果会被事务回滚撤销。 20.13 REVOKE 用途 REVOKE 命令收回之前从一个或者更多角色授予的特权。关键词 PUBLIC 隐式定义的全部角色的组。 特权类型的含义见GRANT 命令的描述。 注意任何特定角色拥有的特权包括直接授予给它的特权、从它作为其成员的角色中得到的特权以及授予给 PUBLIC 的特权。因此,从 PUBLIC 收回 SELECT 特权并不一定会意味着所有角色都会失去在该对象上的 SELECT 特 权:那些直接被授予的或者通过另一个角色被授予的角色仍然会拥有它。类似地,从一个用户收回 SELECT 后,如果 PUBLIC 或者另一个成员关系角色仍有 SELECT 权利,该用户还是可以使用 SELECT。 如果指定了 GRANT OPTION FOR,只会回收该特权的授予选项,特权本身不被回收。否则,特权及其授予选项都 会被回收。 如果一个用户持有一个带有授予选项的特权并且把它授予给了其他用户,那么被那些其他用户持有的该特权被称 为依赖特权。如果第一个用户持有的该特权或者授予选项正在被收回且存在依赖特权,指定 CASCADE 可以连带回收 那些依赖特权,不指定则会导致回收动作失败。这种递归回收只影响通过可追溯到该 REVOKE 命令的主体的用户链授 予的特权。因此,如果该特权经由其他用户授予给受影响用户,受影响用户可能实际上还保留有该特权。 在回收一个表上的特权时,也会在该表的每一个列上自动回收对应的列特权(如果有)。在另一方面,如果一个 角色已经被授予一个表上的特权,那么从个别的列上回收同一个特权将不会生效。 在回收一个角色中的成员关系时,GRANT OPTION 被改称为 ADMIN OPTION,但行为是类似的。也要注意这种形 式的命令不允许噪声词 GROUP。 前置条件 用户只能回收由它直接授出的特权。例如,如果用户 A 已经把一个带有授予选项的特权授予给了用户 B,并且 用户 B 接着把它授予给了用户 C,那么用户 A 无法直接从 C 收回该特权。反而,用户 A 可以从用户 B 收回该授予 选项并且使用 CASCADE 选项,这样该特权会被依次从用户 C 回收。对于另一个例子,如果 A 和 B 都把同一个特权 授予给了 C,A 能够收回它们自己的授权但不能收回 B 的授权,因此 C 实际上仍将拥有该特权。 当一个对象的非拥有者尝试 REVOKE 该对象上的特权时,如果该用户在该对象上什么特权都不拥有,该命令会立 刻失败。只要有某个特权可用,该命令将继续,但是它只会收回那些它具有授予选项的特权。如果没有持有授予选 项,REVOKE ALL PRIVILEGES 形式将发出一个警告,而其他形式在没有持有该命令中特别提到的任何特权的授予选 项时就会发出警告(原则上,这些语句也适用于对象拥有者,但是由于拥有者总是被认为持有所有授予选项,这些情 况永远不会发生)。 1216 第 20 章 SQL 语句: MERGE 到 VALUES 如果一个超级用户选择发出一个 GRANT 或者 “REVOKE“命令,该命令就好像被受影响对象的拥有者发出的一样 被执行。因为所有特权最终来自于对象拥有者(可能是间接地通过授予选项链),可以由超级用户收回所有特权,但 是这可能需要前述的 “CASCADE“。 REVOKE 也可以由一个并非受影响对象的拥有者的角色完成,但是该角色应该是一个拥有该对象的角色的成员或 者是一个在该对象上拥有特权的 WITH GRANT OPTION 的角色的成员。在这种情况中,该命令就好像被实际拥有该对 象或者特权的 WITH GRANT OPTION 的包含角色发出的一样被执行。例如,如果表 t1 被角色 g1 拥有,而 u1 是 g1 的一个成员,那么 u1 能收回 t1 上被记录为由 g1 授出的特权。这会包括由 u1 以及由角色 g1 的其他成员完成的授 予。 如果执行 REVOKE 的角色持有通过多于一条角色成员关系路径间接得到的特权,其中哪一条包含将被用于执行该 命令的角色是没有被指明的。在这种情况中,最好使用 SET ROLE 成为你想作为其身份执行 REVOKE 的特定角色。如 果无法做到这一点可能会导致回收超过你预期的特权,或者根本回收不了任何东西。 查看 权限获得更多关于特定特权类型的信息,以及如何检查对象的特权。 语法 REVOKE [ GRANT OPTION FOR ] { { SELECT | INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES | TRIGGER } [, ...] | ALL [ PRIVILEGES ] } ON { [ TABLE ] table_name [, ...] | ALL TABLES IN SCHEMA schema_name [, ...] } FROM { [ GROUP ] role_name | PUBLIC } [, ...] [ CASCADE | RESTRICT ] REVOKE [ GRANT OPTION FOR ] { { SELECT | INSERT | UPDATE | REFERENCES } ( column_name [, ...] ) [, ...] | ALL [ PRIVILEGES ] ( column_name [, ...] ) } ON [ TABLE ] table_name [, ...] FROM { [ GROUP ] role_name | PUBLIC } [, ...] [ CASCADE | RESTRICT ] REVOKE [ GRANT OPTION FOR ] { { USAGE | SELECT | UPDATE } [, ...] | ALL [ PRIVILEGES ] } ON { SEQUENCE sequence_name [, ...] | ALL SEQUENCES IN SCHEMA schema_name [, ...] } FROM { [ GROUP ] role_name | PUBLIC } [, ...] [ CASCADE | RESTRICT ] REVOKE [ GRANT OPTION FOR ] { { CREATE | CONNECT | TEMPORARY | TEMP } [, ...] | ALL [ PRIVILEGES ] } ON DATABASE database_name [, ...] FROM { [ GROUP ] role_name | PUBLIC } [, ...] [ CASCADE | RESTRICT ] 1217 第 20 章 SQL 语句: MERGE 到 VALUES REVOKE [ GRANT OPTION FOR ] { USAGE | ALL [ PRIVILEGES ] } ON DOMAIN domain_name [, ...] FROM { [ GROUP ] role_name | PUBLIC } [, ...] [ CASCADE | RESTRICT ] REVOKE [ GRANT OPTION FOR ] { USAGE | ALL [ PRIVILEGES ] } ON FOREIGN DATA WRAPPER fdw_name [, ...] FROM { [ GROUP ] role_name | PUBLIC } [, ...] [ CASCADE | RESTRICT ] REVOKE [ GRANT OPTION FOR ] { USAGE | ALL [ PRIVILEGES ] } ON FOREIGN SERVER server_name [, ...] FROM { [ GROUP ] role_name | PUBLIC } [, ...] [ CASCADE | RESTRICT ] REVOKE [ GRANT OPTION FOR ] { EXECUTE | ALL [ PRIVILEGES ] } ON { { FUNCTION | PROCEDURE | ROUTINE | PACKAGE } function_name [ ( [ [ argmode ] [ arg_name ] arg_type [, ...] ] ) ] [, ...] | ALL { FUNCTIONS | PROCEDURES | ROUTINES } IN SCHEMA schema_name [, ...] } FROM { [ GROUP ] role_name | PUBLIC } [, ...] [ CASCADE | RESTRICT ] REVOKE [ GRANT OPTION FOR ] { USAGE | ALL [ PRIVILEGES ] } ON LANGUAGE lang_name [, ...] FROM { [ GROUP ] role_name | PUBLIC } [, ...] [ CASCADE | RESTRICT ] REVOKE [ GRANT OPTION FOR ] { { SELECT | UPDATE } [, ...] | ALL [ PRIVILEGES ] } ON LARGE OBJECT loid [, ...] FROM { [ GROUP ] role_name | PUBLIC } [, ...] [ CASCADE | RESTRICT ] REVOKE [ GRANT OPTION FOR ] { { CREATE | USAGE } [, ...] | ALL [ PRIVILEGES ] } ON SCHEMA schema_name [, ...] FROM { [ GROUP ] role_name | PUBLIC } [, ...] [ CASCADE | RESTRICT ] 1218 第 20 章 SQL 语句: MERGE 到 VALUES REVOKE [ GRANT OPTION FOR ] { CREATE | ALL [ PRIVILEGES ] } ON TABLESPACE tablespace_name [, ...] FROM { [ GROUP ] role_name | PUBLIC } [, ...] [ CASCADE | RESTRICT ] REVOKE [ GRANT OPTION FOR ] { USAGE | ALL [ PRIVILEGES ] } ON TYPE type_name [, ...] FROM { [ GROUP ] role_name | PUBLIC } [, ...] [ CASCADE | RESTRICT ] REVOKE [ ADMIN OPTION FOR ] role_name [, ...] FROM role_name [, ...] [ CASCADE | RESTRICT ] 1219 第 20 章 SQL 语句: MERGE 到 VALUES 1220 第 20 章 SQL 语句: MERGE 到 VALUES 语义 无 示例 从 public 收回表 films 上的插入特权: REVOKE INSERT ON films FROM PUBLIC; 从用户 manuel 收回视图 kinds 上的所有特权: REVOKE ALL PRIVILEGES ON kinds FROM manuel; 注意着实际意味着“收回所有我授出的特权”。 从用户 joe 收回角色 admins 中的成员关系: REVOKE admins FROM joe; 兼容性 GRANT 命令的兼容性注解同样适用于 REVOKE。根据标准,关键词 RESTRICT 或 CASCADE 是必要的,但是 KingbaseES 默认假定为 RESTRICT。 20.14 ROLLBACK 用途 ROLLBACK 回滚当前事务并且导致该事务所作的所有更新都被抛弃。 前置条件 在事务中 语法 ROLLBACK [ WORK | TRANSACTION ] [ AND [ NO ] CHAIN ] 1221 第 20 章 SQL 语句: MERGE 到 VALUES 语义 WORK | TRANSACTION 可选关键词,没有效果。 AND CHAIN 如果指定了 AND CHAIN,则立即启动具有与刚刚完成的事务相同的事务特征的新事务 (参见SET TRANSACTION )。否则,不会启动任何新事务。 示例 要回滚所有更改: ROLLBACK; 兼容性 ROLLBACK 命令符合 SQL 标准。ROLLBACK TRANSACTION 是一个 KingbaseES 扩展。 20.15 ROLLBACK PREPARED 用途 ROLLBACK PREPARED —取消一个之前为两阶段提交准备好的事务 ROLLBACK PREPARED 回滚一个处于准备好状态的事务 前置条件 要回滚一个准备好的事务,你必须是原先执行该事务的同一个用户或者是一个超级用户。但是你必须处在执行该 事务的同一个会话中。 语法 ROLLBACK PREPARED transaction_id 语义 transaction_id 要被回滚的事务的事务标识符。 1222 第 20 章 SQL 语句: MERGE 到 VALUES 示例 用事务标识符 foobar 回滚对应的事务: ROLLBACK PREPARED 'foobar'; 兼容性 ROLLBACK PREPARED 是一种 KingbaseES 扩展。其意图是用于外部事务管理系统,其中有些已经被标准涵盖(例 如 X/Open XA),但是那些系统的 SQL 方面未被标准化。 其他 这个命令不能在一个事务块内被执行。准备好的事务会被立刻回滚。 sys_prepared_xacts 系统视图中列出了当前可用的所有准备好的事务。 20.16 ROLLBACK TO SAVEPOINT 用途 ROLLBACK TO SAVEPOINT —回滚到一个保存点 回滚在该保存点被建立之后执行的所有命令。该保存点保持有效并且可以在以后再次回滚到它(如果需要)。 ROLLBACK TO SAVEPOINT 隐式地销毁在所提及的保存点之后建立的所有保存点。 前置条件 保存点需要提前先建立好 语法 ROLLBACK [ WORK | TRANSACTION ] TO [ SAVEPOINT ] savepoint_name 语义 savepoint_name 要回滚到的保存点。 示例 要撤销在 my_savepoint 建立后执行的命令的效果: 1223 第 20 章 SQL 语句: MERGE 到 VALUES ROLLBACK TO SAVEPOINT my_savepoint; 游标位置不会受保存点回滚的影响: BEGIN; DECLARE foo CURSOR FOR SELECT 1 UNION SELECT 2; SAVEPOINT foo; FETCH 1 FROM foo; ?column? ---------1 ROLLBACK TO SAVEPOINT foo; FETCH 1 FROM foo; ?column? ---------2 COMMIT; 兼容性 SQL 标准指定关键词 SAVEPOINT 是强制的,但是 KingbaseES 和 Oracle 允许省略它。SQL 只允许 WORK 而不是 TRANSACTION 作为 ROLLBACK 之后的噪声词。还有,SQL 有一个可选的子句 AND [ NO ] CHAIN,当前 KingbaseES 并不支持。在其他方面,这个命令符合 SQL 标准。 其他 使用RELEASE SAVEPOINT 销毁一个保存点而不抛弃在它建立之后被执行的命令的效果。 指定一个没有被建立的保存点是一种错误。 相对于保存点,游标有一点非事务的行为。在保存点被回滚时,任何在该保存点内被打开的游标将会被关闭。如 果一个先前打开的游标在一个保存点内被 “FETCH“或 MOVE 命令所影响,而该该保存点后来又被回滚,那么该游标 将保持 FETCH 使它指向的位置(也就是说由 FETCH 导致的游标动作不会被回滚)。回滚也不能撤销关闭一个游标。 但是,其他由游标查询导致的副作用(例如被该查询所调用的易变函数的副作用)可以被回滚,只要它们发生在一个 后来被回滚的保存点期间。如果一个游标的执行导致事务中止,它会被置于一种不能被执行的状态,这样当事务被用 ROLLBACK TO SAVEPOINT 恢复后,该游标也不再能被使用。 1224 第 20 章 SQL 语句: MERGE 到 VALUES 20.17 SAVEPOINT 用途 SAVEPOINT 在当前事务中建立一个新保存点。 保存点是事务内的一种特殊标记,它允许所有在它被建立之后执行的命令被回滚,把该事务的状态恢复到它处于 保存点时的样子。 前置条件 保存点只能在一个事务块内建立。可以在一个事务内定义多个保存点。 语法 SAVEPOINT savepoint_name 语义 savepoint_name 给新保存点的名字。 示例 要建立一个保存点并且后来撤销在它建立之后执行的所有命令的效果: BEGIN; INSERT INTO table1 VALUES (1); SAVEPOINT my_savepoint; INSERT INTO table1 VALUES (2); ROLLBACK TO SAVEPOINT my_savepoint; INSERT INTO table1 VALUES (3); COMMIT; 上面的事务将插入值 1 和 3,但不会插入 2。 要建立并且稍后销毁一个保存点: BEGIN; INSERT INTO table1 VALUES (3); SAVEPOINT my_savepoint; INSERT INTO table1 VALUES (4); RELEASE SAVEPOINT my_savepoint; COMMIT; 上面的事务将插入 3 和 4。 兼容性 1225 第 20 章 SQL 语句: MERGE 到 VALUES 当建立另一个同名保存点时,SQL 标准要求之前的那个保存点自动被销毁。在 KingbaseES 中,旧的保存点会被 保留,但是在进行回滚或释放时只能使用最近的那一个(用 RELEASE SAVEPOINT 释放较新的保存点将会导致较旧的 保存点再次变得可以被 ROLLBACK TO SAVEPOINT 和 RELEASE SAVEPOINT 访问)。在其他方面,SAVEPOINT 完全符合 SQL。 其他 使用 ROLLBACK TO 回滚到一个保存点。使用RELEASE SAVEPOINT 销毁一个保存点,但保持在它被建立之 后执行的命令的效果。 20.18 SECURITY LABEL 用途 SECURITY LABEL —定义或更改应用到一个对象的安全标签 SECURITY LABEL 对一个数据库对象应用一个安全标签。可以把任意数量的安全标签(每个标签提供者对应一 个)关联到一个给定的数据库对象。标签提供者是使用函数“register_label_provider“注册自己的可装载模块。 注意: register_label_provider 不是一个 SQL 函数,它只能在被载入到后端的 C 代码中调用。 前置条件 无 语法 SECURITY LABEL [ FOR provider ] ON { TABLE object_name | COLUMN table_name.column_name | AGGREGATE aggregate_name ( aggregate_signature ) | DATABASE object_name | DOMAIN object_name | EVENT TRIGGER object_name | FOREIGN TABLE object_name FUNCTION function_name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ] | LARGE OBJECT large_object_oid | MATERIALIZED VIEW object_name | [ PROCEDURAL ] LANGUAGE object_name | PUBLICATION object_name | ROLE object_name | SCHEMA object_name | SEQUENCE object_name | SUBSCRIPTION object_name | 1226 第 20 章 SQL 语句: MERGE 到 VALUES TABLESPACE object_name | TYPE object_name | VIEW object_name } IS 'label' 其中 aggregate_signature 是: * | [ argmode ] [ argname ] argtype [ , ... ] | [ [ argmode ] [ argname ] argtype [ , ... ] ] ORDER BY [ argmode ] [ argname ] argtype [ , ... ] 1227 第 20 章 SQL 语句: MERGE 到 VALUES 语义 object_name | table_name.column_name | aggregate_name | function_name 要被贴上标签的对象的名称。表、聚集、域、外部表、函数、序列、类型和视图的名称可以是模式限定 的。 provider 这个标签相关联的提供者的名称。所提到的提供者必须已被载入并且必须赞同所提出的标签操作。如果正 好只载入了一个提供者,可以出于简洁的需要忽略提供者的名称。 argmode 一个函数或者聚集参数的模式:IN、OUT、INOUT 或者 VARIADIC。如果被忽略,默认值会是 IN。注意 SECURITY LABEL 并不真正关心 OUT 参数,因为判断函数的身份时只需要输入参数。因此列出 IN、INOUT 和 VARIADIC 参数足矣。 argname 一个函数或者聚集参数的名称。注意 SECURITY LABEL 并不真正关心参数的名称,因为判断函数的身份时 只需要参数的数据类型。 argtype 一个函数或聚集参数的数据类型。 large_object_oid 大对象的 OID。 PROCEDURAL 这是一个噪声词。 label 写成一个字符串文本的新安全标签。如果写成 NULL 表示删除原有的安全标签。 示例 下面的例子展示了如何更改一个表的安全标签。 SECURITY LABEL FOR selinux ON TABLE mytable IS 'system_u:object_r: sekbsql_table_t:s0'; 兼容性 在 SQL 标准中没有 SECURITY LABEL 命令。 其他 标签提供者决定一个给定标签是否合法并且它是否可以被分配该标签给一个给定对象。一个给定标签的含义也同 样由标签提供者判断。KingbaseES 没有对一个标签提供者是否必须或者如何解释安全标签做出限定,它仅仅只是提 1228 第 20 章 SQL 语句: MERGE 到 VALUES 供了一种机制来存储它们。实际上,这个功能是为了允许与基于标签的强制访问控制(MAC)系统集成(例如 SELinux)。这类系统会基于对象标签而不是传统的自主访问控制(DAC)概念(例如用户和组)做出所有访问控制决 定。 20.19 SELECT 用途 SELECT, TABLE, WITH —从一个表或视图检索行。 SELECT 从零或更多表中检索行。SELECT 的通常处理如下: 1. WITH 列表中的所有查询都会被计算。这些查询实际充当了在 FROM 列表中可以引用的临时表。在 FROM 中被引 用多次的 WITH 查询只会被计算一次。unless specified otherwise with NOT MATERIALIZED. 2. FROM 列表中的所有元素都会被计算(FROM 中的每一个元素都是一个真实表或者虚拟表)。如果在 FROM 列表中 指定了多于一个元素,它们会被交叉连接在一起。 3. 如果指定了 WHERE 子句,所有不满足该条件的行都会被从输出中消除。 4. 如果指定了 GROUP BY 子句或者如果有聚集函数,输出会被组合成由在一个或者多个值上匹配的行构成的分 组,并且在其上计算聚集函数的结果。如果出现了 HAVING 子句,它会消除不满足给定条件的分组。 5. 对于每一个被选中的行或者行组,会使用 SELECT 输出表达式计算实际的输出行。 6. SELECT DISTINCT 从结果中消除重复的行。SELECT DISTINCT ON 消除在所有指定表达式上匹配的行。SELECT ALL(默认)将返回所有候选行,包括重复的行。同时 KingbaseES 中的 SELECT UNIQUE 也可以从结果中消除 重复的行。SELECT UNIQUE ON 消除在所有指定表达式上匹配的行。SELECT ALL(默认)将返回所有候选行, 包括重复的行。 7. 通过使用操作符 UNION、INTERSECT 和 EXCEPT,多于一个 SELECT 语句的输出可以被整合形成一个结果集。 UNION 操作符返回位于一个或者两个结果集中的全部行。INTERSECT 操作符返回同时位于两个结果集中的所有 行。EXCEPT 操作符返回位于第一个结果集但不在第二个结果集中的行。在所有三种情况下,重复行都会被消除 (除非指定 ALL)。可以增加噪声词 DISTINCT 来显式地消除重复行。注意虽然 ALL 是 SELECT 自身的默认行 为,但这里 DISTINCT 是默认行为。 8. 如果指定了 ORDER BY 子句,被返回的行会以指定的顺序排序。如果没有给定 ORDER BY,系统会以能最快产生 行的顺序返回它们(。 9. 如果指定了 LIMIT(或 FETCH FIRST)或者 OFFSET 子句,SELECT 语句只返回结果行的一个子集。 10. 如果指定了 FOR UPDATE、FOR NO KEY UPDATE、FOR SHARE 或者 FOR KEY SHARE,SELECT 语句会把被选中的 行锁定而不让并发更新访问它们。 前置条件 必须拥有在一个 SELECT 命令中使用的每一列上的 SELECT 特权。FOR NO KEY UPDATE、FOR UPDATE、FOR SHARE 或者 FOR KEY SHARE 还要求(对这样选中的每一个表至少一列的)UPDATE 特权。 语法 1229 第 20 章 SQL 语句: MERGE 到 VALUES [ WITH [ RECURSIVE ] with_query [, ...] ] SELECT [ ALL | DISTINCT | UNIQUE [ ON ( expression [, ...] ) ] ] [ * | expression [ [ AS ] output_name ] [, ...] ] [ FROM from_item [, ...] ] [ WHERE condition ] [ 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 ] [ NULLS { FIRST | LAST } ] [, ...] ] [ LIMIT { 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 | SKIP LOCKED | WAIT seconds] [...] ] 1230 第 20 章 SQL 语句: MERGE 到 VALUES 图 20.19.1: 其中 from_item 可以是以下之一: 1231 第 20 章 SQL 语句: MERGE 到 VALUES [ ONLY ] table_name [ * ] [ @dblink ][part_extension_clause] [ [ AS ] alias [ ( column_alias [, ...] ) ] ] [ [ AS OF { TIMESTAMP | CSN | SCN } asof_item ] | [ VERSIONS BETWEEN { TIMESTAMP | CSN | SCN } start_item AND end_item ] ] [ TABLESAMPLE sampling_method ( argument [, ...] ) [ REPEATABLE ( seed ) ] ] Part_extension_clause: { PARTITION (patition) | PARTITION FOR (partition_key_value [, partition_key_value]…) | SUBPARTITION (subpartition) | SUBPARTITION FOR (subpartition_key_value [, subpartition_key_value]…) } 1232 第 20 章 SQL 语句: MERGE 到 VALUES [ ONLY ] table_name SAMPLE [BLOCK]( sample_percent ) [ SEED ( seed_value ) ] [ [ AS ] alias [ ( column_alias [, ...] ) ] ] [ LATERAL ] ( select ) [ AS ] alias [ ( column_alias [, ...] ) ] with_query_name [ [ AS ] alias [ ( column_ alias [, ...] ) ] ] [ LATERAL ] function_name ( [ argument [, ...] ] ) [ WITH ORDINALITY ] [ [ AS ] alias [ ( column_alias [, ...] ) ] ] [ LATERAL ] function_name ( [ argument [, ...] ] ) [ AS ] alias ( column_definition [, ...] ) [ LATERAL ] function_name ( [ argument [, ...] ] ) AS ( column_definition [, ...] ) [ LATERAL ] ROWS FROM( function_name ( [ argument [, ...] ] ) [ AS ( column_definition [, ...] ) ] [, ...] ) [ WITH ORDINALITY ] [ [ AS ] alias [ ( column_alias [, ...] ) ] ] from_item [ NATURAL ] join types from_item [ ON join_condition | USING ( join_column [, ...] ) ] 1233 第 20 章 SQL 语句: MERGE 到 VALUES 图 20.19.2: 并且 grouping_element 可以是以下之一: ( ) expression ( expression [, ...] ) ROLLUP ( { expression | ( expression [, ...] ) } [, ...] ) CUBE ( { expression | ( expression [, ...] ) } [, ...] ) GROUPING SETS ( grouping_element [, ...] ) 1234 第 20 章 SQL 语句: MERGE 到 VALUES 图 20.19.3: 并且 with_query 是: with_query_name [ ( column_name [, ...] ) ] AS [ [ NOT ] MATERIALIZED ] ( select | values | insert | update | delete ) TABLE [ ONLY ] table_name [ * ] plsql_declarations 1235 第 20 章 SQL 语句: MERGE 到 VALUES 语义 1. WITH 子句 WITH 子句允许你指定一个或者多个在主查询中可以其名称引用的子查询。在主查询期间子查询实际扮演了临时 表或者视图的角色。每一个子查询都可以是一个 SELECT、TABLE、VALUES、INSERT、UPDATE 或者 DELETE 语句。在 WITH 中书写一个数据修改语句(INSERT、UPDATE 或者 DELETE)时,通常要包括一个 RETURNING 子句。构成被主查 询读取的临时表的是 RETURNING 的输出,而不是该语句修改的底层表。如果省略 RETURNING,该语句仍会被执行, 但是它不会产生输出,因此它不能作为一个表从主查询引用。 对于每一个 WITH 查询,都必须指定一个名称(无需模式限定)。可选地,可以指定一个列名列表。如果省略该 列表,会从该子查询中推导列名。 如果指定了 RECURSIVE,则允许一个 SELECT 子查询使用名称引用自身。这样一个子查询的形式必须是 non_recursive_term UNION [ ALL | DISTINCT ] recursive_term 其中递归自引用必须出现在 UNION 的右手边。每个查询中只允许一个递归自引用。不支持递归数据修改语句, 但是可以在一个数据查询语句中使用一个递归 SELECT 查询的结果。例子可见 WITH 查询。 RECURSIVE 的另一个效果是 WITH 查询不需要被排序:一个查询可以引用另一个在列表中比它靠后的查询(但 是,循环引用或者互递归没有实现)。如果没有 RECURSIVE,WITH 查询只能引用在 WITH 列表中位置更前面的兄弟 WITH 查询。 主查询以及 WITH 查询全部(理论上)在同一时间被执行。这意味着从该查询的任何部分都无法看到 WITH 中的 一个数据修改语句的效果,但是可以读取其 RETURNING 输出。如果两个这样的数据修改语句尝试修改相同的行,结 果将无法确定。 WITH 查询的关键属性是,在每次执行主查询时,它们通常只被求值一次,即使主查询不止一次地引用它们。特 别是,数据修改语句保证只执行一次,而不管主查询是否读取所有或任何输出。 1236 第 20 章 SQL 语句: MERGE 到 VALUES 但是,WITH 查询能够标记为 NOT MATERIALIZED 来移除此保证。在这种情况下,WITH 查询可以折叠成主查询, 就像它是在主查询的 FROM 子句中一个简单的 SELECT。如果主查询多次引用 WITH 查询,则会导致重复计算; 但是, 如果每个这样的使用只需要 WITH 查询的总输出的几行数据,NOT MATERIALIZED 可以通过允许联合优化查询来提供 净节省。NOT MATERIALIZED 将被忽略,如果它是递归或者不是无副作用的 WITH 查询附加的 (例如:,不是一个普通 的 SELECT 不包含 volatile functions)。 默认情况下,如果在主查询的 FROM 子句中仅使用一次,那么无副作用的 WITH 查询将被折叠到主查询中。这允 许在语义不可见的情况下联合优化两个查询级别。但是,可以通过将 WITH 查询标记为 MATERIALIZED 来防止这种折 叠。这可能是有用的,例如,如果 WITH 查询被用作一个优化围栏,以防止计划员选择一个糟糕的计划。在 v12 之前 的版本中,KingbaseES 从未做过这样的折叠,所以为旧版本编写的查询可能依赖于 WITH 来充当优化屏障。 更多信息请见 WITH 查询。 2. FROM 子句 FROM 子句为 SELECT 指定一个或者更多源表。如果指定了多个源表,结果将是所有源表的笛卡尔积(交叉连 接)。但是通常会增加限定条件(通过 WHERE)来把返回的行限制为该笛卡尔积的一个小子集。 FROM 子句可以包含下列元素: table_name 一个现有表或视图的名称(可以是模式限定的)。如果在表名前指定了 ONLY,则只会扫描该表。如果没 有指定 ONLY,该表及其所有后代表(如果有)都会被扫描。可选地,可以在表名后指定 * 来显式地指示包括后 代表。 @dblink 在 SELECT 语句的 FROM 子句中,用户可以直接在远程数据库对象名称后加 @dblink 来指定一个外部数 据库中的对象。- 访问形式:remote-obj@dblink - 对象名称:支持限定名(schema.name 格式)- 远程对象:可 以是表、视图、物化视图。对象类型对本地数据库透明。 part_extension_clause 支持通过 partitionsubpartition 关键字指定分区名或者子分区名,实现对分区和子分区直接 进行 select 操作。其中 PARTITION FOR(partition_key_value) 指定分区键值,PARTITION (partition)指 定分区名,这里的分区名是指 oralce 语法创建分区表时指定的分区名,而不是分区对象在系统表 sys_class 中 存储的对象名。 alias 一个包含别名的 FROM 项的替代名称。别名被用于让书写简洁或者消除自连接中的混淆(其中同一个表会被扫 描多次)。当提供一个别名时,表或者函数的实际名称会被隐藏。例如,给定 FROM foo AS f,SELECT 的剩 余部分就必须以 f 而不是 foo 来引用这个 FROM 项。如果写了一个别名,还可以写一个列别名列表来为该表的 一个或者多个列提供替代名称。 asof_item “table_name“之后的 “AS OF“子句表示应用闪回查询的功能。闪回查询可以通过指定时间戳 (timestamp)、csn 两种方式进行查询。asof_item 即通过时间戳 (timestamp) 或者 csn 进行闪回查询的时候的一个 历史快照时刻的表达式。 更多信息请见《transplant-oracle 》中的闪回技术。 start_item 和 end_item “table_name“之后的 “VERSIONS BETWEEN“子句表示应用闪回查询的版本历史查询功 能,和 “AS OF“子句里类似,也可以通过时间戳 (timestamp)、csn 两种方式进行查询。闪回版本查询通过指定 起始的快照时刻即:start_item``和结束的快照时刻``end_item,返回这段时间内的所有可见的版本。 更多信息请见《transplant-oracle 》中的闪回技术。 1237 第 20 章 SQL 语句: MERGE 到 VALUES TABLESAMPLE sampling_method ( argument [, ...] ) [ REPEATABLE ( seed ) ] “table_name“之后的 TABLESAMPLE 子句表示应该用指定的 “sampling_method“ 来检索表中行的子集。这种采样优先于任何其他过滤器(例如 WHERE 子句)。标准 KingbaseES 发布包括两种采样方法:BERNOULLI 和 SYSTEM,其他采样方法可以通过扩 展安装在数据库中。 BERNOULLI 以及 SYSTEM 采样方法都接受一个 “参数 “,它表示要采样的表的分数,表示为一个 0 到 100 之间 的百分数。这个参数可以是任意的 实数值表达式(其他的采样方法可能接受更多或者不同的参数)。这两种方 法都返回一个随机选取的该表采样,其中包含了指定百分数的表行。BERNOULLI 方法扫描整个表并且用指定的 几率选择或者忽略行。SYSTEM 方法会做块层的采样,每个块都有指定的机会能被选中,被选中块中的所有行都 会被返回。在指定较小的采样百分数时,SYSTEM 方法要比 BERNOULLI 方法快很多,但是前者可能由于聚簇效 应返回随机性较差的表采样。 可选的 REPEATABLE 子句指定一个用于产生采样方法中随机数的 “种子 “数或表达式。种子值可以是任何非空浮 点值。如果查询时表没有被更改,指定相同种子和 “argument“值的两个查询将会选择该表相同的采样。但是不 同的种子值通常将会产生不同的采样。如果没有给出 REPEATABLE,则会基于一个系统产生的种子为每一个查 询选择一个新的随机采样。注意有些扩展采样方法不接受 REPEATABLE,并且将总是为每一次使用产生新的采 样。 SAMPLE [BLOCK] ( sample_percent ) [ SEED ( seed_value ) ] “table_name“之后的 SAMPLE 子句表示应该用指定 的采样模式来检索表中行的子集。这种采样优先于任何其他过滤器(例如 WHERE 子句)。可选项 BLOCK 表 示块采样,同 TABLESAMPLE 子句中的 SYSTEM。不带 BLOCK 选项表示行采样,同 TABLESAMPLE 子句中的 BERNOULLI。 sample_percent 它表示每行或每块的采样概率,为一个 0 到 100 之间(包含 100)的百分数。这个参数可以是 任意的 实数值表达式。 可选的 SEED 子句指定一个用于产生采样方法中随机数的 “种子 “数或表达式。seed_value 种子值是无 符号整数,允许输入小数,但只会取其整数部分。如果查询时表没有被更改,指定相同 “sample_percent“和 “seed_value“值的两个查询将会选择该表相同的采样。但是不同的种子值通常将会产生不同的采样。如果没有 给出 SEED,则会基于一个系统产生的种子为每一个查询选择一个新的随机采样。 select 一个子-SELECT 可以出现在 FROM 子句中。这就好像把它的输出创建为一个存在于该 SELECT 命令期间的临时 表。注意子-SELECT 必须用圆括号包围,并且必须为它提供一个别名。也可以在这里使用一个VALUES 命令。 with_query_name 可以通过写一个 WITH 查询的名称来引用它,就好像该查询的名称是一个表名(实际上,该 WITH 查询会为主查询隐藏任何具有相同名称的真实表。如果必要,你可以使用带模式限定的方式以相同的名称来引 用真实表)。可以像表一样,以同样的方式提供一个别名。 plsql_declarations select 语句的 with 子句中,使用 plsql_declarations 子句声明和定义函数和存储过程。 具体定义请参见:具体定义参数信息参见 CREATE FUNCTION、CREATE PROCEDURE 等。 使用规则: 1.With 子句定义的函数或者存储过程遵守普通函数或者存储过程的使用规则; 2.With 子句创建的函数或者存储过程的生命周期是当前 select 语句; 3. 一个 with 子句可以定义多个 plsql 函数或者存储过程。并且被调用; 4.with 子句定义存储过程时,不能在 select 语句中被直接使用,但可以在定义的 function 里调用。 1238 第 20 章 SQL 语句: MERGE 到 VALUES function_name 函数调用可以出现在 FROM 子句中(对于返回结果集合的函数特别有用,但是可以使用任何函数)。 这就好像把该函数的输出创建为一个存在于该 SELECT 命令期间的临时表。当为该函数调用增加可选的 WITH ORDINALITY 子句时,会在该函数的输出列之后追加一个新的列来为每一行编号。 可以用和表一样的方式提供一个别名。如果写了一个别名,还可以写一个列别名列表来为该函数的组合返回类 型的一个或者多个属性提供替代名称,包括由 ORDINALITY(如果有)增加的新列。 通过把多个函数调用包围在 ROWS FROM( ... ) 中可以把它们整合在单个 FROM-子句项中。这样一个项的输出 是把每一个函数的第一行串接起来,然后是每个函数的第二行,以此类推。如果有些函数产生的行比其他函数 少,则在缺失数据的地方放上空值,这样被返回的总行数总是和产生最多行的函数一样。 如 果 函 数 被 定 义 为 返 回 record 数 据 类 型, 那 么 必 须 出 现 一 个 别 名 或 者 关 键 词 AS, 后 面 跟 上 形 为 column_name “data_type“ [, ... ]) 的列定义列表。列定义列表必须匹配该函数返回的列的实际数量和类 ( 型。 在使用 ROWS FROM( ... ) 语法时,如果函数之一要求一个列定义列表,最好把该列定义列表放在 ROWS FROM( ... ) 中该函数的调用之后。当且仅当正好只有一个函数并且没有 WITH ORDINALITY 子句时,才能把 列定义列表放在 ROWS FROM( ... ) 结构后面。 要把 ORDINALITY 和列定义列表一起使用,你必须使用 ROWS FROM( ... ) 语法,并且把列定义列表放在 ROWS FROM( ... ) 里面。 join types • [ 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 项(为了方便我们称之为“表”,尽管实际上它们可以是任何类型的 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。 1239 第 20 章 SQL 语句: MERGE 到 VALUES 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 列表的速记,该列表中提到两个表中具有匹配名称的所有的列。如果没有公共列 名,则 NATURAL 等效于 ON TRUE。 LATERAL LATERAL 关键词可以放在一个子-SELECT FROM 项前面。这允许该子-SELECT 引用 FROM 列表中在它之前 的 FROM 项的列(如果没有 LATERAL,每一个子-SELECT 会被独立计算并且因此不能交叉引用任何其他的 FROM 项)。 LATERAL 也可以放在一个函数调用 FROM 项前面,但是在这种情况下它只是一个噪声词,因为在任何情况下函数 表达式都可以引用在它之前的 FROM 项。 LATERAL 项可以出现在 FROM 列表顶层,或者一个 JOIN 中。在后一种情况中,它也可以引用其作为右手端的 JOIN 左手端上的任何项。 当一个 FROM 项包含 LATERAL 交叉引用时,计算会如此进行:对提供被交叉引用列的 FROM 项的每一行或者提 供那些列的多个 FROM 项的每一个行集,使用该行或者行集的那些列值计算 LATERAL 项。结果行会与计算得到 它们的行进行通常的连接。对来自哪些列的源表的每一行或者行集都会重复这样的步骤。 列的源表必须以 INNER 或者 LEFT 的方式连接到 LATERAL 项,否则就没有用于为 LATERAL 项计算每一个行集的 良定行集。尽管 X RIGHT JOIN LATERAL “Y“这样的结构在语法上是合法的,但实际上不允许用于在 “Y“中 引用 “X“。 3. WHERE 子句 可选的 WHERE 子句的形式 WHERE condition 其中 “condition“ 是任一计算得到布尔类型结果的表达式。任何不满足这个条件的行都会从输出中被消除。如果 用一行的实际值替换其中的变量引用后,该表达式返回真,则该行符合条件。 4. GROUP BY 子句 可选的 GROUP BY 子句的形式 GROUP BY grouping_element [, ...] GROUP BY 将会把所有被选择的行中共享相同分组表达式值的那些行压缩成一个行。一个被用在 “grouping_element“中的 “expression“可以是输入列名、输出列(SELECT 列表项)的名称或序号或者由输入列值构成的任 意表达式。在出现歧义时,GROUP BY 名称将被解释为输入列名而不是输出列名。 1240 第 20 章 SQL 语句: MERGE 到 VALUES 如果任何 GROUPING SETS、ROLLUP 或者 CUBE 作为分组元素存在,则 GROUP BY 子句整体上定义了数个独立的 “分组集 “。其效果等效于在子查询间构建一个 UNION ALL,子查询带有分组集作为它们的 GROUP BY 子句。 聚集函数(如果使用)会在组成每一个分组的所有行上进行计算,从而为每一个分组产生一个单独的值(如果有 聚集函数但是没有 GROUP BY 子句,则查询会被当成是由所有选中行构成的一个单一分组)。传递给每一个聚集函数 的行集合可以通过在聚集函数调用附加一个 FILTER 子句来进一步过滤,详见 聚集表达式。当存在一个 FILTER 子句 时,只有那些匹配它的行才会被包括在该聚集函数的输入中。 当存在 GROUP BY 子句或者任何聚集函数时,SELECT 列表表达式不能引用非分组列(除非它出现在聚集函数中 或者它函数依赖于分组列),因为这样做会导致返回非分组列的值时会有多种可能的值。如果分组列是包含非分组列 的表的主键(或者主键的子集),则存在函数依赖。 记住所有的聚集函数都是在 HAVING 子句或者 SELECT 列表中的任何“标量”表达式之前被计算。这意味着一个 CASE 表达式不能被用来跳过一个聚集表达式的计算,见 表达式计算规则。 当前,FOR NO KEY UPDATE、FOR UPDATE、FOR SHARE 和 FOR KEY SHARE 不能和 GROUP BY 一起指定。 注意: Oracle 模式下 Group by 子句中列表达式处理规则: • 针对单个整数,group_by_int_pos 参数设置为 false 时,将整数看做常量,按一个组进行处理;参数为 true 时,将其看做投影列位置,按相应投影列分组,位置越界则报错。 • 支持单个小数常量,按一个组进行处理。 • 支持单个字符串常量,按一个组进行处理。 • 支持单个 null,按一个组进行处理。 5. HAVING 子句 可选的 HAVING 子句的形式 HAVING condition 其中 “condition“与 WHERE 子句中指定的条件相同。 HAVING 消除不满足该条件的分组行。HAVING 与 WHERE 不同:WHERE 会在应用 GROUP BY 之前过滤个体行,而 HAVING 过滤由 GROUP BY 创建的分组行。“condition“中引用的每一个列必须无歧义地引用一个分组列(除非该引用出 现在一个聚集函数中或者该非分组列函数依赖于分组列。 即使没有 GROUP BY 子句,HAVING 的存在也会把一个查询转变成一个分组查询。这和查询中包含聚集函数但没 有 GROUP BY 子句时的情况相同。所有被选择的行都被认为是一个单一分组,并且 SELECT 列表和 HAVING 子句只能 引用聚集函数中的表列。如果该 HAVING 条件为真,这样一个查询将会发出一个单一行;否则不返回行。 当前,FOR NO KEY UPDATE、FOR UPDATE、FOR SHARE 和 FOR KEY SHARE 不能与 HAVING 一起指定。 6. WINDOW 子句 可选的 WINDOW 子句的形式 WINDOW window_name AS ( window_definition ) [, ...] 其中 “window_name“ 是一个可以从 OVER 子句或者后续窗口定义中引用的名称。“window_definition“是 1241 第 20 章 SQL 语句: MERGE 到 VALUES [ existing_window_name ] [ PARTITION BY expression [, ...] ] [ ORDER BY expression [ ASC | DESC | USING operator ] [ NULLS { FIRST | LAST } ] [, ...] ] [ frame_clause ] 如果指定了一个 “existing_window_name“,它必须引用 WINDOW 列表中一个更早出现的项。新窗口将从该项中 复制它的划分子句以及排序子句(如果有)。在这种情况下,新窗口不能指定它自己的 PARTITION BY 子句,并且它 只能在被复制窗口没有 ORDER BY 的情况下指定该子句。新窗口总是使用它自己的帧子句,被复制的窗口不必指定一 个帧子句。 PARTITION BY 列表元素的解释以 GROUP BY 元素的方式进行,但是它们总是简单表达式并且绝不能是输出列 的名称或编号。另一个区别是这些表达式可以包含聚集函数调用,而这在常规 GROUP BY 子句中是不被允许的。它们 被允许的原因是窗口是出现在分组和聚集之后的。 类似地,ORDER BY 列表元素的解释也以 ORDER BY 元素的方式进行,但是该表达式总是被当做简单表达式并 且绝不会是输出列的名称或编号。 可选的 “frame_clause“为依赖帧的窗口函数定义窗口帧(并非所有窗口函数都依赖于帧)。窗口帧是查询中每一 样(称为当前行)的相关行的集合。“frame_clause“可以是 { RANGE | ROWS | GROUPS } frame_start [ frame_exclusion ] { RANGE | ROWS | GROUPS } BETWEEN frame_start AND frame_end [ frame_exclusion ] 之一,其中 “frame_start“和 “frame_end“可以是 UNBOUNDED PRECEDING offset PRECEDING CURRENT ROW offset FOLLOWING UNBOUNDED FOLLOWING 之一,并且 “frame_exclusion“可以是 EXCLUDE CURRENT ROW EXCLUDE GROUP EXCLUDE TIES EXCLUDE NO OTHERS 之 一。 如 果 省 略 “frame_end“, 它 会 被 默 认 为 CURRENT ROW。 限 制 是:“frame_start“不 能 是 UNBOUNDED FOLLOWING,“frame_end“不能是 UNBOUNDED PRECEDING,并且 “frame_end“的选择在上面 of “frame_start“以 及 “frame_end“ 选项的列表中不能早于 “frame_start“的选择—例如 RANGE BETWEEN CURRENT ROW AND offset PRECEDING 是不被允许的。 默 认 的 帧 选 项 是 RANGE UNBOUNDED PRECEDING, 它 和 RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW 相同。它把帧设置为从分区开始直到当前行的最后一个平级行(被该窗口的 ORDER BY 子句认为等价于当前行 的行,如果没有 ORDER BY 则所有的行都是平级的)。通常,UNBOUNDED PRECEDING 表示从分区第一行开始的帧, 类似地 UNBOUNDED FOLLOWING 表示以分区最后一行结束的帧,不论是处于 RANGE、ROWS 或者 GROUPS 模式中。 1242 第 20 章 SQL 语句: MERGE 到 VALUES 在 ROWS 模式中,CURRENT ROW 表示以当前行开始或者结束的帧。而在 RANGE 或者 GROUPS 模式中它表示当前行在 ORDER BY 排序中的第一个或者最后一个平级行开始或者结束的帧。“offset“ PRECEDING 和 “offset“ FOLLOWING 选项 的含义会随着帧模式而变化。在 ROWS 模式中,“offset“是一个整数,表示帧开始或者结束于当前行之前或者之后的 那么多行处。在 GROUPS 模式中,“offset“是一个整数,表示真开始或者结束于当前行的平级组之前或者之后那么多 个平级组处,其中平级组是一组根据窗口的 ORDER BY 子句等效的行。在 RANGE 模式中,“offset“选项的使用要求在 窗口定义中正好有一个 ORDER BY 列。那么该帧包含的行的排序列值不超过 “offset“且小于(对于 PRECEDING)或者 大于(对于 FOLLOWING)当前行的排序列值。在这些情况中,“offset“表达式的数据类型取决于排序列的数据类型。 对于数字排序列,它通常与排序列是相同类型,但对于 datetime 类型的排序列它是 interval。在所有这些情况中, “offset“的值必须是非空和非负。此外,虽然 “offset“并非必须是简单常量,但它不能包含变量、聚集函数或者窗口函 数。 “frame_exclusion“选项允许从帧中排除当前行周围的行,即便根据帧的起始选项来说它们应该被包含在帧中。 EXCLUDE CURRENT ROW 把当前行从帧中排除。EXCLUDE GROUP 把当前行和它在排序上的平级行从帧中排除。EXCLUDE TIES 从帧中排除当前行的任何平级行,但是不排除当前行本身。EXCLUDE NO OTHERS 只是明确地指定不排除当前行 或其平级行的默认行为。 注意,如果 ORDER BY 排序无法把行唯一地排序,则 ROWS 模式可能产生不可预测的结果。RANGE 以及 GROUPS 模式的目的是确保在 ORDER BY 顺序中平等的行被同样对待:一个给定平级组中的所有行将在一个帧中或者被从帧中 排除。 WINDOW 子句的目的是指定出现在查询的 SELECT 列表或 ORDER BY 中的 窗口函数的行为。这些函数可以在 它们的 OVER 子句中用名称引用 WINDOW 子句项。但是,WINDOW 子句项不是必须被引用。如果在查询中没有用到它, 它会被简单地忽略。可以使用根本没有任何 WINDOW 子句的窗口函数,因为窗口函数调用可以直接在其 OVER 子句中 指定它的窗口定义。但是,当多个窗口函数都需要相同的窗口定义时,WINDOW 子句能够减少输入。 当前,FOR NO KEY UPDATE、FOR UPDATE、FOR SHARE 和 FOR KEY SHARE 不能和 WINDOW 一起被指定。 窗口函数的详细描述在 高级特性窗口函数、窗口函数调用 ‘以及:ref:‘窗口函数处理中。 7. SELECT 列表 SELECT 列表(位于关键词 SELECT 和 FROM 之间)指定构成 SELECT 语句输出行的表达式。这些表达式可以(并 且通常确实会)引用 FROM 子句中计算得到的列。 正如在表中一样,SELECT 的每一个输出列都有一个名称。在一个简单的 SELECT 中,这个名称只是被用来标记 要显示的列,但是当 SELECT 是一个大型查询的一个子查询时,大型查询会把该名称看做子查询产生的虚表的列名。 要指定用于输出列的名称,在该列的表达式后面写上 AS “output_name“(你可以省略 AS,但只能在期望的输出名称 不匹配任何 KingbaseES 关键词(见 SQL 关键词)时省略。为了避免和未来增加的关键词冲突,推荐总是写上 AS 或 者用双引号引用输出名称)。如果你不指定列名,KingbaseES 会自动选择一个名称。如果列的表达式是一个简单的 列引用,那么被选择的名称就和该列的名称相同。在使用函数或者类型名称的更复杂的情况中,系统可能会生成诸如 ?column? 之类的名称。 一个输出列的名称可以被用来在 ORDER BY 以及 GROUP BY 子句中引用该列的值,但是不能用于 WHERE 和 HAVING 子句(在其中必须写出表达式)。 可以在输出列表中写 * 来取代表达式,它是被选中行的所有列的一种简写方式。还可以写 table_name.*,它是 只来自那个表的所有列的简写形式。在这些情况中无法用 AS 指定新的名称,输出行的名称将和表列的名称相同。 根据 SQL 标准,输出列表中的表达式应该在应用 DISTINCT、ORDER BY 或者 LIMIT 之前计算。在使用 1243 第 20 章 SQL 语句: MERGE 到 VALUES DISTINCT 时显然必须这样做,否则就无法搞清到底在区分什么值。但是,在很多情况下如果先计算 ORDER BY 和 LIMIT 再计算输出表达式会很方便,特别是如果输出列表中包含任何 volatile 函数或者代价昂贵的函数时尤其如此。 通过这种行为,函数计算的顺序更加直观并且对于从未出现在输出中的行将不会进行计算。只要输出表达式没有被 DISTINCT、ORDER BY 或者 GROUP BY 引用,KingbaseES 实际将在排序和限制行数之后计算输出表达式(作为一个 反例,SELECT f(x) FROM tab ORDER BY 1 显然必须在排序之前计算 f(x))。包含有集合返回函数的输出表达式实 际是在排序之后和限制行数之前被计算,这样 LIMIT 才能切断来自集合返回函数的输出。 注意: V8R2 版本之前的 KingbaseES 不对执行输出表达式、排序、限制行数的时间顺序做任何保证,那将取决于被 选中的查询计划的形式。 8. DISTINCT 子句 如果指定了 SELECT DISTINCT,所有重复的行会被从结果集中移除(为每一组重复的行保留一行)。SELECT ALL 则指定相反的行为:所有行都会被保留,这也是默认情况。 SELECT 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 NO KEY UPDATE、FOR UPDATE、FOR SHARE 和 FOR KEY SHARE 不能和 DISTINCT 一起使用。 9. UNIQUE 子句 如果指定了 SELECT UNIQUE,所有重复的行会被从结果集中移除(为每一组重复的行保留一行)。SELECT ALL 则指定相反的行为:所有行都会被保留,这也是默认情况。 SELECT UNIQUE ON ( expression [, ...] ) 只保留在给定表达式上计算相等的行集合中的第一行。UNIQUE ON 表 达式使用和 ORDER BY 相同的规则(见上文)解释。注意,除非用 ORDER BY 来确保所期望的行出现在第一位,每一 个集合的“第一行”是不可预测的。例如: SELECT UNIQUE ON (location) location, time, report FROM weather_reports ORDER BY location, time DESC; 为每个地点检索最近的天气报告。但是如果我们不使用 ORDER BY 来强制对每个地点的时间值进行降序排序,我 们为每个地点得到的报告的时间可能是无法预测的。 1244 第 20 章 SQL 语句: MERGE 到 VALUES UNIQUE ON 表达式必须匹配最左边的 ORDER BY 表达式。ORDER BY 子句通常将包含额外的表达式,这些额外的 表达式用于决定在每一个 DISTINCT ON 分组内行的优先级。 当前,FOR NO KEY UPDATE、FOR UPDATE、FOR SHARE 和 FOR KEY SHARE 不能和 UNIQUE 一起使用。 10. UNION 子句 UNION 子句具有下面的形式: select_statement UNION [ ALL | DISTINCT ] select_statement “select_statement“ 是任何 没 有 ORDER BY、LIMIT、FOR NO KEY UPDATE、FOR UPDATE、FOR SHARE 和 FOR KEY SHARE 子句的 SELECT 语句(如果子表达式被包围在圆括号内,ORDER BY 和 LIMIT 可以被附着到其上。如果 没有圆括号,这些子句将被应用到 UNION 的结果而不是右手边的表达式上)。 UNION 操作符计算所涉及的 SELECT 语句所返回的行的并集。如果一行至少出现在两个结果集中的一个内,它就 会在并集中。作为 UNION 两个操作数的 SELECT 语句必须产生相同数量的列并且对应位置上的列必须具有兼容的数据 类型。 UNION 的结果不会包含重复行,除非指定了 ALL 选项。ALL 会阻止消除重复(因此,UNION ALL 通常显著地快于 UNION,尽量使用 ALL)。可以写 DISTINCT 来显式地指定消除重复行的行为。 除非用圆括号指定计算顺序,同一个 SELECT 语句中的多个 UNION 操作符会从左至右计算。 当前,FOR NO KEY UPDATE、FOR UPDATE、FOR SHARE 和 FOR KEY SHARE 不能用于 UNION 结果或者 UNION 的任 何输入。 11. INTERSECT 子句 INTERSECT 子句具有下面的形式: select_statement INTERSECT [ ALL | DISTINCT ] select_statement “select_statement“ 是任何没有 ORDER BY, LIMIT、FOR NO KEY UPDATE、FOR UPDATE、FOR SHARE 以及 FOR KEY SHARE 子句的 SELECT 语句。 INTERSECT 操作符计算所涉及的 SELECT 语句返回的行的交集。如果一行同时出现在两个结果集中,它就在交集 中。 INTERSECT 的结果不会包含重复行,除非指定了 ALL 选项。如果有 ALL,一个在左表中有 “m“次重复并且在右 表中有 “n“ 次重复的行将会在结果中出现 min(“m“,“n“) 次。DISTINCT 可以写 DISTINCT 来显式地指定消除重复行的 行为。 除非用圆括号指定计算顺序,同一个 SELECT 语句中的多个 INTERSECT 操作符会从左至右计算。INTERSECT 的 优先级比 UNION 更高。也就是说,A UNION B INTERSECT C 将被读成 A UNION (B INTERSECT C)。 当前,FOR NO KEY UPDATE、FOR UPDATE、FOR SHARE 和 FOR KEY SHARE 不能用于 INTERSECT 结果或者 INTERSECT 的任何输入。 12. EXCEPT 子句 EXCEPT 子句具有下面的形式: 1245 第 20 章 SQL 语句: MERGE 到 VALUES select_statement EXCEPT [ ALL | DISTINCT ] select_statement “select_statement“ 是任何没有 ORDER BY、LIMIT、FOR NO KEY UPDATE、FOR UPDATE、FOR SHARE 以及 FOR KEY SHARE 子句的 SELECT 语句。 EXCEPT 操作符计算位于左 SELECT 语句的结果中但不在右 SELECT 语句结果中的行集合。 EXCEPT 的结果不会包含重复行,除非指定了 ALL 选项。如果有 ALL,一个在左表中有 “m“次重复并且在右表中 有 “n“次重复的行将会在结果集中出现 max(“m“-“n“,0) 次。DISTINCT 可以写 DISTINCT 来显式地指定消除重复行的 行为。 除非用圆括号指定计算顺序,同一个 SELECT 语句中的多个 EXCEPT 操作符会从左至右计算。EXCEPT 的优先级与 UNION 相同。 当前,FOR NO KEY UPDATE、FOR UPDATE、FOR SHARE 和 FOR KEY SHARE 不能用于 EXCEPT 结果或者 EXCEPT 的 任何输入。 13. MINUS 子句 MINUS 子句具有下面的形式: select_statement MINUS [ ALL | DISTINCT ] select_statement “select_statement“ 是任何没有 ORDER BY、LIMIT、FOR NO KEY UPDATE、FOR UPDATE、FOR SHARE 以及 FOR KEY SHARE 子句的 SELECT 语句。 MINUS 操作符计算位于左 SELECT 语句的结果中但不在右 SELECT 语句结果中的行集合。 MINUS 的结果不会包含重复行,除非指定了 ALL 选项。如果有 ALL,一个在左表中有 “m“次重复并且在右表中有 “n“次重复的行将会在结果集中出现 max(“m“-“n“,0) 次。DISTINCT 可以写 DISTINCT 来显式地指定消除重复行的行 为。 除非用圆括号指定计算顺序,同一个 SELECT 语句中的多个 MINUS 操作符会从左至右计算。MINUS 的优先级与 UNION 相同。 当前,FOR NO KEY UPDATE、FOR UPDATE、FOR SHARE 和 FOR KEY SHARE 不能用于 MINUS 结果或者 MINUS 的任 何输入。 14. ORDER BY 子句 可选的 ORDER BY 子句的形式如下: ORDER BY expression [ ASC | DESC | USING operator ] [ NULLS { FIRST | LAST } ] [, ...] ORDER BY 子句导致结果行被按照指定的表达式排序。如果两行按照最左边的表达式是相等的,则会根据下一个 表达式比较它们,依次类推。如果按照所有指定的表达式它们都是相等的,则它们被返回的顺序取决于实现。 每一个 “expression“ 可以是输出列(SELECT 列表项)的名称或者序号,它也可以是由输入列值构成的任意表达 式。 1246 第 20 章 SQL 语句: MERGE 到 VALUES 序号指的是输出列的顺序(从左至右)位置。这种特性可以为不具有唯一名称的列定义一个顺序。这不是绝对必 要的,因为总是可以使用 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 子句中的任何表达式之后增加关键词 ASC(上升)DESC(下降)。如果没有指定,ASC 被假定 为默认值。或者,可以在 USING 子句中指定一个特定的排序操作符名称。一个排序操作符必须是某个 B-树操作符族 的小于或者大于成员。ASC 通常等价于 USING < 而 DESC 通常等价于 USING >(但是一种用户定义数据类型的创建者 可以准确地定义默认排序顺序是什么,并且它可能会对应于其他名称的操作符)。 如果指定 NULLS LAST,空值会排在非空值之后;如果指定 NULLS FIRST,空值会排在非空值之前。如果都没 有指定,在指定或者隐含 ASC 时的默认行为是 NULLS LAST,而指定或者隐含 DESC 时的默认行为是 NULLS FIRST (因此,默认行为是空值大于非空值)。当指定 USING 时,默认的空值顺序取决于该操作符是否为小于或者大于操 作符。 注意顺序选项只应用到它们所跟随的表达式上。例如 ORDER BY x, y DESC 和 ORDER BY x DESC, y DESC 是不 同的。 字符串数据会被根据引用到被排序列上的排序规则排序。根据需要可以通过在 “expression“中包括一个 COLLATE 子句来覆盖,例如 ORDER BY mycolumn COLLATE "en_US"。更多信息请见 排序规则表达式和 排序规则支持。 **注意:**Oracle 模式下 ORDER BY 子句中列表达式处理规则: • 表达式为单个负整数时,看做常量,不影响排序; • 表达式为单个正小数常量时,将小数常量向下取整后看作是投影列位置,在投影列位置范围内按投影列排序, 否则报错; • 表达式为负小数时,看做常量,不影响排序; 15. LIMIT 子句 LIMIT 子句由两个独立的子句构成: LIMIT { count | ALL } OFFSET start “count“指定要返回的最大行数,而 “start“ 指定在返回行之前要跳过的行数。在两者都被指定时,在开始计算要 返回的 “count“行之前会跳过 “start“行。 如果 “count“表达式计算为 NULL,它会被当成 LIMIT ALL,即没有限制。如果 “start“计算为 NULL,它会被当 作 OFFSET 0。 1247 第 20 章 SQL 语句: MERGE 到 VALUES SQL:2008 引入了一种不同的语法来达到相同的结果,KingbaseES 也支持它: OFFSET start { ROW | ROWS } FETCH { FIRST | NEXT } [ count ] { ROW | ROWS } ONLY 在这种语法中,标准要求 “start“或 “count“是一个文本常量、一个参数或者一个变量名。而作为一种 KingbaseES 的扩展,还允许其他的表达式,但通常需要被封闭在圆括号中以避免歧义。如果在一个 FETCH 子句中省略 “count“,它的默认值为 1。ROW 和 ROWS 以及 FIRST 和 NEXT 是噪声,它们不影响这些子句的效果。根据标准,如 果都存在,OFFSET 子句必须出现在 FETCH 子句之前。但是 KingbaseES 更宽松,它允许两种顺序。 在使用 LIMIT 时,用一个 ORDER BY 子句把结果行约束到一个唯一顺序是个好办法。否则你讲得到该查询结果 行的一个不可预测的子集—你可能要求从第 10 到第 20 行,但是在什么顺序下的第 10 到第 20 呢?除非指定 ORDER BY,你是不知道顺序的。 查询规划器在生成一个查询计划时会考虑 LIMIT,因此根据你使用的 LIMIT 和 OFFSET,你很可能得到不同的 计划(得到不同的行序)。所以,使用不同的 LIMIT/OFFSET 值来选择一个查询结果的不同子集将会给出不一致的结 果,除非你用 ORDER BY 强制一种可预测的结果顺序。这不是一个缺陷,它是 SQL 不承诺以任何特定顺序(除非使 用 ORDER BY 来约束顺序)给出一个查询结果这一事实造成的必然后果。 如果没有一个 ORDER BY 来强制选择一个确定的子集,重复执行同样的 LIMIT 查询甚至可能会返回一个表中行 的不同子集。同样,这也不是一种缺陷,再这样一种情况下也无法保证结果的确定性。 16. 锁定子句 FOR UPDATE、FOR NO KEY UPDATE、FOR SHARE 和 FOR KEY SHARE 是锁定子句,它们影响 SELECT 把行从表中 取得时如何对它们加锁。 锁定子句的一般形式: FOR lock_strength [ OF table_name [, ...] ] [ NOWAIT | SKIP LOCKED | WAIT seconds ] 其中 “lock_strength“可以是 UPDATE NO KEY UPDATE SHARE KEY SHARE 之一。 为了防止该操作等待其他事务提交,可使用 NOWAIT 或者 SKIP LOCKED 或者 WAIT seconds 选项。使用 NOWAIT 时,如果选中的行不能被立即锁定,该语句会报告错误而不是等待。使用 SKIP LOCKED 时,无法被立即锁定的任何 选中行都会被跳过。跳过已锁定行会提供数据的一个不一致的视图,因此这不适合于一般目的的工作,但是可以被用 来避免多个用户访问一个类似队列的表时出现锁竞争。使用 WAIT seconds 时,在被锁定的行变为可用之前,最多 等待 seconds 秒,如果等待成功则返回结果集,否则超时报错返回。注意 NOWAIT,SKIP LOCKED 和 WAIT seconds 只适合行级锁—所要求的 ROW SHARE 表级锁仍然会以常规的方式取得。如果想要不等待的表级锁,可以先使用带 NOWAIT 的LOCK 。 1248 第 20 章 SQL 语句: MERGE 到 VALUES 如果在一个锁定子句中提到了特定的表,则只有来自于那些表的行会被锁定,任何 SELECT 中用到的其他表还是 被简单地照常读取。一个没有表列表的锁定子句会影响该语句中用到的所有表。如果一个锁定子句被应用到一个视图 或者子查询,它会影响在该视图或子查询中用到的所有表。但是,这些子句不适用于主查询引用的 WITH 查询。如果 你希望在一个 WITH 查询中发生行锁定,应该在该 WITH 查询内指定一个锁定子句。 如果有必要对不同的表指定不同的锁定行为,可以写多个锁定子句。如果同一个表在多于一个锁定子句中被提到 (或者被隐式的影响到),那么会按照所指定的最强的锁定行为来处理它。类似地,如果在任何影响一个表的子句中 指定了 NOWAIT,就会按照 NOWAIT 的行为来处理该表。否则如果 SKIP LOCKED 在任何影响该表的子句中被指定,该 表就会被按照 SKIP LOCKED 来处理。 如果被返回的行无法清晰地与表中的行保持一致,则不能使用锁定子句。例如锁定子句不能与聚集一起使用。 当一个锁定子句出现在一个 SELECT 查询的顶层时,被锁定的行正好就是该查询返回的行。在连接查询的情况 下,被锁定的行是那些对返回的连接行有贡献的行。此外,自该查询的快照起满足查询条件的行将被锁定,如果它们 在该快照后被更新并且不再满足查询条件,它们将不会被返回。如果使用了 LIMIT,只要已经返回的行数满足了限 制,锁定就会停止(但注意被 OFFSET 跳过的行将被锁定)。类似地,如果在一个游标的查询中使用锁定子句,只有 被该游标实际取出或者跳过的行才将被锁定。 当一个锁定子句出现在一个子-SELECT 中时,被锁定行是那些该子查询返回给外层查询的行。这些被锁定的行的 数量可能比从子查询自身的角度看到的要少,因为来自外层查询的条件可能会被用来优化子查询的执行。例如: SELECT * FROM (SELECT * FROM mytable FOR UPDATE) ss WHERE col1 = 5; 将只锁定具有 col1 = 5 的行(虽然在子查询中并没有写上该条件)。 早前的发行无法维持一个被之后的保存点升级的锁。例如,这段代码: BEGIN; SELECT * FROM mytable WHERE key = 1 FOR UPDATE; SAVEPOINT s; UPDATE mytable SET ... WHERE key = 1; ROLLBACK TO s; 在 ROLLBACK TO 之后将无法维持 FOR UPDATE 锁。在 9.3 中已经修复这个问题。 警告: 一个运行在 READ COMMITTED 事务隔离级别并且使用 ORDER BY 和锁定子句的 SELECT 命令有可能返 回无序的行。这是因为 ORDER BY 会被首先应用。该命令对结果排序,但是可能接着在尝试获得一个或者多个行 上的锁时阻塞。一旦 SELECT 解除阻塞,某些排序列值可能已经被修改,从而导致那些行变成无序的(尽管它们 根据原始列值是有序的)。根据需要,可以通过在子查询中放置 FOR UPDATE/SHARE 来解决之一问题,例如 SELECT * FROM (SELECT * FROM mytable FOR UPDATE) ss ORDER BY column1; 注意这将导致锁定 mytable 的所有行,而顶层的 FOR UPDATE 只会锁定实际被返回的行。这可能会导致显著 的性能差异,特别是把 ORDER BY 与 LIMIT 或者其他限制组合使用时。因此只有在并发更新排序列并且要求严 格的排序结果时才推荐使用这种技术。 在 REPEATABLE READ 或 者 SERIALIZABLE 事 务 隔 离 级 别 上 这 可 能 导 致 一 个 序 列 化 失 败 (SQLSTATE 1249 第 20 章 SQL 语句: MERGE 到 VALUES 是'40001'),因此在这些隔离级别下不可能收到无序行。 17. TABLE 命令 命令 TABLE name 等价于 SELECT * FROM name 它可以被用作一个顶层命令,或者用在复杂查询中以节省空间。只有 WITH、UNION、INTERSECT、EXCEPT、 MINUS、ORDER BY、LIMIT、OFFSET、FETCH 以及 FOR 锁定子句可以用于 TABLE。不能使用 WHERE 子句和任何形式 的聚集。 示例 把表 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 ... 要对所有电影的 len 列求和并且用 kind 对结果分组: 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 要对所有电影的 len 列求和、对结果按照 “kind“分组并且显示总长小于 5 小时的分组: SELECT kind, sum(len) AS total FROM films GROUP BY kind 1250 第 20 章 SQL 语句: MERGE 到 VALUES 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 | id | name -----+-------------- 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 1251 第 20 章 SQL 语句: MERGE 到 VALUES 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 这里是带有增加的序数列的函数的例子: SELECT * FROM unnest(ARRAY['a','b','c','d','e','f']) WITH ORDINALITY; unnest | ordinality --------+---------a | 1 b | 2 c | 3 d | 4 e | 5 f | 6 (6 rows) 这个例子展示了如何使用简单的 WITH 子句: 1252 第 20 章 SQL 语句: MERGE 到 VALUES WITH t AS ( SELECT random() as x FROM generate_series(1, 3) ) SELECT * FROM t UNION ALL SELECT * FROM t x -------------------0.534150459803641 0.520092216785997 0.0735620250925422 0.534150459803641 0.520092216785997 0.0735620250925422 注意该 WITH 查询只被计算一次,这样我们得到的两个集合具有相同的三个随机值。 这个例子使用 WITH RECURSIVE 从一个只显示直接下属的表中寻找雇员 Mary 的所有下属(直接的或者间接的) 以及他们的间接层数: WITH RECURSIVE employee_recursive(distance, employee_name, manager_name) AS ( SELECT 1, employee_name, manager_name FROM employee WHERE manager_name = 'Mary' UNION ALL SELECT er.distance + 1, e.employee_name, e.manager_name FROM employee_recursive er, employee e WHERE er.employee_name = e.manager_name ) SELECT distance, employee_name FROM employee_recursive; 注意这种递归查询的典型形式:一个初始条件,后面跟着 UNION,然后是查询的递归部分。要确保查询的递归部 分最终将不返回任何行,否则该查询将无限循环(WITH 查询)。 这个例子使用 LATERAL 为 manufacturers``表的每一行应用一个集合返回函数\ ``get_product_names(): SELECT m.name AS mname, pname FROM manufacturers m, LATERAL get_product_names(m.id) pname; 当前没有任何产品的制造商不会出现在结果中,因为这是一个内连接。如果我们希望把这类制造商的名称包括在 结果中,我们可以: SELECT m.name AS mname, pname FROM manufacturers m LEFT JOIN LATERAL get_product_names(m.id) pname ON true; 兼容性 1253 第 20 章 SQL 语句: MERGE 到 VALUES 当然,SELECT 语句是兼容 SQL 标准的。但是也有一些扩展和缺失的特性。 18. 省略的 FROM 子句 KingbaseES 允许我们省略 FROM 子句。一种简单的使用是计算简单表达式的结果: SELECT 2+2; ?column? ---------4 某些其他 SQL 数据库需要引入一个假的单行表放在该 SELECT 的 FROM 子句中才能做到这一点。 注意,如果没有指定一个 FROM 子句,该查询就不能引用任何数据库表。例如,下面的查询是非法的: SELECT distributors.* WHERE distributors.name = 'Westward'; KingbaseES 在 8.1 之前的发行会接受这种形式的查询,并且为该查询引用的每一个表在 FROM 子句中隐式增加一 个项。现在已经不再允许这样做。 19. 空 SELECT 列表 SELECT 之后的输出表达式列表可以为空,这会产生一个零列的结果表。对 SQL 标准来说这不是合法的语法。 KingbaseES 允许它是为了与允许零列表保持一致。但是在使用 DISTINCT 时不允许空列表。 20. 省略 AS 关键词 在 SQL 标准中,只要新列名是一个合法的列名(就是说与任何保留关键词不同),就可以省略输出列名之前的 可选关键词 AS。 KingbaseES 要稍微严格些:只要新列名匹配任何关键词(保留或者非保留)就需要 AS。推荐的习惯是使用 AS 或者带双引号的输出列名来防止与未来增加的关键词可能的冲突。 在 FROM 项中,标准和 KingbaseES 都允许省略非保留关键词别名之前的 AS。但是由于语法的歧义,这无法用 于输出列名。 21. ONLY 和继承 在书写 ONLY 时,SQL 标准要求在表名周围加上圆括号,例如 SELECT * FROM ONLY (tab1), ONLY (tab2) WHERE ...。KingbaseES 认为这些圆括号是可选的。 KingbaseES 允许写一个拖尾的 * 来显式指定包括子表的非-ONLY 行为。而标准则不允许这样。 (这些点同等地适用于所有支持 ONLY 选项的 SQL 命令)。 22. TABLESAMPLE 子句限制 当前只在常规表和物化视图上接受 TABLESAMPLE 子句。根据 SQL 标准,应该可以把它应用于任何 FROM 项。 23. FROM 中的函数调用 KingbaseES 允许一个函数调用被直接写作 FROM 列表的一个成员。在 SQL 标准中,有必要把这样一个函数调 用包裹在一个子-SELECT 中。也就是说,语法 FROM func(...) “alias“ 近似等价于 FROM LATERAL (SELECT func(...)) 1254 第 20 章 SQL 语句: MERGE 到 VALUES “alias“。注意该 LATERAL 被认为是隐式的,这是因为标准对于 FROM 中的一个 UNNEST() 项要求 LATERAL 语义。 KingbaseES 会把 UNNEST() 和其他集合返回函数同样对待。 24. GROUP BY 和 ORDER BY 可用的名字空间 在 SQL-92 标准中,一个 ORDER BY 子句只能使用输出列名或者序号,而一个 GROUP BY 子句只能使用基于输 入列名的表达式。KingbaseES 扩展了这两种子句以允许它们使用其他的选择(但如果有歧义时还是使用标准的解 释)。KingbaseES 也允许两种子句指定任意表达式。注意出现在一个表达式中的名称将总是被当做输入列名而不是 输出列名。 SQL:1999 及其后的标准使用了一种略微不同的定义,它并不完全向后兼容 SQL-92。但是,在大部分的情 况下,KingbaseES 会以与 SQL:1999 相同的方式解释 ORDER BY 或 GROUP BY 表达式。 25. 函数依赖 只有当一个表的主键被包括在 GROUP BY 列表中时,KingbaseES 才识别函数依赖(允许从 GROUP BY 中省略 列)。SQL 标准指定了应该要识别的额外情况。 26. LIMIT 和 OFFSET LIMIT 和 OFFSET 子句是 KingbaseES-特有的语法,在 MySQL 也被使用。SQL:2008 标准已经引入了具有相同功 能的子句 OFFSET ... FETCH {FIRST|NEXT} ...(如上文:ref‘LIMIT 子句 ‘ 中所示)。这种语法也被 IBM DB2 使 用(Oracle 编写的应用常常使用自动生成的 rownum 列来实现这些子句的效果,这在 KingbaseES 中是没有的)。 27. FOR NO KEY UPDATE、FOR UPDATE 、FOR SHARE 、FOR KEY SHARE 尽管 SQL 标准中出现了 FOR UPDATE,但标准只允许它作为 DECLARE CURSOR 的一个选项。KingbaseES 允许 它出现在任何 SELECT 查询以及子-SELECT 中,但这是一种扩展。FOR NO KEY UPDATE、FOR SHARE 以及 FOR KEY SHARE 变体以及 NOWAIT 和 SKIP LOCKED 选项没有在标准中出现。 28. WITH 中的数据修改语句 KingbaseES 允许把 INSERT、UPDATE 以及 DELETE 用作 WITH 查询。这在 SQL 标准中是找不到的。 29. 非标准子句 DISTINCT ON ( ... ) 是 SQL 标准的扩展。 ROWS FROM( ... ) 是 SQL 标准的扩展。 WITH 的 MATERIALIZED 和 NOT MATERIALIZED 选项是 SQL 标准的扩展。 该部分不是必有的,如有需做其他说明的内容放在这里。 20.20 SELECT INTO 用途 SELECT INTO —从一个查询的结果定义一个新表 SELECT INTO 创建一个新表并且用一个查询计算得到的数据填充它。这些数据不会像普通的 “SELECT“那样被 返回给客户端。新表的列具有和 SELECT 的输出列相关的名称和数据类型。 1255 第 20 章 SQL 语句: MERGE 到 VALUES 前置条件 无 语法 [ WITH [ RECURSIVE ] with_query [, ...] ] SELECT [ ALL | DISTINCT [ ON ( expression [, ...] ) ] ] * | expression [ [ AS ] output_name ] [, ...] INTO [ TEMPORARY | TEMP | UNLOGGED ] [ TABLE ] new_table [ FROM from_item [, ...] ] [ WHERE condition ] [ GROUP BY expression [, ...] ] [ HAVING condition [, ...] ] [ WINDOW window_name AS ( window_definition ) [, ...] ] [ { UNION | INTERSECT | EXCEPT } [ ALL | DISTINCT ] select ] [ ORDER BY expression [ ASC | DESC | USING operator ] [ NULLS { FIRST | LAST } ] [, ...] ] [ LIMIT { count | ALL } ] [ OFFSET start [ ROW | ROWS ] ] [ FETCH { FIRST | NEXT } [ count ] { ROW | ROWS } ONLY ] [ FOR { UPDATE | SHARE } [ OF table_name [, ...] ] [ NOWAIT ] [...] ] 1256 第 20 章 SQL 语句: MERGE 到 VALUES 1257 第 20 章 SQL 语句: MERGE 到 VALUES 语义 TEMPORARY | TEMP 如果被指定,该表被创建为一个临时表。详见CREATE TABLE 。 UNLOGGED 如果被指定,该表被创建为一个不做日志的表。详见CREATE TABLE 。 new_table 要创建的表的名字(可以是模式限定的)。 所有其他参数在SELECT 中有详细描述。 示例 创建一个只由来自 films 的最近项构成的新表 films_recent: SELECT * INTO films_recent FROM films WHERE date_prod >= '2002-01-01'; 兼容性 SQL 标准使用 SELECT INTO 表示把值选择到一个宿主程序的标量变量中,而不是创建一个新表。这实际上就是 ESQL(见 ESQL C 中的嵌入式 SQL )和 PL/SQL(见 PLSQL SQL 过程语言)中的用法。 KingbaseES 使用 SELECT INTO 的来表示表创建是有历史原因的。最好在新代码中使用 CREATE TABLE AS。 其他 SELECT INTO 创建一个新表并且用一个查询计算得到的数据填充它。这些数据不会像普通的 “SELECT“那样被 返回给客户端。新表的列具有和 SELECT 的输出列相关的名称和数据类型。 20.21 SET 用途 SET —更改一个运行时参数 SET 命令更改运行时配置参数。很多《数据库参考手册》中列出的参数可以用 “SET“即时更改。 SET 只影响当前会话所使用的值。 前置条件 有些参数需要超级用户特权才能更改,并且还有一些在服务器或者会话启动之后不能被更改 语法 SET [ SESSION | LOCAL ] configuration_parameter { TO | = } { value[, ... ] | DEFAULT } { ALTER } SET [ SESSION | LOCAL ] TIME ZONE { TIME_ZONE | time_zone | timezone | LOCAL | DEFAULT } 1258 第 20 章 SQL 语句: MERGE 到 VALUES 语义 SESSION 指定该命令对当前会话有效(这是默认值)。 LOCAL 指定该命令只对当前事务有效。在 COMMIT 或者 ROLLBACK 之后,会话级别的设置会再次生效。在事务块外部 发出这个参数会发出一个警告并且不会有效果。 configuration_parameter 一个可设置运行时参数的名称。可用的参数被记录在《数据库参考手册》和下文中。 value 参数的新值。根据特定的参数,值可以被指定为字符串常量、标识符、数字或者以上构成的逗号分隔列表。写 DEFAULT 可以指定把该参数重置成它的默认值(也就是说在当前会话中还没有执行 SET 命令时它具有的值)。 除了在《数据库参考手册》中记录的配置参数,还有一些参数只能用 SET 命令设置或者具有特殊的语法: SCHEMA SET SCHEMA 'value’ 是 SET search_path TO value 的一个别名。使用这种语法只能指定一个模式。 NAMES SET NAMES value 是 SET client_encoding TO value 的一个别名。 SEED 为随机数生成器(函数 random)设置一个内部种子。允许的值是 -1 和 1 之间的浮点数,它会被乘上 231 -1。 也可以通过调用函数 setseed 来设置种子: SELECT setseed(value); TIME ZONE SET TIME ZONE value 是 SET timezone TO value 的一个别名。语法 SET TIME ZONE 允许用于时区指 定的特殊语法。这里是合法值的例子: 'PST8PDT' 加州伯克利的时区。 1259 第 20 章 SQL 语句: MERGE 到 VALUES 'Europe/Rome' 意大利的时区。 -7 UTC 以西 7 小时的时区(等效于 PDT)。正值则是 UTC 以东。 INTERVAL '-08:00' HOUR TO MINUTE UTC 以西 8 小时的时区(等效于 PST)。 LOCAL DEFAULT 把时区设置为你的本地时区(也就是说服务器的 timezone 默认值)。 以数字或区间给出的时区设置在内部被翻译成 POSIX 时区语法。例如,在 SET TIME ZONE -7 之后,SHOW TIME ZONE 将会报告 <-07>+07。 示例 设置模式搜索路径: SET search_path TO my_schema, public; 把日期风格设置为传统 KINGBASE 的“日在月之前”的输入习惯: SET datestyle TO kingbase, dmy; 设置时区为加州伯克利: SET TIME ZONE 'PST8PDT'; 设置时区为意大利: SET TIME ZONE 'Europe/Rome'; 兼容性 SET TIME ZONE 扩展了 SQL 标准定义的语法。标准只允许数字的时区偏移量而 KingbaseES 允许更灵活的时区 说明。所有其他 SET 特性都是 KingbaseES 扩展。 其他 如果在一个事务内发出 SET``(或者等效的\ ``SET SESSION)而该事务后来中止,在该事务被回滚时 SET 命 令的效果会消失。一旦所在的事务被提交,这些效果将会持续到会话结束(除非被另一个 SET 所覆盖)。 SET LOCAL 的效果只持续到当前事务结束,不管事务是否被提交。一种特殊情况是在一个事务内 SET 后面跟着 “SET LOCAL“:SET LOCAL 值将会在该事务结束前一直可见,但是之后(如果该事务被提交)SET 值将会生效。SET 或“SET LOCAL“的效果也会因为回滚到早于它们的保存点而消失。 如果在一个函数内使用 SET LOCAL 并且该函数还有对同一变量的 SET 选项(见CREATE FUNCTION ),在函 数退出时 “SET LOCAL“命令的效果会消失。也就是说,该函数被调用时的值会被恢复。这允许用 “SET LOCAL“在 函数内动态地或者重复地更改一个参数,同时仍然能便利地使用 SET 选项来保存以及恢复调用者的值。但是,一个 常规的 SET 命令会覆盖它所在的任何函数的 SET 选项,除非回滚,它的效果将一直保持。 1260 第 20 章 SQL 语句: MERGE 到 VALUES 注意: 在 KingbaseES V7 版本中,一个 SET LOCAL 的效果会因为释放较早的保存点或者成功地从一个 PL/SQL 异 常块中退出而被取消。这种行为已经被更改,因为它被认为不直观。 20.22 SET CONSTRAINTS 用途 SET CONSTRAINTS 设置当前事务内约束检查的行为。IMMEDIATE 约束在每个语句结束时被检查。DEFERRED 约束 直到事务提交时才被检查。每个约束都有自己的 IMMEDIATE 或 DEFERRED 模式。 在 创 建 时, 一 个 约 束 会 被 给 定 三 种 特 性 之 一:DEFERRABLE INITIALLY DEFERRED、DEFERRABLE INITIALLY IMMEDIATE 或者 NOT DEFERRABLE。第三类总是 IMMEDIATE 并且不会受到 SET CONSTRAINTS 命令的影响。前两类在 每个事务开始时都处于指定的模式,但是它们的行为可以在一个事务内用 SET CONSTRAINTS 更改。 带有一个约束名称列表的 SET CONSTRAINTS 只更改那些约束(都必须是可延迟的)的模式。每一个约束名 称都可以是模式限定的。如果没有指定模式名称,则当前的模式搜索路径将被用来寻找第一个匹配的名称。SET CONSTRAINTS ALL 更改所有可延迟约束的模式。 当 SET CONSTRAINTS 把一个约束的模式从 DEFERRED 改成 IMMEDIATE 时,新模式会有追溯效果:任何还没有解 决的数据修改(本来会在事务结束时被检查)会转而在 SET CONSTRAINTS 命令的执行期间被检查。如果任何这种约 束被违背,SET CONSTRAINTS 将会失败(并且不会改变该约束模式)。这样,SET CONSTRAINTS 可以被用来在一个 事务中的特定点强制进行约束检查。 当前,只有 UNIQUE、PRIMARY KEY、REFERENCES(外键)以及 EXCLUDE 约束受到这个设置的影响。NOT NULL 以及 CHECK 约束总是在一行被插入或修改时立即检查(不是在语句结束时)。没有被声明为 DEFERRABLE 的唯一和 排除约束也会被立刻检查。 被声明为“约束触发器”的触发器的引发也受到这个设置的控制—它们会在相关约束被检查的同时被引发。 前置条件 无 语法 SET CONSTRAINTS { ALL | name [, ...] } { DEFERRED | IMMEDIATE } 1261 第 20 章 SQL 语句: MERGE 到 VALUES 语义 name 指定约束名称 ALL 指定所有约束 示例 设置约束模式为结束时检查 SET CONSTRAINTS my_constraint IMMEDIATE; 兼容性 这个命令符合 SQL 标准中定义的行为,但有一点限制:在 KingbaseES 中,它不会应用在 NOT NULL 和 CHECK 约束上。还有,KingbaseES 会立刻检查非可延迟的唯一约束,而不是按照标准建议的在语句结束时检查。 其他 因为 KingbaseES 并不要求约束名称在模式内唯一(但是在表内要求唯一),可能有多于一个约束匹配指定的约 束名称。在这种情况下 SET CONSTRAINTS 将会在所有的匹配上操作。对于一个非模式限定的名称,一旦在搜索路径 中的某个模式中发现一个或者多个匹配,路径中后面的模式将不会被搜索。 这个命令只修改当前事务内约束的行为。在事务块外部发出这个命令会产生一个警告并且也不会有任何效果。 20.23 SET ROLE 用途 这个命令把当前 SQL 会话的当前用户标识符设置为 “role_name“。角色名可以写成一个标识符或者一个字符 串。在 SET ROLE 之后,对 SQL 命令的权限检查时就好像该角色就是原先登录的角色一样。 当前会话用户必须是指定的角色 “role_name“ 的一个成员(如果会话用户是一个超级用户,则可以选择任何角 色)。 SESSION 和 LOCAL 修饰符发挥的作用和常规的SET 命令一样。 NONE 和 RESET 形式把当前用户标识符重置为当前会话用户标识符。这些形式可以由任何用户执行。 前置条件 你必须拥有该角色以使用 SET ROLE 。 语法 SET [ SESSION | LOCAL ] ROLE role_name SET [ SESSION | LOCAL ] ROLE NONE RESET ROLE 1262 第 20 章 SQL 语句: MERGE 到 VALUES 语义 role_name 要设定的角色名 NONE 重置为当前会话用户标识符 示例 SELECT SESSION_USER, CURRENT_USER; session_user | current_user --------------+-------------peter | peter SET ROLE 'paul'; SELECT SESSION_USER, CURRENT_USER; session_user | current_user --------------+-------------peter | paul 兼容性 KingbaseES 允许标识符语法("rolename”),而 SQL 标准要求角色名被写成字符串。SQL 不允许在事务中使 用这个命令,而 KingbaseES 并不做此限制,因为并没有原因需要这样做。和 RESET 语法一样,SESSION 和 LOCAL 修饰符是一种 KingbaseES 扩展。 其他 使用这个命令可以增加特权或者限制特权。如果会话用户角色具有 INHERITS 属性,则它会自动具有它能 SET ROLE 到的所有角色的全部特权。在这种情况下 SET ROLE 实际会删除所有直接分配给会话用户的特权以及分配给会 话用户作为其成员的其他角色的特权,只留下所提及角色可用的特权。换句话说,如果会话用户没有 NOINHERITS 属 性,SET ROLE 会删除直接分配给会话用户的特权而得到所提及角色可用的特权。 特别地,当一个超级用户选择 SET ROLE 到一个非超级用户角色时,它们会丢失其超级用户特权。 SET ROLE 的效果堪比SET SESSION AUTHORIZATION ,但是涉及的特权检查完全不同。还有,SET SESSION AUTHORIZATION 决定后来的 SET ROLE 命令可以使用哪些角色,但是用 SET ROLE 更改角色并不会改变后续 SET ROLE 能够使用的角色集。 SET ROLE 不会处理角色的:ref:‘ALTER ROLE‘设置指定的会话变量。这只在登录期间发生。 1263 第 20 章 SQL 语句: MERGE 到 VALUES SET ROLE 不能在一个 SECURITY DEFINER 函数中使用。 20.24 SET SESSION AUTHORIZATION 用途 SET SESSION AUTHORIZATION —设置当前会话的会话用户标识符和当前用户标识符 会话用户标识符初始时被设置为客户端提供的(可能已认证的)用户名。当前用户标识符通常等于会话用户标识 符,但是可能在 “SECURITY DEFINER“函数和类似机制的环境中临时更改。也可以用SET ROLE 更改它。当前用 户标识符与权限检查相关。 会话用户标识符只能在初始会话用户已认证用户具有超级用户特权时被更改。否则,只有该命令指定已认证用户 名时才会被接受。 SESSION 和 LOCAL 修饰符发挥的作用和常规SET 命令一样。 DEFAULT 和 RESET 形式把会话用户标识符和当前用户标识符重置为初始的已认证用户名。这些形式可以由任何 用户执行。 前置条件 会话用户标识符只能在初始会话用户已认证用户具有超级用户特权时被更改。 语法 SET [ SESSION | LOCAL ] SESSION AUTHORIZATION user_name SET [ SESSION | LOCAL ] SESSION AUTHORIZATION DEFAULT RESET SESSION AUTHORIZATION 语义 user_name 这个命令把当前 SQL 会话的会话用户标识符和当前用户标识符设置为 “user_name“。用户名可以被写成 一个标识符或者一个字符串。例如,可以使用这个命令临时成为一个无特权用户并且稍后切换回来成为一个超 级用户。 SESSION 指定该命令对当前会话有效(这是默认值)。 1264 第 20 章 SQL 语句: MERGE 到 VALUES LOCAL 指定该命令只对当前事务有效。在 COMMIT 或者 ROLLBACK 之后,会话级别的设置会再次生效。在事务块外部 发出这个参数会发出一个警告并且不会有效果。 DEFAULT, RESET 当前用户标识符重置为初始的已认证用户名。这些形式可以由任何用户执行。 示例 SELECT SESSION_USER, CURRENT_USER; session_user | current_user --------------+-------------peter | peter SET SESSION AUTHORIZATION 'paul'; SELECT SESSION_USER, CURRENT_USER; session_user | current_user --------------+-------------paul | paul 兼容性 SQL 标准允许一些其他表达式出现在文本 user_name 的位置上,但是实际上这些选项并不重要。KingbaseES 允 许标识符语法("username"),而 SQL 标准不允许。SQL 不允许在事务中使用这个命令,而 KingbaseES 并不做此 限制,因为并没有原因需要这样做。和 RESET 语法一样,SESSION 和 LOCAL 修饰符是一种 KingbaseES 扩展。 标准把执行这个命令所需的特权留给实现定义。 其他 SET SESSION AUTHORIZATION 不能在一个 “SECURITY DEFINER“函数中使用。 开启 “disable_user_switching“参数后,将限制调用 SET [ SESSION | LOCAL ] SESSION AUTHORIZATION 命令,防止切换用户时不用输入密码的操作。 20.25 SET TRANSACTION 用途 SET TRANSACTION 命令设置当前会话的特性。SET SESSION CHARACTERISTICS 设置一个会话后续事务的默认事 务特性。在个体事务中可以用 SET TRANSACTION 覆盖这些默认值。 前置条件 无 语法 1265 第 20 章 SQL 语句: MERGE 到 VALUES SET TRANSACTION transaction_mode [, ...] SET TRANSACTION SNAPSHOT snapshot_id SET SESSION CHARACTERISTICS AS TRANSACTION transaction_mode [, ...] 其中 transaction_mode 是下列之一: ISOLATION LEVEL { SERIALIZABLE | REPEATABLE READ | READ COMMITTED | READ UNCOMMITTED } READ WRITE | READ ONLY [ NOT ] DEFERRABLE 语义 可用的事务特性是事务隔离级别、事务访问模式(读/写或只读)以及可延迟模式。此外,可以选择一个快照, 但是只能用于当前事务而不能作为会话默认值。 一个事务的隔离级别决定当其他事务并行运行时该事务能看见什么数据: 1266 第 20 章 SQL 语句: MERGE 到 VALUES READ COMMITTED 一个语句只能看到在它开始前提交的行。这是默认值。 REPEATABLE READ 当前事务的所有语句只能看到这个事务中执行的第一个查询或者数据修改语句之前提交的行。 SERIALIZABLE 当前事务的所有语句只能看到这个事务中执行的第一个查询或者数据修改语句之前提交的行。如果并 发的可序列化事务间的读写模式可能导致一种那些事务串行(一次一个)执行时不可能出现的情况,其中之一 将会被回滚并且得到一个 serialization_failure 错误。 SQL 标准定义了一种额外的级别:READ UNCOMMITTED。在 KingbaseES 中 READ UNCOMMITTED 被视作 READ COMMITTED。 一个事务执行了第一个查询或者数据修改语句(SELECT、INSERT、DELETE、UPDATE、FETCH 或 COPY)之后就无 法更改事务隔离级别。 事务的访问模式决定该事务是否为读/写或者只读。读/写是默认值。当一个事务为只读时,如果 SQL 命令 INSERT、UPDATE、DELETE 和 COPY FROM 要写的表不是一个临时表,则它们不被允许。不允许 CREATE、ALTER 以及 DROP 命令。不允许 COMMENT、GRANT、REVOKE、TRUNCATE。如果 EXPLAIN ANALYZE 和 EXECUTE 要执行的命令是上 述命令之一,则它们也不被允许。这是一种高层的只读概念,它不能阻止所有对磁盘的写入。 只有事务也是 SERIALIZABLE 以及 READ ONLY 时,DEFERRABLE 事务属性才会有效。当一个事务的所有这三个属 性都被选择时,该事务在第一次获取其快照时可能会阻塞,在那之后它运行时就不会有 SERIALIZABLE 事务的开销并 且不会有任何牺牲或者被一次序列化失败取消的风险。这种模式很适合于长时间运行的报表或者备份。 SET TRANSACTION SNAPSHOT 命令允许新的事务使用与一个现有事务相同的快照运行。已经存在的事务必须 已经把它的快照用 sys_export_snapshot 函数(见 快照同步函数)导出。该函数会返回一个快照标识符,SET TRANSACTION SNAPSHOT 需要被给定一个快照标识符来指定要导入的快照。在这个命令中该标识符必须被写成一个字 符串,例如 '000003A1-1'。SET TRANSACTION SNAPSHOT 只能在一个事务的开始执行,并且要在该事务的第一个查 询或者数据修改语句(SELECT、INSERT、DELETE、UPDATE、FETCH 或 COPY)之前执行。此外,该事务必须已经被设 置为 SERIALIZABLE 或者 REPEATABLE READ 隔离级别(否则,该快照将被立刻抛弃,因为 READ COMMITTED 模式会 为每一个命令取一个新快照)。如果导入事务使用了 SERIALIZABLE 隔离级别,那么导入快照的事务必须也使用该隔 离级别。还有,一个非只读可序列化事务不能导入来自只读事务的快照。 示例 要用一个已经存在的事务的同一快照开始一个新事务,首先要从该现有事务导出快照。这将会返回快照标识符, 例如: BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; SELECT sys_export_snapshot(); sys_export_snapshot --------------------00000003-0000001B-1 (1 row) 然后在一个新开始的事务的开头把该快照标识符用在一个 SET TRANSACTION SNAPSHOT 命令中: BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; SET TRANSACTION SNAPSHOT '00000003-0000001B-1'; 1267 第 20 章 SQL 语句: MERGE 到 VALUES 兼容性 SQL 标准中定义了这些命令,但是 DEFERRABLE 事务模式和 SET TRANSACTION SNAPSHOT 形式除外,这两者是 KingbaseES 扩展。 SERIALIZABLE 是标准中默认的事务隔离级别。在 KingbaseES 中默认值是普通的 READ COMMITTED,但是你可以 按上述的方式更改。 在 SQL 标准中,可以用这些命令设置一个其他的事务特性:诊断区域的尺寸。这个概念与嵌入式 SQL 有关,并 且因此没有在 KingbaseES 服务器中实现。 SQL 标准要求连续的 “transaction_modes“之间有逗号,但是出于历史原因 KingbaseES 允许省略逗号。 其他 如果执行 SET TRANSACTION 之前没有 START TRANSACTION 或者 BEGIN,它会发出一个警告并且不会有任何效 果。 可以通过在 BEGIN 或者 START TRANSACTION 中指定想要的 “transaction_modes“来省掉 SET TRANSACTION。但 是在 SET TRANSACTION SNAPSHOT 中该选项不可用。 会话默认的事务模式也可以通过设置配置参数 default_transaction_isolation 、default_transaction_read_only 和 default_transaction_deferrable 来设置(实际上 SET SESSION CHARACTERISTICS 只是用 SET 设置这些变量的等效 体)。这意味着可以通过配置文件、ALTER DATABASE 等方式设置默认值。详见《数据库参考手册》。 20.26 SHOW 用途 SHOW —显示一个运行时参数的值 SHOW 将显示运行时参数的当前设置。这些变量可以使用 SET 语句、编辑 “kingbase.conf“配置参数、通过 “KINGBASE_OPTIONS“环境变量(使用 libkci 或者基于 libkci 的应用时)或者启动 kingbase 服务器时通过命令 行标志设置。详见《数据库参考手册》。 前置条件 无 语法 SHOW name SHOW ALL 1268 第 20 章 SQL 语句: MERGE 到 VALUES 语义 name 一个运行时参数的名称。可用的参数记录在《数据库参考手册》和SET 参考页。此外,有一些可以显示但不能 设置的参数: SERVER_VERSION 显示服务器的版本号。 SERVER_ENCODING 显示服务器端的字符集编码。当前,这个参数可以被显示但不能被设置,因为该设置是在数 据库创建时决定的。 LC_COLLATE 显示数据库的排序规则(文本序)的区域设置。当前,这个参数可以被显示但不能被设置,因为 该设置是在数据库创建时决定的。 LC_CTYPE 显示数据库的字符分类的区域设置。当前,这个参数可以被显示但不能被设置,因为该设置是在数 据库创建时决定的。 IS_SUPERUSER 如果当前角色具有超级用户特权则为真。 ALL 显示所有配置参数的值,并带有描述。 示例 显示参数 DateStyle 的当前设置: SHOW DateStyle; DateStyle ----------ISO, MDY (1 row) 显示参数 geqo 的当前设置: SHOW geqo; geqo -----on (1 row) 显示所有设置: SHOW ALL; name |setting | description -------------------------+--------+--------------------------------------------allow_system_table_mods |off | Allows modifications of the structure of ... . . . xmloption |content| Sets whether XML data in implicit parsing ... zero_damaged_pages |off |Continues processing past damaged page headers. (196 rows) 1269 第 20 章 SQL 语句: MERGE 到 VALUES 兼容性 SHOW 命令是一种 KingbaseES 扩展。 20.27 START TRANSACTION 用途 START TRANSACTION —开始一个事务块 这个命令开始一个新的事务块。如果指定了隔离级别、读写模式或者可延迟模式,新的事务将会具有这些特性, 就像执行了SET TRANSACTION 一样。这和BEGIN 命令一样。 前置条件 无 语法 START TRANSACTION [ transaction_mode [, ...] ] 其中 transaction_mode 是下列之一: ISOLATION LEVEL { SERIALIZABLE | REPEATABLE READ | READ COMMITTED | READ UNCOMMITTED } READ WRITE | READ ONLY [ NOT ] DEFERRABLE 1270 第 20 章 SQL 语句: MERGE 到 VALUES 语义 这些参数对于这个语句的含义可参考SET TRANSACTION 。 示例 开始一个隔离级别是 READ COMMIT 的事物 start transaction ISOLATION LEVEL READ COMMITTED; 兼容性 在标准中,没有必要发出“START TRANSACTION“来开始一个事务块:任何 SQL 命令会隐式地开始一个块。 KingbaseES 的行为可以被视作在每个命令之后隐式地发出一个没有跟随在 “START TRANSACTION“(或者 BEGIN)之后的 “COMMIT“并且因此通常被称作“自动提交”。为了方便,其他关系型数据库系统也可能会提供自 动提交特性。 DEFERRABLE “transaction_mode“ 是一种 KingbaseES 语言扩展。 SQL 标准要求在连续的 “transaction_modes“之间有逗号,但是由于历史原因 KingbaseES 允许省略逗号。 另见SET TRANSACTION 的兼容性小节。 20.28 TRUNCATE 用途 1271 第 20 章 SQL 语句: MERGE 到 VALUES TRUNCATE 可以从一组表中快速地移除所有行。它具有和在每个表上执行无条件 DELETE 相同的效果,但是它会 更快,因为它没有实际扫描表。此外,它会立刻回收磁盘空间,而不是要求一个后续的 VACUUM 操作。在大表上它最 有用。 前置条件 要截断一个表,你必须具有其上的 TRUNCATE 特权。 语法 TRUNCATE [ TABLE ] [ ONLY ] name [ * ] [, ... ] [ RESTART IDENTITY | CONTINUE IDENTITY ] [ CASCADE | RESTRICT ] 语义 name 要截断的表的名字(可以是模式限定的)。如果在表名前指定了 ONLY,则只会截断该表。如果没有指定 ONLY,该表及其所有后代表(如果有)都会被截断。可选地,可以在表名后指定 * 来显式地包括后代表。 RESTART IDENTITY 自动重新开始被截断表的列所拥有的序列。 CONTINUE IDENTITY 不更改序列值。这是默认值。 CASCADE 自动截断所有对任一所提及表有外键引用的表以及任何由于 CASCADE 被加入到组中的表。 RESTRICT 如果任一表上具有来自命令中没有列出的表的外键引用,则拒绝截断。这是默认值。 示例 截断表 bigtable 和 fattable: TRUNCATE bigtable, fattable; 做同样的事情,并且还重置任何相关联的序列发生器: TRUNCATE bigtable, fattable RESTART IDENTITY; 截断表 othertable,并且级联地截断任何通过外键约束引用 othertable 的表: TRUNCATE othertable CASCADE; 兼容性 SQL:2008 标 准 包 括 了 一 个 TRUNCATE 命 令, 语 法 是 TRUNCATE TABLE tablename。 子 句 CONTINUE IDENTITY/“RESTART IDENTITY“也出现在了该标准中,但是含义有些不同。这个命令的一些并发行为被标准 1272 第 20 章 SQL 语句: MERGE 到 VALUES 留给实现来定义,因此如果必要应该考虑上述注解并且与其他实现进行比较。 其他 TRUNCATE 在要操作的表上要求一个 ACCESS EXCLUSIVE 锁,这会阻塞所有其他在该表上的并发操作。当指定 RESTART IDENTITY 时,任何需要被重新开始的序列也会被排他地锁住。如果要求表上的并发访问,那么应该使用 DELETE 命令。 TRUNCATE 不能被用在被其他表外键引用的表上,除非那些表也在同一个命令中被阶段。这些情况中的可行性检 查将会要求表扫描,并且重点不是为了做扫描。CASCADE 选项可以被用来自动地包括所有依赖表—但使用它时要非常 小心,否则你可能丢失数据! TRUNCATE 将不会引发表上可能存在的任何 ON DELETE 触发器。但是它将会引发 ON TRUNCATE 触发器。如果在 这些表的任意一个上定义了 ON TRUNCATE 触发器,那么所有的 BEFORE TRUNCATE 触发器将在任何截断发生之前被引 发,而所有 AFTER TRUNCATE 触发器将在最后一次截断完成并且所有序列被重置之后引发。触发器将以表被处理的顺 序被引发(首先是那些被列在命令中的,然后是由于级联被加入的)。 TRUNCATE 不是 MVCC 安全的。截断之后,如果并发事务使用的是一个在截断发生前取得的快照,表将对这些并 发事务呈现为空。 从表中数据的角度来说,TRUNCATE 是事务安全的:如果所在的事务没有提交,阶段将会被安全地回滚。 在指定了 RESTART IDENTITY 时,隐含的 ALTER SEQUENCE RESTART 操作也会被事务性地完成。也就是说,如 果所在事务没有提交,它们也将被回滚。这和 ALTER SEQUENCE RESTART 的通常行为不同。注意如果事务回滚前在被 重启序列上还做了额外的序列操作,这些操作在序列上的效果也将被回滚,但是它们在 currval() 上的效果不会被 回滚。也就是说,在事务之后,currval() 将继续反映在失败事务内得到的最后一个序列值,即使序列本身可能已经 不再与此一致。这和失败事务之后 currval() 的通常行为类似。 TRUNCATE 当前不支持外部表。这表示如果一个指定的表具有任何外部的后代表,这个命令将会失败。 20.29 UNLISTEN 用途 UNLISTEN —停止监听一个通知 UNLISTEN 被用来移除一个已经存在的对 NOTIFY 事件的注册。 UNLISTEN 取消任何已经存在的把当前 KingbaseES 会话作为名为 *“channel“* 的通知频道的监听者的注册。特殊 的通配符 * 取消当前会话的所有监听者注册。 NOTIFY 包含有关 LISTEN``和\ ``NOTIFY 使用的更深入讨论。 前置条件 无。 语法 1273 第 20 章 SQL 语句: MERGE 到 VALUES UNLISTEN { channel | * } 语义 channel 一个通知频道的名称(任何标识符)。 * 所有用于这个会话的当前监听注册都会被清除。 示例 做一次注册: LISTEN virtual; NOTIFY virtual; Asynchronous notification "virtual" received from server process with PID 8448. 一旦执行了 UNLISTEN,进一步的 NOTIFY 消息将被忽略: UNLISTEN virtual; NOTIFY virtual; -- no NOTIFY event is received 兼容性 在 SQL 标准中没有 VACUUM 语句。 其他 你可以 unlisten 你没有监听的东西,不会出现警告或者错误。 在每一个会话末尾,会自动执行 UNLISTEN *。 一个已经执行了 UNLISTEN 的事务不能为两阶段提交做准备。 20.30 UPDATE 用途 UPDATE 更改满足条件的所有行中指定列的值。只有要被修改的列需要在 SET 子句中提及,没有被显式修改的列 保持它们之前的值。 有两种方法使用包含在数据库其他表中的信息来修改一个表:使用子查询或者在 FROM 子句中指定额外的表。这 种技术只适合特定的环境。 1274 第 20 章 SQL 语句: MERGE 到 VALUES 可选的 RETURNING 子句导致 UPDATE 基于实际被更新的每一行计算并且返回值。任何使用该表的列以及 FROM 中提到的其他表的列的表达式都能被计算。计算时会使用该表的列的新(更新后)值。RETURNING 列表的语法和 SELECT 的输出列表相同。 前置条件 你必须拥有该表上的 UPDATE 特权,或者至少拥有要被更新的列上的该特权。如果任何一列的值需要被 “expressions“或者 “condition“读取,你还必须拥有该列上的 SELECT 特权。 语法 [ WITH [ RECURSIVE ] with_query [, ...] ] UPDATE [ ONLY ] table_name [part_extension_clause] [ * ] [ [ AS ] alias ] | sub_query [alias] SET {[{ column_name = { expression | DEFAULT } | ( column_name [, ...] ) = [ ROW ] ( { expression | DEFAULT } [, ...] ) | ( column_name [, ...] ) = ( sub-SELECT ) } [, ...]] | [ ROW = record]} [ FROM from_list ] [ WHERE condition | WHERE CURRENT OF cursor_name ] [ RETURNING * | output_expression [ [ AS ] output_name ] [, ...] ] 1275 第 20 章 SQL 语句: MERGE 到 VALUES 1276 第 20 章 SQL 语句: MERGE 到 VALUES Part_extension_clause: { PARTITION (patition) | PARTITION FOR (partition_key_value [, partition_key_value]…) | SUBPARTITION (subpartition) | SUBPARTITION FOR (subpartition_key_value [, subpartition_key_value]…) } 语义 with_query WITH 子句允许你指定一个或者更多个在 UPDATE 中可用其名称引用的子查询。详见 WITH 查询 和SELECT 。 table_name 要更新的表的名称(可以是模式限定的)。如果在表名前指定了 ONLY,只会更新所提及表中的匹配行。 如果没有指定 ONLY,任何从所提及表继承得到的表中的匹配行也会被更新。可选地,在表名之后指定 * 可以显 式地指示要把后代表也包括在内。 part_extension_clause 支持通过 partitionsubpartition 关键字指定分区名或者子分区名,实现对分区和子分区直接 进行 update 操作。其中 PARTITION FOR(partition_key_value) 指定分区键值,PARTITION (partition) 指定分区名,这里的分区名是指 oralce 语法创建分区表时指定的分区名,而不是分区对象在系统表 sys_class 中 存储的对象名。 alias 目标表的一个替代名称。在提供了一个别名时,它会完全隐藏表的真实名称。例如,给定 UPDATE foo AS f,UPDATE 语句的剩余部分必须用 f 而不是 foo 来引用该表。 sub_query • 当子查询作为 UPDATE 目标时,UPDATE 的目标是子查询中的基表; • Update set 列必须在子查询的投影列中,且必须是基表中的列, • 子查询投影列中不包含聚集函数(avg,count,max,min,sum 等),distinct 等; • 不支持 GROUP BY, ORDER BY, MODEL, CONNECT BY, START WITH clause 子句; 1277 第 20 章 SQL 语句: MERGE 到 VALUES • 子查询不支持 Union/Intersect/Except/Minus 等集合查询。 column_name “table_name“ 所指定的表的一列的名称, 可以用表名 (可以被模式名限定) 做限定。如果需要,该列名 可以用一个子域名称 (子域名需要和表名、模式名一同用小括号包围起来进行限定) 或者数组下标限定。 expression 要被赋值给该列的一个表达式。该表达式可以使用该表中这一列或者其他列的旧值。 DEFAULT 将该列设置为它的默认值(如果没有为它指定默认值表达式,默认值将会为 NULL)。 sub-SELECT 一个 SELECT 子查询,它产生和在它之前的圆括号中的列表中一样多的输出列。被执行时,该子查询必 须得到不超过一行。如果它得到一行,其列值会被赋予给目标列。如果它得不到行,NULL 值将被赋予给目标 列。该子查询可以引用被更新表中当前行的旧值。 from_list 表表达式的列表,允许来自其他表的列出现在 WHERE 条件和更新表达式中。这类似于可以在 SELECT 语 句的 FROM 中指定的表列表。注意目标表不能出现在 “from_list“中,除非你想做自连接(这种情况下它必须 以别名出现在 “from_list“中)。 condition 一个返回 boolean 类型值的表达式。让这个表达式返回 true 的行将会被更新。 cursor_name 要在 WHERE CURRENT OF 条件中使用的游标名。要被更新的是从这个游标中最近取出的行。该游标必 须是一个在 UPDATE 目标表上的非分组查询。注意 WHERE CURRENT OF 不能和一个布尔条件一起指定。有关对 游标使用 WHERE CURRENT OF 的更多信息请见DECLARE 。 output_expression 在每一行被更新后,要被 UPDATE 命令计算并且返回的表达式。该表达式可以使用 “table_name“指定的表或者 FROM 列出的表中的任何列名。写“*“可以返回所有列。 output_name 用于一个被返回列的名称。 record record 变量名,变量类型是自定义 RECORD 或%ROWTYPE。UPDATE 语句更新行数据为 record 变量 值。对于行数据的每列,record 的成员必须与表对应列类型兼容。如果表列有 NOT NULL 约束,对应的 record 成员不能有 NULL 值。record 成员个数必须与前面 table 的列数相同,且类型兼容。否则报错。 示例 把表 films 的列 kind 中的单词 Drama 改成 Dramatic: UPDATE films SET kind = 'Dramatic' WHERE kind = 'Drama'; 在表 weather 的一行中调整温度项并且把沉淀物重置为它的默认值: UPDATE weather SET temp_lo = temp_lo+1, temp_hi = temp_lo+15, prcp = DEFAULT WHERE city = 'San Francisco' AND date = '2003-07-03'; 执行相同的操作并且返回更新后的项: UPDATE weather SET temp_lo = temp_lo+1, temp_hi = temp_lo+15, prcp = DEFAULT WHERE city = 'San Francisco' AND date = '2003-07-03' RETURNING temp_lo, temp_hi, prcp; 使用另一种列列表语法来做同样的更新: 1278 第 20 章 SQL 语句: MERGE 到 VALUES UPDATE weather SET (temp_lo, temp_hi, prcp) = (temp_lo+1, temp_lo+15, DEFAULT) WHERE city = 'San Francisco' AND date = '2003-07-03'; 为管理 Acme Corporation 账户的销售人员增加销售量,使用 FROM 子句语法: UPDATE employees SET sales_count = sales_count + 1 FROM accounts WHERE accounts.name = 'Acme Corporation' AND employees.id = accounts.sales_person; 执行相同的操作,在 WHERE 子句中使用子选择: UPDATE employees SET sales_count = sales_count + 1 WHERE id = (SELECT sales_person FROM accounts WHERE name = 'Acme Corporation'); 更新 accounts 表中的联系人姓名以匹配当前被分配的销售员: UPDATE accounts SET (contact_first_name, contact_last_name) = (SELECT first_name, last_name FROM salesmen WHERE salesmen.id = accounts.sales_id); 可以用连接完成类似的结果: UPDATE accounts SET contact_first_name = first_name, contact_last_name = last_name FROM salesmen WHERE salesmen.id = accounts.sales_id; 但是,如果 salesmen.id 不是一个唯一键,第二个查询可能会给出令人意外的结果,然而如果有多个 id 匹配, 第一个查询保证会发生错误。还有,如果对于一个特定的 accounts.sales_id 项没有匹配,第一个查询将把相应的 姓名域设置为 NULL,而第二个查询完全不会更新该行。 更新一个统计表中的统计数据以匹配当前数据: UPDATE summary s SET (sum_x, sum_y, avg_x, avg_y) = (SELECT sum(x), sum(y), avg(x), avg(y) FROM data d WHERE d.group_id = s.group_id); 尝试插入一个新库存项及其库存量。如果该项已经存在,则转而更新已有项的库存量。要这样做并且不让整个事 务失败,可以使用保存点: BEGIN; -- 其他操作 SAVEPOINT sp1; INSERT INTO wines VALUES('Chateau Lafite 2003', '24'); -- 假定上述语句由于未被唯一键失败, -- 那么现在我们发出这些命令: ROLLBACK TO sp1; 1279 第 20 章 SQL 语句: MERGE 到 VALUES UPDATE wines SET stock = stock + 24 WHERE winename = 'Chateau Lafite 2003'; -- 继续其他操作,并且最终 COMMIT; 更改表 films 中由游标 c_films``定位的行的\ ``kind 列: UPDATE films SET kind = 'Dramatic' WHERE CURRENT OF c_films; 更改表数据为 record 变量值: CREATE TABLE t1(id INT, name VARCHAR(20)); \set SQLTERM / DECLARE TYPE myrecord IS RECORD(id INT, name VARCHAR(20)); r1 myrecord; BEGIN r1.id := 1; r1.name := 'new'; UPDATE t1 SET ROW = r1; END; / 兼容性 这个命令符合 SQL 标准,但是 FROM 和 RETURNING 子句是 KingbaseES 扩展,把 WITH 用于 UPDATE 也是扩 展。 有些其他数据库系统提供了一个 FROM 选项,在其中在其中目标表可以在 FROM 中被再次列出。但 KingbaseES 不是这样解释 FROM 的。在移植使用这种扩展的应用时要小心。 根据标准,一个目标列名的圆括号子列表的来源值可以是任意得到正确列数的行值表达式。KingbaseES 只允许 来源值是一个行构造器或者一个子查询。一个列的被更新值可以在行构造器的情况中被指定为 DEFAULT,但在子查 询的情况中不能这样做。 其他 1. 输出 成功完成时,一个 UPDATE 命令返回形如 UPDATE count 的命令标签。“count“是被更新的行数,包括值没有更改的匹配行。注意,当更新被一个 BEFORE UPDATE 触发器 抑制时,这个数量可能比匹配 “condition“的行数少。如果 “count“为零,没有行被该查询更新(这不是一个错误)。 如果 UPDATE 命令包含一个 RETURNING 子句,其结果将类似于一个包含 RETURNING 列表中定义的列和值的 SELECT 语句(在被该命令更新的行上计算)的结果。 2. 说明 1280 第 20 章 SQL 语句: MERGE 到 VALUES 当存在 FROM 子句时,实际发生的是:目标表被连接到 “from_list“中的表,并且该连接的每一个输出行表示对 目标表的一个更新操作。在使用 FROM 时,你应该确保该连接对每一个要修改的行产生至多一个输出行。换句话说, 一个目标行不应该连接到来自其他表的多于一行上。如果发生这种情况,则只有一个连接行将被用于更新目标行,但 是将使用哪一行是很难预测的。 由于这种不确定性,只在一个子选择中引用其他表更安全,但是这种语句通常很难写并且也比使用连接慢。 在分区表的情况下,更新一行有可能导致它不再满足其所在分区的分区约束。此时,如果这个行满足分区树中某 个其他分区的分区约束,那么这个行会被移动到那个分区。如果没有这样的分区,则会发生错误。在后台,行的移动 实际上是一次 DELETE 操作和一次 INSERT 操作。 对于正在移动的行,并发的 UPDATE 或 DELETE 将会得到序列化失败错误。假设会话 1 在一个分区键上执行一个 UPDATE,同时,一个可以看到这一行的并发会话 2 在这一行上执行一个 UPDATE 或 DELETE 操作。在这种情况下,会 话 2 的 UPDATE 或 DELETE 将检测行移动并引发序列化失败错误 (它总是返回一个 SQLSTATE 代码’40001’)。如果发 生这种情况,应用程序可能希望重试事务。在通常情况下,如果表没有分区,或者没有行移动,会话 2 将识别新更新 的行,并在这个新行版本上执行 UPDATE/DELETE。 注意,虽然行可以从本地分区移动到外部表分区 (假设外部数据包装器支持元组路由),但是它们不能从外部表分 区移动到另一个分区。 对于 SET ROW = record 语句,有下面限制条件: a. UPDATE SET ROW = record 只能在 PLSQL 中使用。 b. Record 变量只允许出现在: 1)UPDATE 语句 SET 子句的右边。 2)RETURNING 子句的 INTO 子句中。 c. ROW 关键字只允许在 SET 的左边,不可以在子查询中使用 ROW。 d. UPDATE 语句中,如果是使用 ROW,只允许出现一个 ROW 子句。 e. 如果 RETURNING INTO 子句包含一个 record 变量,不允许出现其他变量或值。 f. record 成员个数必须都前面 table 列数相同,且类型兼容。否则报错。 g. 不支持: 1)嵌套的 record 类型。 2)返回 record 类型的函数。 3)EXECUTE IMMEDIATE 的 INSERT, UPDATE 语句的 record 20.31 UPDATE(MySQL 模式) 本小节仅针对于 MySQL 模式下特有属性,其他具体细节可参考UPDATE 。 单表语法 1281 第 20 章 SQL 语句: MERGE 到 VALUES [ WITH [ RECURSIVE ] with_query [, ...] ] UPDATE [ ONLY ] table_name [ * ] [ [ AS ] alias ] | sub_query [alias] SET {[{ column_name = { expression | DEFAULT } | ( column_name [, ...] ) = [ ROW ] ( { expression | DEFAULT } [, ...] ) | ( column_name [, ...] ) = ( sub-SELECT ) } [, ...]] | [ ROW = record]} [ FROM from_list ] [ WHERE condition | WHERE CURRENT OF cursor_name ] [ ORDER BY expression [ ASC | DESC | USING operator ] [ NULLS { FIRST | LAST } ] [, ...] ] [ LIMIT { count | ALL } ] [ RETURNING * | output_expression [ [ AS ] output_name ] [, ...] ] 1282 第 20 章 SQL 语句: MERGE 到 VALUES 1283 第 20 章 SQL 语句: MERGE 到 VALUES 语义 MySQL 模式 UPDATE 支持 ORDER BY/LIMIT 子句。 • ORDER BY 子句表示按照指定的顺序更新表中的数据; • LIMIT row_count 子句表示更新表中限定 row_count 行数的数据。 多表语法 UPDATE table_references SET assignment_list [WHERE where_condition] 图 20.31.1: 其中: assignment_list: col_name = {expr | DEFAULT} [, col_name = {expr | DEFAULT}] ... table_references: table_refence [, table_refence]... table_refence: { table_factor | joined_table } 1284 第 20 章 SQL 语句: MERGE 到 VALUES table_factor:{ tbl_name [[AS] alias] | [LATERAL] table_subquery [AS] alias | (table_references) } joined_table: { table_refence {[INNER | CROSS] JOIN} table_factor [join_specification] | table_refence {LEFT|RIGHT} [OUTER] JOIN table_refence join_specification | table_refence NATURAL [INNER | {LEFT|RIGHT} [OUTER]] JOIN table_factor } 1285 第 20 章 SQL 语句: MERGE 到 VALUES 语义 MySQL 模式多表 UPDATE 可以基于多表查询更新数据,可以同时更新多个目标表。UPDATE 更新 table_references 中命名的每个表中满足条件的行。每个匹配的行都会更新一次,即使它多次匹配条件。对于分区表, 多表更新的形式支持使用其作为表引用的一部分。此选项采用一个或多个分区或子分区(或两者)的列表。仅检查列 出的分区(或子分区)是否匹配,并且不更新不在这些分区或子分区中的行,无论它是否满足 where_condition。 20.32 VACUUM 用途 VACUUM —垃圾收集并根据需要分析一个数据库 VACUUM 收回由死亡元组占用的存储空间。在通常的 KingbaseES 操作中,被删除或者被更新废弃的元组并没有在物理上从它们的表中移除,它们将一直存在直到一次 VACUUM 被执行。因此有必要周期性地做 VACUUM,特别是在频繁被更新的表上。 在没有 “table_and_columns“列表的情况下,VACUUM 会处理当前用户具有清理权限的当前数据库中的每一个表 和物化视图。如果给出一个列表,VACUUM 可以只处理列表中的那些表。 VACUUM ANALYZE 对每一个选定的表 ANALYZE。这是两种命令的一种方便的组合形式,可以用于例行的维护脚 本。其处理细节可参考ANALYZE 。 简单的 “VACUUM“(不带 FULL)简单地收回空间并使其可以被重用。这种形式的命令可以和表的普通读写操 作并行,因为它不会获得一个排他锁。但是,这种形式中额外的空间并没有被还给操作系统(在大多数情况下),它 仅仅被保留在同一个表中以备重用。VACUUM FULL 将表的整个内容重写到一个新的磁盘文件中,并且不包含额外的空 间,这使得没有被使用的空间被还给操作系统。这种形式的命令更慢并且在其被处理时要求在每个表上保持一个排他 锁。 1286 第 20 章 SQL 语句: MERGE 到 VALUES 当选项列表被包围在圆括号中时,选项可以被写成任何顺序。如果没有圆括号,选项必须严格按照上面所展示的 顺序指定。有圆括号的语法在 KingbaseES V8R2 时被加入,无圆括号的语法则被废弃。 前置条件 要清理一个表,操作者通常必须是表的拥有者或者超级用户。但是,数据库拥有者被允许清理他们的数据库中除 了共享目录之外的所有表(对于共享目录的限制意味着一个真正的数据库范围的 VACUUM 只能被超级用户执行)。 VACUUM 将会跳过执行者不具备清理权限的表。 语法 VACUUM [ ( option [, ...] ) ] [ table_and_columns [, ...] ] VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] [ ANALYZE ] [ table_and_columns [, ...] ] 其中 option 可以是下列之一: FULL [ boolean ] FREEZE [ boolean ] VERBOSE [ boolean ] ANALYZE [ boolean ] DISABLE_PAGE_SKIPPING [ boolean ] SKIP_LOCKED [ boolean ] INDEX_CLEANUP [ boolean ] TRUNCATE [ boolean ] 而 table_and_columns 是: table_name [ ( column_name [, ...] ) ] 1287 第 20 章 SQL 语句: MERGE 到 VALUES table_and_columns ::= 语义 FULL 选择“完全”清理,它可以收回更多空间,并且需要更长时间和表上的排他锁。这种方法还需要额外的磁盘空 间,因为它会创建该表的一个新拷贝,并且在操作完成之前都不会释放旧的拷贝。通常这种方法只用于需要从 表中收回数量庞大的空间时。 FREEZE 选 择 激 进 的 元 组 “冻 结”。 指 定 “FREEZE“ 等价于参数 vacuum_freeze_min_age 和 vac- uum_freeze_table_age 设置为 0 的 “VACUUM“。当表被重写时总是会执行激进的冻结,因此指定 FULL 时这个选项是多余的。 VERBOSE 为每个表打印一份详细的清理活动报告。 ANALYZE 更新优化器用以决定最有效执行一个查询的方法的统计信息。 DISABLE_PAGE_SKIPPING 通常,VACUUM 将基于可见性映射跳过页面。已知所有元组都被冻结的页面总是会被跳过, 而那些所有元组对所有事务都可见的页面则可能会被跳过(除非执行的是激进的清理)。此外,除非在执行激 进的清理时,一些页面也可能会被跳过,这样可避免等待其他页面完成对其使用。这个选项禁用所有的跳过页 面的行为,其意图是只在可见性映射内容被怀疑时使用,这种情况只有在硬件或者软件问题导致数据库损坏时 才会发生。 1288 第 20 章 SQL 语句: MERGE 到 VALUES SKIP_LOCKED 指定 VACUUM 在开始处理一个关系时,不应等待任何冲突锁被释放: 如果一个关系不能立即被锁定而 不等待,则跳过该关系。注意,即使使用这个选项,VACUUM 在打开关系的索引时仍然可能阻塞。此外,当从分 区、表继承子表和某些类型的外部表获取样本行时,VACUUM ANALYZE 可能仍然会阻塞。此外,当 VACUUM 通常 处理指定分区表的所有分区时,如果分区表上有冲突的锁,则此选项将导致 VACUUM 跳过所有分区。 INDEX_CLEANUP 指 定 VACUUM 尝 试 删 除 指 向 死 元 组 的 索 引 项。 这 通 常 是 需 要 的 行 为, 并 且 是 默 认 的, 除 非 将 vacuum_index_cleanup 选项设置为 false,以便对表进行空化。当需要使 vacuum 尽可能快地运行时,将该选 项设置为 false 可能是有用的,例如为了避免即将发生的事务 ID 封装 (请参阅 防止事务 ID 回卷失败)。但是, 如果不定期执行索引清理,性能可能会受到影响,因为当表被修改时,索引将积累死元组,而表本身将积累死 行指针,这些指针在索引清理完成之前无法删除。此选项对没有索引的表无效,如果使用 FULL 选项,则会忽 略此选项。 TRUNCATE 指定 VACUUM 应该尝试截断表末尾的任何空页,并允许将截断的页返回给操作系统。这通常是需要的行 为,并且是默认的,除非将 vacuum_truncate 选项设置为 false,以便对表进行真空处理。将此选项设置为 false 可能有助于避免截断所需的表上的 ACCESS EXCLUSIVE 锁。如果使用 FULL 选项,则忽略此选项。 boolean 指定所选选项应该打开还是关闭。可以编写 TRUE,ON,或 1 来启用这个选项,编写 FALSE,OFF,或 0 来 禁用它。也可以省略 “boolean“,此时假设 TRUE。 table_name 要清理的表或物化视图的名称(可以有模式修饰)。如果指定的表示一个分区表,则它所有的叶子分区 也会被清理。 column_name 要分析的指定列的名称。缺省是所有列。如果指定了一个列的列表,则 ANALYZE 也必须被指定。 示例 清理单一表 onek,为优化器分析它并且打印出详细的清理活动报告: VACUUM (VERBOSE, ANALYZE) onek; 兼容性 在 SQL 标准中没有 VACUUM 语句。 其他 VACUUM 不能在一个事务块内被执行。 对具有 GIN 索引的表,VACUUM(任何形式)也会通过将待处理索引项移动到主要 GIN 索引结构中的合适位置来 完成任何待处理的索引插入。 我们建议经常清理活动的生产数据库(至少每晚一次),以保证移除失效的行。在增加或删除了大量行之后,对 受影响的表执行 VACUUM ANALYZE 命令是一个很好的做法。这样做将把最近的更改更新到系统目录,并且允许 KingbaseES 查询规划器在规划用户查询时做出更好的选择。 日常使用时,不推荐 FULL 选项,但在特殊情况时它会有用。一个例子是当你删除或者更新了一个表中的绝大部 分行时,如果你希望在物理上收缩表以减少磁盘空间占用并且允许更快的表扫描,则该选项是比较合适的。VACUUM FULL 通常会比简单 VACUUM 更多地收缩表。 VACUUM 会导致 I/O 流量的大幅度增加,这可能导致其他活动会话性能变差。因此,有时建议使用基于代价的清 理延迟特性。详情请参阅 基于代价的清理延迟。 1289 第 20 章 SQL 语句: MERGE 到 VALUES KingbaseES 包括了一个“autovacuum”工具,它可以自动进行例行的清理维护。关于自动和手动清理的更多信 息请见 日常清理。 20.33 VALUES 用途 VALUES -- 计算由值表达式指定的一个行值或者一组行值。更常见的是把它用来生成一个大型命令内的“常 量表”,但是它也可以被独自使用。 当多于一行被指定时,所有行都必须具有相同数量的元素。结果表的列数据类型由出现在该列的表达式的显式或 者推导类型组合决定,决定的规则与 UNION 相同(见 UNION CASE 和相关结构)。 在大型的命令中,在语法上允许 VALUES 出现在 “SELECT“出现的任何地方。因为语法把它当做一个 “SELECT“,可以为一个 VALUES 命令使用 ORDER BY、LIMIT(或者等效的 FETCH FIRST)以及 OFFSET 子句。 前置条件 无。 语法 VALUES ( expression [, ...] ) [, ...] [ ORDER BY sort_expression [ ASC | DESC | USING operator ] [, ...] ] [ LIMIT { count | ALL } ] [ OFFSET start [ ROW | ROWS ] ] [ FETCH { FIRST | NEXT } [ count ] { ROW | ROWS } ONLY ] 1290 第 20 章 SQL 语句: MERGE 到 VALUES 语义 expression 要在结果表(行集合)中指定位置计算并且插入的一个常量或者表达式。在一个出现于 INSERT 顶层的 VALUES 列表中,“expression“可以被 DEFAULT 替代以表示应该插入目标列的默认值。当 VALUES 出现在其他环 境中时,不能使用 DEFAULT。 sort_expression 一个指示如何排序结果行的表达式或者整型常量。这个表达式可以用 column1、column2 等来引 用该 VALUES 结果的列。详见“ORDER BY“子句 ORDER BY 。 operator 一个排序操作符。详见 ORDER BY 子句 ORDER BY 。 count 要返回的最大行数。详见 LIMIT 子句 LIMIT 。 start 开始返回行之前要跳过的行数。详见 LIMIT 子句 LIMIT 。 示例 一个纯粹的 VALUES 命令: VALUES (1, 'one'), (2, 'two'), (3, 'three'); 这将返回一个具有两列、三行的表。它实际等效于: SELECT 1 AS column1, 'one' AS column2 UNION ALL SELECT 2, 'two' 1291 第 20 章 SQL 语句: MERGE 到 VALUES UNION ALL SELECT 3, 'three'; 更常用地,VALUES 可以被用在一个大型 SQL 命令中。在 INSERT 中最常用: INSERT INTO films (code, title, did, date_prod, kind) VALUES ('T_601', 'Yojimbo', 106, '1961-06-16', 'Drama'); 在 INSERT 的环境中,一个 VALUES 列表的项可以是 DEFAULT 来指示应该使用该列的默认值而不是指定一个 值: INSERT INTO films VALUES ('UA502', 'Bananas', 105, DEFAULT, 'Comedy', '82 minutes'), ('T_601', 'Yojimbo', 106, DEFAULT, 'Drama', DEFAULT); VALUES 也可以被用在可以写子-SELECT``的地方,例如在一个\ ``FROM 子句中: SELECT f.* FROM films f, (VALUES('MGM', 'Horror'), ('UA', 'Sci-Fi')) AS t (studio, kind) WHERE f.studio = t.studio AND f.kind = t.kind; UPDATE employees SET salary = salary * v.increase FROM (VALUES(1, 200000, 1.2), (2, 400000, 1.4)) AS v (depno, target, increase) WHERE employees.depno = v.depno AND employees.sales >= v.target; 注意当 VALUES 被用在一个 FROM 子句中时,需要提供一个 AS 子句,与 SELECT 相同。不需要为所有的列用 AS 子句指定名称,但是那样做是一种好习惯(在 KingbaseES 中,VALUES 的默认列名是 column1、column2 等,但在 其他数据库系统中可能会不同)。 当在 INSERT 中使用 VALUES 时,值都会被自动地强制为相应目标列的数据类型。当在其他环境中使用时,有必 要指定正确的数据类型。如果项都是带引号的字符串常量,强制第一个就足以为所有项假设数据类型: SELECT * FROM machines WHERE ip_address IN (VALUES('192.168.0.1'::inet), ('192.168.0.10'), ('192.168.1.43')); 提示: 对于简单的 IN 测试,最好使用 IN 的 list-of-scalars 而不是写一个上面那样的 VALUES 查询。标量列表方法的 书写更少并且常常更加高效。 兼容性 VALUES 符合 SQL 标准。LIMIT 和 OFFSET 是 KingbaseES 扩展,另见SELECT 。 其他 1292 第 20 章 SQL 语句: MERGE 到 VALUES 应该避免具有大量行的 VALUES 列表,否则可能会碰到内存不足失败或者很差的性能。出现在 INSERT``中的\ ``VALUES 是一种特殊情况(因为想要的列类型可以从 INSERT 的目标表得知,并且不需要通过扫描该 VALUES 列表 来推导),因此它可以处理比其他环境中更大的列表。 1293 第 21 章 KINGBASEES 正则表达式支持 21章 KingbaseES 正则表达式支持 第 21.1 正则表达式语法 21.1.1 POSIX 正则表达式 下表列出了所有可用于 POSIX 正则表达式模式匹配的操作符。 表 21.1.1: 正则表达式匹配操作符 操作符 描述 例子 ~ 匹配正则表达式,大小写敏感 'thomas' ~ '.*thomas.*' ~ 匹配正则表达式,大小写不敏感 'thomas' ~* '.*Thomas.*' !~ 不匹配正则表达式,大小写敏感 'thomas' !~ '.*Thomas.*' !~ 不匹配正则表达式,大小写不敏感 'thomas' !~* '.*vadim.*' POSIX 正则表达式提供了比 LIKE 和 SIMILAR TO 操作符更强大的含义。许多 Unix 工具,例如 egrep、sed 或 awk 使用一种与我们这里描述的类似的模式匹配语言。 正则表达式是一个字符序列,它是定义一个串集合(一个正则集)的缩写。 如果一个串是正则表达式描述的正则集中的一员时,我们就说这个串匹配该正则表达式。和 LIKE 一样,模式字 符准确地匹配串字符,除非在正则表达式语言里有特殊字符—不过正则表达式用的特殊字符和 LIKE 用的不同。和 LIKE 模式不一样的是,正则表达式允许匹配串里的任何位置,除非该正则表达式显式地挂接在串的开头或者结尾。 一些例子: SELECT 'abc' ~ 'abc'; ?column? ---------t (1 row) 1294 第 21 章 KINGBASEES 正则表达式支持 SELECT 'abc' ~ '^a'; ?column? ---------t (1 row) SELECT 'abc' ~ '(b|d)'; ?column? ---------t (1 row) SELECT 'abc' ~ '^(b|c)'; ?column? ---------f (1 row) POSIX 模式语言的详细描述见下文。 带两个参数的 substring 函数,即 substring(string from pattern) ,提供了抽取一个匹配 POSIX 正则表 达式模式的子串的方法。如果没有匹配它返回空值,否则就是文本中匹配模式的那部分。但是如果该模式包含任何圆 括号,那么将返回匹配第一对子表达式(对应第一个左圆括号的)的文本。如果你想在表达式里使用圆括号而又不想 导致这个例外,那么你可以在整个表达式外边放上一对圆括号。如果你需要在想抽取的子表达式前有圆括号,参阅后 文描述的非捕获性圆括号。 一些例子: SELECT substring('foobar' from 'o.b'); substring ----------oob (1 row) SELECT substring('foobar' from 'o(.)b'); substring ----------o (1 row) regexp_replace 函数提供了将匹配 POSIX 正则表达式模式的子串替换为新文本的功能。它的语法是 regexp_replace ( source , pattern , replacement [, flags ])。如果没有匹配 pattern ,那么返回不加修改的 source 串。如果有匹配,则返回的 source 串里面的匹配子串将被 replacement 串替换掉。replacement 串可以包 含\ n ,其中\ n 是 1 到 9,表明源串里匹配模式里第 n 个圆括号子表达式的子串应该被插入,并且它可以包含\& 表 示应该插入匹配整个模式的子串。如果你需要放一个文字形式的反斜线在替换文本里,那么写\\。flags 参数是一个 1295 第 21 章 KINGBASEES 正则表达式支持 可选的文本串,它包含另个或更多单字母标志,这些标志可以改变函数的行为。标志 i 指定大小写无关的匹配,而 标志 g 指定替换每一个匹配的子串而不仅仅是第一个。支持的标志(但不是 g)在表 7-9 中描述。 一些例子: SELECT regexp_replace('foobarbaz', 'b..', 'X'); regexp_replace ---------------fooXX (1 row) SELECT regexp_replace('foobarbaz', 'b..', 'X', 'g'); regexp_replace ---------------fooXX (1 row) SELECT regexp_replace('foobarbaz', 'b(..)', 'X\1Y', 'g'); regexp_replace ---------------fooXarYXazY (1 row) regexp_match 返回一个文本数组,它包含一个 POSIX 正则表达式模式与一个字符串第一个匹配所得到的子串。 其语法是 regexp_match ( string , pattern [, flags ])。如果没有匹配,则结果为 NULL 。如果找到一个匹配并且 pattern 不包含带括号的子表达式,那么结果是一个单一元素的文本数组,其中包含匹配整个模式的子串。如果找到 一个匹配并且 pattern 含有带括号的子表达式,那么结果是一个文本数组,其中第 n 个元素是与 pattern 的第 n 个 圆括号子表达式匹配的子串(“非捕获”圆括号不计入在内,详见下文)。flags 参数是一个可选的文本字符串,它 包含零个或者更多个可以改变该函数行为的单字母标志。 一些例子: SELECT regexp_match('foobarbequebaz', 'bar.*que'); regexp_match -------------{barbeque} (1 row) SELECT regexp_match('foobarbequebaz', '(bar)(beque)'); regexp_match -------------{bar,beque} (1 row) 在通常情况下,只需要整个匹配的匹配的子串或者 NULL 表示不匹配的话,可以写成这样 1296 第 21 章 KINGBASEES 正则表达式支持 SELECT (regexp_match('foobarbequebaz', 'bar.*que'))[1]; regexp_match -------------barbeque (1 row) regexp_matches 函数返回一个文本数组的集合,其中包含着一个 POSIX 正则表达式模式与一个字符串匹配得 到的子串。它和 regexp_match 具有相同的语法。如果没有匹配,这个函数不会返回行。如果有一个匹配并且给定 了 g 标志,则返回一行。如果有 N 个匹配并且给定了 g 标志,则返回 N 行。每一个返回的行都是一个文本数组, 其中含有整个匹配的子串或者匹配 pattern 的圆括号子表达式的子串,这和上面对 regexp_match 的介绍一样。 regexp_matches 接受表 7-9 中展示的所有标志,外加令它返回所有匹配而不仅仅是第一个匹配的 g 标志。 一些例子: SELECT regexp_matches('foo', 'not there'); regexp_matches ---------------(0 rows) SELECT regexp_matches('foobarbequebazilbarfbonk', '(b[^b]+)(b[^b]+)', 'g'); regexp_matches ---------------{bar,beque} {bazil,barf} (2 rows) 提示: 在大部分情况下,regexp_matches() 应该与 g 标志一起使用,因为如果只是想要第一个匹配,使用 regexp_match() 会更加简单高效。不过,regexp_match() 仅存在于 KingbaseES V8R3 版本以及更高的版本中。 当在较老的版本中使用时,一种常用的技巧是把 regexp_matches() 调用放在子选择中,例如: SELECT col1, (SELECT regexp_matches(col2, '(bar)(beque)')) FROM tab; 如果有一个匹配,则这个语句会产生一个文本数组,否则返回 NULL ,这和 regexp_match() 的做法一样。如果 没有子选择,这个查询对于没有匹配的表行根本不会产生输出,显然那不是想要的行为。 regexp_split_to_table 把一个 POSIX 正则表达式模式当作一个定界符来分离一个串。它的语法形式是 regexp_split_to_table ( string , pattern [, flags ])。如果没有与 pattern 的匹配,该函数返回 string 。如 果有至少有一个匹配,对每一个匹配它都返回从上一个匹配的末尾(或者串的开头)到这次匹配开头之间的文本。当 没有更多匹配时,它返回从上一次匹配的末尾到串末尾之间的文本。flags 参数是一个可选的文本串,它包含零个或 更多单字母标志,这些标识可以改变该函数的行为。regexp_split_to_table 能支持的标志在表 7-9 中描述。 regexp_split_to_array 函数的行为和 regexp_split_to_table 相同,不过 regexp_split_to_array 会把它 的结果以一个 text 数组的形式返回。它的语法是 regexp_split_to_array ( string , pattern [, flags ])。这些参 数和 regexp_split_to_table 的相同。 1297 第 21 章 KINGBASEES 正则表达式支持 一些例子: SELECT foo FROM regexp_split_to_table('the quick brown fox jumps over the lazy dog', '\s+') AS foo; foo ------the quick brown fox jumps over the lazy dog (9 rows) SELECT regexp_split_to_array('the quick brown fox jumps over the lazy dog', '\s+'); regexp_split_to_array ----------------------------------------------{the,quick,brown,fox,jumps,over,the,lazy,dog} (1 row) SELECT foo FROM regexp_split_to_table('the quick brown fox', '\s*') AS foo; foo ----t h e q u i c k b r o w n f o x (16 rows) 正如上一个例子所示,正则表达式分离函数会忽略零长度的匹配,这种匹配发生在串的开头或结尾或者正好发生 在前一个匹配之后。这和正则表达式匹配的严格定义是相悖的,后者由 regexp_match 和 regexp_matches 实现, 但是通常前者是实际中最常用的行为。其他软件系统如 Perl 也使用相似的定义。 1298 第 21 章 KINGBASEES 正则表达式支持 21.1.2 正则表达式细节 KingbaseES 的正则表达式是使用 Henry Spencer 写的一个包来实现的。下面的正则表达式的大部分描述都是从 他的手册页中逐字拷贝过来的。 正则表达式(RE),在 POSIX 1003.2 中定义,它有两种形式:扩展的 RE 或者是 ERE(大概地说就是那些在 egrep 里的),基本的 RE 或者是 BRE(大概地说就是那些在 ed 里的)。KingbaseES 支持两种形式,并且还实现 了一些 POSIX 标准中没有但是在类似 Perl 或者 Tcl 这样的语言中得到广泛应用的一些扩展。使用了那些非 POSIX 扩展的 RE 叫高级 RE,或者本文档里说的 ARE。ARE 几乎完全是 ERE 的超集,但是 BRE 有几个符号上的不兼容 (以及更多的限制)。我们首先描述 ARE 和 ERE 形式,描述那些只适用于 ARE 的特性,然后描述 BRE 的区别是 什么。 注意: KingbaseES 初始时总是推测一个正则表达式遵循 ARE 规则。但是,可以通过为 RE 模式预置一个 embedded option 来选择限制更多的 ERE 或 BRE 规则,如正则表达式元语法 中所述。这对为期望准确的 POSIX 1003.2 规则 的应用提供兼容性很有用。 一个正则表达式被定义为一个或更多分支,它们之间被 | 分隔。只要能匹配其中一个分支的东西都能匹配正则 表达式。 一个分支是一个或多个量化原子或者约束连接而成。一个原子匹配第一个,然后后面的原子匹配第二个,以此类 推;一个空分支匹配空串。 一个量化原子是一个原子,后面可能跟着一个量词。没有量词的时候,它匹配一个原子,有量词的时候,它可以 匹配若干个原子。一个原子可以是在 表 21.1.2 里面显示的任何可能。可能的量词和它们的含义在 表 21.1.3 里显示。 一个约束匹配一个空串,但只是在满足特定条件下才匹配。约束可以在能够使用原子的地方使用,只是它不能跟 着量词。简单的约束在 表 21.1.4 里显示;更多的约束稍后描述。 1299 第 21 章 KINGBASEES 正则表达式支持 表 21.1.2: 正则表达式原子 原子 描述 (re) (其中 re 是任何正则表达式)匹配一个对 re 的匹配,匹配将为可能的报告被记下 ( ?:re) 同上,但是匹配不会为了报告而被记下(一个“非捕获”圆括号集)(只对 ARE) . 匹配任意单个字符 [chars] 一个方括号表达式,匹配 chars 中的任意一个 \k (其中 k 是一个非字母数字字符)匹配一个被当作普通字符看待的特定字符,例如,\\匹 配一个反斜线字符 其中 c 是一个字母数字(可它字符)能跟着其,它是一个转义,(仅对 ARE;在 ERE 和 \c BRE 中,它匹配 c) 如果后面跟着一个字符,而不是数字,那么就匹配左花括弧 {;如果跟着一个数字,那么 { 它是 range 的开始(见下文) 其中 x 是一个没有其它意义的单个字符,则匹配该字符 x RE 不能以反斜线(\)结尾。 注意: 如果你关掉了 standard_conforming_strings ,任何你写在文字串常量中的反斜线都需要被双写。详见字符串 常量 。 1300 第 21 章 KINGBASEES 正则表达式支持 表 21.1.3: 正则表达式量词 量词 匹配 ““ 一个由原子的 0 次或更多次匹配组成的序列 + 一个由原子的 1 次或更多次匹配组成的序列 ? 一个由原子的 0 次或 1 次匹配组成的序列 {m} 一个由原子的正好 m 次匹配组成的序列 {m,} 一个由原子的 m 次或更多次匹配组成的序列 { m,n} 一个由原子的从 m 次到 n 次(包括)匹配组成的序列;m 不能超过 n ? ““ 的非贪婪版本 +? + 的非贪婪版本 ?? ? 的非贪婪版本 {m}? {m} 的非贪婪版本 {m,}? {m,} 的非贪婪版本 {m,n}? {m,n} 的非贪婪版本 使用 {...} 的形式被称作范围。一个范围内的数字 m 和 n 都是无符号十进制整数,允许的数值从 0 到 255(包 含)。 非贪婪的量词(只在 ARE 中可用)匹配对应的正常(贪婪)模式,区别是它寻找最少的匹配,而不是最多的匹 配。详见正则表达式匹配规则 。 注意: 一个量词不能紧跟在另外一个量词后面,例如 “ \ 是非法的。量词不能作为表达式或者子表达式的开头,也 不能跟在\ ``^ 或者 | 后面。 1301 第 21 章 KINGBASEES 正则表达式支持 表 21.1.4: 正则表达式约束 约束 描述 ^ 串开头的匹配 $ 串末尾的匹配 (?=re) 在匹配 re 的子串开始的任何点的 positivelookahead 匹配(只对 ARE) (?!re) 在匹配 re 的子串开始的任何点的 negativelookahead 匹配(只对 ARE) (?<=re) 只要有一个点上有一个子串匹配 re 端,positivelookbehind 就在这个点上匹配(只对 ARE) (?:]] 是约束,分别匹配一个单词开头和结束的空 串。单词定义为一个单词字符序列,前面和后面都没有其它单词字符。单词字符是一个 alnum 字符(和 POSIX 特性 描述中的定义一样)或者一个下划线。这是一个扩展,兼容 POSIX 1003.2,但那里面并没有说明,而且在准备移植 到其他系统里去的软件里一定要小心使用。通常下文描述的约束转义更好些(它们并非更标准,但是更容易键入)。 21.1.4 正则表达式转义 转义是以\开头,后面跟着一个字母数字字符得特殊序列。转义有好几种变体:字符项、类缩写、约束转义以及 后引用。在 ARE 里,如果一个\后面跟着一个字母数字,但是并未组成一个合法的转义,那么它是非法的。在 ERE 中没有转义:在方括号表达式之外,一个后面跟着字母数字字符的\只是表示该字符是一个普通的字符,而且在一个 方括号表达式里,\是一个普通的字符(后者实际上在 ERE 和 ARE 不兼容)。 字符项转义用于便于我们在 RE 中声明那些不可打印的或其他习惯的字符。它们显示在 表 21.1.5 中。 类缩写转义用来提供一些常用的字符类缩写。它们显示在 表 21.1.6 中。 约束转义是一个约束,如果满足特定的条件,它匹配该空串。它们显示在 POSIX-CONSTRAINT-ESCAPES-TABLE 中。 后引用(\n)匹配数字\n 指定的被前面的圆括号子表达式匹配的同一个串(参阅 表 21.1.7 )。例如,([bc])\1 匹配 bb 或者 cc,但是不匹配 bc 或者 cb。RE 中子表达式必须完全在后引用前面。子表达式以它们的先导圆括号 的顺序编号。非捕获圆括号并不定义子表达式。 1303 第 21 章 KINGBASEES 正则表达式支持 表 21.1.5: 正则表达式字符项转义 转义 描述 \a 警告(响铃)字符,和 C 中一样 \b 退格,和 C 中一样 \B 反斜线(\)的同义词,用来减少双写反斜线 \cX (其中 X 是任意字符)低序 5 位和 X 相同的字符,它的其他位都是零 \e 排序序列名为 ESC 的字符,如果无法做到该字符为八进制值 033 \f 换页,和 C 中一样 \n 新行,和 C 中一样 \r 回车,和 C 中一样 \t 水平制表符,和 C 中一样 \uwxyz (其中 wxyz 正好是四个十六进制位)十六进制值为 0xwxyz 的字符 \ (其中 stuvwxyz 正好是八个十六进制位)十六进制值为 0xstuvwxyz 的字符 Ustuvwxyz \v 垂直制表符,和 C 中一样 \xhhh (其中 hhh 是十六进制位的任意序列)十六进制值为 0xhhh 的字符(一个单一字符,不管用了多少 个十六进制位) \0 值为 0(空字节)的字符 \xy (其中 xy 正好是两个八进制位,并且不是一个后引用)八进制值为 0xy 的字符 \xyz (其中 xyz 正好是三个八进制位,并且不是一个后引用)八进制值为 0xyz 的字符 十六进制位是 0-9、a-f 和 A-F。八进制位是 0-7。 指定 ASCII 范围(0-127)之外的值的数字字符项转义的含义取决于数据库编码。当编码是 UTF-8 时,转义值等 价于 Unicode 代码点,例如 \u1234 表示字符 U+1234。对于其他多字节编码,字符项转义通常只是指定该字符的字 节值的串接。如果该转义值不对应数据库编码中的任何合法字符,将不会发生错误,但是它不会匹配任何数据。 字符项转义总是被当作普通字符。例如,\135 是 ASCII 中的],但\135 并不终止一个方括号表达式。 1304 第 21 章 KINGBASEES 正则表达式支持 表 21.1.6: 正则表达式类缩写转义 转义 描述 \d [[:digit:]] \s [[:space:]] \w [[:alnum:]_](注意下划线是被包括的) \D [^[:digit:]] \S [^[:space:]] \W [^[:alnum:]_] (注意下划线是被包括的) 在方括号表达式里,\d、\s 和\w 会失去它们的外层方括号,而\D、\S 和 \W 是非法的(也就是说,例如 [a-c\ d] 等效于 [a-c[:digit:]]。同样 [a-c\D] 等效于 [a-c^[:digit:]] 的,也是非法的)。 一个词被定义成在上面 [[:<:]] 和 [[:>:]] 中的声明。在方括号表达式里,约束转义是非法的。 表 21.1.7: 正则表达式后引用 转 描述 义 \m (其中 m 是一个非零位)一个到第 m 个子表达式的后引用 \ (其中 m 是一个非零位,并且 nn 是一些更多的位,并且十六进制值 mnn 不超过目前能看到的封闭捕获圆 mnn 括号的数目)一个到第 mnn 个子表达式的后引用 注意: 在八进制字符项转义和后引用之间有一个历史继承的歧义存在,这个歧义是通过下面的启发式规则解决的,像 上面描述地那样。前导零总是表示这是一个八进制转义。而单个非零数字,如果没有跟着任何其它位,那么总是被认 为后引用。一个多位的非零开头的序列也被认为是后引用,只要它出现在合适的子表达式后面(也就是说,在后引用 的合法范围中的数),否则就被认为是一个八进制。 21.1.5 正则表达式元语法 除了上面描述的主要语法之外,还有几种特殊形式和杂项语法。 如果一个 RE 以 **: 开头,那么剩下的 RE 都被当作 ARE(这在 KingbaseES 中通常是无效的,因为 RE 被假 定为 ARE,但是如果 ERE 或 BRE 模式通过 flags 参数被指定为一个正则表达式函数时,它确实能产生效果)。如 果一个 RE 以 **= 开头,那么剩下的 RE 被当作一个文本串,所有的字符都被认为是一个普通字符。 1305 第 21 章 KINGBASEES 正则表达式支持 一个 ARE 可以以嵌入选项开头:一个序列 (?xyz)(这里的 xyz 是一个或多个字母字符)声明影响剩余 RE 的 选项。这些选项覆盖任何前面判断的选项—特别地,它们可以覆盖一个正则表达式操作符隐含的大小写敏感的行为, 或者覆盖 flags 参数中的正则表达式函数。可用的选项字母在下表中显示。注意这些同样的选项字母也被用在正则表 达式函数的 flags 参数中。 嵌入选项在) 终止序列时发生作用。它们只在 ARE 的开始处起作用(在任何可能存在的 **: 控制器后面)。 除了通常的(紧密的)RE 语法(这种情况下所有字符都有效),还有一种扩展语法,可以通过声明嵌入的 x 选 项获得。在扩展语法里,RE 中的空白字符被忽略,就像那些在 # 和其后的新行(或 RE 的末尾)之间的字符一样。 这样就允许我们给一个复杂的 RE 分段和注释。不过这个基本规则有三种例外: • 空白字符或前置了\的 # 将被保留 • 方括号表达式里的空白或者 # 将被保留 • 在多字符符号里面不能出现空白和注释,例如 (?: 为了这个目的,空白是空格、制表符、新行和任何属于 空白字符类的字符。 最后,在 ARE 里,方括号表达式外面,序列 (?#ttt)(其中 ttt 是任意不包含一个)) 的文本)是一个注释,它 被完全忽略。同样,这样的东西是不允许出现在多字符符号的字符中间的,例如 (?:。这种注释更像是一种历史产物 而不是一种有用的设施,并且它们的使用已经被废弃;请使用扩展语法来替代。 如果声明了一个初始的 **= 控制器,那么所有这些元语法扩展都不能使用,因为这样表示把用户输入当作一个 文字串而不是 RE 对待。 21.1.6 正则表达式匹配规则 在 RE 可以在给定串中匹配多于一个子串的情况下,RE 匹配串中最靠前的那个子串。如果 RE 可以匹配在那个 位置开始的多个子串,要么是取最长的子串,要么是最短的,具体哪种,取决于 RE 是贪婪的还是非贪婪的。 一个 RE 是否贪婪取决于下面规则: • 大多数原子以及所有约束,都没有贪婪属性(因为它们毕竟无法匹配个数变化的文本)。 • 在一个 RE 周围加上圆括号并不会改变其贪婪性。 • 带一个固定重复次数量词({m} 或者 {m}?)的量化原子和原子自身具有同样的贪婪性(可能是没有)。 • 一个带其他普通的量词(包括 {m,n} 中 m 等于 n 的情况)的量化原子是贪婪的(首选最长匹配)。 • 一个带非贪婪量词(包括 {m,n}? 中 m 等于 n 的情况)的量化原子是非贪婪的(首选最短匹配)。 • 一个分支—也就是说,一个没有顶级 | 操作符的 RE —和它里面的第一个有贪婪属性的量化原子有着同样的贪 婪性。 • 一个由 | 操作符连接起来的两个或者更多分支组成的 RE 总是贪婪的。 上面的规则所描述的贪婪属性不仅仅适用于独立的量化原子,而且也适用于包含量化原子的分支和整个 RE。这 里的意思是,匹配是按照分支或者整个 RE 作为一个整体匹配最长或者最短的可能子串。一旦整个匹配的长度确定, 那么匹配任意特定子表达式的部分就基于该子表达式的贪婪属性进行判断,在 RE 里面靠前的子表达式的优先级高于 靠后的子表达式。 1306 第 21 章 KINGBASEES 正则表达式支持 一个相应的例子: SELECT SUBSTRING('XY1234Z', 'Y*([0-9]{1,3})'); substring ----------123 (1 row) SELECT SUBSTRING('XY1234Z', 'Y*?([0-9]{1,3})'); substring ----------1 (1 row) 在第一个例子里,RE 作为整体是贪婪的,因为 Y ``\ 是贪婪的。它可以匹配从\ ``Y 开始的东西,并且它匹 配从这个位置开始的最长的串,也就是,Y123。输出是这里的圆括号包围的部分,或者说是 123。在第二个例子里, RE 总体上是一个非贪婪的 RE,因为 Y*? 是非贪婪的。它可以匹配从 Y 开始的最短的子串,也就是说 Y1。子表达 式 [0-9]{1,3} 是贪婪的,但是它不能修改总体匹配长度的决定;因此它被迫只匹配 1。 简而言之,如果一个 RE 同时包含贪婪和非贪婪的子表达式,那么总的匹配长度要么是尽可能长,要么是尽可能 短,这取决于给整个 RE 赋予的属性。给子表达式赋予的属性只影响在这个匹配里,各个子表达式之间相互允许“吃 掉”的多少。 量词 {1,1} 和 {1,1}? 可以分别用于在一个子表达式或者整个 RE 上强制贪婪或者非贪婪。当需要整个 RE 具 有不同于从其元素中推导出的贪婪属性时,这很有用。例如,假设我们尝试将一个包含一些数字的字符串分隔成数字 以及在它们之前和之后的部分,我们可能会尝试这样做: SELECT regexp_matches('abc01234xyz', '(.*)(\d+)(.*)'); regexp_matches ----------------{abc0123,4,xyz} (1 row) 这不会有用:第一个. ``\ 是贪婪的,因此它会“吃掉”尽可能多的字符而留下\ ``\d+ 去匹配在最后一个可能 位置上的最后一个数字。我们可能会通过让它变成非贪婪来修复: SELECT regexp_matches('abc01234xyz', '(.*?)(\d+)(.*)'); regexp_matches ---------------{abc,0,""} (1 row) 这也不会有用:因为现在 RE 作为整体来说是非贪婪的,因此它会尽快结束全部的匹配。我们可以通过强制 RE 整体是贪婪的来得到我们想要的: 1307 第 21 章 KINGBASEES 正则表达式支持 SELECT regexp_matches('abc01234xyz', '(?:(.*?)(\d+)(.*)){1,1}'); regexp_matches ---------------{abc,01234,xyz} (1 row) 独立于 RE 的组件的贪婪性之外控制 RE 的整体贪婪性为处理变长模式提供了很大的灵活性。 在决定更长或者更短的匹配时,匹配长度是以字符衡量的,而不是排序元素。一个空串会被认为比什么都不匹 配长。例如:bb ``\ 匹配\ ``abbbc 的中间三个字符;(week|wee)(night|knights) 匹配 weeknights 的所有十 个字符;而 (.*). ``\ 匹配 ``abc 的时候,圆括号包围的子表达式匹配所有三个字符;当 (a*) ``\ 被拿来匹配\ ``bc 时,整个 RE 和圆括号子表达式都匹配一个空串。 如果声明了大小写无关的匹配,那么效果就好像所有大小写区别在字母表中消失了。如果在多个情况中一个字母 以一个普通字符的形式出现在方括号表达式外面,那么它实际上被转换成一个包含大小写的方括号表达式,也就是 说,x 变成 [xX]。如果它出现在一个方括号表达式里面,那么它的所有大小写的同族都被加入方括号表达式中,也就 是说,x 变成 [xX]。当它出现在一个方括号表达式内时,它的所有大小写副本都被加入到方括号表达式中,例如, [x] 会变成 [xX],而 [^x] 会变成 [^xX]。 如果指定了新行敏感的匹配,. 和使用 ^ 的方括号表达式将永远不会匹配新行字符(这样,匹配就绝对不会跨越 新行,除非 RE 显式地安排了这样的情况)并且 ^ 和 $ 除了分别匹配串开头和结尾之外,还将分别匹配新行后面和 前面的空串。但是 ARE 转义\A 和\Z 仍然只匹配串的开头和结尾。 如果指定了部分新行敏感的匹配,那么它影响. 和方括号表达式,这个时候和新行敏感的匹配一样,但是不影响 ^ 和 $。 如果指定了逆新行敏感匹配,那么它影响 ^ 和 $,其作用和在新行敏感的匹配里一样,但是不影响. 和方括号表 达式。这个并不是很有用,只是为了满足对称性而提供的。 21.2 正则表达式兼容性与限制 在 KingbaseES 的 ARE 正则表达式实现里,对 RE 的长度没有特别的限制。但是,那些希望高移植性的程序应 该避免使用长度超过 256 字节的 RE,因为 POSIX 兼容的实现可以拒绝接受这样的 RE。 21.2.1 ERE 兼容性 ARE 实际上和 POSIX ERE 不兼容的唯一的特性是在方括号表达式里\并不失去它特殊的含义。所有其它 ARE 特性都使用在 POSIX ERE 里面是非法或者是未定义、未声明效果的语法;指示器的 “ * “就是在 POSIX 的 BRE 和 ERE 之外的语法。 KingbaseES V7 之前的版本中识别的 ARE 和 ERE 语法存在两个非常明显的不兼容: • 在 ARE 中,后面跟着一个字母数字字符的\要么是一个转义要么是一个错误,但是在以前的版本里,它只是写 该字母数字字符的另外一种方法。这个应该不是什么问题,因为在以前的版本里没有什么理由会让我们写这样 1308 第 21 章 KINGBASEES 正则表达式支持 的序列。 • 在 ARE 里,\在 [] 里还是一个特殊字符,因此在方括号表达式里的一个文本\必须被写成\\。 21.2.2 BRE 兼容性 BRE 在几个方面和 ERE 不太一样。在 BRE 中,|、+ 和? 都是普通字符并且没有与它们功能等价的东西。范围 的定界符是\{和\},因为 {和} 本身是普通字符。嵌套的子表达式的圆括号是\(和\),因为 (和) 自身是普通字符。 除非在 RE 开头或者是圆括号子表达式开头,^ 都是一个普通字符。除非在 RE 结尾或者是圆括号子表达式的结尾, $ 是一个普通字符。如果 “ \ 出现在 RE 开头或者是圆括号封装的子表达式开头(前面可能有\ ``^),那么它是个 普通字符。最后,可以用单数字的后引用,\< 和\> 分别是 [[:<:]] 和 [[:>:]] 的同义词;在 BRE 中没有其它可 用的转义。 21.2.3 Perl 正则表达式兼容性 许多 ARE 扩展都是从 Perl 那里借来的(但是有些被做了修改来清理它们),以及一些 Perl 里没有出现的扩展。 要注意的不兼容性包括\b、\B、对结尾的新行缺乏特别的处理、对那些被新行敏感匹配的东西附加的补齐方括号表达 式、在 lookahead/lookbehind 约束里对圆括号和后引用的限制以及最长/最短匹配(而不是第一匹配)的语义。 1309 第 22 章 SQL 保留字和关键字 22章 SQL 保留字和关键字 第 下表列出了 KingbaseES SQL 中作为关键字的所有标记。 SQL 区分保留关键字和非保留关键字。根据标准,保留关键字是唯一真实的关键字;它们永远不允许作为标识 符。非保留关键字仅在特定上下文中具有特殊含义,并且可以在其他上下文中用作标识符。大多数非保留关键字实际 上是 SQL 指定的内置表和函数的名称。非保留关键字的概念本质上只存在于声明在某些上下文中某个单词附加了一 些预定义的含义。 在 KingbaseES 解析器中,生活有点复杂。有几种不同类别的令牌,从那些永远不能用作标识符的令牌到那些与 普通标识符相比在解析器中绝对没有特殊地位的令牌。(SQL 指定的函数通常是后者。)即使保留关键字在 KingbaseES 中也不是完全保留的,但可以用作列标签(例如,选择 55 作为 CHECK,即使 CHECK 是保留关键字)。 我们将解析器明确知道但允许作为列或表名的关键字分类为“非保留”关键字。一些非保留关键字不能用作函数 或数据类型名称,因此会相应地进行标记。(这些词中的大多数表示具有特殊语法的内置函数或数据类型。函数或类 型仍然可用,但用户无法重新定义。)标记为“保留”的是那些不允许作为列或表名的标记。允许一些保留关键字作 为函数或数据类型的名称;表中也显示了这一点。如果没有这样标记,则只允许保留关键字作为“as”列标签名称。 一般来说,如果命令包含任何列出的关键字作为标识符,那么如果您遇到错误的解析器,您应该尝试引用该标识 符,以查看问题是否消失。 在研究表之前,必须了解,KingbaseES 中没有保留关键字并不意味着没有实现与该单词相关的功能。相反,关 键字的存在并不表示特征的存在。 关键字 KingbaseES 说明 ABORT 非保留 可以做函数名和类型名 ABSOLUTE 非保留 不能做函数名和类型名 ACCESS 非保留 不能做函数名和类型名 ACCOUNT 非保留 可以做函数名和类型名 ACTION 非保留 可以做列名 ADD 非保留 可以做列名 见续表 1310 第 22 章 SQL 保留字和关键字 表 22.1 – 续表 关键字 KingbaseES 说明 ADMIN 非保留 不能做函数名和类型名 AFTER 非保留 不能做函数名和类型名 AGGREGATE 非保留 不能做函数名和类型名 ALL 保留 不能做函数名和类型名 ALSO 非保留 不能做函数名和类型名 ALTER 非保留 可以做函数名和类型名 ALWAYS 非保留 可以做函数名和类型名 ANALYSE 保留 可以做列名 ANALYZE 保留 可以做函数名和类型名 AND 保留 可以做函数名和类型名 ANY 保留 可以做列名 ARRAY 保留 可以做列名 AS 保留 可以做列名 ASC 保留 不能做函数名和类型名 ASSERTION 非保留 不能做函数名和类型名 ASSIGNMENT 非保留 不能做函数名和类型名 ASYMMETRIC 保留 不能做函数名和类型名 AT 非保留 可以做列名 ATTACH 非保留 不能做函数名和类型名 ATTRIBUTE 非保留 不能做函数名和类型名 AUTHID 非保留 可以做函数名和类型名 AUTHORIZATION 保留 可以做函数名和类型名 AUTO_INCREMENT 保留 不能做函数名和类型名 BACKWARD 非保留 可以做列名 见续表 1311 第 22 章 SQL 保留字和关键字 表 22.1 – 续表 关键字 KingbaseES 说明 BEFORE 非保留 不能做函数名和类型名 BEGIN 非保留 可以做函数名和类型名 BETWEEN 非保留 可以做函数名和类型名 BIGINT 非保留 不能做函数名和类型名 BINARY 保留 不能做函数名和类型名 BINARY_DOUBLE 非保留 不能做函数名和类型名 BINARY_FLOAT 非保留 不能做函数名和类型名 BIT 非保留 可以做函数名和类型名 BODY 非保留 可以做函数名和类型名 BOOLEAN 非保留 可以做函数名和类型名 BOTH 保留 不能做函数名和类型名 BY 非保留 可以做函数名和类型名 BYTE 非保留 可以做函数名和类型名 CACHE 非保留 可以做列名 CALL 非保留 不能做函数名和类型名 CALLED 非保留 可以做函数名和类型名 CASCADE 非保留 不能做函数名和类型名 CASCADED 非保留 可以做列名 CASE 保留 不能做函数名和类型名 CAST 保留 可以做列名 CATALOG 非保留 不能做函数名和类型名 CHAIN 非保留 可以做列名 CHAR 非保留 可以做列名 CHARACTER 非保留 不能做函数名和类型名 见续表 1312 第 22 章 SQL 保留字和关键字 表 22.1 – 续表 关键字 KingbaseES 说明 CHARACTERISTICS 非保留 可以做函数名和类型名 CHECK 保留 可以做函数名和类型名 CHECKPOINT 非保留 不能做函数名和类型名 CLASS 非保留 可以做列名 CLOSE 非保留 不能做函数名和类型名 CLOSEUP 非保留 不能做函数名和类型名 CLUSTER 非保留 不能做函数名和类型名 COALESCE 非保留 可以做函数名和类型名 COLLATE 保留 不能做函数名和类型名 COLLATION 保留 不能做函数名和类型名 COLUMN 保留 不能做函数名和类型名 COLUMNS 非保留 可以做函数名和类型名 COMMENT 非保留 不能做函数名和类型名 COMMENTS 非保留 不能做函数名和类型名 COMMIT 非保留 不能做函数名和类型名 COMMITTED 非保留 不能做函数名和类型名 COMPILE 非保留 可以做函数名和类型名 CONCURRENTLY 保留 不能做函数名和类型名 CONFIGURATION 非保留 不能做函数名和类型名 CONFLICT 非保留 不能做函数名和类型名 CONNECT 保留 不能做函数名和类型名 CONNECT_BY_ISCYCLE 保留 不能做函数名和类型名 CONNECT_BY_ISLEAF 保留 不能做函数名和类型名 CONNECT_BY_ROOT 保留 不能做函数名和类型名 见续表 1313 第 22 章 SQL 保留字和关键字 表 22.1 – 续表 关键字 KingbaseES 说明 CONNECTION 非保留 可以做函数名和类型名 CONSTRAINT 保留 不能做函数名和类型名 CONSTRAINTS 非保留 不能做函数名和类型名 CONSTRUCTOR 非保留 不能做函数名和类型名 CONTENT 非保留 不能做函数名和类型名 CONTEXT 非保留 不能做函数名和类型名 CONTINUE 非保留 不能做函数名和类型名 CONVERSION 非保留 不能做函数名和类型名 CONVERT 非保留 不能做函数名和类型名 COPY 非保留 不能做函数名和类型名 COST 非保留 不能做函数名和类型名 CREATE 保留 不能做函数名和类型名 CROSS 保留 CSN 非保留 CSV 非保留 CUBE 非保留 CURRENT 非保留 CURRENT_CATALOG 保留 CURRENT_DATE 保留 CURRENT_ROLE 保留 CURRENT_SCHEMA 保留 CURRENT_TIME 保留 CURRENT_TIMESTAMP 保留 CURRENT_USER 保留 见续表 1314 第 22 章 SQL 保留字和关键字 表 22.1 – 续表 关键字 KingbaseES CURSOR 非保留 CYCLE 非保留 DATA 非保留 DATABASE 非保留 DATE_PART 非保留 DATEADD 非保留 DATEDIFF 非保留 DAY 非保留 DAY_HOUR 非保留 DAY_MINUTE 非保留 DAY_SECOND 非保留 DEALLOCATE 非保留 DEC 非保留 DECIMAL 非保留 DECLARE 非保留 DECODE 非保留 DEFAULT 保留 DEFAULTS 非保留 DEFERRABLE 保留 DEFERRED 非保留 DEFINER 非保留 DELETE 非保留 DELIMITER 非保留 DELIMITERS 非保留 说明 见续表 1315 第 22 章 SQL 保留字和关键字 表 22.1 – 续表 关键字 KingbaseES DEPENDS 非保留 DESC 保留 DETACH 非保留 DICTIONARY 非保留 DIRECTORY 非保留 DISABLE 非保留 DISCARD 非保留 DISTINCT 保留 DO 保留 DOCUMENT 非保留 DOMAIN 非保留 DOUBLE 非保留 DROP 非保留 DUPLICATE 非保留 EACH 非保留 EDITIONABLE 非保留 ELSE 保留 ENABLE 非保留 ENCKEY 非保留 ENCODING 非保留 ENCRYPT 非保留 ENCRYPTED 非保留 END 保留 ENUM 非保留 说明 见续表 1316 第 22 章 SQL 保留字和关键字 表 22.1 – 续表 关键字 KingbaseES ESCAPE 非保留 EVENT 非保留 EXCEPT 保留 EXCHANGE 非保留 EXCLUDE 非保留 EXCLUDING 非保留 EXCLUSIVE 非保留 EXEC 非保留 EXECUTE 非保留 EXISTS 非保留 EXISTSNODE 非保留 EXPLAIN 非保留 EXTENSION 非保留 EXTERNAL 非保留 EXTRACT 非保留 FALSE 保留 FAMILY 非保留 FETCH 保留 FINAL 非保留 FILTER 非保留 FIRST 非保留 FLASHBACK 非保留 FLOAT 非保留 FOLLOWING 非保留 说明 见续表 1317 第 22 章 SQL 保留字和关键字 表 22.1 – 续表 关键字 KingbaseES FOR 保留 FORCE 非保留 FOREIGN 保留 FORWARD 非保留 FREEZE 保留 FROM 保留 FULL 保留 FUNCTION 非保留 FUNCTIONS 非保留 GENERATED 非保留 GLOBAL 非保留 GRANT 保留 GRANTED 非保留 GREATEST 非保留 GROUP 保留 GROUP_CONCAT 非保留 GROUPING 非保留 GROUPS 非保留 HANDLER 非保留 HASH 非保留 HAVING 保留 HEADER 非保留 HOLD 非保留 HOUR 非保留 说明 见续表 1318 第 22 章 SQL 保留字和关键字 表 22.1 – 续表 关键字 KingbaseES HOUR_MINUTE 非保留 HOUR_SECOND 非保留 IDENTIFIED 非保留 IDENTITY 非保留 IF 非保留 IFNULL 非保留 ILIKE 保留 IMMEDIATE 非保留 IMMUTABLE 非保留 IMPLICIT 非保留 IMPORT 非保留 IN 保留 INCLUDE 非保留 INCLUDING 非保留 INCREMENT 非保留 INDEX 非保留 INDEXES 非保留 INFINITE 非保留 INHERIT 非保留 INHERITS 非保留 INITIALLY 保留 INLINE 非保留 INNER 保留 INOUT 非保留 说明 见续表 1319 第 22 章 SQL 保留字和关键字 表 22.1 – 续表 关键字 KingbaseES INPUT 非保留 INSENSITIVE 非保留 INSERT 非保留 INSTEAD 非保留 INT 非保留 INTEGER 非保留 INTERNAL 非保留 INTERSECT 保留 INTERVAL 非保留 INTO 保留 INVALIDATE 非保留 INVISIBLE 非保留 INVOKER 非保留 IS 保留 ISNULL 保留 ISOLATION 非保留 INSTANTIABLE 非保留 JOIN 保留 JSON 非保留 KEY 非保留 KEYS 非保留 KINGBASE_INTERNAL_LEVEL 非保留 LABEL 非保留 LANGUAGE 非保留 说明 见续表 1320 第 22 章 SQL 保留字和关键字 表 22.1 – 续表 关键字 KingbaseES LARGE 非保留 LAST 非保留 LATERAL 保留 LAX 非保留 LEADING 保留 LEAKPROOF 非保留 LEAST 非保留 LEFT 保留 LESS 非保留 LEVEL 非保留 LIKE 保留 LIMIT 保留 LINK 非保留 LIST 非保留 LISTEN 非保留 LOAD 非保留 LOCAL 非保留 LOCALTIME 保留 LOCALTIMESTAMP 保留 LOCATION 非保留 LOCK 非保留 LOCKED 非保留 LOGGED 非保留 LONG 非保留 说明 见续表 1321 第 22 章 SQL 保留字和关键字 表 22.1 – 续表 关键字 KingbaseES LOOP 非保留 MAPPING 非保留 MASTER 非保留 MATCH 非保留 MATCHED 非保留 MATERIALIZED 非保留 MAXVALUE 非保留 MEMBER 非保留 MERGE 非保留 METHOD 非保留 MINUS 保留 MINUTE 非保留 MINUTE_SECOND 非保留 MINVALUE 非保留 MODE 非保留 MODIFY 非保留 MONTH 非保留 MOVE 非保留 NAME 非保留 NAMES 非保留 NAN 非保留 NATIONAL 非保留 NATURAL 保留 NCHAR 非保留 说明 见续表 1322 第 22 章 SQL 保留字和关键字 表 22.1 – 续表 关键字 KingbaseES NEW 非保留 NEXT 非保留 NO 非保留 NOCACHE 非保留 NOCYCLE 保留 NOFORCE 非保留 NOLABEL 非保留 NOMAXVALUE 非保留 NOMINVALUE 非保留 NONE 非保留 NONEDITIONABLE 非保留 NOORDER 非保留 NOPARALLEL 非保留 NOT 保留 NOTHING 非保留 NOTIFY 非保留 NOTNULL 保留 NOVALIDATE 非保留 NOWAIT 非保留 NULL 保留 NULLIF 非保留 NULLS 非保留 NUMBER 非保留 NUMERIC 非保留 说明 见续表 1323 第 22 章 SQL 保留字和关键字 表 22.1 – 续表 关键字 KingbaseES NVARCHAR 非保留 NVARCHAR2 非保留 NVL 保留 NVL2 保留 OBJECT 非保留 OF 非保留 OFF 非保留 OFFLINE 非保留 OFFSET 保留 OIDS 非保留 OLD 非保留 ON 保留 ONLINE 保留 ONLY 保留 OPENUP 非保留 OPERATOR 非保留 OPTION 非保留 OPTIONS 非保留 OR 保留 ORDER 保留 ORDINALITY 非保留 OTHERS 非保留 OUT 非保留 OUTER 保留 说明 见续表 1324 第 22 章 SQL 保留字和关键字 表 22.1 – 续表 关键字 KingbaseES OVER 非保留 OVERLAPS 保留 OVERLAY 非保留 OVERRIDING 非保留 OWNED 非保留 OWNER 非保留 PACKAGE 非保留 PARALLEL 非保留 PARSER 非保留 PARTIAL 非保留 PARTITION 非保留 PARTITIONS 非保留 PASSING 非保留 PASSWORD 非保留 PERCENT 非保留 PIPELINED 非保留 PIVOT 非保留 PLACING 保留 PLANS 非保留 PLS_INTEGER 非保留 POLICY 非保留 POSITION 非保留 PRECEDING 非保留 PRECISION 非保留 说明 见续表 1325 第 22 章 SQL 保留字和关键字 表 22.1 – 续表 关键字 KingbaseES PREPARE 非保留 PREPARED 非保留 PRESERVE 非保留 PRIMARY 保留 PRIOR 非保留 PRIVILEGES 非保留 PROCEDURAL 非保留 PROCEDURE 非保留 PROCEDURES 非保留 PROGRAM 非保留 PUBLIC 非保留 PUBLICATION 非保留 PURGE 非保留 QUOTE 非保留 RANGE 非保留 RAW 非保留 READ 非保留 REAL 非保留 REASSIGN 非保留 RECHECK 非保留 RECURSIVE 非保留 RECYCLEBIN 非保留 REF 非保留 REFERENCES 保留 说明 见续表 1326 第 22 章 SQL 保留字和关键字 表 22.1 – 续表 关键字 KingbaseES REFERENCING 非保留 REFRESH 非保留 REINDEX 非保留 RELATIVE 非保留 RELEASE 非保留 RENAME 非保留 REPEATABLE 非保留 REPLACE 非保留 REPLICA 非保留 RESET 非保留 RESOURCE 非保留 RESTART 非保留 RESTRICT 非保留 RESULT 非保留 RETURN 保留 RETURNING 保留 RETURNS 非保留 REUSE 非保留 REVOKE 非保留 RIGHT 保留 ROLE 非保留 ROLLBACK 非保留 ROLLUP 非保留 ROUTINE 非保留 说明 见续表 1327 第 22 章 SQL 保留字和关键字 表 22.1 – 续表 关键字 KingbaseES ROUTINES 非保留 ROW 非保留 ROWID 保留 ROWNUM 保留 ROWS 非保留 ROWTYPE 非保留 RULE 非保留 SAVEPOINT 非保留 SCHEMA 非保留 SCHEMAS 非保留 SCN 非保留 SCROLL 非保留 SEARCH 非保留 SECOND 非保留 SECURITY 非保留 SELECT 保留 SELF 非保留 SEPARATOR 非保留 SEQUENCE 非保留 SEQUENCES 非保留 SERIALIZABLE 非保留 SERVER 非保留 SESSION 非保留 SESSION_USER 保留 说明 见续表 1328 第 22 章 SQL 保留字和关键字 表 22.1 – 续表 关键字 KingbaseES SESSIONTIMEZONE 非保留 SET 非保留 SETOF 非保留 SETS 非保留 SHARE 非保留 SHOW 非保留 SIBLINGS 非保留 SIMILAR 保留 SIMPLE 非保留 SKIP 非保留 SKIP_ERRORS 非保留 SMALLINT 非保留 SNAPSHOT 非保留 SOME 保留 SPECIFICATION 非保留 SPLIT 非保留 SQL 非保留 STABLE 非保留 STANDALONE 非保留 START 非保留 STATEMENT 非保留 STATIC 非保留 STATISTICS 非保留 STDIN 非保留 说明 见续表 1329 第 22 章 SQL 保留字和关键字 表 22.1 – 续表 关键字 KingbaseES STDOUT 非保留 STORAGE 非保留 STORE 非保留 STORED 非保留 STRICT 非保留 STRIP 非保留 SUBPARTITION 非保留 SUBPARTITIONS 非保留 SUBSCRIPTION 非保留 SUBSTRING 非保留 SUPPORT 非保留 SYMMETRIC 保留 SYNONYM 保留 SYS_CONNECT_BY_PATH 保留 SYS_REFCURSOR 非保留 SYSDATE 非保留 SYSID 非保留 SYSTEM 非保留 SYSTIMESTAMP 保留 TABLE 保留 TABLES 非保留 TABLESAMPLE 保留 TABLESPACE 非保留 TEMP 非保留 说明 见续表 1330 第 22 章 SQL 保留字和关键字 表 22.1 – 续表 关键字 KingbaseES TEMPLATE 非保留 TEMPORARY 非保留 TERMINATOR 非保留 TEXT 非保留 THAN 非保留 THEN 保留 TIES 非保留 TIME 非保留 TIMESTAMP 非保留 TO 保留 TOP 保留 TRAILING 保留 TRANSACTION 非保留 TRANSFORM 非保留 TREAT 非保留 TRIGGER 非保留 TRIGGERS 非保留 TRIM 非保留 TRUE 保留 TRUNCATE 非保留 TRUSTED 非保留 TYPE 非保留 TYPES 非保留 UNBOUNDED 非保留 说明 见续表 1331 第 22 章 SQL 保留字和关键字 表 22.1 – 续表 关键字 KingbaseES UNCOMMITTED 非保留 UNENCRYPTED 非保留 UNION 保留 UNIQUE 保留 UNKNOWN 非保留 UNLISTEN 非保留 UNLOCK 非保留 UNLOGGED 非保留 UNPIVOT 非保留 UNTIL 非保留 UPDATE 非保留 USER 保留 USING 保留 VACUUM 非保留 VALID 非保留 VALIDATE 非保留 VALIDATION 非保留 VALIDATOR 非保留 VALUE 非保留 VALUES 非保留 VARBINARY 非保留 VARCHAR 非保留 VARCHAR2 非保留 VARIADIC 保留 说明 见续表 1332 第 22 章 SQL 保留字和关键字 表 22.1 – 续表 关键字 KingbaseES VARRAY 非保留 VARYING 非保留 VERBOSE 保留 VERSION 非保留 VERSIONS 非保留 VIEW 非保留 VIEWS 非保留 VISIBLE 非保留 VOLATILE 非保留 WAIT 非保留 WALLET 非保留 WHEN 保留 WHERE 保留 WHITESPACE 非保留 WINDOW 保留 WITH 保留 WITHIN 非保留 WITHOUT 非保留 WORK 非保留 WRAPPED 非保留 WRAPPER 非保留 WRITE 非保留 XML 非保留 XMLATTRIBUTES 非保留 说明 见续表 1333 第 22 章 SQL 保留字和关键字 表 22.1 – 续表 关键字 KingbaseES XMLCONCAT 非保留 XMLELEMENT 非保留 XMLEXISTS 非保留 XMLFOREST 非保留 XMLNAMESPACES 非保留 XMLPARSE 非保留 XMLPI 非保留 XMLROOT 非保留 XMLSERIALIZE 非保留 XMLTABLE 非保留 YEAR 非保留 YEAR_MONTH 非保留 YES 非保留 ZONE 非保留 说明 1334 第 23 章 第 MYSQL 模式索引 23章 MySQL 模式索引 MySQL 模式与默认模式的差异点主要体现在如下方面: • 数据类型方面 • 操作符方面 • 函数方面 • 语法方面 23.1 数据类型方面 23.1.1 整数类型 SIGNED/ UNSIGNED 数据类型:MySQL 模式下,KingbaseES 支持 signed 和 unsigned 属性。具体请参 考SIGNED/UNSIGNED 数据类型 23.1.2 日期与时间类型 DATETIME 数据类型:DATETIME 数据类型仅在 MySQL 模式下支持,具体请参考DATETIME 数据类型 TIME 数据类型:在 MySQL 模式下,TIME 值的范围可以从’-838:59:59.000000’ 到’838:59:59.000000’,默认精 度为 0。具体请参考TIME 数据类型 TIMESTAMP 数据类型:timestamp[ (p)] [ without time zone ],其中 p 表示秒精度即秒字段中小数点后面的位 数,取值范围为 0~6,如果未定义,在精度上没有明确的边界。在 MySQL 模式下默认精度的说明,默认精度为 0。 具体请参考TIMESTAMP 数据类型 year 类型:其只在 MySQL 模式下可用,兼容 MySQL 的 year 类型。具体请参考YEAR 类型 1335 第 23 章 23.1.3 MYSQL 模式索引 大对象数据类型 BLOB 相关类型:包括 TINYBLOB、MEDUIMBLOB 和 LONGBLOB,具体请参考BLOB 类型 23.1.4 JSON 类型 JSON 类型:MySQL 模式下 JSON 类型与 KES 默认模式的 JSON、JSONB 类型的差异,具体请参考MySQL 模式 JSON 类型 23.1.5 用户自定义类型 SET 类型: 仅在 MySQL 模式下有效。具体请参考SET 类型 23.2 操作符方面 MySQL 模式支持逻辑操作符 XOR、&&、|| 和!,具体请参考逻辑操作符 23.3 函数方面 • ADDDATE 具体请参考ADDDATE(MySQL 模式) • ADDTIME 具体请参考ADDTIME(MySQL 模式) • CURDATE 具体请参考CURDATE(MySQL 模式) • CURTIME 具体请参考CURTIME(MySQL 模式) • CONVERT 具体请参考CONVERT(MySQL 模式) • CURRENT_TIME 具体请参考CURRENT_TIME(MySQL 模式) • CURRENT_TIMESTAMP 具体请参考CURRENT_TIMESTAMP(MySQL 模式) • CONVERT_TZ 具体请参考CONVERT_TZ(MySQL 模式) • DATEDIFF 具体请参考DATEDIFF(MySQL 模式) • DAY 具体请参考DAY(MySQL 模式) • DAYNAME 具体请参考DAYNAME(MySQL 模式) • DAYOFMONTH 具体请参考DAYOFMONTH(MySQL 模式) • DAYOFWEEK 具体请参考DAYOFWEEK(MySQL 模式) • DAYOFYEAR 具体请参考DAYOFYEAR(MySQL 模式) 1336 第 23 章 MYSQL 模式索引 • EXTRACT 具体请参考EXTRACT(MySQL 模式) • FORMAT_PICO_TIME 具体请参考FORMAT_PICO_TIME(MySQL 模式) • FROM_BASE64 具体请参考FROM_BASE64(MySQL 模式) • FROM_DAYS 具体请参考FROM_DAYS(MySQL 模式) • FROM_UNIXTIME 具体请参考FROM_UNIXTIME(MySQL 模式) • GET_FORMAT 具体请参考GET_FORMAT(MySQL 模式) • HOUR 具体请参考HOUR(MySQL 模式) • ISNULL 具体请参考ISNULL(MySQL 模式) • LOCATE 具体请参考LOCATE(MySQL 模式) • LOCALTIME 具体请参考LOCALTIME(MySQL 模式) • LOCALTIMESTAMP 具体请参考LOCALTIMESTAMP(MySQL 模式) • MAKEDATE 具体请参考MAKEDATE(MySQL 模式) • MAKETIME 具体请参考MAKETIME(MySQL 模式) • MICROSECOND 具体请参考MICROSECOND(MySQL 模式) • MINUTE 具体请参考MINUTE(MySQL 模式) • MONTH 具体请参考MONTH(MySQL 模式) • MONTHNAME 具体请参考MONTHNAME(MySQL 模式) • PERIOD_ADD 具体请参考PERIOD_ADD(MySQL 模式) • PERIOD_DIFF 具体请参考PERIOD_DIFF(MySQL 模式) • QUARTER 具体请参考QUARTER(MySQL 模式) • ROW_COUNT 具体请参考ROW_COUNT(MySQL 模式) • STDDEV 具体请参考STDDEV(MySQL 模式) • SUBSTRING_INDEX 具体请参考SUBSTRING_INDEX(MySQL 模式) • SEC_TO_TIME 具体请参考SEC_TO_TIME(MySQL 模式) • SECOND 具体请参考SECOND(MySQL 模式) • SUBTIME 具体请参考SUBTIME(MySQL 模式) • TIME 具体请参考TIME(MySQL 模式) • TIMEDIFF 具体请参考TIMEDIFF(MySQL 模式) • TIMESTAMP 具体请参考TIMESTAMP(MySQL 模式) • TIMESTAMPADD 具体请参考TIMESTAMPADD(MySQL 模式) • TIMESTAMPDIFF 具体请参考TIMESTAMPDIFF(MySQL 模式) 1337 第 23 章 MYSQL 模式索引 • TIME_TO_SEC 具体请参考TIME_TO_SEC(MySQL 模式) • TO_BASE64 具体请参考TO_BASE64(MySQL 模式) • TO_DAYS 具体请参考TO_DAYS(MySQL 模式) • TO_SECONDS 具体请参考TO_SECONDS(MySQL 模式) • UTC_DATE 具体请参考UTC_DATE(MySQL 模式) • UTC_TIME 具体请参考UTC_TIME(MySQL 模式) • UTC_TIMESTAMP 具体请参考UTC_TIMESTAMP(MySQL 模式) • DATE_SUB 具体请参考DATE_SUB(MySQL 模式) • YEARWEEK 具体请参考YEARWEEK(MySQL 模式) • WEEK 具体请参考WEEK(MySQL 模式) • WEEKDAY 具体请参考WEEKDAY(MySQL 模式) • WEEKOFYEAR 具体请参考WEEKOFYEAR(MySQL 模式) • UNIX_TIMESTAMP 具体请参考UNIX_TIMESTAMP(MySQL 模式) • VARIANCE 具体请参考VARIANCE(MySQL 模式) 23.3.1 mysql_json 插件相关函数 • json_array_append 末尾添加数组元素 • json_array_insert 插入数组元素 • json_contains 判断是否包含某个 json 值 • json_contains_patch 判断某个路径下是否包含 json 值 • json_depth 返回 json 文档的最大深度 • json_extract 提取 json 值 • json_insert 插入新值,但不替换存在的旧值 • json_keys 提取 json 中的键值为 json 数组 • json_length 返回 json 文档的长度 • json_merge_patch 多个 json 进行合并,相同键名,后面的覆盖前面的。 • json_merge_preserve 多个 json 进行合并,相同键名,则键值组成新的对象。 • json_quote 将 json 转成 json 字符串类型 • json_remove 删除 json 数据 • json_replace 替换值,只替换已存在的旧值 1338 第 23 章 MYSQL 模式索引 • json_search 按给定字符串关键字搜索 json,返回匹配的路径 • json_set 设置值(替换旧值,并插入不存在的新值) • json_type 返回 json 值的类型 • json_unquote 去除 json 字符串的引号,将值转成 string 类型 • json_valid 判断是否为合法 json 文档 注意: mysql_json 插件相关函数语法详情参见《KingbaseES 插件参考手册》的 mysql_json 。 23.4 语法方面 23.4.1 CREATE TABLE MySQL 模式下,若表中的时间列设置了 ON UPDATE 属性,当数据行发生更新时,数据库自动设置该列的值 为当前的时间戳。具体请参考CREATE TABLE 1339 版权声明 版权声明 北京人大金仓信息技术股份有限公司(简称:人大金仓)版权所有,并保留对本手册及本声明的一切权利。 未得到人大金仓的书面许可,任何人不得以任何方式或形式对本手册内的任何部分进行复制、摘录、备份、修 改、传播、翻译成其他语言、将其全部或部分用于商业用途。 免责声明 本手册内容依据现有信息制作,由于产品版本升级或其他原因,其内容有可能变更。人大金仓保留在没有任何通 知或者提示的情况下对手册内容进行修改的权利。 本手册仅作为使用指导,人大金仓在编写本手册时已尽力保证其内容准确可靠,但并不确保手册内容完全没有错 误或遗漏,本手册中的所有信息也不构成任何明示或暗示的担保。 技术支持 • 人大金仓官方网站:http://www.kingbase.com.cn/ • 人大金仓文档中心:http://help.kingbase.com.cn/ • 全国服务热线:400-601-1188 • 人大金仓技术支持与反馈信箱:support@kingbase.com.cn 1340 服务周期承诺 服务周期承诺 由于市场需求在不断变化,技术创新和发展的进程不断加剧,产品的版本更迭不可避免。人大金仓对于产品版本 生命周期的有效管理,有助于您提前规划项目,更好地从产品服务终止上过渡。 表 1: KingbaseES 产品生命周期里程碑 关键里程碑点 定义 产品发布日期 产品正式发布版本,即 GA(general availability)版本的发布日期。 停止销售日期 正式停止销售的日期,版本停止接受订单日。该日之后,产品将不再销售。 停止功能升级日期 在该日期之后,不再提供新特性和新硬件支持。但依旧提供错误修复、安全修复、功 能维护等服务。 停止功能维护日期 在该日期之后,不再维护功能,修复问题。但依旧提供安全修复等服务 停止安全维护日期 在该日期之后,不再发布补丁版本修复中高风险漏洞,仅提供有限的支持。 产品服务终止日期 停止提供产品服务和支持的日期。包括软件维护版本,缺陷修复,以及针对该产品的 所有服务支持(包括服务热线和远程/现场支持)。 服务周期策略 金仓数据库管理系统 KingbaseES 产品确保以下的服务周期: 1)产品自发布之日起至产品停止功能升级(包含新特性、新硬件支持)之日不少于 5 年。 2)产品停止功能升级之日起至产品停止功能维护(主要包括问题修复)之日不少于 4 年。 3)产品功能维护停止之日起至产品停止安全维护(包括中高风险漏洞修复)之日不少于 2 年。 服务终止策略 金仓数据库管理系统 KingbaseES 产品确保在销售后,至少提供 6 年的服务支持。 注意: 人大金仓将会综合各方因素来确定产品服务终止日期。并将在实际产品服务终止日期之前至少 90 天,通过公 1341 服务周期承诺 开方式宣布产品服务终止日期。 1342 BIBLIOGRAPHY Bibliography [a] 如果需要对现有行或新行 (例如,WHERE 或 RETURNING 引用关系中的列) 进行读访问。 1343

相关文章