选择 打开 改范围 完整检索页

pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。

受支持版本: 当前版本 (18) / 17 / 16 / 15 / 14
测试与开发版本: 19 / devel
不受支持的版本: 13 / 12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0
历史版本PostgreSQL 9.0 已于 2015 年 10 月结束社区维护,本页译文保留供仍在使用旧版本的读者参考。新系统请看当前版本

33.9. 使用描述符区域 #

SQL 描述符区域是一种处理SELECTFETCHDESCRIBE语句结果的高级方法。SQL 描述符区域将一行数据及其元数据项组合到一个数据结构中。在执行动态 SQL 语句时,结果列的性质可能无法提前获知,此时元数据特别有用。PostgreSQL 提供两种使用描述符区域的方式:命名 SQL 描述符区域和 C 结构体 SQLDA。

33.9.1. 命名 SQL 描述符区域 #

一个命名 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关键词是可选的,因此使用DESCRIPTORSQL DESCRIPTOR都会产生命名 SQL 描述符区域。现在该关键词是强制性的,省略SQL关键词会产生 SQLDA 描述符区域(见第 33.9.2 节)。

DESCRIBEFETCH语句中,INTOUSING关键词的用法相似:它们在描述符区域中生成结果集和元数据。

那么如何从描述符区域中取得数据呢?你可以把描述符区域当作一个包含命名字段的结构。要从头部取得某个字段的值并存入一个主变量,可使用以下命令:

EXEC SQL GET DESCRIPTOR name :hostvar = field;

目前只定义了一个头部字段:COUNT,它表示存在多少个条目描述符区域(即结果中包含多少列)。主变量需要是整数类型。要从条目描述符区域取得一个字段,可使用以下命令:

EXEC SQL GET DESCRIPTOR name VALUE num :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)

列的数据类型的数字编码

EXECUTEDECLARE以及OPEN语句中,INTOUSING关键词的效果不同。也可以手工建立一个描述符区域来为一个查询或者游标提供输入参数,并且USING SQL DESCRIPTOR name是用来传递输入参数给参数化查询的方法。建立一个命名 SQL 描述符区域的语句如下:

EXEC SQL SET DESCRIPTOR name VALUE num field = :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;

33.9.2. SQLDA 描述符区域 #

SQLDA 描述符区域是一个 C 语言结构体,它也能被用来得到一个查询的结果集和元数据。一个结构体存储一个来自结果集的记录。

EXEC SQL include sqlda.h;
sqlda_t         *mysqlda;

EXEC SQL FETCH 3 FROM mycursor INTO DESCRIPTOR mysqlda;

注意,这里省略了SQL关键词。第 33.9.1 节中关于INTOUSING关键词用法的说明也适用于这里,并有一项补充规则:在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关键词传递给OPENDECLAREEXECUTE语句时,它包含参数化查询的输入参数个数。如果它用作SELECTEXECUTEFETCH语句的输出,其值与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。

sqlname

struct sqlname sqlname在一个结构体中包含该字段的名称:

struct sqlname
{
        short           length;
        char            data[NAMEDATALEN];
};
length

sqlname.length包含字段名的长度。

data

sqlname.data包含实际的字段名。

提交更正

译文有误、术语不当或页面显示问题,请到译文仓库 pgsty/pgdoc 报告译文问题。 英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。