direktori cari
前言 何为PostgreSQL? PostgreSQL简史 格式约定 更多信息 臭虫汇报指导 I. 教程 章1. 从头开始 1.1. 安装 1.2. 体系基本概念 1.3. 创建一个数据库 1.4. 访问数据库 章2. SQL语言 2.1. 介绍 2.2. 概念 2.3. 创建新表 2.4. 向表中添加行 2.5. 查询一个表 2.6. 表间链接 2.7. 聚集函数 2.8. 更新 2.9. 删除 章3. 高级特性 3.1. 介绍 3.2. 视图 3.3. 外键 3.4. 事务 3.5. 窗口函数 3.6. 继承 3.7. 结论 II. SQL语言 章4. SQL语法 4.1. 词法结构 4.2. 值表达式 4.3. 调用函数 章5. 数据定义 5.1. 表的基本概念 5.2. 缺省值 5.3. 约束 5.4. 系统字段 5.5. 修改表 5.6. 权限 5.7. 模式 5.8. 继承 5.9. 分区 5.10. 其它数据库对象 5.11. 依赖性跟踪 章 6. 数据操作 6.1. 插入数据 6.2. 更新数据 6.3. 删除数据 章7. 查询 7.1. 概述 7.2. 表表达式 7.3. 选择列表 7.4. 组合查询 7.5. 行排序 7.6. LIMIT和OFFSET 7.7. VALUES列表 7.8. WITH的查询(公用表表达式) 章8. 数据类型 8.1. 数值类型 8.2. 货币类型 8.3. 字符类型 8.4. 二进制数据类型 8.5. 日期/时间类型 8.6. 布尔类型 8.7. 枚举类型 8.8. 几何类型 8.9. 网络地址类型 8.10. 位串类型 8.11. 文本搜索类型 8.12. UUID类型 8.13. XML类型 8.14. 数组 8.15. 复合类型 8.16. 对象标识符类型 8.17. 伪类型 章 9. 函数和操作符 9.1. 逻辑操作符 9.2. 比较操作符 9.3. 数学函数和操作符 9.4. 字符串函数和操作符 9.5. 二进制字符串函数和操作符 9.6. 位串函数和操作符 9.7. 模式匹配 9.8. 数据类型格式化函数 9.9. 时间/日期函数和操作符 9.10. 支持枚举函数 9.11. 几何函数和操作符 9.12. 网络地址函数和操作符 9.13. 文本检索函数和操作符 9.14. XML函数 9.15. 序列操作函数 9.16. 条件表达式 9.17. 数组函数和操作符 9.18. 聚合函数 9.19. 窗口函数 9.20. 子查询表达式 9.21. 行和数组比较 9.22. 返回集合的函数 9.23. 系统信息函数 9.24. 系统管理函数 9.25. 触发器函数 章10. 类型转换 10.3. 函数 10.2. 操作符 10.1. 概述 10.4. 值存储 10.5. UNION 章11. 索引 11.1. 介绍 11.2. 索引类型 11.3. 多字段索引 11.4. 索引和ORDER BY 11.5. 组合多个索引 11.6. 唯一索引 11.7. 表达式上的索引 11.8. 部分索引 11.9. 操作类和操作簇 11.10. 检查索引的使用 章12. Full Text Search 12.1. Introduction 12.2. Tables and Indexes 12.3. Controlling Text Search 12.4. Additional Features 12.5. Parsers 12.6. Dictionaries 12.7. Configuration Example 12.8. Testing and Debugging Text Search 12.9. GiST and GIN Index Types 12.10. psql Support 12.11. Limitations 12.12. Migration from Pre-8.3 Text Search 章13. 并发控制 13.1. 介绍 13.2. 事务隔离 13.3. 明确锁定 13.4. 应用层数据完整性检查 13.5. 锁和索引 章14. 性能提升技巧 14.1. 使用EXPLAIN 14.2. 规划器使用的统计信息 14.3. 用明确的JOIN语句控制规划器 14.4. 向数据库中添加记录 14.5. 非持久性设置 III. 服务器管理 章15. 安装指导 15.1. 简版 15.2. 要求 15.3. 获取源码 15.4. 升级 15.5. 安装过程 15.6. 安装后的设置 15.7. 支持的平台 15.8. 特殊平台的要求 章16. Installation from Source Code on Windows 16.1. Building with Visual C++ or the Platform SDK 16.2. Building libpq with Visual C++ or Borland C++ 章17. 服务器安装和操作 17.1. PostgreSQL用户帐户 17.2. 创建数据库集群 17.3. 启动数据库服务器 17.4. 管理内核资源 17.5. 关闭服务 17.6. 防止服务器欺骗 17.7. 加密选项 17.8. 用SSL进行安全的TCP/IP连接 17.9. Secure TCP/IP Connections with SSH Tunnels 章18. 服务器配置 18.1. 设置参数 18.2. 文件位置 18.3. 连接和认证 18.4. 资源消耗 18.5. 预写式日志 18.6. 查询规划 18.7. 错误报告和日志 18.8. 运行时统计 18.9. 自动清理 18.10. 客户端连接缺省 18.12. 版本和平台兼容性 18.11. 锁管理 18.13. 预置选项 18.14. 自定义的选项 18.15. 开发人员选项 18.16. 短选项 章19. 用户认证 19.1. pg_hba.conf 文件 19.2. 用户名映射 19.3. 认证方法 19.4. 用户认证 章20. 数据库角色和权限 20.1. 数据库角色 20.2. 角色属性 20.3. 权限 20.4. 角色成员 20.5. 函数和触发器 章21. 管理数据库 21.1. 概述 21.2. 创建一个数据库 21.3. 临时库 21.4. 数据库配置 21.5. 删除数据库 21.6. 表空间 章22. 本土化 22.1. 区域支持 22.2. 字符集支持 章23. 日常数据库维护工作 23.1. Routine Vacuuming日常清理 23.2. 经常重建索引 23.3. 日志文件维护 章24. 备份和恢复 24.1. SQL转储 24.2. 文件系统级别的备份 24.3. 在线备份以及即时恢复(PITR) 24.4. 版本间迁移 章25. 高可用性与负载均衡,复制 25.1. 不同解决方案的比较 25.2. 日志传送备份服务器 25.3. 失效切换 25.4. 日志传送的替代方法 25.5. 热备 章26. 恢复配置 26.1. 归档恢复设置 26.2. 恢复目标设置 26.3. 备服务器设置 章27. 监控数据库的活动 27.1. 标准Unix工具 27.2. 统计收集器 27.3. 查看锁 27.4. 动态跟踪 章28. 监控磁盘使用情况 28.1. 判断磁盘的使用量 28.2. 磁盘满导致的失效 章29. 可靠性和预写式日志 29.1. 可靠性 29.2. 预写式日志(WAL) 29.3. 异步提交 29.4. WAL配置 29.5. WAL内部 章30. Regression Tests 30.1. Running the Tests 30.2. Test Evaluation 30.3. Variant Comparison Files 30.4. Test Coverage Examination IV. 客户端接口 章31. libpq-C库 31.1. 数据库联接函数 31.2. 连接状态函数 31.3. 命令执行函数 31.4. 异步命令处理 31.5. 取消正在处理的查询 31.6. 捷径接口 31.7. 异步通知 31.8. 与COPY命令相关的函数 31.9. Control Functions 控制函数 31.10. 其他函数 31.11. 注意信息处理 31.12. 事件系统 31.13. 环境变量 31.14. 口令文件 31.15. 连接服务的文件 31.16. LDAP查找连接参数 31.17. SSL支持 31.18. 在多线程程序里的行为 31.19. 制作libpq程序 31.20. 例子程序 章32. 大对象 32.1. 介绍 32.2. 实现特点 32.3. 客户端接口 32.4. 服务器端函数 32.5. 例子程序 章33. ECPG - Embedded SQL in C 33.1. The Concept 33.2. Connecting to the Database Server 33.3. Closing a Connection 33.4. Running SQL Commands 33.5. Choosing a Connection 33.6. Using Host Variables 33.7. Dynamic SQL 33.8. pgtypes library 33.9. Using Descriptor Areas 33.10. Informix compatibility mode 33.11. Error Handling 33.12. Preprocessor directives 33.13. Processing Embedded SQL Programs 33.14. Library Functions 33.15. Internals 章34. 信息模式 34.1. 关于这个模式 34.2. 数据类型 34.3. information_schema_catalog_name 34.4. administrable_role_authorizations 34.5. applicable_roles 34.6. attributes 34.7. check_constraint_routine_usage 34.8. check_constraints 34.9. column_domain_usage 34.10. column_privileges 34.11. column_udt_usage 34.12. 字段 34.13. constraint_column_usage 34.14. constraint_table_usage 34.15. data_type_privileges 34.16. domain_constraints 34.18. domains 34.17. domain_udt_usage 34.19. element_types 34.20. enabled_roles 34.21. foreign_data_wrapper_options 34.22. foreign_data_wrappers 34.23. foreign_server_options 34.24. foreign_servers 34.25. key_column_usage 34.26. parameters 34.27. referential_constraints 34.28. role_column_grants 34.29. role_routine_grants 34.30. role_table_grants 34.31. role_usage_grants 34.32. routine_privileges 34.33. routines 34.34. schemata 34.35. sequences 34.36. sql_features 34.37. sql_implementation_info 34.38. sql_languages 34.39. sql_packages 34.40. sql_parts 34.41. sql_sizing 34.42. sql_sizing_profiles 34.43. table_constraints 34.44. table_privileges 34.45. tables 34.46. triggered_update_columns 34.47. 触发器 34.48. usage_privileges 34.49. user_mapping_options 34.50. user_mappings 34.51. view_column_usage 34.52. view_routine_usage 34.53. view_table_usage 34.54. 视图 V. 服务器端编程 章35. 扩展SQL 35.1. 扩展性是如何实现的 35.2. PostgreSQL类型系统 35.3. User-Defined Functions 35.4. Query Language (SQL) Functions 35.5. Function Overloading 35.6. Function Volatility Categories 35.7. Procedural Language Functions 35.8. Internal Functions 35.9. C-Language Functions 35.10. User-Defined Aggregates 35.11. User-Defined Types 35.12. User-Defined Operators 35.13. Operator Optimization Information 35.14. Interfacing Extensions To Indexes 35.15. 用C++扩展 章36. 触发器 36.1. 触发器行为概述 36.3. 用 C 写触发器 36.2. 数据改变的可视性 36.4. 一个完整的例子 章37. 规则系统 37.1. The Query Tree 37.2. 视图和规则系统 37.3. 在INSERT,UPDATE和DELETE上的规则 37.4. 规则和权限 37.5. 规则和命令状态 37.6. 规则与触发器得比较 章38. Procedural Languages 38.1. Installing Procedural Languages 章39. PL/pgSQL - SQL过程语言 39.1. 概述 39.2. PL/pgSQL的结构 39.3. 声明 39.4. 表达式 39.5. 基本语句 39.6. 控制结构 39.7. 游标 39.8. 错误和消息 39.9. 触发器过程 39.10. PL/pgSQL Under the Hood 39.11. 开发PL/pgSQL的一些提示 39.12. 从OraclePL/SQL 进行移植 章40. PL/Tcl - Tcl Procedural Language 40.1. Overview 40.2. PL/Tcl Functions and Arguments 40.3. Data Values in PL/Tcl 40.4. Global Data in PL/Tcl 40.5. Database Access from PL/Tcl 40.6. Trigger Procedures in PL/Tcl 40.7. Modules and the unknown command 40.8. Tcl Procedure Names 章41. PL/Perl - Perl Procedural Language 41.1. PL/Perl Functions and Arguments 41.2. Data Values in PL/Perl 41.3. Built-in Functions 41.4. Global Values in PL/Perl 41.6. PL/Perl Triggers 41.5. Trusted and Untrusted PL/Perl 41.7. PL/Perl Under the Hood 章42. PL/Python - Python Procedural Language 42.1. Python 2 vs. Python 3 42.2. PL/Python Functions 42.3. Data Values 42.4. Sharing Data 42.5. Anonymous Code Blocks 42.6. Trigger Functions 42.7. Database Access 42.8. Utility Functions 42.9. Environment Variables 章43. Server Programming Interface 43.1. Interface Functions Spi-spi-connect Spi-spi-finish Spi-spi-push Spi-spi-pop Spi-spi-execute Spi-spi-exec Spi-spi-execute-with-args Spi-spi-prepare Spi-spi-prepare-cursor Spi-spi-prepare-params Spi-spi-getargcount Spi-spi-getargtypeid Spi-spi-is-cursor-plan Spi-spi-execute-plan Spi-spi-execute-plan-with-paramlist Spi-spi-execp Spi-spi-cursor-open Spi-spi-cursor-open-with-args Spi-spi-cursor-open-with-paramlist Spi-spi-cursor-find Spi-spi-cursor-fetch Spi-spi-cursor-move Spi-spi-scroll-cursor-fetch Spi-spi-scroll-cursor-move Spi-spi-cursor-close Spi-spi-saveplan 43.2. Interface Support Functions Spi-spi-fname Spi-spi-fnumber Spi-spi-getvalue Spi-spi-getbinval Spi-spi-gettype Spi-spi-gettypeid Spi-spi-getrelname Spi-spi-getnspname 43.3. Memory Management Spi-spi-palloc Spi-realloc Spi-spi-pfree Spi-spi-copytuple Spi-spi-returntuple Spi-spi-modifytuple Spi-spi-freetuple Spi-spi-freetupletable Spi-spi-freeplan 43.4. Visibility of Data Changes 43.5. Examples VI. 参考手册 I. SQL命令 Sql-abort Sql-alteraggregate Sql-alterconversion Sql-alterdatabase Sql-alterdefaultprivileges Sql-alterdomain Sql-alterforeigndatawrapper Sql-alterfunction Sql-altergroup Sql-alterindex Sql-alterlanguage Sql-alterlargeobject Sql-alteroperator Sql-alteropclass Sql-alteropfamily Sql-alterrole Sql-alterschema Sql-altersequence Sql-alterserver Sql-altertable Sql-altertablespace Sql-altertsconfig Sql-altertsdictionary Sql-altertsparser Sql-altertstemplate Sql-altertrigger Sql-altertype Sql-alteruser Sql-alterusermapping Sql-alterview Sql-analyze Sql-begin Sql-checkpoint Sql-close Sql-cluster Sql-comment Sql-commit Sql-commit-prepared Sql-copy Sql-createaggregate Sql-createcast Sql-createconstraint Sql-createconversion Sql-createdatabase Sql-createdomain Sql-createforeigndatawrapper Sql-createfunction Sql-creategroup Sql-createindex Sql-createlanguage Sql-createoperator Sql-createopclass Sql-createopfamily Sql-createrole Sql-createrule Sql-createschema Sql-createsequence Sql-createserver Sql-createtable Sql-createtableas Sql-createtablespace Sql-createtsconfig Sql-createtsdictionary Sql-createtsparser Sql-createtstemplate Sql-createtrigger Sql-createtype Sql-createuser Sql-createusermapping Sql-createview Sql-deallocate Sql-declare Sql-delete Sql-discard Sql-do Sql-dropaggregate Sql-dropcast Sql-dropconversion Sql-dropdatabase Sql-dropdomain Sql-dropforeigndatawrapper Sql-dropfunction Sql-dropgroup Sql-dropindex Sql-droplanguage Sql-dropoperator Sql-dropopclass Sql-dropopfamily Sql-drop-owned Sql-droprole Sql-droprule Sql-dropschema Sql-dropsequence Sql-dropserver Sql-droptable Sql-droptablespace Sql-droptsconfig Sql-droptsdictionary Sql-droptsparser Sql-droptstemplate Sql-droptrigger Sql-droptype Sql-dropuser Sql-dropusermapping Sql-dropview Sql-end Sql-execute Sql-explain Sql-fetch Sql-grant Sql-insert Sql-listen Sql-load Sql-lock Sql-move Sql-notify Sql-prepare Sql-prepare-transaction Sql-reassign-owned Sql-reindex Sql-release-savepoint Sql-reset Sql-revoke Sql-rollback Sql-rollback-prepared Sql-rollback-to Sql-savepoint Sql-select Sql-selectinto Sql-set Sql-set-constraints Sql-set-role Sql-set-session-authorization Sql-set-transaction Sql-show Sql-start-transaction Sql-truncate Sql-unlisten Sql-update Sql-vacuum Sql-values II. 客户端应用程序 App-clusterdb App-createdb App-createlang App-createuser App-dropdb App-droplang App-dropuser App-ecpg App-pgconfig App-pgdump App-pg-dumpall App-pgrestore App-psql App-reindexdb App-vacuumdb III. PostgreSQL服务器应用程序 App-initdb App-pgcontroldata App-pg-ctl App-pgresetxlog App-postgres App-postmaster VII. 内部 章44. PostgreSQL内部概览 44.1. 查询路径 44.2. 连接是如何建立起来的 44.3. 分析器阶段 44.4. ThePostgreSQL规则系统 44.5. 规划器/优化器 44.6. 执行器 章45. 系统表 45.1. 概述 45.2. pg_aggregate 45.3. pg_am 45.4. pg_amop 45.5. pg_amproc 45.6. pg_attrdef 45.7. pg_attribute 45.8. pg_authid 45.9. pg_auth_members 45.10. pg_cast 45.11. pg_class 45.12. pg_constraint 45.13. pg_conversion 45.14. pg_database 45.15. pg_db_role_setting 45.16. pg_default_acl 45.17. pg_depend 45.18. pg_description 45.19. pg_enum 45.20. pg_foreign_data_wrapper 45.21. pg_foreign_server 45.22. pg_index 45.23. pg_inherits 45.24. pg_language 45.25. pg_largeobject 45.26. pg_largeobject_metadata 45.27. pg_namespace 45.28. pg_opclass 45.29. pg_operator 45.30. pg_opfamily 45.31. pg_pltemplate 45.32. pg_proc 45.33. pg_rewrite 45.34. pg_shdepend 45.35. pg_shdescription 45.36. pg_statistic 45.37. pg_tablespace 45.38. pg_trigger 45.39. pg_ts_config 45.40. pg_ts_config_map 45.41. pg_ts_dict 45.42. pg_ts_parser 45.43. pg_ts_template 45.44. pg_type 45.45. pg_user_mapping 45.46. System Views 45.47. pg_cursors 45.48. pg_group 45.49. pg_indexes 45.50. pg_locks 45.51. pg_prepared_statements 45.52. pg_prepared_xacts 45.53. pg_roles 45.54. pg_rules 45.55. pg_settings 45.56. pg_shadow 45.57. pg_stats 45.58. pg_tables 45.59. pg_timezone_abbrevs 45.60. pg_timezone_names 45.61. pg_user 45.62. pg_user_mappings 45.63. pg_views 章46. Frontend/Backend Protocol 46.1. Overview 46.2. Message Flow 46.3. Streaming Replication Protocol 46.4. Message Data Types 46.5. Message Formats 46.6. Error and Notice Message Fields 46.7. Summary of Changes since Protocol 2.0 47. PostgreSQL Coding Conventions 47.1. Formatting 47.2. Reporting Errors Within the Server 47.3. Error Message Style Guide 章48. Native Language Support 48.1. For the Translator 48.2. For the Programmer 章49. Writing A Procedural Language Handler 章50. Genetic Query Optimizer 50.1. Query Handling as a Complex Optimization Problem 50.2. Genetic Algorithms 50.3. Genetic Query Optimization (GEQO) in PostgreSQL 50.4. Further Reading 章51. 索引访问方法接口定义 51.1. 索引的系统表记录 51.2. 索引访问方法函数 51.3. 索引扫描 51.4. 索引锁的考量 51.5. 索引唯一性检查 51.6. 索引开销估计函数 章52. GiST Indexes 52.1. Introduction 52.2. Extensibility 52.3. Implementation 52.4. Examples 52.5. Crash Recovery 章53. GIN Indexes 53.1. Introduction 53.2. Extensibility 53.3. Implementation 53.4. GIN tips and tricks 53.5. Limitations 53.6. Examples 章54. 数据库物理存储 54.1. 数据库文件布局 54.2. TOAST 54.3. 自由空间映射 54.4. 可见映射 54.5. 数据库分页文件 章55. BKI后端接口 55.1. BKI 文件格式 55.2. BKI命令 55.3. 系统初始化的BKI文件的结构 55.4. 例子 章56. 规划器如何使用统计信息 56.1. 行预期的例子 VIII. 附录 A. PostgreSQL错误代码 B. 日期/时间支持 B.1. 日期/时间输入解析 B.2. 日期/时间关键字 B.3. 日期/时间配置文件 B.4. 日期单位的历史 C. SQL关键字 D. SQL Conformance D.1. Supported Features D.2. Unsupported Features E. Release Notes Release-0-01 Release-0-02 Release-0-03 Release-1-0 Release-1-01 Release-1-02 Release-1-09 Release-6-0 Release-6-1 Release-6-1-1 Release-6-2 Release-6-2-1 Release-6-3 Release-6-3-1 Release-6-3-2 Release-6-4 Release-6-4-1 Release-6-4-2 Release-6-5 Release-6-5-1 Release-6-5-2 Release-6-5-3 Release-7-0 Release-7-0-1 Release-7-0-2 Release-7-0-3 Release-7-1 Release-7-1-1 Release-7-1-2 Release-7-1-3 Release-7-2 Release-7-2-1 Release-7-2-2 Release-7-2-3 Release-7-2-4 Release-7-2-5 Release-7-2-6 Release-7-2-7 Release-7-2-8 Release-7-3 Release-7-3-1 Release-7-3-10 Release-7-3-11 Release-7-3-12 Release-7-3-13 Release-7-3-14 Release-7-3-15 Release-7-3-16 Release-7-3-17 Release-7-3-18 Release-7-3-19 Release-7-3-2 Release-7-3-20 Release-7-3-21 Release-7-3-3 Release-7-3-4 Release-7-3-5 Release-7-3-6 Release-7-3-7 Release-7-3-8 Release-7-3-9 Release-7-4 Release-7-4-1 Release-7-4-10 Release-7-4-11 Release-7-4-12 Release-7-4-13 Release-7-4-14 Release-7-4-15 Release-7-4-16 Release-7-4-17 Release-7-4-18 Release-7-4-19 Release-7-4-2 Release-7-4-20 Release-7-4-21 Release-7-4-22 Release-7-4-23 Release-7-4-24 Release-7-4-25 Release-7-4-26 Release-7-4-27 Release-7-4-28 Release-7-4-29 Release-7-4-3 Release-7-4-30 Release-7-4-4 Release-7-4-5 Release-7-4-6 Release-7-4-7 Release-7-4-8 Release-7-4-9 Release-8-0 Release-8-0-1 Release-8-0-10 Release-8-0-11 Release-8-0-12 Release-8-0-13 Release-8-0-14 Release-8-0-15 Release-8-0-16 Release-8-0-17 Release-8-0-18 Release-8-0-19 Release-8-0-2 Release-8-0-20 Release-8-0-21 Release-8-0-22 Release-8-0-23 Release-8-0-24 Release-8-0-25 Release-8-0-26 Release-8-0-3 Release-8-0-4 Release-8-0-5 Release-8-0-6 Release-8-0-7 Release-8-0-8 Release-8-0-9 Release-8-1 Release-8-1-1 Release-8-1-10 Release-8-1-11 Release-8-1-12 Release-8-1-13 Release-8-1-14 Release-8-1-15 Release-8-1-16 Release-8-1-17 Release-8-1-18 Release-8-1-19 Release-8-1-2 Release-8-1-20 Release-8-1-21 Release-8-1-22 Release-8-1-23 Release-8-1-3 Release-8-1-4 Release-8-1-5 Release-8-1-6 Release-8-1-7 Release-8-1-8 Release-8-1-9 Release-8-2 Release-8-2-1 Release-8-2-10 Release-8-2-11 Release-8-2-12 Release-8-2-13 Release-8-2-14 Release-8-2-15 Release-8-2-16 Release-8-2-17 Release-8-2-18 Release-8-2-19 Release-8-2-2 Release-8-2-20 Release-8-2-21 Release-8-2-3 Release-8-2-4 Release-8-2-5 Release-8-2-6 Release-8-2-7 Release-8-2-8 Release-8-2-9 Release-8-3 Release-8-3-1 Release-8-3-10 Release-8-3-11 Release-8-3-12 Release-8-3-13 Release-8-3-14 Release-8-3-15 Release-8-3-2 Release-8-3-3 Release-8-3-4 Release-8-3-5 Release-8-3-6 Release-8-3-7 Release-8-3-8 Release-8-3-9 Release-8-4 Release-8-4-1 Release-8-4-2 Release-8-4-3 Release-8-4-4 Release-8-4-5 Release-8-4-6 Release-8-4-7 Release-8-4-8 Release-9-0 Release-9-0-1 Release-9-0-2 Release-9-0-3 Release-9-0-4 F. 额外提供的模块 F.1. adminpack F.2. auto_explain F.3. btree_gin F.4. btree_gist F.5. chkpass F.6. citext F.7. cube F.8. dblink Contrib-dblink-connect Contrib-dblink-connect-u Contrib-dblink-disconnect Contrib-dblink Contrib-dblink-exec Contrib-dblink-open Contrib-dblink-fetch Contrib-dblink-close Contrib-dblink-get-connections Contrib-dblink-error-message Contrib-dblink-send-query Contrib-dblink-is-busy Contrib-dblink-get-notify Contrib-dblink-get-result Contrib-dblink-cancel-query Contrib-dblink-get-pkey Contrib-dblink-build-sql-insert Contrib-dblink-build-sql-delete Contrib-dblink-build-sql-update F.9. dict_int F.10. dict_xsyn F.11. earthdistance F.12. fuzzystrmatch F.13. hstore F.14. intagg F.15. intarray F.16. isn F.17. lo F.18. ltree F.19. oid2name F.20. pageinspect F.21. passwordcheck F.22. pg_archivecleanup F.23. pgbench F.24. pg_buffercache F.25. pgcrypto F.26. pg_freespacemap F.27. pgrowlocks F.28. pg_standby F.29. pg_stat_statements F.30. pgstattuple F.31. pg_trgm F.32. pg_upgrade F.33. seg F.34. spi F.35. sslinfo F.36. tablefunc F.37. test_parser F.38. tsearch2 F.39. unaccent F.40. uuid-ossp F.41. vacuumlo F.42. xml2 G. 外部项目 G.1. 客户端接口 G.2. 过程语言 G.3. 扩展 H. The Source Code Repository H.1. Getting The Source Via Git I. 文档 I.1. DocBook I.2. 工具集 I.3. 制作文档 I.4. 文档写作 I.5. 风格指导 J. 首字母缩略词 参考书目 Bookindex Index
watak

