↑↓ 选择 ↵ 打开 ⌫ 改范围 完整检索页

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

不受支持的版本: 7.1 / 7.0 / 6.5
历史版本PostgreSQL 7.1 已于 2006 年 4 月结束社区维护,本页译文保留供仍在使用旧版本的读者参考。新系统请看当前版本手册首页。

1.4. SQL 语言 #

与大多数现代关系语言一样,SQL 基于元组关系演算。 因此,每个能用元组关系演算(或者等价地,关系代数)表述的查询也都能用 SQL 表述。不过,SQL 也有一些超出 关系代数或演算范围的能力。下面列出 SQL 提供的一些 不属于关系代数或演算的附加特性:

  • 用于插入、删除或修改数据的命令。

  • 算术能力:在 SQL 中可以使用算术运算和比较,例如:

    A < B + 3.
    

    注意 + 或其他算术操作符既不出现在关系代数中,也不出现在关系演算中。

  • 赋值和打印命令:可以打印由查询构造出的关系,也可以把计算得到的关系 赋给一个关系名。

  • 聚合函数:可以对关系的列应用诸如平均值、 求和、最大值等操作, 以获得单一的量。

1.4.1. Select #

SQL 中最常用的命令是用于检索数据的 SELECT 语句。其语法为:

SELECT [ ALL | DISTINCT [ ON ( expression [, ...] ) ] ]
    * | expression [ AS output_name ] [, ...]
    [ INTO [ TEMPORARY | TEMP ] [ TABLE ] new_table ]
    [ FROM from_item [, ...] ]
    [ WHERE condition ]
    [ GROUP BY expression [, ...] ]
    [ HAVING condition [, ...] ]
    [ { UNION | INTERSECT | EXCEPT [ ALL ] } select ]
    [ ORDER BY expression [ ASC | DESC | USING operator ] [, ...] ]
    [ FOR UPDATE [ OF class_name [, ...] ] ]
    [ LIMIT { count | ALL } [ { OFFSET | , } start ]]
     

下面我们将用各种示例来说明 SELECT 语句的复杂语法。示例所用的表定义于 供应商与零件数据库。

1.4.1.1. 简单 Select

下面是一些使用 SELECT 语句的简单示例:

例 1.4. 带限定条件的简单查询

要检索表 PART 中属性 PRICE 大于 10 的所有元组,我们写出如下查询:

SELECT * FROM PART
    WHERE PRICE > 10;
        

并得到表:

 PNO |  PNAME  |  PRICE
-----+---------+--------
  3  |  Bolt   |   15
  4  |  Cam    |   25
        

在 SELECT 语句中使用 "*" 将交付该表的所有属性。如果只想检索表 PART 的属性 PNAME 和 PRICE,我们使用如下语句:

SELECT PNAME, PRICE 
    FROM PART
    WHERE PRICE > 10;
        

此时结果为:

                      PNAME  |  PRICE
                     --------+--------
                      Bolt   |   15
                      Cam    |   25
        

注意,SQL 的 SELECT 对应于关系代数中的"投影"而不是"选择"(更多细节见 关系代数)。

WHERE 子句中的限定条件也可以用关键字 OR、AND 和 NOT 进行逻辑连接:

SELECT PNAME, PRICE 
    FROM PART
    WHERE PNAME = 'Bolt' AND
         (PRICE = 0 OR PRICE <= 15);
        

将得到结果:

 PNAME  |  PRICE
--------+--------
 Bolt   |   15
        

目标列表和 WHERE 子句中可以使用算术运算。例如,如果我们想知道取一个零件的两件要花多少钱,可以用如下查询:

SELECT PNAME, PRICE * 2 AS DOUBLE
    FROM PART
    WHERE PRICE * 2 < 50;
        

我们得到:

 PNAME  |  DOUBLE
--------+---------
 Screw  |    20
 Nut    |    16
 Bolt   |    30
        

注意,关键字 AS 之后的单词 DOUBLE 是第二列的新标题。此技术可用于目标列表的每个元素,为结果列指派新标题。这个新标题通常称为别名。别名不能在查询的其余部分中使用。


1.4.1.2. 连接

下面的示例演示了SQL中如何实现连接。

要通过公共属性连接 SUPPLIER、PART 和 SELLS 三张表,我们表述如下语句:

