I. 教程
II. SQL 语言
III. 服务器管理
- 章14. 安装指导
- 章15. 在 Windows 上安装客户端
- 章16. 操作系统环境
- 章17. 服务器配置
- 章18. 数据库角色和权限
- 章19. 管理数据库
- 章21. 区域
- 章20. 用户认证
- 章22. 日常数据库维护工作
- 章23. 备份与恢复
- 章24. 高可用性与负载均衡
- 章25. 监控数据库的活动
- 章26. 监控磁盘使用情况
- 章27. 可靠性和预写式日志
- 章28. 回归测试
IV. 客户端接口
- Chapter 28. libpq - C 库
- 章29.
- Chapter 30. ecpg - 在 C 里嵌入 SQL
- Chapter 31. 信息模式
- 31.2. 数据类型
- 31.3. informationschemacatalog_name
- 31.4. applicable_roles
- 31.5. check_constraints
- 31.6. columndomainusage
- 31.7. column_privileges
- 31.8. columnudtusage
- 31.9. columns
- 31.10. constraintcolumnusage
- 31.11. constrainttableusage
- 31.12. datatypeprivileges
- 31.13. domain_constraints
- 31.14. domainudtusage
- 31.15. domains
- 31.16. element_types
- 31.17. enabled_roles
- 31.18. keycolumnusage
- 31.20. referential_constraints
- 31.21. rolecolumngrants
- 31.22. roleroutinegrants
- 31.23. roletablegrants
- 31.24. roleusagegrants
- 31.25. routine_privileges
- 31.26. routines
- 31.27. schemata
- 31.28. sql_features
- 31.29. sqlimplementationinfo
- 31.30. sql_languages
- 31.31. sql_packages
- 31.32. sql_sizing
- 31.33. sqlsizingprofiles
- 31.34. table_constraints
- 31.35. table_privileges
- 31.36. tables
- 31.37. triggers
- 31.38. usage_privileges
- 31.39. viewcolumnusage
- 31.40. viewtableusage
- 31.41. views
V. 服务器端编程
- 章33. 扩展 SQL
- 章34. 触发器
- 章35. 规则系统
- 章36. 过程语言
- 章37. PL/pgSQL - SQL 过程语言
- 章38. PL/Tcl - Tcl 过程语言
- 章39. PL/Perl - Perl 过程语言
- 章40. PL/Python - Python 过程语言
- 章41. 服务器编程接口
VI. 参考手册
- I. SQL 命令
- ABORT
- ALTER AGGREGATE
- ALTER CONVERSION
- ALTER DATABASE
- ALTER DOMAIN
- ALTER FUNCTION
- ALTER GROUP
- ALTER INDEX
- ALTER LANGUAGE
- ALTER OPERATOR
- ALTER OPERATOR CLASS
- ALTER ROLE
- ALTER SCHEMA
- ALTER SEQUENCE
- ALTER TABLE
- ALTER TABLESPACE
- ALTER TRIGGER
- ALTER TYPE
- ALTER USER
- ANALYZE
- BEGIN
- CHECKPOINT
- CLOSE
- CLUSTER
- COMMENT
- COMMIT PREPARED
- COMMIT
- COPY
- CREATE AGGREGATE
- CREATE CAST
- CREATE CONSTRAINT TRIGGER
- CREATE CONVERSION
- CREATE DATABASE
- CREATE DOMAIN
- CREATE FUNCTION
- CREATE GROUP
- CREATE INDEX
- CREATE LANGUAGE
- CREATE OPERATOR CLASS
- CREATE OPERATOR
- CREATE ROLE
- CREATE RULE
- CREATE SCHEMA
- CREATE SEQUENCE
- CREATE TABLE
- CREATE TABLE AS
- CREATE TABLESPACE
- CREATE TRIGGER
- CREATE TYPE
- CREATE USER
- CREATE VIEW
- DEALLOCATE
- DECLARE
- DELETE
- DROP OWNED
- DROP AGGREGATE
- DROP CAST
- DROP CONVERSION
- DROP DATABASE
- DROP DOMAIN
- DROP FUNCTION
- DROP GROUP
- DROP INDEX
- DROP LANGUAGE
- DROP OPERATOR CLASS
- DROP OPERATOR
- DROP ROLE
- DROP RULE
- DROP SCHEMA
- DROP SEQUENCE
- DROP TABLE
- DROP TABLESPACE
- DROP TRIGGER
- DROP TYPE
- DROP USER
- DROP VIEW
- END
- EXECUTE
- EXPLAIN
- FETCH
- GRANT
- INSERT
- LISTEN
- LOAD
- LOCK
- MOVE
- NOTIFY
- PREPARE TRANSACTION
- PREPARE
- REASSIGN OWNED
- REINDEX
- RELEASE SAVEPOINT
- RESET
- REVOKE
- ROLLBACK PREPARED
- ROLLBACK TO SAVEPOINT
- ROLLBACK
- SAVEPOINT
- SELECT
- SELECT INTO
- SET
- SET CONSTRAINTS
- SET ROLE
- SET SESSION AUTHORIZATION
- SET TRANSACTION
- SHOW
- START TRANSACTION
- TRUNCATE
- UNLISTEN
- UPDATE
- VACUUM
- II. PostgreSQL 客户端应用程序
- III. PostgreSQL 服务器应用程序
VII. 内部
- 章42. PostgreSQL 内部概貌
- 章43. 系统表
- 43.1. 概述
- 43.2. pg_aggregate
- 43.3. pg_am
- 43.4. pg_amop
- 43.5. pg_amproc
- 43.6. pg_attrdef
- 43.7. pg_attribute
- 43.8. pg_authid
- 43.9. pgauthmembers
- 43.10. pg_autovacuum
- 43.11. pg_cast
- 43.12. pg_class
- 43.13. pg_constraint
- 43.14. pg_conversion
- 43.15. pg_database
- 43.16. pg_depend
- 43.17. pg_description
- 43.18. pg_index
- 43.19. pg_inherits
- 43.20. pg_language
- 43.21. pg_largeobject
- 43.22. pg_listener
- 43.23. pg_namespace
- 43.24. pg_opclass
- 43.25. pg_operator
- 43.26. pg_pltemplate
- 43.27. pg_proc
- 43.28. pg_rewrite
- 43.29. pg_shdepend
- 43.30. pg_shdescription
- 43.31. pg_statistic
- 43.32. pg_tablespace
- 43.33. pg_trigger
- 43.34. pg_type
- 43.35. 系统视图
- 43.36. pg_cursors
- 43.37. pg_group
- 43.38. pg_indexes
- 43.39. pg_locks
- 43.40. pgpreparedstatements
- 43.41. pgpreparedxacts
- 43.42. pg_roles
- 43.43. pg_rules
- 43.44. pg_settings
- 43.45. pg_shadow
- 43.46. pg_stats
- 43.47. pg_tables
- 43.48. pgtimezoneabbrevs
- 43.49. pgtimezonenames
- 43.50. pg_user
- 43.51. pg_views
- 章44. 前/后端协议
- 章45. PostgreSQL 编码约定
- 章46. 本地语言支持
- 章47. 书写一个过程语言处理器
- 章48. 基因查询优化器
- 章49. 索引访问方法接口定义
- 章50. GiST 索引
- 章51. GIN 索引
- 章52. 数据库物理存储
- 章53. BKI 后端接口
- 章54. 规划器如何使用统计信息
VIII. 附录
28.8. 与COPY命令相关的函数
PostgreSQL 里的 COPY
命令里有用于 libpq 里从网络连接读出或者写入的选项。本节描述的函数允许应用通过提供或者消耗拷贝数据,充分利用这个功能。
整个过程是应用首先通过PQexec
或者一个等效的函数发出 SQL COPY
命令。 对这个命令的相应(如果命令无误)将是一个带着状态码 PGRES_COPY_OUT
或者PGRES_COPY_IN
的 PGresult
(具体根据声明的拷贝方向)。应用然后就应该使用本节的函数接受或者发送数据行。在数据传输结束之后,返回另外一个 PGresult
对象以表明传输的成功或者失败。它的状态将是 PGRES_COMMAND_OK
表示成功或者如果发生了一些问题,是 PGRES_FATAL_ERROR
。这个时候开始我们可以通过PQexec
发出更多 SQL 命令。(在 COPY
操作在处理的过程中,我们不可能用同一个连接执行其它 SQL 命令。
如果一个 COPY
是通过PQexec
在一个可以包含额外命令的字串里发出的,那么应用在完成 COPY
序列之后必须继续用PQgetResult
抓取结果。只有在PQgetResult
返回 NULL
的时候,我们才能确信PQexec
的命令字串已经处理完毕,并且已经可以安全地发出更多命令。
本节地这些函数应该只在从PQexec
或PQgetResult
获得了 PGRES_COPY_OUT
或 PGRES_COPY_IN
结果状态的情况下执行。
一个承载了这些状态值之一地 PGresult
对象运载了某些有关正在开始地 COPY
操作的额外信息。这些额外的数据可以用那些同时也处理查询结果的函数获取。
PQnfields
返回要拷贝的字段(数据域)个数。
PQbinaryTuples
0 表示全部拷贝格式都是文本的(行之间用换行分隔,字段用分隔符分隔,等等)。1 表示全部拷贝格式都是二进制。参阅COPY 获取更多信息。
PQfformat
返回和拷贝操作的每个字段相关的格式代码(0 是文本,1 是二进制)。 如果全部拷贝格式是文本,那么每字段的格式码将总是零,但是(总体)二进制格式可以支持文本和二进制字段并存。 (不过,就目前的
COPY
实现,在二进制拷贝里只出现二进制字段; 所以目前每字段的格式总是匹配纵起格式。)
注意:这些额外的数据值只能在使用 3.0 版本的协议的时候获得。在使用 2.0 版本的协议时,所有这些函数都返回 0。
28.8.1. 用于发送 COPY
数据的函数
这些函数用于在 COPY FROM STDIN
过程中发送数据。 如果在连接不是处于 COPY_IN
状态下,它们会失败。
PQputCopyData
在
COPY_IN
状态期间向服务器发送数据。int PQputCopyData(PGconn *conn, const char *buffer, int nbytes);
传输指定的
buffer
里的,长度为nbytes
的COPY
数据到服务器。如果数据发送成功,结果是 1,如果因为发送企图会阻塞(这种情况只有在连接是非阻塞模式时才有可能)而没有成功,那么是零,或者是在发生错误的时候是 -1。(如果返回 -1,那么使用PQerrorMessage
检索细节。如果值是零,那么等待写准备好然后重试。)应用可以把
COPY
数据流分隔成任意合适的大小放到缓冲区里。在发送的时候,缓冲区的边界没有什么特殊的语意。数据流的内容必须匹配COPY
命令预期的数据格式;参阅COPY 获取细节。PQputCopyEnd
在
COPY_IN
状态里向服务器发送数据完毕的指示。int PQputCopyEnd(PGconn *conn, const char *errormsg);
如果
errormsg
是NULL
,则成功结束COPY_IN
操作。如果errormsg
不是NULL
则COPY
操作被强制失败,errormsg
指向的字串是错误信息。(我们不能认为同样的信息可能会从服务器传回,因为服务器可能已经因为自己的原因让COPY
失败。还要注意的是在使用 3.0 版本之前的协议连接时,强制失败的选项是不能用的。)如果终止数据发送,则结果为 1,如果发送企图会阻塞(只有在连接是在非阻塞模式的情况下才可能出现这个情况),则为零,如果发生错误则返回 -1。(如果返回值是 -1,用
PQerrorMessage
检索细节。如果值是零,那么等待写准备好然后重新尝试。)在成功调用
PQputCopyEnd
之后,调用PQgetResult
获取COPY
命令的最终结果状态。我们可以用平常的方法来等待这个结果可用。然后返回到正常的操作。
28.8.2. 用于接收 COPY
数据的函数
这些函数用于在 COPY TO STDOUT
的过程中检索数据。 如果连接不在 COPY_OUT
状态,那么他们将会失败。
PQgetCopyData
在
COPY_OUT
状态下从服务器接收数据。int PQgetCopyData(PGconn *conn, char **buffer, int async);
在一个
COPY
的过程中试图获取另外一行数据。数据总是每次返回一个数据行;如果只有一行的部分可用,那么它不会被返回。成功返回一个数据行包括分配一个内存块来保存这些数据。buffer
参数必须是非NULL
。*buffer
设置为指向分配出来的内存的指针,或者是如果没有返回缓冲区,那么为NULL
。一个非NULL
的结果缓冲区在不再需要的时候必须用PQfreemem
释放。在成功返回一行之后,那么返回的值就是该数据行里数据的字节数(这个将总是大于零)。返回的字串总是空结尾的,虽然可能只是对文本的
COPY
有用。一个零的结果表示该COPY
仍然在处理中,但是还没有可以用的行(这个只有在async
为真的时候才可能)。一个结果为 -1 的值表示COPY
已经结束。结果为 -2 表示发生了错误(参考PQerrorMessage
获取原因)。在
async
为真的时候(非零),PQgetCopyData
将不会阻塞住等待输入;如果该COPY
仍在处理过程中并且没有可用的完整行,那么它将返回零。(在这种情况下它等待读准备好,然后在再次调用PQgetCopyData
之前,调用PQconsumeInput
。)在async
是假(零)的时候,PQgetCopyData
将阻塞住,知道有可用的数据或者操作完成。在
PQgetCopyData
返回 -1 之后,调用PQgetResult
获取COPY
命令的最后结果状态。我们可以用通常的方法等待这个结果可用。然后返回到正常操作。
28.8.3. 用于 COPY
的废弃的函数
下面的这些函数代表了以前的处理 COPY
的方法。 尽管他们还能用,但是现在已经废弃了,因为他们的错误处理实在是太糟糕了, 并且检测数据结束的方法也很不方便,并且缺少对二进制何非阻塞传输的支持。
PQgetline
读取一个以新行符结尾的字符行中指定字节数的字符(由服务器服务器传输)到一个长度为
length
的字符串缓冲区。int PQgetline(PGconn *conn, char *buffer, int length);
这个函数拷贝最多
length
-1 个字符到缓冲区里,然后把终止的新行符转换成一个字节零。PQgetline
在输入结束时返回EOF
,如果整行都被读取了返回 0,如果缓冲区填满了而还没有遇到结束的新行符则返回 1。注意,应用程序必须检查新行是否包含两个字符
\.
,这表明服务器服务器已经完成了COPY
命令的结果的发送。如果应用可能收到超过length
-1 字符长的字符,我们就应该确保正确识别\.
行(例如,不要把一个长的行的结束当作一个终止行)。PQgetlineAsync
不做阻塞地读取一行
COPY
数据(由服务器服务器传输)到一个缓冲区中。int PQgetlineAsync(PGconn *conn, char *buffer, int bufsize);
这个函数类似于
PQgetline
,但是可以用于那些必须异步地读取COPY
数据的应用,也就是不阻塞的应用。在使用了COPY
命令和获取了PGRES_COPY_OUT
响应之后,应用应该调用PQconsumeInput
和PQgetlineAsync
直到收到数据结束的信号。不象
PQgetline
,这个函数负责检测数据结束。在每次调用时,如果libpq的输入缓冲区内有可用的一个完整的换行符结尾的数据行,
PQgetlineAsync
都将返回数据。否则,在其他数据到达之前不会返回数据。如果见到了拷贝数据结束的标志,此函数返回 -1,如果没有可用数据返回 0,或者是给出一个正数表明返回的数据的字节数。如果返回 -1,调用者下一步必须调用PQendcopy
,然后回到正常处理。返回的数据将不超过一行的范围。如果可能,每次将返回一个完整行。但如果调用者提供的缓冲区太小,无法容下服务器发出的整行,那么将返回部分行。这个可以通过测试返回的最后一个字节是否
\n
来确认。在二进制 COPY 中,我们需要对 COPY 数据格式进行实际的分析,以便做相同的判断。)返回的字符串不是空结尾的。(如果你想得到一个空结尾的字串,确保你传递了一个比实际可用空间少一字节的bufsize
。)PQputline
向服务器服务器发送一个空结尾的字符串。成功时返回 0,如果不能发送字符串返回
EOF
。int PQputline(PGconn *conn, const char *string);
一系列
PQputline
调用发送的 COPY 数据流和PQgetlineAsync
返回的数据有着一样的格式,只是应用不需要明确地在每次PQputline
调用中发送一个数据行;我们每次调用里发送多行或者部分行都是可以的。注意:在 PostgreSQL 3.0 版本的协议之前,应用必须明确地发送两个字符
\.
给服务器,告诉服务器它已经完成 COPY 数据的发送。虽然这么做仍然有效,但是已经废弃了,\.
的特殊含义可能在将来的版本中删除。在发送完实际数据之后,调用PQendcopy
就足够了。PQputnbytes
向服务器服务器发送一个非空结尾的字符串。成功时返回 0,如果不能发送字符串返回
EOF
。int PQputnbytes(PGconn *conn,const char *buffer,int nbytes);
此函数类似
PQputline
,除了数据缓冲区不需要是空结尾的之外,因为要发送的字节数是直接声明的。在发送二进制数据的时候使用这个过程。PQendcopy
与服务器同步。
int PQendcopy(PGconn *conn);
这个函数等到服务器完成拷贝(才返回?)。你可以在用
PQputline
向服务器发送完最后一个字符串后或者用PGgetline
从服务器获取最后一行字符串后调用它。我们必须调用这个函数,否则服务器可能会和前端"同步丢失"。在这个函数返回后,服务器就已经准备好接收下一个 SQL 命令了。成功时返回0,否则返回非零值。(如果返回值为非 0,用PQerrorMessage
检索细节。)在使用
PQgetResult
时,应用应该对PGRES_COPY_OUT
的结果做出反应:重复调用PQgetline
,并且在收到结束行时调用PQendcopy
。然后应该返回到PQgetResult
循环直到PQgetResult
返回 NULL。类似地,PGRES_COPY_IN
结果是用一系列PQputline
调用最后跟着PQendcopy
,然后返回到PQgetResult
循环。这样的排列将保证嵌入到一系列 SQL命令里的COPY
命令将被正确执行。旧的应用大多通过
PQexec
提交一个COPY
命令并且假设在PQendcopy
后事务完成。这样只有在COPY
是命令字串里的唯一的SQL 命令时才能正确工作。
Prev | Home | Next |
异步通知 | Up | 控制函数 |
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论