39.6. 控制结构

控制结构可能是PL/pgSQL中最有用的(以及最重要)的部分了。 利用PL/pgSQL的控制结构,你可以以非常灵活而且强大的方法操纵PostgreSQL的数据。

39.6.1. 从函数返回

有两个命令可以用来从函数中返回数据:RETURNRETURN NEXT

39.6.1.1. RETURN

RETURN expression;

带表达式的RETURN用于终止函数并把expression的值返回给调用者。 这种形式用于不返回集合的PL/pgSQL函数。

如果返回标量类型,那么可以使用任何表达式。 表达式的类型将被自动转换成函数的返回类型,就像在赋值中描述的那样。 要返回一个复合(行)数值,你必须写一个记录或者行变量的expression

如果你声明函数带输出参数,那么就只需要写无表达式的RETURN。 那么输出参数变量的当前值将被返回。

如果你声明函数返回void,那么一个RETURN语句可以用于提前退出函数; 但是不要在RETURN后面写一个表达式。

一个函数的返回值不能是未定义。 如果控制到达了函数最顶层的块而没有碰到一个RETURN语句,那么它就会发生一个错误。 不过,这个限制不适用于带输出参数的函数以及那些返回void的函数。 在这些例子里,如果顶层的块结束,则自动执行一个RETURN语句。