SELECT S.SNAME, P.PNAME
    FROM SUPPLIER S, PART P, SELLS SE
    WHERE S.SNO = SE.SNO AND
          P.PNO = SE.PNO;

并得到以下表作为结果:

 SNAME | PNAME
-------+-------
 Smith | Screw
 Smith | Nut
 Jones | Cam
 Adams | Screw
 Adams | Bolt
 Blake | Nut
 Blake | Bolt
 Blake | Cam
      

在 FROM 子句中,我们为每个关系引入了一个别名,因为这些关系之间存在 同名属性(SNO 和 PNO)。现在只需在属性名前加上别名和一个点号,就可以 区分这些同名属性。连接的计算方式与 一个内连接中所示的相同。 首先导出笛卡尔积 SUPPLIER × PART × SELLS 然后只选出满足 WHERE 子句所给条件的元组(即同名属性必须相等)。 最后把除 S.SNAME 和 P.PNAME 之外的所有列都投影出去。

执行连接的另一种方式是使用 SQL 的 JOIN 语法,如下所示:

select sname, pname from supplier
    JOIN sells USING (sno)
    JOIN part USING (pno);

同样得到:

 sname | pname
-------+-------
 Smith | Screw
 Adams | Screw
 Smith | Nut
 Blake | Nut
 Adams | Bolt
 Blake | Bolt
 Jones | Cam
 Blake | Cam
(8 rows) 
         

使用 JOIN 语法创建的连接表是出现在 FROM 子句中、并且位于任何 WHERE、 GROUP BY 或 HAVING 子句之前的表引用列表项。其他表引用(包括表名或 其他 JOIN 子句)只要用逗号分隔,也可以包含在 FROM 子句中。连接表在 逻辑上与 FROM 子句中列出的其他任何表一样。

SQL 的 JOIN 分为两大类型:CROSS JOIN(非限定连接)和 限定 JOIN。限定连接还可以进一步按 连接条件的指定方式(ON、USING 或 NATURAL) 以及应用方式(INNER 或 OUTER 连接)细分。

连接类型

CROSS JOIN

{ T1 } CROSS JOIN { T2 }

交叉连接取分别有 N 行和 M 行的两张表 T1 和 T2,返回包含所有 N*M 种可能连接行的连接表。对 T1 的每一行 R1,T2 的每一行 R2 都与 R1 连接,产生由 R1 和 R2 的所有字段组成的连接表行 JR。 CROSS JOIN 等价于 INNER JOIN ON TRUE。

限定 JOIN

{ T1 } [ NATURAL ] [[ INNER ] | [ { LEFT | RIGHT | FULL } [ OUTER ] ]] JOIN { T2 } {[ ON search condition] | [ USING ( join column list ) ]}

限定 JOIN 必须通过给出 NATURAL、ON 或 USING 三者之一(且仅一者) 来指定其连接条件。ON 子句接受一个 search condition(搜索条件),它与 WHERE 子句中的相同。 USING 子句接受一个逗号分隔的列名列表,这些列是两张被连接表所 共有的,连接在这些列相等的基础上进行。NATURAL 是 USING 子句的 简写形式,它列出两张表所有公共列名。USING 和 NATURAL 都有一个 副作用:每个被连接列只有一份副本会输出到结果表中(对比前面给出 的 JOIN 的关系代数定义)。

[ INNER ] JOIN

对 T1 的每一行 R1,连接表都为 T2 中满足与 R1 的连接条件的 每一行各包含一行。

提示

对所有 JOIN 而言,单词 INNER 和 OUTER 都是可选的。 INNER 是默认值。LEFT、RIGHT 和 FULL 意味着 OUTER JOIN。

LEFT [ OUTER ] JOIN

首先执行 INNER JOIN。然后,对 T1 中不满足与 T2 任何行的 连接条件的每一行,额外返回一个连接行,其来自 T2 的列为 空值。

提示

连接表无条件地为 T1 的每一行各包含一行。

RIGHT [ OUTER ] JOIN

首先执行 INNER JOIN。然后,对 T2 中不满足与 T1 任何行的 连接条件的每一行,额外返回一个连接行,其来自 T1 的列为 空值。

提示

连接表无条件地为 T2 的每一行各包含一行。

FULL [ OUTER ] JOIN

首先执行 INNER JOIN。然后,对 T1 中不满足与 T2 任何行的 连接条件的每一行,额外返回一个连接行,其来自 T2 的列为 空值。 同样,对 T2 中不满足与 T1 任何行的连接条件的每一行,额外返回 一个连接行,其来自 T1 的列为空值。

