PostgreSQL 9.4.4 中文手册
上一页 | 上一级 |  | 下一页

# UPDATE

## 名称

UPDATE -- 更新一个表中的行

## 大纲

    [ WITH [ RECURSIVE ] with_query [, ...] ]
    UPDATE [ ONLY ] table_name [ * ] [ [ AS ] alias ]
        SET { column_name = { expression | DEFAULT } |
              ( column_name [, ...] ) = ( { expression | DEFAULT } [, ...] ) } [, ...]
        [ FROM from_list ]
        [ WHERE condition | WHERE CURRENT OF cursor_name ]
        [ RETURNING * | output_expression [ [ AS ] output_name ] [, ...] ]

## 描述

`UPDATE`改变满足条件的所有行中指定的字段值。 只在`SET`子句中出现需要修改的行，没有出现的其他字段保持它们原来的数值。

使用同一数据库里其它表的信息来更新一个表有两种方法：使用子查询， 或者在`FROM`子句里声明另外一个表。哪个方法更好取决于具体的环境。

可选的`RETURNING`子句将导致`UPDATE`基于每个被更新的行计算返回值。 任何使用表的字段的表达式或`FROM`中使用的其他表的字段都可以用于计算。 计算的时候使用刚刚被更新过的字段新值。`RETURNING` 列表的语法与`SELECT`的输出列表相同。

你必须对表或至少在列出的要被更新的字段上有`UPDATE`权限， 同样在`expressions` 或`condition` 条件里提到的任何字段上也要有`SELECT`权限。

## 参数

`with_query`

  `WITH`子句允许声明一个或多个可以在`UPDATE` 查询中通过名字引用的子查询。参阅第 7.8 节 和 SELECT获取详细信息。

`table_name`

  要更新的表的名称(可以有模式修饰)。如果在表名前声明了`ONLY`， 那么只在该表中更新匹配的行。如果没有声明`ONLY`，那么该表的任何继承表内的匹配行也要更新。 可选的，可以在表名后面声明`*`以明确表明包含后代表。

`alias`

  目标表的别名。如果指定了别名，那么它将完全遮盖表的本名。例如，给定 `UPDATE foo AS f`之后，剩余的`UPDATE` 语句必须用`f`而不是`foo`引用这个表。

`column_name`

  表`table_name`中的字段名。必要时， 字段名可以用子域名或者数组下标修饰。不要在指定字段名的时候加上表名字。 比如`UPDATE tab SET tab.col = 1`就是错误的。

`expression`

  给字段赋值的表达式。表达式可以使用这个或其它字段更新前的旧值。

`DEFAULT`

  把字段设置为它的缺省值，如果没有缺省表达式，那么就是 NULL。

`from_list`

  一个表表达式的列表，允许来自其它表中的字段出现在`WHERE`条件里和更新表达式中。 这个类似于可以在一个`SELECT`语句的FROM 子句 子句里声明表列表。请注意目标表绝对不能出现在`from_list`里， 除非你是在使用一个自连接(此时它必须以`from_list`的别名出现)。

`condition`

  一个返回`boolean`结果的表达式。只有这个表达式返回`true`的行才会被更新。

`cursor_name`

  在`WHERE CURRENT OF`条件下使用的游标的名称。要更新的行是最近从该游标中抓去的行。 该游标必须是一个`UPDATE`目标表中的非分组查询。请注意`WHERE CURRENT OF` 不能与布尔条件一起声明。参阅DECLARE获取更多关于通过 `WHERE CURRENT OF`使用游标的信息。

`output_expression`

  在所有需要更新的行都被更新之后，`UPDATE`命令用于计算返回值的表达式。 这个表达式可以使用任何`table_name` 命名的表以及`FROM`中列出的表的字段。写上`*`表示返回所有字段。

`output_name`

  字段的返回名称。

## Outputs

成功完成后，`UPDATE`返回形如

    UPDATE count

的命令标签。`count`是更新的行数， 包括没有改变值的匹配行。请注意当更新受到`BEFORE UPDATE`触发器的抑制时， 这个数字可能小于匹配`condition`的行数。 如果`count`为 0，则没有行被这个查询更新 (这个不认为是错误)。