39.6.1.2. RETURN NEXTRETURN QUERY

RETURN NEXT expression;
RETURN QUERY query;
RETURN QUERY EXECUTE command-string [ USING expression [, ... ] ];

如果一个PL/pgSQL函数声明为返回SETOFsometype,那么遵循的过程则略有不同。 在这种情况下,要返回的独立项是在 RETURN NEXTRETURN QUERY命令里声明的, 然后最后有一个不带参数的RETURN命令用于告诉这个函数已经完成执行了。 RETURN NEXT可以用于标量和复合数据类型;对于复合类型,将返回一个完整的结果"table"RETURN QUERY命令将一条查询的结果追加到一个函数的结果集中。 RETURN NEXTRETURN QUERY RETURN QUERY appends the results of executing a query to the function's result set. RETURN NEXT and RETURN QUERY can be freely intermixed in a single set-returning function, in which case their results will be concatenated.

RETURN NEXTRETURN QUERY实际上不会从函数中返回,它们是将0或者多个行追加到函数的结果集中。 然后执行继续执行PL/pgSQL函数里的下一条语句。 随着后继的RETURN NEXTRETURN QUERY命令的执行,结果集就建立起来了。 最后一个RETURN应该没有参数, 它导致控制退出该函数(或者你可以简单地让控制到达函数的结尾)。