提示

连接表无条件地为 T1 的每一行和 T2 的每一行各包含一行。

所有类型的 JOIN 都可以串联或嵌套在一起, T1 和 T2 之一或两者都可以是 连接表。可以在 JOIN 子句周围使用圆括号来控制 JOIN 的顺序, 否则 JOIN 按从左到右的顺序处理。

1.4.1.3. 聚合函数

SQL 提供聚合运算符 (例如 AVG、COUNT、SUM、MIN、MAX),它们接受一个表达式作为参数。该表达式在满足 WHERE 子句的每一行上求值,聚合运算符就在这组输入值上计算。通常,一个聚合为整个 SELECT 语句交付单个结果。但如果查询中指定了分组,则会对每个组的行分别计算,每个组交付一个聚合结果(见下一节)。

例 1.5. 聚合

如果我们想知道表 PART 中所有零件的平均价格,使用以下查询:

SELECT AVG(PRICE) AS AVG_PRICE
    FROM PART;
        

结果是:

 AVG_PRICE
-----------
   14.5
        

如果我们想知道表 PART 中定义了多少个零件,使用语句:

SELECT COUNT(PNO)
    FROM PART;
        

并得到:

 COUNT
-------
   4
        


1.4.1.4. 按组聚合

SQL 允许把表的元组划分成组。然后就可以把上面描述的聚合运算符应用到这些组上——即聚合运算符的值不再是对指定列的所有值计算,而是对一个组的所有值计算。这样,聚合运算符会对每个组分别求值。

把元组划分成组的工作通过关键字 GROUP BY 后跟定义 组的属性列表来完成。如果有 GROUP BY A1, [tdot ], Ak, 我们就把关系划分为若干组,使得两个元组处于同一组当且仅当它们在所有 属性 A1, [tdot ], Ak 上 都一致。

例 1.6. 聚合

如果我们想知道每个供应商销售多少个零件,可以表述如下查询:

SELECT S.SNO, S.SNAME, COUNT(SE.PNO)
    FROM SUPPLIER S, SELLS SE
    WHERE S.SNO = SE.SNO
    GROUP BY S.SNO, S.SNAME;
        

并得到:

 SNO | SNAME | COUNT
-----+-------+-------
  1  | Smith |   2
  2  | Jones |   1
  3  | Adams |   2
  4  | Blake |   3
        

现在来看看这里发生了什么。首先导出表 SUPPLIER 和 SELLS 的连接:

 S.SNO | S.SNAME | SE.PNO
-------+---------+--------
   1   |  Smith  |   1
   1   |  Smith  |   2
   2   |  Jones  |   4
   3   |  Adams  |   1
   3   |  Adams  |   3
   4   |  Blake  |   2
   4   |  Blake  |   3
   4   |  Blake  |   4
        

接下来,把在 S.SNO 和 S.SNAME 两个属性上都一致的元组放在一起, 将元组划分为组:

 S.SNO | S.SNAME | SE.PNO
-------+---------+--------
   1   |  Smith  |   1
                 |   2
--------------------------
   2   |  Jones  |   4
--------------------------
   3   |  Adams  |   1
                 |   3
--------------------------
   4   |  Blake  |   2
                 |   3
                 |   4
        

在我们的例子中得到了四个组,现在可以对每个组应用聚合函数 COUNT, 从而得到上面给出的查询最终结果。


注意,要让一个使用 GROUP BY 和聚合函数的查询有意义,目标列表只能直接 引用被分组的那些属性。其他属性只能用在聚合函数的参数内部。否则, 其他属性就无法关联到一个唯一的值。

还要注意,请求聚合的聚合(例如 AVG(MAX(sno)))是没有意义的,因为 SELECT 只做一轮分组和聚合。你可以通过临时表或 FROM 子句中的子 SELECT 完成第一级聚合来得到这类结果。

1.4.1.5. Having

HAVING 子句的作用与 WHERE 子句很像,用于只考虑满足 HAVING 子句中限定条件的那些组。本质上,WHERE 在分组和聚合之前过滤掉不需要的输入行,而 HAVING 在 GROUP 之后过滤掉不需要的组行。因此,WHERE 不能引用聚合函数的结果。另一方面,写不涉及聚合函数的 HAVING 条件毫无意义!如果你的条件不涉及聚合,不妨直接把它写进 WHERE,从而避免为反正要丢弃的组计算聚合。

