Postgresql 中文操作指南

UPDATE

UPDATE — 更新表的行

UPDATE — update rows of a table

Synopsis

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

Description

UPDATE 更改与条件相符的所有行中的指定列的值。仅需在 SET 子句中提及要修改的列;未明确修改的列保留其先前的值。

UPDATE changes the values of the specified columns in all rows that satisfy the condition. Only the columns to be modified need be mentioned in the SET clause; columns not explicitly modified retain their previous values.

有两种方法可以用包含在数据库中的其他表中的信息来修改表:使用子查询,或者在 FROM 子句中指定附加表。采用哪种技术取决于具体情况。

There are two ways to modify a table using information contained in other tables in the database: using sub-selects, or specifying additional tables in the FROM clause. Which technique is more appropriate depends on the specific circumstances.

可选的 RETURNING 子句导致 UPDATE 计算并根据每个实际更新的行返回一个或多个值。可以使用表的列和/或 FROM 中提到的其他表的列来计算任何表达式。用于表的列的新(更新后)值。 RETURNING 列表的语法与 SELECT 的输出列表相同。

The optional RETURNING clause causes UPDATE to compute and return value(s) based on each row actually updated. Any expression using the table’s columns, and/or columns of other tables mentioned in FROM, can be computed. The new (post-update) values of the table’s columns are used. The syntax of the RETURNING list is identical to that of the output list of SELECT.

您必须对表(或至少列出要更新的列)具有 UPDATE 权限。您还必须对在 expressionscondition 中读取其值的任何列具有 SELECT 权限。

You must have the UPDATE privilege on the table, or at least on the column(s) that are listed to be updated. You must also have the SELECT privilege on any column whose values are read in the expressions or condition.

Parameters

  • with_query

    • The WITH clause allows you to specify one or more subqueries that can be referenced by name in the UPDATE query. See Section 7.8 and SELECT for details.

  • table_name

    • The name (optionally schema-qualified) of the table to update. If ONLY is specified before the table name, matching rows are updated in the named table only. If ONLY is not specified, matching rows are also updated in any tables inheriting from the named table. Optionally, * can be specified after the table name to explicitly indicate that descendant tables are included.

  • alias

    • A substitute name for the target table. When an alias is provided, it completely hides the actual name of the table. For example, given UPDATE foo AS f, the remainder of the UPDATE statement must refer to this table as f not foo.

  • column_name

    • The name of a column in the table named by table_name. The column name can be qualified with a subfield name or array subscript, if needed. Do not include the table’s name in the specification of a target column — for example, UPDATE table_name SET table_name.col = 1 is invalid.

  • expression

    • An expression to assign to the column. The expression can use the old values of this and other columns in the table.

  • DEFAULT

    • Set the column to its default value (which will be NULL if no specific default expression has been assigned to it). An identity column will be set to a new value generated by the associated sequence. For a generated column, specifying this is permitted but merely specifies the normal behavior of computing the column from its generation expression.

  • sub-SELECT

    • A SELECT sub-query that produces as many output columns as are listed in the parenthesized column list preceding it. The sub-query must yield no more than one row when executed. If it yields one row, its column values are assigned to the target columns; if it yields no rows, NULL values are assigned to the target columns. The sub-query can refer to old values of the current row of the table being updated.

  • from_item

    • A table expression allowing columns from other tables to appear in the WHERE condition and update expressions. This uses the same syntax as the FROM clause of a SELECT statement; for example, an alias for the table name can be specified. Do not repeat the target table as a from_item unless you intend a self-join (in which case it must appear with an alias in the from_item).

  • condition

    • An expression that returns a value of type boolean. Only rows for which this expression returns true will be updated.

  • cursor_name

    • The name of the cursor to use in a WHERE CURRENT OF condition. The row to be updated is the one most recently fetched from this cursor. The cursor must be a non-grouping query on the UPDATE's target table. Note that WHERE CURRENT OF cannot be specified together with a Boolean condition. See DECLARE for more information about using cursors with WHERE CURRENT OF.

  • output_expression

    • An expression to be computed and returned by the UPDATE command after each row is updated. The expression can use any column names of the table named by table_name or table(s) listed in FROM. Write * to return all columns.

  • output_name

    • A name to use for a returned column.

Outputs

成功完成后, UPDATE 命令返回形式为以下的命令标记

