UPDATE

Name

UPDATE -- 更新一个表中的行

Synopsis

UPDATE [ ONLY ] table SET column = { expression | DEFAULT } [, ...]
    [ FROM fromlist ]
    [ WHERE condition ]

描述

UPDATE 改变满足条件的所有行的声明了的列/字段的值。 只有要更改的列/字段需要在 SET 子句中出现,没有明确修改的字段保持它们原来的数值。

缺省时,UPDATE 将更新所声明的表和所有子表的记录。 如果你希望只更新所声明的表,你应该使用 ONLY 子句。

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

要更改表,你必须对它有UPDATE 权限, 同样对 expression 或者 condition 条件里提到的任何表也要有SELECT权限。

参数

table

现存表的名称(可以有模式修饰)。

column

table 中字段名。 必要时,字段名可以用子域名或者数组下标修饰。

expression

赋予列/字段的一个有效的值或表达式。表达式可以使用表中这个或其它字段的旧数值。

DEFAULT

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

fromlist

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

condition

一个表达式,返回 boolean 类型。只有这个表达式返回 true 的行被更新。

输出

成功完成后,UPDATE 命令返回形如

UPDATE count

的命令标签。count 是更新的行数。 如果 count 是 0, 那么没有符合 condition 的行(这个不认为是错误)。

注意

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

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

例子

把表 films 里的字段 kind 里的词 DramaDramatic 代替:

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';

增加负责 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');

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

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;

兼容性

这条命令遵循 SQL 标准。 只是 FROM 子句是 PostgreSQL 扩展。

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