34.3. 命令执行函数#
成功建立与数据库服务器的连接后,此处描述的函数用于执行 SQL 查询和命令。
34.3.1. 主要函数#
PQexec
#向服务器提交命令并等待结果。
PGresult *PQexec(PGconn *conn, const char *command);
返回一个
PGresult
指针或一个空指针。通常会返回一个非空指针,除非在内存不足或无法将命令发送到服务器等严重错误的情况下。应调用PQresultStatus
函数来检查返回值是否有任何错误(包括空指针的值,在这种情况下它将返回PGRES_FATAL_ERROR
)。使用PQerrorMessage
来获取有关此类错误的更多信息。
命令字符串可以包含多个 SQL 命令(用分号分隔)。在单个PQexec
调用中发送的多个查询在单个事务中处理,除非查询字符串中包含显式的BEGIN
/COMMIT
命令将其分成多个事务。(有关服务器如何处理多查询字符串的更多详细信息,请参见第 55.2.2.1 节。)但请注意,返回的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
,但提供了附加功能:可以将参数值与命令字符串本身分开指定,并且可以以文本或二进制格式请求查询结果。函数参数为
conn
用于发送命令的连接对象。
command
要执行的 SQL 命令字符串。如果使用参数,则在命令字符串中将它们称为
$1
、$2
等。nParams
提供的参数数量;它是数组
paramTypes[]
、paramValues[]
、paramLengths[]
和paramFormats[]
的长度。(当nParams
为零时,数组指针可以为NULL
。)paramTypes[]
通过 OID 指定要分配给参数符号的数据类型。如果
paramTypes
为NULL
,或数组中的任何特定元素为零,则服务器将推断参数符号的数据类型,就像它对未输入类型的字符串文本所做的那样。paramValues[]
指定参数的实际值。此数组中的空指针表示相应参数为 null;否则,指针指向零终止文本字符串(对于文本格式)或服务器期望格式的二进制数据(对于二进制格式)。
paramLengths[]
指定二进制格式参数的实际数据长度。它忽略 null 参数和文本格式参数。当没有二进制参数时,数组指针可以为 null。
paramFormats[]
指定参数是文本(在相应参数的数组条目中放入零)还是二进制(在相应参数的数组条目中放入一)。如果数组指针为 null,则假定所有参数都是文本字符串。
以二进制格式传递的值需要了解后端期望的内部表示形式。例如,整数必须以网络字节序传递。传递
numeric
值需要了解服务器存储格式,如在src/backend/utils/adt/numeric.c::numeric_send()
和src/backend/utils/adt/numeric.c::numeric_recv()
中实现的那样。resultFormat
指定零以文本格式获取结果,或指定一以二进制格式获取结果。(目前没有规定以不同格式获取不同的结果列,尽管这在底层协议中是可能的。)
与PQexec
相比,PQexecParams
的主要优点是参数值可以与命令字符串分开,从而避免了繁琐且容易出错的引用和转义。
与PQexec
不同,PQexecParams
允许给定字符串中最多有一个 SQL 命令。(其中可以有分号,但不能有多个非空命令。)这是底层协议的限制,但作为抵御 SQL 注入攻击的额外防御措施,它有一定的用处。
提示
通过 OID 指定参数类型很繁琐,特别是如果你不想将特定 OID 值硬编码到程序中时。但是,即使在服务器本身无法确定参数类型或选择与你想要的类型不同的类型的情况下,你也可以避免这样做。在 SQL 命令文本中,将显式转换附加到参数符号以显示你将发送的数据类型。例如这会强制将参数$1
视为bigint
,而默认情况下,它将被分配与x
相同的类型。强烈建议通过这种方式或通过指定数字类型 OID 来强制参数类型决策,尤其是在以二进制格式发送参数值时,因为二进制格式的冗余性低于文本格式,因此服务器检测到类型不匹配错误的可能性较小。
PQprepare
#提交一个请求以创建具有给定参数的已准备语句,并等待完成。
PGresult *PQprepare(PGconn *conn, const char *stmtName, const char *query, int nParams, const Oid *paramTypes);
PQprepare
为以后使用PQexecPrepared
执行创建已准备语句。此功能允许重复执行命令,而无需每次都进行解析和规划;有关详细信息,请参见 PREPARE。该函数从
query
字符串(其中必须包含一个 SQL 命令)创建一个名为stmtName
的已准备语句。stmtName
可以是""
以创建一个未命名语句,在这种情况下,任何预先存在的未命名语句都会自动替换;否则,如果在当前会话中已定义语句名称,则会出错。如果使用任何参数,则在查询中将它们称为$1
、$2
等。nParams
是在数组paramTypes[]
中预先指定类型的参数的数量。(当nParams
为零时,数组指针可以是NULL
。)paramTypes[]
通过 OID 指定要分配给参数符号的数据类型。如果paramTypes
是NULL
,或者数组中的任何特定元素为零,则服务器将以与对非类型化字符串文本执行相同的方式将数据类型分配给参数符号。此外,查询可以使用高于nParams
的参数符号;也将为这些符号推断数据类型。(请参见PQdescribePrepared
,了解找出推断出哪些数据类型的办法。)与
PQexec
一样,结果通常是一个PGresult
对象,其内容指示服务器端的成功或失败。空结果表示内存不足或根本无法发送命令。使用PQerrorMessage
获取有关此类错误的更多信息。
也可以通过执行 SQLPREPARE语句来创建用于PQexecPrepared
的预处理语句。此外,虽然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
,但要执行的命令是通过命名先前准备好的语句来指定的,而不是给出一个查询字符串。此功能允许将重复使用的命令仅解析和计划一次,而不是每次执行时都解析和计划。该语句必须在当前会话中预先准备。这些参数与
PQexecParams
相同,不同之处在于给出了预处理语句的名称而不是查询字符串,并且没有paramTypes[]
参数(不需要它,因为预处理语句的参数类型已在创建时确定)。PQdescribePrepared
#提交请求以获取有关指定预处理语句的信息,并等待完成。
PGresult *PQdescribePrepared(PGconn *conn, const char *stmtName);
PQdescribePrepared
允许应用程序获取有关先前准备好的语句的信息。stmtName
可以是""
或NULL
以引用未命名的语句,否则它必须是现有预处理语句的名称。成功时,将返回状态为PGRES_COMMAND_OK
的PGresult
。可以将函数PQnparams
和PQparamtype
应用于此PGresult
以获取有关预处理语句参数的信息,而函数PQnfields
、PQfname
、PQftype
等提供有关语句(如果有)的结果列的信息。PQdescribePortal
#提交请求以获取有关指定门户的信息,并等待完成。
PGresult *PQdescribePortal(PGconn *conn, const char *portalName);
PQdescribePortal
允许应用程序获取有关先前创建的门户的信息。(libpq 不提供对门户的任何直接访问,但你可以使用此函数检查使用DECLARE CURSOR
SQL 命令创建的游标的属性。)portalName
可以是""
或NULL
以引用未命名的门户,否则它必须是现有门户的名称。成功时,将返回状态为PGRES_COMMAND_OK
的PGresult
。可以将函数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
包含当前命令的单个结果元组。仅当为查询选择了单行模式时才会出现此状态(请参阅 第 34.6 节)。PGRES_PIPELINE_SYNC
#当
PQpipelineSync
请求时,PGresult
表示管道模式中的同步点。仅在已选择管道模式时才会出现此状态。PGRES_PIPELINE_ABORTED
#PGresult
表示已从服务器收到错误的管道。必须重复调用PQgetResult
,每次调用都会返回此状态代码,直到当前管道结束,此时它将返回PGRES_PIPELINE_SYNC
,并且可以恢复正常处理。
如果结果状态为
PGRES_TUPLES_OK
或PGRES_SINGLE_TUPLE
,则可以使用下面描述的函数来检索查询返回的行。请注意,碰巧检索到零行的SELECT
命令仍显示PGRES_TUPLES_OK
。PGRES_COMMAND_OK
适用于永远无法返回行的命令(INSERT
或不带RETURNING
子句的UPDATE
等)。PGRES_EMPTY_QUERY
响应可能表明客户端软件存在错误。状态为
PGRES_NONFATAL_ERROR
的结果永远不会由PQexec
或其他查询执行函数直接返回;此类结果将传递给通知处理器(请参见第 34.13 节)。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);
在某些情况下,客户端可能希望获取先前报告的错误的更详细版本。
PQresultVerboseErrorMessage
通过计算当给定的PGresult
被生成时,如果指定的详细设置对连接有效,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 内部生成的错误将具有严重性和主要消息,但通常没有其他字段。
请注意,错误字段仅可从
PGresult
对象获得,而不能从PGconn
对象获得;没有PQerrorField
函数。PQclear
#释放与
PGresult
关联的存储空间。当不再需要每个命令结果时,都应通过PQclear
释放该结果。void PQclear(PGresult *res);
如果参数是
NULL
指针,则不执行任何操作。你可以保留
PGresult
对象,只要你需要它;当你发出新命令时,它不会消失,即使你关闭连接也不会消失。要摆脱它,你必须调用PQclear
。如果不这样做,你的应用程序中会出现内存泄漏。
34.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);
如果列号超出范围,或者如果指定的列不是对表列的简单引用,则返回
InvalidOid
。您可以查询系统表pg_class
以准确确定引用的表。当您包含 libpq 头文件时,将定义类型
Oid
和常量InvalidOid
。它们都将是某种整数类型。PQftablecol
#返回构成指定查询结果列的列(在其表中)的列号。查询结果列号从 0 开始,但表列具有非零编号。
int PQftablecol(const PGresult *res, int column_number);
如果列号超出范围,或者如果指定的列不是对表列的简单引用,则返回零。
PQfformat
#返回指示给定列格式的格式代码。列号从 0 开始。
int PQfformat(const PGresult *res, int column_number);
格式代码零表示文本数据表示,而格式代码一表示二进制表示。(其他代码保留以供将来定义。)
PQftype
#返回与给定列号关联的数据类型。返回的整数是类型的内部 OID 号码。列号从 0 开始。
Oid PQftype(const PGresult *res, int column_number);
您可以查询系统表
pg_type
以获取各种数据类型的名称和属性。内置数据类型的 在 PostgreSQL 安装的include
目录中的文件catalog/pg_type_d.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
返回的值是字段值的以 null 结尾的字符串表示。对于二进制格式的数据,该值采用由数据类型的typsend
和typreceive
函数确定的二进制表示。(在这种情况下,该值实际上后面还跟着一个零字节,但这通常没有用,因为该值可能包含嵌入的 null。)如果字段值为空,则返回一个空字符串。请参阅
PQgetisnull
以区分空值和空字符串值。PQgetvalue
返回的指针指向PGresult
结构的一部分的存储。不应修改它指向的数据,并且如果要在PGresult
结构本身的生命周期后使用数据,则必须将数据显式复制到其他存储中。PQgetisnull
#测试字段的空值。行号和列号从 0 开始。
int PQgetisnull(const PGresult *res, int row_number, int column_number);
如果字段为空,此函数返回 1,如果字段包含非空值,则返回 0。(请注意,
PQgetvalue
将为 null 字段返回一个空字符串,而不是一个 null 指针。)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, /* output stream */ const PGresult *res, const PQprintOpt *po); typedef struct { pqbool header; /* print output field headings and row count */ pqbool align; /* fill align the fields */ pqbool standard; /* old brain dead format */ pqbool html3; /* output HTML tables */ pqbool expanded; /* expand tables */ pqbool pager; /* use pager for output if needed */ char *fieldSep; /* field separator */ char *tableOpt; /* attributes for HTML table element */ char *caption; /* HTML table caption */ char **fieldName; /* null-terminated array of replacement field names */ } PQprintOpt;
此函数以前由 psql 用于打印查询结果,但现在不再使用。请注意,它假定所有数据都为文本格式。
34.3.3. 检索其他结果信息#
这些函数用于从PGresult
对象中提取其他信息。
PQcmdStatus
#从生成
PGresult
的 SQL 命令中返回命令状态标记。char *PQcmdStatus(PGresult *res);
通常,这只是命令的名称,但它可能包括其他数据,例如已处理的行数。调用方不应直接释放结果。当关联的
PGresult
句柄传递给PQclear
时,它将被释放。PQcmdTuples
#返回受 SQL 命令影响的行数。
char *PQcmdTuples(PGresult *res);
此函数返回一个字符串,其中包含受生成
PGresult
的 语句影响的行数。此函数只能在执行SELECT
、CREATE TABLE AS
、INSERT
、UPDATE
、DELETE
、MERGE
、MOVE
、FETCH
或COPY
语句后使用,或执行包含INSERT
、UPDATE
、DELETE
或MERGE
语句的已准备查询的EXECUTE
。如果生成PGresult
的命令是其他任何命令,PQcmdTuples
将返回一个空字符串。调用方不应直接释放返回值。当关联的PGresult
句柄传递给PQclear
时,它将被释放。PQoidValue
#如果 命令是
INSERT
,将插入一行到具有 OID 的表中,或者执行包含合适的INSERT
语句的已准备查询的EXECUTE
,则返回插入行的 OID。否则,此函数返回InvalidOid
。如果受INSERT
语句影响的表不包含 OID,此函数也将返回InvalidOid
。Oid PQoidValue(const PGresult *res);
PQoidStatus
#此函数已弃用,建议使用
PQoidValue
,并且不是线程安全的。它返回一个包含插入行的 OID 的字符串,而PQoidValue
返回 OID 值。char *PQoidStatus(const PGresult *res);
34.3.4. 转义字符串以包含在 SQL 命令中#
PQescapeLiteral
#char *PQescapeLiteral(PGconn *conn, const char *str, size_t length);
PQescapeLiteral
转义字符串以在 SQL 命令中使用。这在将数据值作为 SQL 命令中的文字常量插入时很有用。某些字符(例如引号和反斜杠)必须转义,以防止 SQL 解析器对它们进行特殊解释。PQescapeLiteral
执行此操作。PQescapeLiteral
在使用malloc()
分配的内存中,返回str
参数的转义版本。当不再需要结果时,应使用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
参数的版本,该版本已转义为使用malloc()
分配的内存中的 SQL 标识符。当不再需要结果时,必须使用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
设置为零,在出错时设置为非零。目前,唯一可能出现的错误条件涉及源字符串中的无效多字节编码。输出字符串仍会在出错时生成,但可以预期服务器会将其拒绝为格式错误。出错时,无论error
是否为NULL
,都会在conn
对象中存储一条合适的错误消息。PQescapeStringConn
返回写入to
的字节数,不包括终止零字节。PQescapeString
#PQescapeString
是PQescapeStringConn
的较旧版本,已弃用。size_t PQescapeString (char *to, const char *from, size_t length);
与
PQescapeStringConn
唯一的区别在于PQescapeString
不采用PGconn
或error
参数。因此,它无法根据连接属性(例如字符编码)调整其行为,因此 可能会给出错误的结果。此外,它也没有办法报告错误情况。PQescapeString
可以安全地用于一次只处理一个 PostgreSQL 连接的客户端程序(在这种情况下,它可以找出它需要了解的内容 “幕后”)。在其他情况下,它是一个安全隐患,应该避免使用,而应该使用PQescapeStringConn
。PQescapeByteaConn
#转义二进制数据,以便在类型为
bytea
的 SQL 命令中使用。与PQescapeStringConn
一样,这仅在将数据直接插入 SQL 命令字符串时使用。unsigned char *PQescapeByteaConn(PGconn *conn, const unsigned char *from, size_t from_length, size_t *to_length);
在 语句中用作
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
接收字符串时,不期望字符串“转义”。特别是,这意味着不需要考虑字符串引用,因此不需要PGconn
参数。