On successful completion, an UPDATE command returns a command tag of the form

UPDATE count

count 是所更新行的数量,包括未更改值且匹配的行。请注意,这个数字可能小于匹配 condition 的行数,当更新被 BEFORE UPDATE 触发器禁止时会出现这种情况。如果 count 为 0,那么没有任何行被查询更新(这不是错误)。

The count is the number of rows updated, including matched rows whose values did not change. Note that the number may be less than the number of rows that matched the condition when updates were suppressed by a BEFORE UPDATE trigger. If count is 0, no rows were updated by the query (this is not considered an error).

如果 UPDATE 命令包含 RETURNING 从句,则结果会类似于 SELECT 语句,其中包含 RETURNING 列表中定义的列和值,并根据该命令更新的行来计算出来。

If the UPDATE command contains a RETURNING clause, the result will be similar to that of a SELECT statement containing the columns and values defined in the RETURNING list, computed over the row(s) updated by the command.

Notes

FROM 从句在场时,实际上会发生目标表连接到 from_item 列表中所提及的表,并且连接的每个输出行表示针对目标表的更新操作。使用 FROM 时,您应确保该连接针对要修改的每行最多产生一个输出行。换句话说,目标行不应该连接到其他表中的两行。如果确实发生了这种情况,那么将只用其中一个连接行来更新目标行,但是无法轻易预测将使用哪一个连接行。

When a FROM clause is present, what essentially happens is that the target table is joined to the tables mentioned in the from_item list, and each output row of the join represents an update operation for the target table. When using FROM you should ensure that the join produces at most one output row for each row to be modified. In other words, a target row shouldn’t join to more than one row from the other table(s). If it does, then only one of the join rows will be used to update the target row, but which one will be used is not readily predictable.

由于这种不确定性,在子选择中引用其他表更为安全,尽管这种方式通常比使用连接更难理解且更慢。

Because of this indeterminacy, referencing other tables only within sub-selects is safer, though often harder to read and slower than using a join.

对于分区表,更新行可能会导致行不再满足所含分区的分区约束。在这种情况中,如果分区树中还有其他分区,而该行满足其分区约束,则该行会移至该分区。如果没有这样的分区,将会出现错误。实际操作中,行移动实际上是 DELETEINSERT 操作。

In the case of a partitioned table, updating a row might cause it to no longer satisfy the partition constraint of the containing partition. In that case, if there is some other partition in the partition tree for which this row satisfies its partition constraint, then the row is moved to that partition. If there is no such partition, an error will occur. Behind the scenes, the row movement is actually a DELETE and INSERT operation.

并发 UPDATEDELETE 在被移动行上出现时可能会导致序列化失败错误。假设会话 1 对分区键执行 UPDATE ,而此时,一个并发会话 2 对该行可见,并且执行此行上的 UPDATEDELETE 操作。在这种情况下,会话 2 的 UPDATEDELETE 将检测到行移动并引发序列化失败错误(总是返回 SQLSTATE 代码“40001”)。如果发生这种情况,应用程序可能希望重试该事务。在通常情况下,表格未分区,或者没有行移动,会话 2 会识别新更新的行并在这个新行版本上执行 UPDATE / DELETE

There is a possibility that a concurrent UPDATE or DELETE on the row being moved will get a serialization failure error. Suppose session 1 is performing an UPDATE on a partition key, and meanwhile a concurrent session 2 for which this row is visible performs an UPDATE or DELETE operation on this row. In such case, session 2’s UPDATE or DELETE will detect the row movement and raise a serialization failure error (which always returns with an SQLSTATE code '40001'). Applications may wish to retry the transaction if this occurs. In the usual case where the table is not partitioned, or where there is no row movement, session 2 would have identified the newly updated row and carried out the UPDATE/DELETE on this new row version.

请注意,虽然可以将行从本地分区移动到外来表分区(如果外来数据包装器支持元组路由),但无法从外来表分区移动到另一个分区。

Note that while rows can be moved from local partitions to a foreign-table partition (provided the foreign data wrapper supports tuple routing), they cannot be moved from a foreign-table partition to another partition.

如果发现外键直接引用源分区的一个不同于 UPDATE 查询中提及的祖先分区,则将行从一个分区移动到另一个分区的尝试会失败。

An attempt of moving a row from one partition to another will fail if a foreign key is found to directly reference an ancestor of the source partition that is not the same as the ancestor that’s mentioned in the UPDATE query.