如果`UPDATE`包含`RETURNING`子句，那么返回的结果将类似于包含在 `RETURNING`列表中定义的字段和值的`SELECT`语句， 只不过返回结果是基于被更新的行而已。

## 注意

在出现`FROM`子句的时候，实际上发生的事情是目标表和`from_list` 里提到的表连接在一起，并且每个连接输出行都代表一个目标表的更新操作。 在使用`FROM`的时候，你应该保证连接为每个需要修改的行最多生成一个输出行。 换句话说，一个目标行不应该和超过一行来自其它表的数据行连接。如果它连接了多于一个行， 那么连接行里面将会只有一行用于更新目标行，但是究竟使用哪行是很难预期的事情。

因为这个不确定性，只在子查询里面引用其它表是安全的，尽管通常更难读并且比使用连接也更慢些。

## 例子

把表`films`里的字段`kind`里的词 `Drama`用`Dramatic`代替：

    UPDATE films SET kind = 'Dramatic' WHERE kind = 'Drama';

调整表`weather`中的某行的温度并把该行的降水量设置为缺省值：

    UPDATE weather SET temp_lo = temp_lo+1, temp_hi = temp_lo+15, prcp = DEFAULT
      WHERE city = 'San Francisco' AND date = '2003-07-03';

做同样的事情并返回更新后的条目：

    UPDATE weather SET temp_lo = temp_lo+1, temp_hi = temp_lo+15, prcp = DEFAULT
      WHERE city = 'San Francisco' AND date = '2003-07-03'
      RETURNING temp_lo, temp_hi, prcp;

使用另一种字段列表语法来做同样的事情：

    UPDATE weather SET (temp_lo, temp_hi, prcp) = (temp_lo+1, temp_lo+15, DEFAULT)
      WHERE city = 'San Francisco' AND date = '2003-07-03';

增加负责 Acme 公司客户的销售员的销售计数，使用`FROM`子句语法：

    UPDATE employees SET sales_count = sales_count + 1 FROM accounts
      WHERE accounts.name = 'Acme Corporation'
      AND employees.id = accounts.sales_person;

使用`WHERE`子句里的子查询执行同样的操作：

    UPDATE employees SET sales_count = sales_count + 1 WHERE id =
      (SELECT sales_person FROM accounts WHERE name = 'Acme Corporation');

试图带着库存量插入一个新的库存项。如果该项存在，则更新现有项的库存数。 要做这件事情而又不使整个事务失效，使用保留点。

    BEGIN;
    -- 其它操作
    SAVEPOINT sp1;
    INSERT INTO wines VALUES('Chateau Lafite 2003', '24');
    -- 假设上面因为一个唯一键字违例而失效，
    -- 因此现在发出这些命令：
    ROLLBACK TO sp1;
    UPDATE wines SET stock = stock + 24 WHERE winename = 'Chateau Lafite 2003';
    -- 继续其它操作，最后
    COMMIT;

更改表`films`的`kind`列， 在游标`c_films`目前定位的行上：

    UPDATE films SET kind = 'Dramatic' WHERE CURRENT OF c_films;

## 兼容性

这条命令遵循SQL标准。只是`FROM`和`RETURNING` 子句是PostgreSQL扩展，就像和`UPDATE`一起使用`WITH`。

标准的字段列表语法允许从行值表达式指定字段列表，比如一个子查询：

    UPDATE accounts SET (contact_last_name, contact_first_name) =
        (SELECT last_name, first_name FROM salesmen
         WHERE salesmen.id = accounts.sales_id);

这个功能目前尚未实现：源必须是一个独立的表达式。

有些其它数据库系统提供一个`FROM`选项，在这个选项下， 认为目标表会再次在`FROM`里列出。这不是PostgreSQL 解析`FROM`的方式。移植使用这类扩展的应用时要注意。

上一页 | 起始页 | 下一页
UNLISTEN | 上一级 | VACUUM