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.3. 命令执行函数
一旦与数据库服务器的连接成功建立,便可用这里描述的函数执行 SQL 查询和命令。
28.3.1. 主函数
PQexec
给服务器提交一条命令并且等待结果。
PGresult *PQexec(PGconn *conn, const char *command);
返回一个
PGresult
指针或者也可能是一个 NULL 指针。通常返回一个非空(non-NULL)的指针,除非没有内存或发生了象不能把命令发送到服务器这样的严重错误。如果返回的是 NULL,它应该被当作PGRES_FATAL_ERROR
结果处理。用PQerrorMessage
获取有关错误的更多信息。
我们可以在命令行字串里包含多个 SQL 命令(用分号分隔)。在一次PQexec
调用中发送的多个查询是在一个事务里处理的,除非在查询字串里有明确的 BEGIN
/COMMIT
命令用于把整个字串分隔成多个事务。请注意这样返回的 PGresult
结构只描述字串里执行的最后一条命令的结果。如果有一个命令失败,那么字串处理的过程就会停止并且返回的 PGresult
会描述错误条件。
PQexecParams
向服务器提交一条命令并且等待结果,还有额外的传递与 SQL 命令文本独立的参数的能力。
PGresult *PQexecParams(PGconn *conn, const char *command, int nParams, const Oid *paramTypes, const char * const *paramValues, const int *paramLengths, const int *paramFormats, int resultFormat);
PQexecParams
类似PQexec
,但是提供了额外的功能:参数值可以独立于命令串进行声明,并且可以要求查询结果的格式是文本或者二进制格式。PQexecParams
只是在协议 3.0 以及以后的版本中支持;在使用 2.0 的版本的时候会失败。如果使用了参数,那么它们是以
$1
,$2
,等等在命令字串中引用的。nParams
是提供的参数的个数;它是数组paramTypes[]
,paramValues[]
,paramLengths[]
,和paramFormats[]
的长度。(如果nParams
是零,那么数组指针可以是NULL
。)paramTypes[]
用 OID 的形式声明了赋与参数符号的数据类型。如果paramTypes
是NULL
,或者数组中任意元素是零,那么服务器给对应的参数符号赋与和无类型文本串一样的数据类型。paramValues[]
声明该参数的实际数值。这个数组中的空指针意味着对应的参数是空;否则,这个指针指向一个空零结尾的文本字串(文本格式)或者服务器期待的格式的二进制数据(用于二进制格式)。paramLengths[]
声明二进制格式参数的实际数据长度。对于空参数和文本格式的参数会忽略这个参数。如果没有二进制参数,那么这个数组指针可以是空。paramFormats[]
声明某个参数是文本(在数组中放一个零)还是二进制(在数组中放一个1)。如果这个数组指针是空,那么所有参数都认为是文本的。resultFormat
为零则获取以文本方式返回的结果,为一则获取以二进制形式返回的结果。(目前不能规定从不同的字段获取不同格式的结果,尽管对下层的协议是可能的。)
PQexecParams
比PQexec
最主要的优势是我们可以和命令串分开声明参数值,这样就可以避免枯燥无聊并且很容易出错的引起和逃逸。和PQexec
不同的是,PQexecParams
在一个给出的字串里最多允许一个 SQL 命令。(里面可以有分号,但是不得超过一个非空的命令。)这是下层的协议的一个限制,但是也有些额外的好处,比如可以有另外一层防止 SQL 注射攻击的层次。
提示:通过 OID 声明参数类型是非常烦琐的,尤其是你不希望在你的程序里写死特定的 OID值的时候。不过,你可以避免这么做,即使在服务器自己无法判断参数类型,或者是选择了一种与你预期不同的参数类型的时候也一样。在 SQL 命令文本里,给参数负号附加一个明确的类型转换,显示你准备发送的数据类型。比如:
select * from mytable where x = $1::bigint;这样强制参数
$1
当作bigint
看待,即使缺省情况下它会被赋予和x
一样的类型。在以二进制格式发送参数值的时候,我们强烈建议通过这种方法或者是声明数字类型 OID 的方法强制类型判断,因为二进制格式比文本格式少一些冗余,因此服务器就会少一些机会捕捉类型的错误匹配。
PQprepare
用给定的参数提交请求,创建一个准备好的语句,然后等待结束。
PGresult *PQprepare(PGconn *conn, const char *stmtName, const char *query, int nParams, const Oid *paramTypes);
PQprepare
创建一个为后面PQexecPrepared
执行用的准备好语句。这个特性允许那些重复使用的语句只分析和规划一次,而不是每次执行都分析规划。这个语句必须在当前会话的前面已经准备好。只是在协议 3.0 和以后的连接里支持PQprepare
;在使用 2.0 协议的时候,它会失败。这个函数从
query
字串里创建一个叫stmtName
的准备好的语句,query
必须只包含一个 SQL 命令。stmtName
可以是""
,这样就创建一个无名的语句,这种情况下,任何前面存在的无名语句都会自动被代替;否则,如果语句名已经在当前会话里定义,那就是一个错误。如果使用了参数,那么在查询里它们引用成$1
,$2
等等。nParams
是参数的个数,参数的类型在数组paramTypes[]
里事先声明好了。(如果nParams
是零,那么这个数组指针可以是NULL
。)paramTypes[]
用 OID 的方式声明与参数符号关联的数据类型。如果paramTypes
为NULL
,或者数组中某个特定元素是零,那么服务器将用处理无类型文本同样的方法给这个参数符号赋予数据类型。还有,查询可以使用比nParams
数值更大的参数符号编号;这些参数的数据类型也是用一样的方法推导的。和
PQexec
类似,结果通常是一个PGresult
对象,其内容表明服务器端是成功还是失败。空的结果表示内存耗尽或者完全不能发送命令。使用PQerrorMessage
获取有关这类错误的更多信息。目前,没有任何方法可以帮助我们得到所推导出来的那些
paramTypes[]
里面没有声明类型之参数的实际数据类型。这是 libpq 的一个忽略,将来版本可能会纠正这点。
用于PQexecPrepared
的准备好语句也可以通过执行 SQLPREPARE 语句来创建。(不过PQprepare
更灵活,因为它不要求预先声明参数类型。)还有,尽管没有 libpq 函数可以删除一个准备好语句,SQLDEALLOCATE 语句却可以删除。
PQexecPrepared
发送一个请求,执行一个带有给出参数的准备好的语句,并且等待结果。
PGresult *PQexecPrepared(PGconn *conn, const char *stmtName, int nParams, const char * const *paramValues, const int *paramLengths, const int *paramFormats, int resultFormat);
PQexecPrepared
和PQexecParams
类似,但是要执行的命令是通过命名一个前面准备好的语句声明的,而不是给出一个查询字串。这个特性允许那些要重复使用的命令只进行一次分析和规划,而不是每次执行都来一遍。PQexecPrepared
只在协议 3.0 和以后的版本里支持;在使用 2.0 版本的协议的时候,它们会失败。参数和
PQexecParams
一样,只是给出的是一个准备好语句的名字,而不是一个查询字串,并且没有paramTypes[]
参数(没必要,因为准备好语句的参数类型是在创建的时候确定的)。
PGresult
结构封装了服务器返回的结果。libpq 应该小心维护 PGresult
的抽象。使用下面的访问函数获取 PGresult
的内容。避免直接引用 PGresult
里面的字段,因为它们在未来版本里可能会被修改。
PQresultStatus
返回命令的结果状态。
ExecStatusType PQresultStatus(const PGresult *res);
PQresultStatus
可以返回下面数值之一:PGRES_EMPTY_QUERY
发送给服务器的字串是空的
PGRES_COMMAND_OK
成功完成一个不返回数据的命令
PGRES_TUPLES_OK
成功执行一个返回数据的查询查询(比如
SELECT
或者SHOW
)。PGRES_COPY_OUT
(从服务器)Copy Out (拷贝出)数据传输开始
PGRES_COPY_IN
Copy In (拷贝入)(到服务器)数据传输开始
PGRES_BAD_RESPONSE
服务器的响应无法理解
PGRES_NONFATAL_ERROR
发生了一个非致命错误(通知或者警告)
PGRES_FATAL_ERROR
发生了一个致命错误
如果结果状态是
PGRES_TUPLES_OK
,那么可以用下面的函数从查询的返回中抽取元组信息。注意一个碰巧检索了零条元组的SELECT
仍然显示PGRES_TUPLES_OK
。PGRES_COMMAND_OK
用于不返回元组的命令(INSERT
,UPDATE
,等)。返回PGRES_EMPTY_QUERY
的响应通常意味着暴露了客户端软件里面的臭虫。状态为
PGRES_NONFATAL_ERROR
的结果永远不会直接由PQexec
或者其它查询执行函数返回;这类的结果会被传递给通知处理器(参阅 Section 28.10)。PQresStatus
把
PQresultStatus
返回的枚举类型转换成一个描述状态码的字符串常量。调用者不应该释放结果。char *PQresStatus(ExecStatusType status);
PQresultErrorMessage
返回与查询关联的错误信息,或在没有错误时返回一个空字符串。
char *PQresultErrorMessage(const PGresult *res);
如果有错误,那么返回的字串将包括一个结尾的新行。调用者不应该直接释放结果。在相关的
PGresult
句柄传递给PQclear
之后,它会自动释放。紧跟在一个
PQexec
或PQgetResult
调用后面,PQerrorMessage
(对连接)将返回与PQresultErrorMessage
(对结果)一样的字符串。不过,一个PGresult
将保有其错误信息直到被删除,而连结的错误信息将在后续的操作完成时被改变。当你想知道与某个PGresult
相关联的状态时用PQresultErrorMessage
;当你想知道与连接的最近一个操作相关联的状态时用PQerrorMessage
。PQresultErrorField
返回一个独立的错误报告字段。
char *PQresultErrorField(const PGresult *res, int fieldcode);
fieldcode
是一个错误字段标识符;参阅下面列出的符号。如果PGresult
不是错误或者警告结果或者不包括指定的字段,那么返回NULL
。字段值通常将不包括结尾的新行。调用者不应该直接释放结果。在相关联的PGresult
句柄传递给PQclear
之后,它将被自动释放。下列代码是可用的:
PG_DIAG_SEVERITY
严重程度,这个字段的内容是
ERROR
,FATAL
,或者PANIC
(在错误信息里),或者WARNING
,NOTICE
,DEBUG
,INFO
,或者LOG
(在注意信息里),或者是这些东西的一个本地化翻译。总是出现。PG_DIAG_SQLSTATE
这个错误的 SQLSTATE 代码。SQLSTATE 代码表示所发生的错误的类型;可以由前端应用用于对特定的数据库错误执行特定的操作(比如错误处理)。关于可能的 SQLSTATE 代码的列表,请参阅 Appendix A。这个字段是不能区域化的,并且总是出现。
PG_DIAG_MESSAGE_PRIMARY
主要的人类可读的信息(通常是联机)。总是出现。
PG_DIAG_MESSAGE_DETAIL
细节:一个可选的从属错误信息,里面有更多有关该问题的细节。可能有多行。
PG_DIAG_MESSAGE_HINT
提示:一个可选的有关如何处理该问题的建议。它和细节的区别是它提供了建议(可能不太合适)而不光是事实。可能有好几行。
PG_DIAG_STATEMENT_POSITION
一个包含十进制整数的字串,当作一个错误游标使用,指出最初的语句串出错的地方的下标。第一个字符的索引是 1,并且这个位置是用字符计,而不是用字节计。
PG_DIAG_INTERNAL_POSITION
这个和
PG_DIAG_STATEMENT_POSITION
字段定义是一样的,区别是它用于内部生成的命令的下标指示,而不是客户端提交的命令。如果出现了这个字段,那么PG_DIAG_INTERNAL_QUERY
字段也总是出现。PG_DIAG_INTERNAL_QUERY
一个失败的内部生成的命令的文本。比如,这个可能是一个 PL/pgSQL 函数发出的 SQL 查询。
PG_DIAG_CONTEXT
一个指示器,表明错误发生的环境。目前这个包括活跃的过程语言函数和内部生成的查询的调用堆栈。堆栈是每行一条,最近的在上面。
PG_DIAG_SOURCE_FILE
所报告的错误的源代码位置的所在文件。
PG_DIAG_SOURCE_LINE
报告的这个错误所在的源代码位置的行号。
PG_DIAG_SOURCE_FUNCTION
报告这个错误的源代码函数的名字。
按照自身的要求格式化显示信息是客户端的责任;特别是根据需要对长行进行折行。在错误信息字段里出现的新行字符应该当作分段符号,而不是换行。
libpq 生成的错误将会有严重性和主信息,但是通常没有其它字段。3.0 协议之前返回的错误将包含严重性和主信息,有时候还有详细信息,但是没有其它字段。
请注意这些错误字段只能从
PGresult
对象里获得,而不是PGconn
对象;没有PQerrorField
函数。PQclear
PQclear
释放于PGresult
相关联的存储空间。任何不再需要的查询结果在不需要的时候都应该用PQclear
释放掉。void PQclear(PGresult *res);
只要你需要,你可以保留
PGresult
对象任意长的时间;当你提交新的查询时它并不消失,甚至你断开连接后也是这样。要删除它,你必须调用PQclear
。不这么做将导致你的应用中的内存泄漏。PQmakeEmptyPGresult
构造一个带有给出的状态的,空的
PGresult
对象。PGresult* PQmakeEmptyPGresult(PGconn *conn, ExecStatusType status);
这是libpq的内部函数,用于分配和初始化一个空
PGresult
对象。在无法分配内存的时候,这个函数返回 NULL。它被输出是因为一些应用需要自行生成结果对象(尤其是特定的带有错误状态的对象)。如果conn
非空(NULL)并且状态指示一个错误,连接当前的错误信息被拷贝到PGresult
。注意最终对该对象还是要调用PQclear
,正如libpq本身返回的PGresult
一样。
28.3.2. 检索查询结果信息
这些函数用于从一个代表着成功查询结果(也就是说,状态为 PGRES_TUPLES_OK
的查询)的 PGresult
对象。对于其它状态值的对象,他们的行为会好像他们有零行和零列一样。
PQntuples
返回查询结果里的行(元组)个数。
int PQntuples(const PGresult *res);
PQnfields
返回查询结果里数据行的数据域(字段)的个数。
int PQnfields(const PGresult *res);
PQfname
返回与给出的数据域编号相关联的数据域(字段)的名称。数据域编号从 0 开始。调用者不应该直接释放结果。在相关联的
PGresult
句柄传递给PQclear
之后,结果会被自动释放。char *PQfname(const PGresult *res, int column_number);
如果字段编号超出范围,那么返回
NULL
。PQfnumber
返回与给出的数据域名称相关联的数据域(字段)的编号。
int PQfnumber(const PGresult *res, const char *column_name);
如果给出的名字不匹配任何字段,返回 -1。
给出的名字是当作 SQL 命令里的一个标识符看待的,也就是说,如果没有加双引号,那么会转换为小写。比如,如果我们有一个从 SQL 命令里生成的查询结果
select 1 as FOO, 2 as "BAR";
那么我们会有下面的结果:
PQfname(res, 0) fooPQfname(res, 1) BARPQfnumber(res, "FOO") 0PQfnumber(res, "foo") 0PQfnumber(res, "BAR") -1PQfnumber(res, "\"BAR\"") 1
PQftable
返回我们抓取的字段所在的表的 OID。字段编号从 0 开始。
Oid PQftable(const PGresult *res, int column_number);
如果字段编号超出了范围,或者声明的字段不是一个指向某个表的字段的简单引用,或者使用了 3.0 版本之前的协议,那么就会返回
InvalidOid
。你可以查询系统表pg_class
来判断究竟引用了哪个表。在你包含 libpq 头文件的时候, 就会定义类型
Oid
和常量InvalidOid
。 他们都是相同的整数类型。PQftablecol
返回组成声明的查询结果字段的字段号(在它的表内部)。查询结果字段编号从 0 开始,但是表字段编号不会是 0。
int PQftablecol(const PGresult *res, int column_number);
如果字段编号超出范围,或者声明的字段并不是一个表字段的简单引用,或者使用的是 3.0 之前的协议,那么返回零。
PQfformat
返回说明给出字段的格式的格式代码。字段编号从 0 开始。
int PQfformat(const PGresult *res, int column_number);
格式码为 0 表示文本数据,而格式码是一表示二进制数据。(其它编码保留给将来定义。)
PQftype
返回与给定数据域编号关联的数据域类型。返回的整数是一个该类型的内部 OID 号。数据域编号从0 开始。
Oid PQftype(const PGresult *res, int column_number);
你可以查询系统表
pg_type
以获取各种数据类型的名称和属性。内建的数据类型的 OID 在源码树的src/include/catalog/pg_type.h
文件里定义。PQfmod
返回与给定字段编号相关联的类型修饰词。字段编号从 0 开始。
int PQfmod(const PGresult *res, int column_number);
类型修饰符的值是类型相关的;他们通常包括精度或者尺寸限制。数值 -1 用于表示"没有可用信息"。大多数数据类型不用修饰词,这种情况下该值总是 -1。
PQfsize
返回与给定字段编号关联的字段以字节计的大小。字段编号从0 开始。
int PQfsize(const PGresult *res, int column_number);
PQfsize
返回在数据库行里面给该数据字段分配的空间,换句话说就是该数据类型在服务器里的二进制形式的大小(尺寸)。(因此,这个对客户端没有什么用。)如果该数据域是可变尺寸,返回 -1。PQbinaryTuples
如果
PGresult
包含二进制元组数据时返回 1,如果包含 ASCII 数据返回 0。int PQbinaryTuples(const PGresult *res);
这个函数已经废弃了(除了还用于与
COPY
连接之外),因为我们可能在一个PGresult
的某些字段里包含文本数据,而另外一些字段包含二进制数据。更好的是使用PQfformat
。PQbinaryTuples
只有在结果中的所有字段都是二进制(格式 1)的时候才返回 1。PQgetvalue
返回一个
PGresult
里面一行的单独的一个字段的值。行和字段编号从 0 开始。调用者不应该直接释放结果。在把PGresult
句柄传递给PQclear
之后,结果会被自动释放。char *PQgetvalue(const PGresult *res, int row_number, int column_number);
对于文本格式的数据,
PQgetvalue
返回的值是一个表示字段值的空(NULL)结尾的字符串。对于二进制格式,返回的值就是由该数据类型的typsend
和typreceive
决定的二进制表现形式。(在这种情况下,数值实际上也跟着一个字节零,但是通常这个字节没什么用处,因为数值本身很可能包含内嵌的空。)如果字段值是空,则返回一个空字串。参阅
PQgetisnull
来区别空值和空字串值。PQgetvalue
返回的指针指向一个本身是PGresult
结构的一部分的存储区域。我们不能更改它,并且如果我们要在PGresult
结构的生存期后还要使用它的话,我们必须明确地把该数值拷贝到其他存储器中。PQgetisnull
测试一个字段是否为空(NULL)。行和字段编号从 0 开始。
int PQgetisnull(const PGresult *res,int row_number,int column_number);
如果该域包含 NULL,函数返回 1,如果包含非空(non-null )值,返回 0。(注意,对一个 NULL 数据域,
PQgetvalue
将返回一个空字符串,不是一个空指针。)PQgetlength
返回以字节计的字段的长度。行和字段编号从 0 开始。
int PQgetlength(const PGresult *res,int row_number,int column_number);
这是某一特定数据值的实际数据长度。行和字段编号从 0 开始。
int PQgetlength(const PGresult *res, int row_number, int column_number);
这是特定数值的实际数据长度,也就是说,
PQgetvalue
指向的对象的大小。对于文本数据格式,它和strlen()
相同。对于二进制格式,这是潜在的信息。请注意我们不应该依靠PQfsize
获取实际数据长度。PQprint
向指定的输出流打印所有的行和(可选的)字段名称。
void PQprint(FILE *fout, /* 输出流 */ const PGresult *res, const PQprintOpt *po);struct { pqbool header; /* 打印输出域头和行计数 */ pqbool align; /* 填充对齐各字段 */ pqbool standard; /* 旧的傻格式 */ pqbool html3; /* 输出 HTML 表 */ pqbool expanded; /* 扩展表 */ pqbool pager; /* 必要时在输出中使用分页器 */ char *fieldSep; /* 字段分隔符 */ char *tableOpt; /* 在 HTML 中插入
table ...
*/ char *caption; /* HTMLcaption
*/ char **fieldName; /* 替换字段名组成的空零结尾的数组 */} PQprintOpt;这个函数以前被 psql用于打印查询结果,但是现在已经不用这个函数了。请注意它假设所有的数据都是文本格式。
28.3.3. 检索其它命令的结果信息
这些函数用于从 PGresult
对象里检索那些非 SELECT
结果的信息。
PQcmdStatus
返回产生
PGresult
的 SQL 命令的命令状态字符串。char *PQcmdStatus(PGresult *res);
通常这只是命令的名字,但是它可能包括额外的数据,比如处理过的行数。调用者不应该释放结果。结果会在把
PGresult
句柄传递给PQclear
的时候释放。PQcmdTuples
返回被 SQL 命令影响的行的数量。
char *PQcmdTuples(PGresult *res);
这个函数返回一个生成这个
PGresult
的这个 SQL 语句影响的行数的字串。这个函数只能用于INSERT
,UPDATE
,DELETE
,MOVE
,或者FETCH
语句执行之后的结果。或者是一个包含INSERT
,UPDATE
,或者DELETE
语句EXECUTE
的一个准备好的查询。如果生成这个PGresult
的命令是其他的东西,那么PQcmdTuples
返回一个空字串。调用者不应该直接释放返回的数值。在相关联的PGresult
被传递给PQclear
之后,它会被自动释放。PQoidValue
返回一个插入的行的对象标识(OID)——如果SQL 命令是
INSERT
,或者是一个包含合适INSERT
语句的准备好的EXECUTE
的时候。否则,函数返回InvalidOid
。如果受INSERT
影响的表不包含 OID,也返回InvalidOid
。Oid PQoidValue(const PGresult *res);
PQoidStatus
如果 SQL 命令是
INSERT
,或者包含合适INSERT
的准备好语句EXECUTE
了。返回一个被插入的行的 OID 的字串。(如果INSERT
并非恰好插入一行,或者目标表没有OID,那么字串将是0
。)如果命令不是INSERT
,则返回一个空字串。char *PQoidStatus(const PGresult *res);
这个函数已经废弃了,因为有了
PQoidValue
,而且它也不是线程安全的。
28.3.4. 逃逸包含在 SQL 命令中的字串
PQescapeString
为在 SQL 命令中使用字串而对之进行逃逸处理。在我们向 SQL 命令里把数据值当作文本常量插入的时候很有用。有些字符(比如单引号和反斜杠)必须被逃逸,以避免他们被 SQL 分析器作为特殊字符解析。PQescapeString
执行这个操作。
提示:如果我们从一个不可信的来源收到一个字串的话,那么做恰当的逃逸就更重要了。否则就有安全性危险:你会收到"SQL 注射"攻击,这个时候会有你不想看到的 SQL 喂给你的数据库。
请注意,如果一个数据值是作为PQexecParams
或者同族函数的一个独立参数传递的,那么逃逸就既不必要,也不正确。
size_t PQescapeString (char *to, const char *from, size_t length);
参数 from
指向将要逃逸的字串的第一个字符,length
参数给出在这个字串里的字符数量。字串结尾的字节零不是必须的,也不计入 length
。(如果在处理 length
个字节之前出现了一个字节零,那么PQescapeString
在这个字节零处停止;这个行为类似strncpy
。)to
应该指向一个缓冲区,这个缓冲区至少能保存length
数值的两倍还多一个的字符,否则该函数行为将不可预测。调用PQescapeString
就会把逃逸的 from
字串转换到 to
缓冲区,把特殊字符以免它们导致任何问题,并且追加终止的字节零。那些必须包围在PostgreSQL字串文本周围的单引号不算结果字串的一部分;你应该在把单引号放在插入这个处理结果的SQL命令周围。
PQescapeString
返回写到 to
里面的字符数目,不包括结尾的字节零。
如果 to
和 from
字串相互重叠,那么其行为不可预测。
28.3.5. 逃逸包含在 SQL 命令中的二进制字串
PQescapeBytea
逃逸那些在 SQL 命令中使用的用
bytea
表示的二进制数据。和PQescapeString
一样,这个函数只有在直接向 SQL 字串插入数据的时候使用。unsigned char *PQescapeBytea(const unsigned char *from, size_t from_length, size_t *to_length);
在 SQL 语句中用做
bytea
字串文本的一部分的时候,有些字节值必需逃逸(但是对于所有字节而言是可以逃逸)。通常,要逃逸一个字节,它是被转换成一个三位八进制数字,该数字数值等于该字节的数值,然后前缀两个反斜杠。单引号('
)和反斜杠字符(\
)有自己特殊的逃逸序列。参阅Section 8.4 获取更多信息。PQescapeBytea
执行这个操作,它只逃逸需要逃逸的最少的字符。from
参数指向需要逃逸的字串的第一个字节,from_length
参数反映在这个二进制字串(结尾的字节零既不必要也不计算在内的字串)里字节的个数。to_length
参数应该是一个指向某个缓冲区的指针,它的空间应该能够保存逃逸后的结果字串长度。结果字串长度不包括结果结尾的字节零。PQescapeBytea
在内存重返回一个from
参数的二进制字串的逃逸后的版本,这片内存是用malloc()
分配的(如果无法分配内存,则返回空指针)。在不再需要结果的时候,必须用PQfreemem()
释放它。返回的字串已经把所有特殊的字符替换掉了,这样他们就可以由PostgreSQL 的字串文本分析器以及bytea
的输入函数正确地处理。同时还追加了一个结尾的字节零。那些必需包围在PostgreSQL字串文本周围的单引号并非结果字串的一部分。PQunescapeBytea
把一个二进制数据的逃逸后的字串表现形式转换成二进制数据 —
PQescapeBytea
的反作用。在以文本格式抽取bytea
数据的时候是必须的,但是在以二进制格式抽取的时候是不必要的。unsigned char *PQunescapeBytea(const unsigned char *from, size_t *to_length);
from
参数指向一个逃逸后的字串,比如PQgetvalue
处理过一个bytea
字段后返回的。PQunescapeBytea
把它的字串表现形式转换成二进制形式,它返回一个用malloc()
分配的指向该缓冲区的指针,或者是出错时返回空,缓冲区的尺寸放在to_length
里。在不再需要这个结果之后,这片内存必须用PQfreemem()
释放。PQfreemem
释放 libpq 分配的内存。
void PQfreemem(void *ptr);
释放由 libpq 分配的内存,特别是
PQescapeBytea
,PQunescapeBytea
,和PQnotifies
。这是 Microsoft Windows 必须的,因为它不能跨越 DLL 释放内存,除非使用了多线程的 DLL (VC6 中的 /MD)。在其它平台上,这个函数和标准的库函数free()
一样。
Prev | Home | Next |
连接状态函数 | Up | 异步命令处理 |
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论