RETURN QUERY has a variant RETURN QUERY EXECUTE, which specifies the query to be executed dynamically. Parameter expressions can be inserted into the computed query string via USING, in just the same way as in the EXECUTE command.

If you declared the function with output parameters, write just RETURN NEXT with no expression. On each execution, the current values of the output parameter variable(s) will be saved for eventual return as a row of the result. Note that you must declare the function as returning SETOF record when there are multiple output parameters, or SETOF sometype when there is just one output parameter of type sometype, in order to create a set-returning. function with output parameters. 如果你声明函数带有输出参数,那么就只需要写不带表达式的 RETURN NEXT 。 输出参数的当前值将被保存,用于最终返回。 请注意如果有多个输出参数, 比如声明函数为返回 SETOF record 或者是在只有一个类型为 sometype 的输出参数时声明为 SETOF sometype , 这样才能创建一个带有输出参数的返回集合的函数。

下面是一个使用RETURN NEXT的函数例子:

CREATE TABLE foo (fooid INT, foosubid INT, fooname TEXT);
INSERT INTO foo VALUES (1, 2, 'three');
INSERT INTO foo VALUES (4, 5, 'six');

CREATE OR REPLACE FUNCTION getAllFoo() RETURNS SETOF foo AS
$body$
DECLARE
    r foo%rowtype;
