pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。
SQL 描述符区域是一种处理SELECT、FETCH或DESCRIBE语句结果的高级方法。SQL 描述符区域将一行数据及其元数据项组合到一个数据结构中。在执行动态 SQL 语句时,结果列的性质可能无法提前获知,此时元数据特别有用。PostgreSQL 提供两种使用描述符区域的方式:命名 SQL 描述符区域和 C 结构体 SQLDA。
一个命名 SQL 描述符区域由一个头部以及一个或多个条目描述符区域构成,头部包含与整个描述符相关的信息,而条目描述符区域则描述结果行中的每一列。
在使用 SQL 描述符区域之前,需要先分配一个:
EXEC SQL ALLOCATE DESCRIPTOR identifier;
identifier 会作为该描述符区域的“变量名”。当不再需要该描述符时,应当释放它:
EXEC SQL DEALLOCATE DESCRIPTOR identifier;
要使用一个描述符区域,把它指定为INTO子句的存储目标(而不是列出主变量):
EXEC SQL FETCH NEXT FROM mycursor INTO SQL DESCRIPTOR mydesc;
如果结果集为空,该描述符区域仍然会包含查询的元数据,即字段的名称。
对于还没有执行的预备查询,DESCRIBE可以被用来得到其结果集的元数据:
EXEC SQL BEGIN DECLARE SECTION; char *sql_stmt = "SELECT * FROM table1"; EXEC SQL END DECLARE SECTION; EXEC SQL PREPARE stmt1 FROM :sql_stmt; EXEC SQL DESCRIBE stmt1 INTO SQL DESCRIPTOR mydesc;
在 PostgreSQL 9.0 之前,SQL关键词是可选的,因此使用DESCRIPTOR和SQL DESCRIPTOR都会产生命名 SQL 描述符区域。现在该关键词是强制性的,省略SQL关键词会产生 SQLDA 描述符区域(见第 33.9.2 节)。
在DESCRIBE和FETCH语句中,INTO和USING关键词的用法相似:它们在描述符区域中生成结果集和元数据。
那么如何从描述符区域中取得数据呢?你可以把描述符区域当作一个包含命名字段的结构。要从头部取得某个字段的值并存入一个主变量,可使用以下命令:
EXEC SQL GET DESCRIPTORname:hostvar=field;
目前只定义了一个头部字段:COUNT,它表示存在多少个条目描述符区域(即结果中包含多少列)。主变量需要是整数类型。要从条目描述符区域取得一个字段,可使用以下命令:
EXEC SQL GET DESCRIPTORnameVALUEnum:hostvar=field;
num可以是一个整数字面量或者一个包含整数的宿主变量。可能的字段有:
CARDINALITY (integer)结果集中的行数
DATA实际的数据项(因此,这个字段的数据类型取决于查询)
DATETIME_INTERVAL_CODE (integer)?
DATETIME_INTERVAL_PRECISION (integer)没有实现
INDICATOR (integer)指示符(表示一个空值或者一个值截断)
KEY_MEMBER (integer)没有实现
LENGTH (integer)以字符计的数据长度
NAME (string)列名
NULLABLE (integer)没有实现
OCTET_LENGTH (integer)以字节计的数据字符表示的长度
PRECISION (integer)精度(用于类型numeric)
RETURNED_LENGTH (integer)以字符计的数据长度
RETURNED_OCTET_LENGTH (integer)以字节计的数据字符表示的长度
SCALE (integer)小数位数(用于类型 numeric)
TYPE (integer)列的数据类型的数字编码
在EXECUTE、DECLARE以及OPEN语句中,INTO和USING关键词的效果不同。也可以手工建立一个描述符区域来为一个查询或者游标提供输入参数,并且USING SQL DESCRIPTOR 是用来传递输入参数给参数化查询的方法。建立一个命名 SQL 描述符区域的语句如下:name
EXEC SQL SET DESCRIPTORnameVALUEnumfield= :hostvar;
PostgreSQL 支持在一条FETCH语句中检索多条记录。在这种情况下,要将数据存入主变量,该变量必须是数组。例如:
EXEC SQL BEGIN DECLARE SECTION; int id[5]; EXEC SQL END DECLARE SECTION; EXEC SQL FETCH 5 FROM mycursor INTO SQL DESCRIPTOR mydesc; EXEC SQL GET DESCRIPTOR mydesc VALUE 1 :id = DATA;
SQLDA 描述符区域是一个 C 语言结构体,它也能被用来得到一个查询的结果集和元数据。一个结构体存储一个来自结果集的记录。
EXEC SQL include sqlda.h; sqlda_t *mysqlda; EXEC SQL FETCH 3 FROM mycursor INTO DESCRIPTOR mysqlda;
注意,这里省略了SQL关键词。第 33.9.1 节中关于INTO和USING关键词用法的说明也适用于这里,并有一项补充规则:在DESCRIBE语句中,如果使用了INTO关键词,就可以完全省略DESCRIPTOR关键词:
EXEC SQL DESCRIBE prepared_statement INTO mysqlda;
The structure of SQLDA is:
#define NAMEDATALEN 64
struct sqlname
{
short length;
char data[NAMEDATALEN];
};
struct sqlvar_struct
{
short sqltype;
short sqllen;
char *sqldata;
short *sqlind;
struct sqlname sqlname;
};
struct sqlda_struct
{
char sqldaid[8];
long sqldabc;
short sqln;
short sqld;
struct sqlda_struct *desc_next;
struct sqlvar_struct sqlvar[1];
};
typedef struct sqlvar_struct sqlvar_t;
typedef struct sqlda_struct sqlda_t;
为一个 SQLDA 结构体分配的数据是可变的,因为它取决于一个结果集中字段的数量,也取决于一条记录中字符串数据值的长度。SQLDA结构的各个字段是:
sqldaid它包含"SQLDA "字面字符串。
sqldabc它包含已分配空间的尺寸(以字节计)。
sqln当它通过USING关键词传递给OPEN、DECLARE或EXECUTE语句时,它包含参数化查询的输入参数个数。如果它用作SELECT、EXECUTE或FETCH语句的输出,其值与sqld相同。
sqld它包含一个结果集中的域的数量。
desc_next如果查询返回不止一个记录,会返回多个链接在一起的 SQLDA 结构体,并且desc_next保存一个指向下一个项的指针。
sqlvar这是结果集中字段的数组。这些字段是:
sqltype包含该字段的类型标识符。值可以参考ecpgtype.h中的enum ECPGttype。
sqllen包含字段的二进制长度,例如ECPGt_int是 4 字节。
sqldata(char *)sqldata 指向数据。
sqlind(char *)sqlind 指向数据的 NULL 指示符。 0 表示 NOT NULL,-1 表示 NULL。
sqlnamestruct sqlname sqlname在一个结构体中包含该字段的名称:
struct sqlname
{
short length;
char data[NAMEDATALEN];
};
lengthsqlname.length包含字段名的长度。
datasqlname.data包含实际的字段名。
译文有误、术语不当或页面显示问题,请到译文仓库 pgsty/pgdoc 报告译文问题。 英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。