例 1.7. Having

如果我们只想要销售多于一个零件的供应商,我们使用如下查询:

SELECT S.SNO, S.SNAME, COUNT(SE.PNO)
    FROM SUPPLIER S, SELLS SE
    WHERE S.SNO = SE.SNO
    GROUP BY S.SNO, S.SNAME
    HAVING COUNT(SE.PNO) > 1;
        

并得到:

 SNO | SNAME | COUNT
-----+-------+-------
  1  | Smith |   2
  3  | Adams |   2
  4  | Blake |   3
        


1.4.1.6. 子查询

在 WHERE 和 HAVING 子句中,凡是期望一个值的地方都允许使用子查询(子 SELECT)。此时该值必须先通过求值子查询得出。子查询的使用扩展了 SQL 的表达能力。

例 1.8. 子选择

如果我们想知道所有比名为 'Screw' 的零件价格更高的零件,我们使用如下查询:

SELECT * 
    FROM PART 
    WHERE PRICE > (SELECT PRICE FROM PART
                   WHERE PNAME='Screw');
        

结果是:

 PNO |  PNAME  |  PRICE
-----+---------+--------
  3  |  Bolt   |   15
  4  |  Cam    |   25
        

观察上面的查询可以看到关键字 SELECT 出现了两次。第一次在查询的开头——我们称之为外层 SELECT——另一次在 WHERE 子句中,它开始一个嵌套查询——我们称之为内层 SELECT。对外层 SELECT 的每个元组,都必须求值内层 SELECT。每次求值后我们就知道了名为 'Screw' 的元组的价格,从而可以检查当前元组的价格是否更大。(实际上在本例中,内层查询只需求值一次,因为它不依赖外层查询的状态。)

如果我们想知道没有销售任何零件的供应商(例如,以便能从数据库中删除 这些供应商),使用:

SELECT * 
    FROM SUPPLIER S
    WHERE NOT EXISTS
        (SELECT * FROM SELLS SE
         WHERE SE.SNO = S.SNO);
        

在本例中结果将为空,因为每个供应商都至少销售一个零件。注意我们在内层 SELECT 的 WHERE 子句中使用了来自外层 SELECT 的 S.SNO。这里子查询必须对外层查询的每个元组重新求值,即 S.SNO 的值总是取自外层 SELECT 的当前元组。


1.4.1.7. FROM 中的子查询

使用子查询的一种略有不同的方式是把它们放到 FROM 子句中。这是一个 有用的特性,因为这种子查询可以输出多列多行,而用在表达式中的子查询 必须只给出单个结果。它还让我们无需借助临时表就能进行不止一轮的 分组/聚合。

例 1.9. FROM 中的子选择

如果我们想知道所有供应商中最高的平均零件价格,不能写成 MAX(AVG(PRICE)),但可以写成:

SELECT MAX(subtable.avgprice)
    FROM (SELECT AVG(P.PRICE) AS avgprice
          FROM SUPPLIER S, PART P, SELLS SE
          WHERE S.SNO = SE.SNO AND
                P.PNO = SE.PNO
          GROUP BY S.SNO) subtable;

子查询为每个供应商返回一行(因为它有 GROUP BY),然后我们在外层 查询中对这些行进行聚合。


1.4.1.8. Union, Intersect, Except

这些操作计算两个子查询所得元组的并集、交集和集合论差。

例 1.10. Union, Intersect, Except

下面的查询是 UNION 的例子:

SELECT S.SNO, S.SNAME, S.CITY
    FROM SUPPLIER S
    WHERE S.SNAME = 'Jones'
UNION
    SELECT S.SNO, S.SNAME, S.CITY
    FROM SUPPLIER S
    WHERE S.SNAME = 'Adams';

给出结果:

 SNO | SNAME |  CITY
-----+-------+--------
  2  | Jones | Paris
  3  | Adams | Vienna
        

下面是 INTERSECT 的例子:

SELECT S.SNO, S.SNAME, S.CITY
    FROM SUPPLIER S
    WHERE S.SNO > 1
INTERSECT
    SELECT S.SNO, S.SNAME, S.CITY
    FROM SUPPLIER S
    WHERE S.SNO < 3;
        

给出结果:

 SNO | SNAME |  CITY
