33.3. 命令执行函数
一旦到一个数据库服务器的连接被成功建立,这里描述的函数可以被用来执行 SQL 查询和命令。
33.3.1. 主要函数
命令字符串可以包括多个 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 协议时它会失败。该函数的参数是:
conn
-
要在其中发送命令的连接对象。
command
-
要执行的 SQL 命令字符串。如果使用了参数,它们在该命令字符串中被引用为
$1
、$2
等。 nParams
-
提供的参数数量。它是数组
paramTypes[]
、paramValues[]
、paramLengths[]
和paramFormats[]
的长度(当nParams
为零时,数组指针可以是NULL
)。 paramTypes[]
-
通过 OID 指定要赋予给参数符号的数据类型。如果
paramTypes
为NULL
或者该数组中任何特定元素为零,服务器会用对待未知类型文字串的方式为参数符号推测一种数据类型。 paramValues[]
-
指定参数的实际值。这个数组中的一个空指针表示对应的参数为空,否则该指针指向一个以零终止的文本字符串(用于文本格式)或者以服务器所期待格式的二进制数据(用于二进制格式)。
paramLengths[]
-
指定二进制格式参数的实际数据长度。它对空参数和文本格式参数被忽略。当没有二进制参数时,该数组指针可以为空。
paramFormats[]
-
指定参数是否为文本(在参数相应的数组项中放一个零)或二进制(在参数相应的数组项中放一个一)。如果该数组指针为空,那么所有参数都会被假定为文本串。
以二进制格式传递的值要求后端所期待的内部表示形式的知识。例如,整数必须以网络字节序被传递。传递
numeric
值要求关于服务器存储格式的知识,正如src/backend/utils/adt/numeric.c::numeric_send()
以及src/backend/utils/adt/numeric.c::numeric_recv()
中所实现的。 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
执行的预备语句。这种特性允许将被反复执行的命令只被解析和规划一次,而不是在每次被执行时都解析和规划。PQprepare
只在协议 3.0 及之后的连接中被支持,当使用协议 2.0 时它将失败。该函数从
query
串创建一个名为stmtName
的预备语句,该串必须包含一个单一 SQL 命令。stmtName
可以是""
来创建一个未命名语句,在这种情况下任何已存在未命名语句将被自动替换。如果语句名称已经在当前会话中被定义,则是一种错误。如果使用了任何参数,它们在查询中以$1
、$2
等引用。nParams
是参数的个数,其类型在数组paramTypes[]
中被预先指定(当nParams
为零时,该数组指针可以是NULL
)。paramTypes[]
通过 OID 指定要赋予给参数符号的数据类型。如果paramTypes
是NULL
或者该数组中任何特定元素为零,服务器会用对待未知类型文字串的方式为参数符号推测一种数据类型。还有,查询能够使用编号高于nParams
的参数符号,它们的数据类型也会被自动推测(找出推测出的数据类型的方法见PQdescribePrepared
)。正如
PQexec
一样,结果通常是一个PGresult
对象,其内容代表服务器端成功或失败。一个空结果表示内存不足或者根本无法发送命令。关于错误的更多信息请见PQerrorMessage
。
用于PQexecPrepared
的预备语句也能通过执行 SQL PREPARE语句来创建。还有,尽管没有libpq函数来删除一个预备语句,SQL DEALLOCATE语句可被用于此目的。
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[]
参数(因为预备语句的参数类型已经在它被创建时决定好了)。 PQdescribePrepared
-
提交一个请求来获得有关指定预备语句的信息,并且等待完成。
PGresult *PQdescribePrepared(PGconn *conn, const char *stmtName);
PQdescribePrepared
允许一个应用获得有关一个之前预备好的语句的信息。PQdescribePrepared
仅被协议 3.0 及之后的连接支持,当使用协议 2.0 时它会失败。stmtName
可以用""
或者NULL
来引用未命名语句,否则它必须是一个现有预备语句的名字。如果成功,一个PGresult
以及状态PGRES_COMMAND_OK
会被返回。函数PQnparams
和PQparamtype
可以被应用到这个PGresult
来得到关于该预备语句参数的额外信息,而函数PQnfields
、PQfname
、PQftype
等提供该语句结果列(如果有)的信息。 PQdescribePortal
-
提交一个请求来得到有关指定入口的信息,并且等待完成。
PGresult *PQdescribePortal(PGconn *conn, const char *portalName);
PQdescribePortal
允许一个应用获得有关一个之前被创建的入口的信息(libpq不提供对入口任何直接的访问,但是你可以使用这个函数来观察一个通过DECLARE CURSOR
SQL 命令创建的游标的属性)。PQdescribePortal
仅被协议 3.0 及之后的连接支持,当使用协议 2.0 时它会失败。portalName
可以用""
或者NULL
来引用未命名入口,否则它必须是一个现有入口的名字。如果成功,一个PGresult
和状态PGRES_COMMAND_OK
会被返回。函数PQnfields
、PQfname
、PQftype
等可以被应用到PGresult
来获得有关该入口结果列(如果有)的信息。
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
-
从服务器复制出数据的传输开始。
PGRES_COPY_IN
-
复制数据到服务器的传输开始。
PGRES_BAD_RESPONSE
-
无法理解服务器的响应。
PGRES_NONFATAL_ERROR
-
发生了一次非致命错误(一个提示或警告)。
PGRES_FATAL_ERROR
-
发生了一次致命错误。
PGRES_COPY_BOTH
-
向服务器复制数据/从服务器复制数据的传输开始。这个特性当前只被用于流复制,因此这个状态应该不会在普通应用中出现。
PGRES_SINGLE_TUPLE
-
PGresult
包含来自于当前命令的一个单一结果元组。这个状态只在查询选择了单一行模式时发生(见第 33.5 节)。
如果结果状态是
PGRES_TUPLES_OK
或者PGRES_SINGLE_TUPLE
,那么下面所描述的函数能被用来检索该查询所返回的行。注意,一个恰好检索零行的SELECT
命令仍然会显示PGRES_TUPLES_OK
。PGRES_COMMAND_OK
用于从不返回行的命令(不带RETURNING
子句的INSERT
或者UPDATE
等)。一个PGRES_EMPTY_QUERY
可能表示客户端软件中的一个缺陷。一个状态为
PGRES_NONFATAL_ERROR
的结果将不会被PQexec
或者其他查询执行函数直接返回,这类结果将被传递给提示处理器(见 第 33.12 节)。 PQresStatus
-
将
PQresultStatus
返回的枚举转换成描述状态编码的字符串常量。调用者不应该释放结果。char *PQresStatus(ExecStatusType status);
PQresultErrorMessage
-
返回与该命令相关的错误消息,如果有错误则会返回一个空字符串。
char *PQresultErrorMessage(const PGresult *res);
如果有一个错误,被返回的字符串将包含一个收尾的新行。调用者不应该直接释放结果。它将在相关的
PGresult
句柄被传递给PQclear
之后被释放。紧跟着一个
PQexec
或PQgetResult
调用,PQerrorMessage
(在连接上)将返回与PQresultErrorMessage
相同的字符串(在结果上)。不过,一个PGresult
将保持它的错误消息直到被销毁,而连接的错误消息将在后续操作被执行时被更改。当你想要知道与一个特定PGresult
相关的状态,使用PQresultErrorMessage
。而当你想要知道连接上最后一个操作的状态,使用PQerrorMessage
。 PQresultVerboseErrorMessage
-
返回与
PGresult
对象相关的错误消息的重新格式化的版本。char *PQresultVerboseErrorMessage(const PGresult *res, PGVerbosity verbosity, PGContextVisibility show_context);
在有些情况下,客户端可能希望得到之前报告过的错误的更加详尽的版本。 如果在产生给定
PGresult
的连接上 verbosity 设置有效,PQresultVerboseErrorMessage
会通过计算已经被PQresultErrorMessage
产生过的消息来满足这种需求。 如果PGresult
不是一个错误结果,则会报告 “PGresult is not an error result”。 返回的字符串包括一个新行作为结尾。和大部分从
PGresult
中提取数据的其他函数不同, 这个函数的结果是一个全新分配的字符串。调用者在不需要这个字符串以后, 必须使用PQfreemem()
释放它。如果内存不足,可能会返回 NULL。
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_SEVERITY_NONLOCALIZED
-
严重。域的内容是
ERROR
、FATAL
或PANIC
(在一个错误消息中)。或者是WARNING
、NOTICE
、DEBUG
、INFO
或LOG
(在一个提示消息中)。 这和PG_DIAG_SEVERITY
域相同,不过内容不会被本地化。 只存在于PostgreSQL 9.6 及以后版本产生的报告中。 PG_DIAG_SQLSTATE
-
用于错误的 SQLSTATE 代码。SQLSTATE 代码标识了已经发生的错误的类型,它可以被前端应用用来执行特定操作(例如错误处理)来响应一个特定数据库错误。一个可能的 SQLSTATE 代码列表可见附录 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_SCHEMA_NAME
-
如果错误与某个特定的数据库对象相关,这里是包含该对象的模式名(如果有)。
PG_DIAG_TABLE_NAME
-
如果错误与某个特定表相关,这里是该表的名字(该表的模式参考模式名域)。
PG_DIAG_COLUMN_NAME
-
如果错误与一个特定表列相关,这里是该表列的名字(参考模式和表名域来标识该表)。
PG_DIAG_DATATYPE_NAME
-
如果错误与一个特定数据类型相关,这里是该数据类型的名字(该数据类型的模式名参考模式名域)。
PG_DIAG_CONSTRAINT_NAME
-
如果错误与一个特定约束相关,这里是该约束的名字。相关的表或域参考上面列出的域(为了这个目的,索引也被视作约束,即使它们不是用约束语法创建的)。
PG_DIAG_SOURCE_FILE
-
报告错误的源代码所在的文件名。
PG_DIAG_SOURCE_LINE
-
报告错误的源代码行号。
PG_DIAG_SOURCE_FUNCTION
-
报告错误的源代码函数的名字。
注意
用于模式名、表明、列名、数据类型名和约束名的域只提供给有限的错误类型,见附录 A。不要假定任何这些域的存在保证另一个域的存在。核心错误源会遵守上面提到的内在联系,但是用户定义的函数可能以其他方式使用这些域。同样地,不要假定这些域代表当前数据库中同类的对象。
客户端负责格式化显示信息来迎合它的需要,特别是根据需要打断长的行。出现在错误消息域中的新行字符应该被当作分段而不是换行。
libpq内部产生的错误将有严重和主要消息,但是通常没有其他域。3.0 协议之前的服务器返回的错误将包括严重和主要消息,并且有时候还有细节消息,但是没有其他域。
注意错误域只对
PGresult
对象中有效,对PGconn
对象无效。没有PQerrorField
函数。 PQclear
-
Frees the storage associated with a 释放与一个
PGresult
相关的存储。每一个命令结果不再需要时应该用PQclear
释放。void PQclear(PGresult *res);
你可以按照需要保留
PGresult
对象,当你发出一个新命令时它也不会消失,甚至关闭连接时也不会消失。要去掉它,你必须调用PQclear
。没有这样做将会导致在应用中的内存泄露。
33.3.2. 检索查询结果信息
这些函数被用来从一个代表成功查询结果(也就是状态为PGRES_TUPLES_OK
或者PGRES_SINGLE_TUPLE
)的PGresult
对象中抽取信息。它们也可以被用来从一个成功的 Describe 操作中抽取信息:一个 Describe 的结果具有和该查询被实际执行所提供的完全相同的列信息,但是它没有行。对于其他状态值的对象,这些函数会认为结果具有零行和零列。
PQntuples
-
返回查询结果中的行(元组)数。 (请注意,
PGresult
对象限制为不超过INT_MAX
行, 所以int
结果是足够的。)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) foo PQfname(res, 1) BAR PQfnumber(res, "FOO") 0 PQfnumber(res, "foo") 0 PQfnumber(res, "BAR") -1 PQfnumber(res, "\"BAR\"") 1
PQftable
-
返回取出给定列的表的 OID。列号从 0 开始。
Oid PQftable(const PGresult *res, int column_number);
如果列号超出范围或者指定的列不是对一个表列的简单引用或者在使用 3.0 协议时,返回
InvalidOid
。你可以查询系统表pg_class
来确定究竟是哪个表被引用。当你包括libpq头文件,类型
Oid
以及常数InvalidOid
将被定义。它们将都是某种整数类型。 PQftablecol
-
返回构成指定查询结果列的列(在其表中)的列号。查询结果列号从 0 开始,但是表列具有非零编号。
int PQftablecol(const PGresult *res, int column_number);
如果列号超出范围或者指定的列不是对一个表列的简单引用或者在使用 3.0 协议时,返回零。
PQfformat
-
返回指示给定列格式的格式编码。列号从 0 开始。
int PQfformat(const PGresult *res, int column_number);
格式代码零指示文本数据表示,而格式代码一表示二进制表示(其他代码被保留用于未来的定义)。
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
返回在一个数据库行中为这个列分配的空间,换句话说是服务器对该数据类型的内部表示的尺寸(因此,它对客户端并不是真地非常有用)。一个负值指示该数据类型是变长的。 PQbinaryTuples
-
如果
PGresult
包含二进制数据,返回 1。如果包含的是文本数据,返回 0。int PQbinaryTuples(const PGresult *res);
这个函数已经被废弃(除了与
COPY
一起使用),因为一个单一PGresult
可以在某些列中包含文本数据而且在另一些列中包含二进制数据。PQfformat
要更好。只有结果的所有列是二进制(格式 1)时PQbinaryTuples
才返回 1。 PQgetvalue
-
返回一个
PGresult
的一行的单一域值。行和列号从 0 开始。调用者不应该直接释放该结果。它将在相关的PGresult
句柄被传递给PQclear
之后被释放。char *PQgetvalue(const PGresult *res, int row_number, int column_number);
对于文本格式的数据,
PQgetvalue
返回的值是该域值的一种空值结束的字符串表示。对于二进制格式的数据,该值是由该数据类型的typsend
和typreceive
函数决定的二进制表示(在这种情况下该值实际上也跟随着一个零字节,但是这通常没有用处,因为该值很可能包含嵌入的空)。如果该域值为空,则返回一个空串。关于区分空值和空字符串值请见
PQgetisnull
。PQgetvalue
返回的指针指向作为PGresult
结构一部分的存储。我们不应该修改它指向的数据,并且如果要在超过PGresult
结构本身的生命期之外使用它,我们必须显式地把该数据拷贝到其他存储中。 PQgetisnull
-
测试一个域是否为空值。行号和列号从 0 开始。
int PQgetisnull(const PGresult *res, int row_number, int column_number);
如果该域是空,这个函数返回 1。如果它包含一个非空值,则返回 0(注意
PQgetvalue
将为一个空域返回一个空串,不是一个空指针)。 PQgetlength
-
返回一个域值的真实长度,以字节计。行号和列号从 0 开始。
int PQgetlength(const PGresult *res, int row_number, int column_number);
这是特定数据值的真实数据长度,也就是
PQgetvalue
指向的对象的尺寸。对于文本数据格式,这和strlen()
相同。对于二进制格式这是基本信息。注意我们不应该依赖于PQfsize
来得到真实的数据长度。 PQnparams
-
返回一个预备语句的参数数量。
int PQnparams(const PGresult *res);
只有在查看
PQdescribePrepared
的结果时,这个函数才有用。对于其他类型的查询,它将返回零。 PQparamtype
-
返回所指示的语句参数的数据类型。参数号从 0 开始。
Oid PQparamtype(const PGresult *res, int param_number);
只有在查看
PQdescribePrepared
的结果时,这个函数才有用。对于其他类型的查询,它将返回零。 PQprint
-
将所有的行打印到指定的输出流,以及有选择地将列名打印到指定的输出流。
void PQprint(FILE *fout, /* 输出流 */ const PGresult *res, const PQprintOpt *po); typedef struct { pqbool header; /* 打印输出域标题和行计数 */ pqbool align; /* 填充对齐域 */ pqbool standard; /* 旧的格式 */ pqbool html3; /* 输出 HTML 表格 */ pqbool expanded; /* 扩展表格 */ pqbool pager; /* 如果必要为输出使用页 */ char *fieldSep; /* 域分隔符 */ char *tableOpt; /* 用于 HTML 表格元素的属性 */ char *caption; /* HTML 表格标题 */ char **fieldName; /* 替换域名称的空终止数组 */ } PQprintOpt;
这个函数以前被psql用来打印查询结果,但是现在不是这样了。注意它假定所有的数据都是文本格式。
33.3.3. 检索其他结果信息
这些函数被用来从PGresult
对象中抽取其他信息。
PQcmdStatus
-
返回来自于产生
PGresult
的 SQL 命令的命令状态标签。char *PQcmdStatus(PGresult *res);
通常这就是该命令的名称,但是它可能包括额外数据,例如已被处理的行数。调用者不应该直接释放该结果。它将在相关的
PGresult
句柄被传递给PQclear
之后被释放。 PQcmdTuples
-
返回受该 SQL 命令影响的行数。
char *PQcmdTuples(PGresult *res);
这个函数返回一个字符串,其中包含着产生
PGresult
的SQL语句影响的行数。这个只能被用于下列情况:执行一个SELECT
、CREATE TABLE AS
、INSERT
、UPDATE
、DELETE
、MOVE
、FETCH
或COPY
语句,或者一个包含INSERT
、UPDATE
或DELETE
语句的预备查询的EXECUTE
。如果产生PGresult
的命令是其他什么东西,PQcmdTuples
会返回一个空串。调用者不应该直接释放该结果。它将在相关的PGresult
句柄被传递给PQclear
之后被释放。 PQoidValue
-
如果该SQL命令是一个正好将一行插入到具有 OID 的表的
INSERT
,或者是一个包含合适INSERT
语句的预备查询的EXECUTE
,这个函数返回被插入行的 OID。否则,这个函数返回InvalidOid
。如果被INSERT
语句影响的表不包含 OID,这个函数也将返回InvalidOid
。Oid PQoidValue(const PGresult *res);
PQoidStatus
-
由于支持
PQoidValue
以及不是线程安全的,这个函数已经被废弃。它返回包含被插入行的 OID 的一个字符串,而PQoidValue
返回 OID 值。char *PQoidStatus(const PGresult *res);
33.3.4. 用于包含在 SQL 命令中的转移字符串
PQescapeLiteral
-
char *PQescapeLiteral(PGconn *conn, const char *str, size_t length);
为了让一个串能用在 SQL 命令中,
PQescapeLiteral
可对它进行转义。当在 SQL 命令中插入一个数据值作为文字常量时,这个函数很有用。一些字符(例如引号和反斜线)必须被转义以防止它们被 SQL 解析器解释成特殊的意思。PQescapeLiteral
执行这种操作。PQescapeLiteral
返回一个str
参数的已被转义版本,该版本被放在用malloc()
分配的内存中。当该结果不再被需要时,这个内存应该用PQfreemem()
释放。一个终止的零字节不是必须的,并且不应该被计入length
(如果在length
字节被处理之前找到一个终止字节,PQescapeLiteral
会停止在零,该行为更像strncpy
)。返回串中的所有特殊字符都被替换掉,这样它们能被PostgreSQL字符串解析器正确地处理。还会加上一个终止零字节。包括在结果串中的PostgreSQL字符串必须用单引号包围。发生错误时,
PQescapeLiteral
返回NULL
并且一个合适的消息会被存储在conn
对象中。提示
在处理从一个非可信源接收到的串时,做正确的转义特别重要。否则就会有安全性风险:你容易受到“SQL 注入”攻击,其中可能会有预期之外的 SQL 语句会被喂给你的数据库。
注意,当一个数据值被作为
PQexecParams
或其兄弟例程中的一个独立参数传递时,没有必要做转义而且做转义也不正确。 PQescapeIdentifier
-
char *PQescapeIdentifier(PGconn *conn, const char *str, size_t length);
PQescapeIdentifier
转义一个要用作 SQL 标识符的字符串,例如表名、列名或函数名。当一个用户提供的标识符可能包含被 SQL 解析器解释为标识符一部分的特殊字符时,或者当该标识符可能包含大小写形式应该被保留的大写字符时,这个函数很有用。PQescapeIdentifier
返回一个str
参数的已被转义为 SQL 标识符的版本,该版本被放在用malloc()
分配的内存中。当该结果不再被需要时,这个内存应该用PQfreemem()
释放。一个终止的零字节不是必须的,并且不应该被计入length
(如果在length
字节被处理之前找到一个终止字节,PQescapeIdentifier
会停止在零,该行为更像strncpy
)。返回串中的所有特殊字符都被替换掉,这样它们能被作为一个 SQL 标识符正确地处理。还会加上一个终止零字节。返回串也将被双引号包围。发生错误时,
PQescapeIdentifier
返回NULL
并且一个合适的消息会被存储在conn
对象中。提示
与字符串一样,要阻止 SQL 注入攻击,当从一个不可信的来源接收到 SQL 标识符时,它们必须被转义。
PQescapeStringConn
-
size_t PQescapeStringConn(PGconn *conn, char *to, const char *from, size_t length, int *error);
PQescapeStringConn
转义字符串,它很像PQescapeLiteral
。与PQescapeLiteral
不一样的是,调用者负责提供一个合适尺寸的缓冲区。此外,PQescapeStringConn
不产生必须包围PostgreSQL字符串的单引号。它们应该在结果要插入的 SQL 命令中提供。参数from
指向要被转义的串的第一个字符,并且length
参数给出了这个串中的字节数。一个终止的零字节不是必须的,并且不应该被计入length
(如果在length
字节被处理之前找到一个终止字节,PQescapeStringConn
会停止在零,该行为更像strncpy
)。to
应当指向一个缓冲区,它能够保持至少比length
值的两倍还要多至少一个字节,否则该行为是未被定义的。如果to
和from
串重叠,行为也是未被定义的。如果
error
参数不是NULL
,那么成功时*error
被设置为零,错误时设置为非零。当前唯一可能的错误情况涉及源串中非法的多字节编码。错误时仍然会产生输出串,但是可以预期服务器将认为它是畸形的并且拒绝它。在发生错误时,一个合适的消息被存储在conn
对象中,不管error
是不是NULL
。PQescapeStringConn
返回写到to
的字节数,不包括终止的零字节。 PQescapeString
-
PQescapeString
是一个更老的被废弃的PQescapeStringConn
版本。size_t PQescapeString (char *to, const char *from, size_t length);
PQescapeStringConn
和PQescapeString
之间的唯一区别是不需要PGconn
或error
参数。正因为如此,它不能基于连接属性(例如字符编码)调整它的行为并且因此它可能给出错误的结果。还有,它没有方法报告错误情况。PQescapeString
可以在一次只使用一个PostgreSQL连接的客户端程序中安全地使用(在这种情况下它可以“在现象后面”找出它需要知道的东西)。在其他环境中它是一个安全性灾难并且应该用PQescapeStringConn
来避免。 PQescapeByteaConn
-
把要用于一个 SQL 命令的二进制数据用类型
bytea
转义。和PQescapeStringConn
一样,只有在将数据直接插入到一个 SQL 命令串时才使用它。unsigned char *PQescapeByteaConn(PGconn *conn, const unsigned char *from, size_t from_length, size_t *to_length);
当某些字节值被用作一个SQL语句中的
bytea
文字的一部分时,它们必须被转义。PQescapeByteaConn
转义使用十六进制编码或反斜线转义的字节。详见第 8.4 节。from
参数指向要被转义的串的第一个字节,并且from_length
参数给出这个二进制串中的字节数(一个终止的零字节是不需要的也是不被计算的)。to_length
参数指向一个将保持生成的已转义串长度的变量。这个结果串长度包括结果的终止零字节。PQescapeByteaConn
返回一个from
参数的已被转义为二进制串的版本,该版本被放在用malloc()
分配的内存中。当该结果不再被需要时,这个内存应该用PQfreemem()
释放。返回串中的所有特殊字符都被替换掉,这样它们能被PostgreSQL的字符串解析器以及bytea
输入函数正确地处理。还会加上一个终止零字节。不是结果串一部分的PostgreSQL字符串必须被单引号包围。在发生错误时,将返回一个空指针,并且一个合适的错误消息被存储在
conn
对象中。当前,唯一可能的错误是没有足够的内存用于结果串。 PQescapeBytea
-
PQescapeBytea
是一个更老的被废弃的PQescapeByteaConn
版本。unsigned char *PQescapeBytea(const unsigned char *from, size_t from_length, size_t *to_length);
与
PQescapeByteaConn
的唯一区别是PQescapeBytea
不用一个PGconn
参数。正因为这样,PQescapeBytea
只能在一次只使用一个PostgreSQL连接的客户端程序中安全地使用(在这种情况下它可以“在现象后面”找出它需要知道的东西)。如果在有多个数据库连接的程序中使用,它可能给出错误的结果(在那种情况下使用PQescapeByteaConn
)。 PQunescapeBytea
-
将二进制数据的一个字符串表示转换成二进制数据 — 它是
PQescapeBytea
的逆向函数。当检索文本格式的bytea
数据时,需要这个函数,但检索二进制个事时则不需要它。unsigned char *PQunescapeBytea(const unsigned char *from, size_t *to_length);
from
参数指向一个字符串,例如PQgetvalue
被应用到一个bytea
列上所返回的。PQunescapeBytea
把这个串表示转换成它的二进制表示。它返回一个指向用malloc()
分配的缓冲区的指针,在错误时返回NULL
,并且把缓冲区的尺寸放在to_length
中。当结果不再需要时,它必须使用PQfreemem
释放。这种转换并不完全是
PQescapeBytea
的逆函数,因为当从PQgetvalue
接收到字符串时,我们并不能期待它被“转义”。特别地这意味着不需要考虑字符串引用,并且因此也不需要一个参数。 -
本文转自PostgreSQL中文社区,原文链接:33.3. 命令执行函数