UPDATE
Name
UPDATE -- 更新一个表中的行
Synopsis
[ 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
查询中通过名字引用的子查询。参阅Section 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
的方式。移植使用这类扩展的应用时要注意。