BEGIN
    FOR r IN SELECT * FROM foo
    WHERE fooid > 0
    LOOP
        -- can do some processing here
        RETURN NEXT r; -- return current row of SELECT
    END LOOP;
    RETURN;
END
$body$
LANGUAGE 'plpgsql' ;

SELECT * FROM getallfoo();

Note: 目前RETURN NEXTRETURN QUERY实现在从函数返回之前把整个结果集都保存起来,就像上面描述的那样。 这意味着如果一个PL/pgSQL函数生成一个非常大的结果集,性能可能会很差: 数据将被写到磁盘上以避免内存耗尽,但是函数在完成整个结果集的生成之前不会退出。 将来的PL/pgSQL版本可能会允许用户定义没有这样限制的返回集合的函数。 目前,数据开始向磁盘里写的时刻是由配置变量work_mem控制的。 拥有足够内存的管理员如果想在内存里存储更大的结果集,则可以考虑把这个参数增大一些。

39.6.2. 条件

IFCASE语句让你可以根据某种条件执行命令。PL/pgSQL有三种形式的IF

  • IF ... THEN

  • IF ... THEN ... ELSE

  • IF ... THEN ... ELSIF ... THEN ... ELSE

以及两种形式的CASE:

  • CASE ... WHEN ... THEN ... ELSE ... END CASE

  • CASE WHEN ... THEN ... ELSE ... END CASE