-----+-------+--------
  2  | Jones | Paris
        

查询两部分都返回的唯一元组是 SNO=2 的那一个。

最后是 EXCEPT 的例子:

SELECT S.SNO, S.SNAME, S.CITY
    FROM SUPPLIER S
    WHERE S.SNO > 1
EXCEPT
    SELECT S.SNO, S.SNAME, S.CITY
    FROM SUPPLIER S
    WHERE S.SNO > 3;
        

给出结果:

 SNO | SNAME |  CITY
-----+-------+--------
  2  | Jones | Paris
  3  | Adams | Vienna
        


1.4.2. 数据定义 #

SQL 语言中包含一组用于数据定义的命令。

1.4.2.1. 创建表 #

数据定义最基本的命令是创建新关系(新表)的命令。 CREATE TABLE 命令的语法为:

CREATE TABLE table_name
    (name_of_attr_1 type_of_attr_1
     [, name_of_attr_2 type_of_attr_2 
     [, ...]]);
      

例 1.11. 创建表

要创建供应商与零件数据库中定义的表, 使用以下 SQL 语句:

CREATE TABLE SUPPLIER
    (SNO   INTEGER,
     SNAME VARCHAR(20),
     CITY  VARCHAR(20));
     
CREATE TABLE PART
    (PNO   INTEGER,
     PNAME VARCHAR(20),
     PRICE DECIMAL(4 , 2));
     
CREATE TABLE SELLS
    (SNO INTEGER,
     PNO INTEGER);
        


1.4.2.2. SQL 中的数据类型

下面是 SQL 支持的一些数据类型的列表:

  • INTEGER:有符号全字二进制整数(31 位精度)。

  • SMALLINT:有符号半字二进制整数(15 位精度)。

  • DECIMAL(p[,q]): 有符号压缩十进制数,最多 p 位数字,其中小数点右边有 q 位数字。如果省略 q,则假定为 0。

  • FLOAT:有符号双字浮点数。

  • CHAR(n): 长度为 n 的定长 字符串。

  • VARCHAR(n): 最大长度为 n 的 变长字符串。

1.4.2.3. 创建索引

索引用来加快对关系的访问。如果关系 R 在属性 A 上有一个索引,那么检索所有满足 t(A) = a 的元组 t 时,所需时间大致与这类元组 t 的数量成正比,而不再与 R 的大小成正比。

要在 SQL 中创建索引,使用 CREATE INDEX 命令。其语法为:

CREATE INDEX index_name 
    ON table_name ( name_of_attribute );
      

例 1.12. 创建索引

要在关系 SUPPLIER 的属性 SNAME 上创建名为 I 的索引,使用以下语句:

CREATE INDEX I ON SUPPLIER (SNAME);
      

创建的索引会被自动维护,即每当有新元组插入关系 SUPPLIER 时,索引 I 都会随之调整。注意,存在索引时用户能察觉到的唯一变化是 SELECT 的速度提高和更新的速度降低。


1.4.2.4. 创建视图

视图可以被看作一张虚拟表,即一张在数据库中 并不物理存在、但在用户看来好像存在的表。相比之下, 当我们谈论基表时,表的每一行在物理存储中的 某处确实有一个物理存储的对应物。

视图没有自己的、物理上独立、可区分的存储数据。系统只是把视图的定义 (即如何访问物理存储的基表以物化该视图的规则)存储在系统目录的某个 地方(见 系统目录)。 关于实现视图的不同技术的讨论,参见 SIM98。

在 SQL 中使用 CREATE VIEW 命令定义视图。语法为:

CREATE VIEW view_name
    AS select_stmt

其中 select_stmt 是一个 如Select中所定义的有效的 select 语句。注意,创建视图时并不执行 select_stmt,它只是被存储在 系统目录中,每当对视图进行查询时才被执行。

给定下面的视图定义(我们再次使用 供应商与零件数据库中的表):

CREATE VIEW London_Suppliers
    AS SELECT S.SNAME, P.PNAME
        FROM SUPPLIER S, PART P, SELLS SE
        WHERE S.SNO = SE.SNO AND
              P.PNO = SE.PNO AND
              S.CITY = 'London';
      

现在我们就可以像使用另一张基表一样使用这个 虚拟关系 London_Suppliers:

SELECT * FROM London_Suppliers
    WHERE PNAME = 'Screw';

它将返回以下表:

 SNAME | PNAME