Examples

在表 films 的列 kind 中将单词 Drama 更改为 Dramatic

Change the word Drama to Dramatic in the column kind of the table films:

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

调整温度项,并在表 weather 的一行中将降水量重置为其默认值:

Adjust temperature entries and reset precipitation to its default value in one row of the table 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';

执行相同操作并返回更新后的项:

Perform the same operation and return the updated entries:

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;

使用备用列列表语法执行相同的更新:

Use the alternative column-list syntax to do the same update:

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

使用 FROM 子句语法增加管理 Acme Corporation 帐户的销售人员的销售计数:

Increment the sales count of the salesperson who manages the account for Acme Corporation, using the FROM clause syntax:

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

执行相同操作,在 WHERE 子句中使用子查询:

Perform the same operation, using a sub-select in the WHERE clause:

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

在帐号表中更新联系人的姓名,以匹配当前分配的销售人员:

Update contact names in an accounts table to match the currently assigned salespeople:

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

使用联接也可以实现类似的效果:

A similar result could be accomplished with a join:

UPDATE accounts SET contact_first_name = first_name,
                    contact_last_name = last_name
  FROM employees WHERE employees.id = accounts.sales_person;

但是,如果 employees . id 不是唯一键,第二个查询可能会出现意外的结果,而第一个查询在有多个 id 匹配项时保证会引发错误。此外,如果 accounts . sales_person 条目没有匹配项,第一个查询会将对应的姓名字段设置为 NULL,而第二个查询根本不会更新该行。

However, the second query may give unexpected results if employees.id is not a unique key, whereas the first query is guaranteed to raise an error if there are multiple id matches. Also, if there is no match for a particular accounts.sales_person entry, the first query will set the corresponding name fields to NULL, whereas the second query will not update that row at all.

在摘要表中更新统计数据以匹配当前数据:

Update statistics in a summary table to match the current data:

UPDATE summary s SET (sum_x, sum_y, avg_x, avg_y) =
    (SELECT sum(x), sum(y), avg(x), avg(y) FROM data d
     WHERE d.group_id = s.group_id);

尝试插入新的库存项目以及库存数量。如果项目已存在,则更新现有项目的库存量。若要进行上述操作而不使整个事务失败,可以使用保存点:

Attempt to insert a new stock item along with the quantity of stock. If the item already exists, instead update the stock count of the existing item. To do this without failing the entire transaction, use savepoints:

BEGIN;
-- other operations
SAVEPOINT sp1;
INSERT INTO wines VALUES('Chateau Lafite 2003', '24');
-- Assume the above fails because of a unique key violation,
-- so now we issue these commands:
ROLLBACK TO sp1;
UPDATE wines SET stock = stock + 24 WHERE winename = 'Chateau Lafite 2003';
-- continue with other operations, and eventually
COMMIT;

更改当前指针 c_films 定位到的行中的表 filmskind 列:

Change the kind column of the table films in the row on which the cursor c_films is currently positioned:

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

Compatibility

此命令符合 SQL 标准,但 FROMRETURNING 子句是 PostgreSQL 的扩展,而将 WITHUPDATE 配合使用也是 PostgreSQL 的扩展。

This command conforms to the SQL standard, except that the FROM and RETURNING clauses are PostgreSQL extensions, as is the ability to use WITH with UPDATE.

其他一些数据库系统提供 FROM 选项,其中目标表应在 FROM 中再次列出。这不是 PostgreSQL 的解释方式。在移植使用此扩展的应用程序时要小心。

Some other database systems offer a FROM option in which the target table is supposed to be listed again within FROM. That is not how PostgreSQL interprets FROM. Be careful when porting applications that use this extension.

根据该标准,目标列名的带括号的子列表的源值可以是产生正确数量列的任何行值表达式。PostgreSQL 仅允许源值为 row constructor 或子 SELECT 。在行构造函数的情况下,可以将单个列的更新值指定为 DEFAULT ,但不能在 SELECT 内指定。

According to the standard, the source value for a parenthesized sub-list of target column names can be any row-valued expression yielding the correct number of columns. PostgreSQL only allows the source value to be a row constructor or a sub-SELECT. An individual column’s updated value can be specified as DEFAULT in the row-constructor case, but not inside a sub-SELECT.