39.6.2.1. IF-THEN

IF boolean-expression THEN
    statements
END IF;

IF-THEN语句是IF的最简单形式。 如果条件为真,在THENEND IF之间的语句将被执行。 否则,将忽略它们。

例子:

IF v_user_id <> 0 THEN
    UPDATE users SET email = v_email WHERE user_id = v_user_id;
END IF;

39.6.2.2. IF-THEN-ELSE

IF boolean-expression THEN
    statements
ELSE
    statements
END IF;

IF-THEN语句增加了add to,你可以声明在条件为假的时候执行的语句(包括条件为NULL的情况)。

例子:

IF parentid IS NULL OR parentid = ''
THEN
    RETURN fullname;
ELSE
    RETURN hp_true_filename(parentid) || '/' || fullname;
END IF;

IF v_count > 0 THEN
    INSERT INTO users_count (count) VALUES (v_count);
    RETURN 't';
ELSE
    RETURN 'f';
END IF;

39.6.2.3. IF-THEN-ELSIF

IF boolean-expression THEN
    statements
[ ELSIF boolean-expression THEN
    statements
[ ELSIF boolean-expression THEN
    statements
    ...]]
[ ELSE
    statements ]
END IF;

有时不知两个选择。IF-THEN-ELSIF反过来提供了一个简便的方法来检查选择条件。 IF判断会陆续检查,直到找到第一个为真的,然后执行相关声明,如此,直到END IF(不会检测IF子查询)。 如果没有一个条件符合IF判断,那么会接着执行ELSE判断。

例子:

IF number = 0 THEN
    result := 'zero';
ELSIF number > 0 THEN
    result := 'positive';
ELSIF number < 0 THEN
    result := 'negative';
ELSE
    -- hmm, the only other possibility is that number is null
    result := 'NULL';
END IF;

ELSIF关键字也可以写成ELSEIF.

另一个可以实现该目的的方法是使用IF-THEN-ELSE声明,如下:

IF demo_row.sex = 'm' THEN
    pretty_sex := 'man';
ELSE
    IF demo_row.sex = 'f' THEN
        pretty_sex := 'woman';
    END IF;
END IF;

然而,这个方法需要为每个IFEND IF,因此当有很多选择时,这种方法明显比ELSIF繁琐。

39.6.2.4. Simple CASE

CASE search-expression
    WHEN expression [, expression [ ... ]] THEN
      statements
  [ WHEN expression [, expression [ ... ]] THEN
      statements
    ... ]
  [ ELSE
      statements ]
END CASE;

The simple form of CASE provides conditional execution based on equality of operands. The search-expression is evaluated (once) and successively compared to each expression in the WHEN clauses. If a match is found, then the corresponding statements are executed, and then control passes to the next statement after END CASE. (Subsequent WHEN expressions are not evaluated.) If no match is found, the ELSE statements are executed; but if ELSE is not present, then a CASE_NOT_FOUND exception is raised.

例如:

CASE x
    WHEN 1, 2 THEN
        msg := 'one or two';
    ELSE
        msg := 'other value than one or two';
END CASE;

39.6.2.5. Searched CASE

CASE
    WHEN boolean-expression THEN
      statements
  [ WHEN boolean-expression THEN
      statements
    ... ]
  [ ELSE
      statements ]