-------+-------
 Smith | Screw                 
      

为了计算这个结果,数据库系统必须先隐蔽地访问 基表 SUPPLIER、SELLS 和 PART。它通过对这些基表执行视图定义中给出的 查询来完成这一步。之后,再应用(针对视图的查询中给出的)附加限定条件, 即可得到结果表。

1.4.2.5. Drop Table、Drop Index、Drop View

要销毁一个表(包括该表中存储的所有元组),使用 DROP TABLE 命令:

DROP TABLE table_name;
       

要销毁 SUPPLIER 表,使用以下语句:

DROP TABLE SUPPLIER;
      

要销毁一个索引,使用 DROP INDEX 命令:

DROP INDEX index_name;
      

最后,要销毁一个给定的视图,使用命令 DROP VIEW:

DROP VIEW view_name;
      

1.4.3. 数据操纵

1.4.3.1. Insert Into

一旦创建了表(见 创建表),就可以用 INSERT INTO 命令向其中填入元组。语法为:

INSERT INTO table_name (name_of_attr_1 
    [, name_of_attr_2 [,...]])
    VALUES (val_attr_1 [, val_attr_2 [, ...]]);
      

要向关系 SUPPLIER(来自 供应商与零件数据库)插入第一个元组, 使用以下语句:

INSERT INTO SUPPLIER (SNO, SNAME, CITY)
    VALUES (1, 'Smith', 'London');
      

要向关系 SELLS 插入第一个元组,使用:

INSERT INTO SELLS (SNO, PNO)
    VALUES (1, 1);
      

1.4.3.2. Update

要更改关系中元组的一个或多个属性值,使用 UPDATE 命令。其语法为:

UPDATE table_name
    SET name_of_attr_1 = value_1 
        [, ... [, name_of_attr_k = value_k]]
    WHERE condition;
      

要修改关系 PART 中零件'Screw'的属性 PRICE 的值,使用:

UPDATE PART
    SET PRICE = 15
    WHERE PNAME = 'Screw';
      

名为'Screw'的元组的属性 PRICE 的新值现在是 15。

1.4.3.3. Delete

要从特定的表中删除元组,使用 DELETE FROM 命令。语法为:

DELETE FROM table_name
    WHERE condition;
      

要删除表 SUPPLIER 中名为'Smith'的供应商,使用以下语句:

DELETE FROM SUPPLIER
    WHERE SNAME = 'Smith';
      

1.4.4. 系统目录 #

在每个 SQL 数据库系统中,都使用 系统目录来记录数据库中定义了哪些表、视图、 索引等。这些系统目录可以像普通关系一样被查询。例如,有一个用于视图 定义的目录,该目录存储视图定义中的查询。每当对视图进行查询时,系统 首先从目录中取出视图定义查询并物化该视图, 然后再继续处理用户的查询(更详细的描述见 Simkovics, 1998 )。关于系统目录的更多信息,参见 Date, 1994 。

1.4.5. 嵌入式 SQL

本节将概述如何把 SQL 嵌入到宿主语言 (例如 C)中。我们想从宿主语言中使用 SQL 有两个主要原因:

  • 有些查询无法用纯 SQL 表述(即递归查询)。要能够 执行这类查询,我们需要一种表达能力比 SQL 更强 的宿主语言。

  • 我们只是想从用宿主语言编写的应用程序访问数据库(例如,一个带图形 用户界面的订票系统用 C 编写,而关于还剩哪些票的信息存储在可以用 嵌入式 SQL 访问的数据库中)。

在宿主语言中使用嵌入式 SQL 的程序由宿主语言的 语句和嵌入式 SQL (ESQL)语句组成。每条 ESQL 语句都以关键字 EXEC SQL 开头。 ESQL 语句由预编译器转换成 宿主语言的语句(预编译器通常会插入对库例程的调用,由这些例程执行各种 SQL 命令)。

纵观 Select 中的示例可以意识到,查询的结果常常是一个元组的集合。而大多数宿主语言并非为操作集合而设计,因此我们需要一种机制来访问 SELECT 语句返回的元组集合中的每一个元组。这一机制可以通过声明一个游标来提供。之后我们就可以用 FETCH 命令检索一个元组并把游标移到下一个元组。

关于嵌入式 SQL 的详细讨论,参见 Date and Darwen, 1997 、 Date, 1994 或 Ullman, 1988 。

提交更正

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