END CASE;

The searched form of CASE provides conditional execution based on truth of Boolean expressions. Each WHEN clause's boolean-expression is evaluated in turn, until one is found that yields true. Then the corresponding statements are executed, and then control passes to the next statement after END CASE. (Subsequent WHEN expressions are not evaluated.) If no true result is found, the ELSE statements are executed; but if ELSE is not present, then a CASE_NOT_FOUND exception is raised.

Here is an example:

CASE
    WHEN x BETWEEN 0 AND 10 THEN
        msg := 'value is between zero and ten';
    WHEN x BETWEEN 11 AND 20 THEN
        msg := 'value is between eleven and twenty';
END CASE;

This form of CASE is entirely equivalent to IF-THEN-ELSIF, except for the rule that reaching an omitted ELSE clause results in an error rather than doing nothing.

39.6.3. 简单循环

使用LOOP, EXIT,CONTINUE, WHILE,HE FOR语句, 可以控制PL/pgSQL函数重复一系列命令。

39.6.3.1. 循环

[ <<label>> ]
LOOP
    statements
END LOOP [ label ];

LOOP定义一个无条件的循环,无限循环,直到由EXITRETURN语句终止。 可选的label可以由EXITCONTINUE语句使用,用于在嵌套循环中声明应该应用于哪一层循环。

39.6.3.2. 退出

EXIT [ label ] [ WHEN boolean-expression ];

如果没有给出label,那么退出最内层的循环,然后执行跟在END LOOP后面的语句。 如果给出label,那么它必须是当前或者更高层的嵌套循环块或者语句块的标签。 然后该命名块或者循环就会终止,而控制落到对应循环/块的END语句后面的语句上。

如果声明了WHEN,循环退出只有在boolean-expression为真的时候才发生, 否则控制会落到EXIT后面的语句上。

EXIT可以用于在所有的循环类型中,它并不仅仅限制于在无条件循环中使用。

在和BEGIN块一起使用的时候,EXIT把控制交给块结束后的下一个语句。 需要注意的是,一个标签必须用于这个目的;一个没有标记的EXIT永远无法与BEGIN进行匹配。

例如:

LOOP
    -- some computations
    IF count > 0 THEN
        EXIT;  -- exit loop
    END IF;
END LOOP;

LOOP
    -- some computations
    EXIT WHEN count > 0;  -- same result as previous example
END LOOP;

<<ablock>>
BEGIN
    -- some computations
    IF stocks > 100000 THEN
        EXIT ablock;  -- causes exit from the BEGIN block
    END IF;
    -- computations here will be skipped when stocks > 100000
END;

39.6.3.3. CONTINUE

CONTINUE [ label ] [ WHEN boolean-expression ];

如果没有给出label,那么就开始最内层循环的下一次执行。 也就是说,控制传递回给循环控制表达式(如果有),然后重新计算循环体。 如果出现了label,它声明即将继续执行的循环的标签。

如果声明了WHEN,那么循环的下一次执行只有在boolean-expression为真的情况下才进行。 否则,控制传递给CONTINUE后面的语句。

CONTINUE可以用于所有类型的循环;它并不仅仅限于无条件循环。

例如:

LOOP
    -- 一些计算
    EXIT WHEN count > 100;
    CONTINUE WHEN count < 50;
    -- 一些count数值在[50 .. 100]之间的计算

END LOOP;

39.6.3.4. WHILE

[ <<label>> ]
WHILE boolean-expression LOOP
    statements
END LOOP [ label ];

只要条件表达式(boolean-expression)为真,WHILE语句就会不停的在一系列语句上进行循环, 条件是在每次进入循环体的时候检查的。

例如:

WHILE amount_owed > 0 AND gift_certificate_balance > 0 LOOP
    -- some computations here
END LOOP;

WHILE NOT done LOOP
    -- some computations here
END LOOP;

39.6.3.5. FOR (integer variant)

[ <<label>> ]
FOR name IN [ REVERSE ] expression .. expression [ BY expression ] LOOP
    statements
END LOOP [ label ];

这种形式的FOR对一定范围的整数进行迭代的循环。 变量name会自动定义为integer类型并且只在循环里存在(任何该变量名的现存定义在此循环内都将被忽略)。 给出范围上下界的两个表达式在进入循环的时候计算一次。 BY子句指定迭代步长(缺省为 1),但如果声明了REVERSE步长将变为相应的负值。

一些整数 FOR 循环的例子:

FOR i IN 1..10 LOOP
    -- i will take on the values 1,2,3,4,5,6,7,8,9,10 within the loop
END LOOP;

FOR i IN REVERSE 10..1 LOOP
    -- i will take on the values 10,9,8,7,6,5,4,3,2,1 within the loop
END LOOP;

FOR i IN REVERSE 10..1 BY 2 LOOP
    -- i will take on the values 10,8,6,4,2 within the loop
END LOOP;

如果下界大于上界(或者是在REVERSE情况下是小于),那么循环体将完全不被执行。 而且不会抛出任何错误。

If a label is attached to the FOR loop then the integer loop variable can be referenced with a qualified name, using that label.

39.6.4. 遍历命令结果

使用不同类型的FOR循环,你可以遍历一个命令的结果并且对其进行相应的操作。 语法是:

[ <<label>> ]
FOR target IN query LOOP
    statements
END LOOP [ label ];

target是一个记录变量、行变量、逗号分隔的标量变量列表 target被连续不断被赋予所有来自query的行,并且循环体将为每行执行一次。 下面是一个例子:

CREATE FUNCTION cs_refresh_mviews() RETURNS integer AS $$
DECLARE
    mviews RECORD;
BEGIN
    PERFORM cs_log('Refreshing materialized views...');

    FOR mviews IN SELECT * FROM cs_materialized_views ORDER BY sort_key LOOP

        -- 现在"mviews"里有了一条来自 cs_materialized_views 的记录 

        PERFORM cs_log('Refreshing materialized view '
                   || quote_ident(mviews.mv_name) || ' ...');
        EXECUTE 'TRUNCATE TABLE ' || quote_ident(mviews.mv_name);
        EXECUTE 'INSERT INTO '
                   || quote_ident(mviews.mv_name) || ' ' 
                   || mviews.mv_query;
    END LOOP;

    PERFORM cs_log('Done refreshing materialized views.');
    RETURN 1;
END;
$$ LANGUAGE plpgsql;

如果循环是用一个EXIT语句终止的,那么在循环之后你仍然可以访问最后赋值的行

FOR语句中使用的这种query可以是任何返回行的SQL命令, 通常是SELECT,不过带有RETURNING子句的INSERT, UPDATE,或DELETE也是可以的, 一些诸如EXPLAIN之类的命令也可以

PL/pgSQL variables are substituted into the query text, and the query plan is cached for possible re-use, as discussed in detail in Section 39.10.1 and Section 39.10.2. PL/pgSQL变量 正如在Section 39.10.1和Section 39.10.2中讨论的那样。

FOR-IN-EXECUTE语句是遍历所有行的另外一种方法:

[ <<label>> ]
FOR target IN EXECUTE text_expression [ USING expression [, ... ] ] LOOP
    statements
END LOOP [ label ];

这个例子类似前面的形式,只不过源查询语句声明为了一个字符串表达式, 这样它在每次进入FOR循环的时候都会重新计算和生成执行计划。 这样就允许程序员在一个预先规划好了的命令所获得的速度和一个动态命令所获得的灵活性 (就像一个简单的EXECUTE语句那样)之间进行选择。 当使用EXECUTE时,可以通过USING将参数值插入到动态命令中。

对于一个需要将结果迭代的查询,另外一个声明的方法是将它定义为游标(cursor),可参阅Section 39.7.4。

39.6.5. Trapping Errors捕获错误

缺省时,一个在PL/pgSQL函数里发生的错误退出函数的执行, 并且实际上其周围的事务也会退出。 你可以使用一个带有EXCEPTION子句的BEGIN块捕获错误并且从中恢复。 其语法是正常的BEGIN块语法的一个扩展:

[ <<label>> ]
[ DECLARE
    declarations ]
BEGIN
    statements
EXCEPTION
    WHEN condition [ OR condition ... ] THEN
        handler_statements
    [ WHEN condition [ OR condition ... ] THEN
          handler_statements
      ... ]
END;

如果没有发生错误,这种形式的块只是简单地执行所有statements, 然后转到下一个END之后的语句。 但是如果在statements内部发生了一个错误,则对statements的进一步处理将废弃, 然后转到 EXCEPTION 列表。 系统搜索这个列表,寻找匹配错误的第一个condition。 如果找到匹配,则执行对应的handler_statements,然后转到END之后的下一个语句。 如果没有找到匹配,该错误就会广播出去, 就好像根本没有EXCEPTION子句一样:该错误可以被一个包围块用EXCEPTION捕获, 如果没有包围块,则退出函数的处理。

condition的名字可以是 附录A里显示的任何名字。 一个范畴名匹配任意该范畴里的错误。 特殊的条件名OTHERS匹配除了QUERY_CANCELED之外的所有错误类型。 可以用名字捕获QUERY_CANCELED,不过通常是不明智的。条件名是大小写无关的。 同时也可以通过SQLSTATE来声明一个错误条件,例如:

WHEN division_by_zero THEN ...
WHEN SQLSTATE '22012' THEN ...

如果在选中的handler_statements里发生了新错误, 那么它不能被这个EXCEPTION子句捕获,而是传播出去。 一个外层的EXCEPTION子句可以捕获它。

如果一个错误被EXCEPTION捕获,PL/pgSQL函数的局部变量保持错误发生时的原值, 但是所有该块中想固化在数据库中的状态都回滚。 作为一个例子,让我们看看下面片断

INSERT INTO mytab(firstname, lastname) VALUES('Tom', 'Jones');
BEGIN
    UPDATE mytab SET firstname = 'Joe' WHERE lastname = 'Jones';
    x := x + 1;
    y := x / 0;
EXCEPTION
    WHEN division_by_zero THEN
        RAISE NOTICE 'caught division_by_zero';
        RETURN x;
END;

当控制到达给y赋值的地方时,它会带着一个division_by_zero错误失败。 这个错误将被EXCEPTION子句捕获。 而在RETURN语句里返回的数值将是x的增量值。 但是UPDATE已经被回滚。然而,在该块之前的INSERT将不会回滚, 因此最终的结果是数据库包含Tom Jones而不是Joe Jones

Tip: 进入和退出一个包含EXCEPTION子句的块要比不包含的块开销大的多。 因此,不必要的时候不要使用EXCEPTION

在异常处理器中,SQLSTATE变量包含抛出错误对应的错误代码(参考Table A-1获取可能的错误码的列表)。 SQLSTATE变量包含与异常关联的错误信息。 这些变量在异常处理器外面是未定义的。

Example 39-2. UPDATE/INSERT异常

这个例子根据使用异常处理器执行恰当的UPDATEINSERT

CREATE TABLE db (a INT PRIMARY KEY, b TEXT);

CREATE FUNCTION merge_db(key INT, data TEXT) RETURNS VOID AS
$$
BEGIN
    LOOP
        -- first try to update the key
        UPDATE db SET b = data WHERE a = key;
        IF found THEN
            RETURN;
        END IF;
        -- not there, so try to insert the key
        -- if someone else inserts the same key concurrently,
        -- we could get a unique-key failure
        BEGIN
            INSERT INTO db(a,b) VALUES (key, data);
            RETURN;
        EXCEPTION WHEN unique_violation THEN
            -- do nothing, and loop to try the UPDATE again
        END;
    END LOOP;
END;
$$
LANGUAGE plpgsql;

SELECT merge_db(1, 'david');
SELECT merge_db(1, 'dennis');

Artikel sebelumnya: Artikel seterusnya: