UPDATE
is a DML statement that modifies rows in a table.是一个DML语句,用于修改表中的行。
An UPDATE
statement can start with a WITH
clause to define common table expressions accessible within the UPDATE
. UPDATE
语句可以以with
子句开头,以定义在UPDATE
中可访问的公共表表达式。See Section 13.2.15, “WITH (Common Table Expressions)”.见第13.2.15节,“WITH(公共表表达式)”。
Single-table syntax:单表语法:
UPDATE [LOW_PRIORITY] [IGNORE]table_reference
SETassignment_list
[WHEREwhere_condition
] [ORDER BY ...] [LIMITrow_count
]value
: {expr
| DEFAULT}assignment
:col_name
=value
assignment_list
:assignment
[,assignment
] ...
Multiple-table syntax:多表语法:
UPDATE [LOW_PRIORITY] [IGNORE]table_references
SETassignment_list
[WHEREwhere_condition
]
For the single-table syntax, the 对于单表语法,UPDATE
statement updates columns of existing rows in the named table with new values. UPDATE
语句用新值更新命名表中现有行的列。The SET
clause indicates which columns to modify and the values they should be given. SET
子句指示要修改哪些列以及应该给出哪些列的值。Each value can be given as an expression, or the keyword 可以将每个值作为表达式或关键字DEFAULT
to set a column explicitly to its default value. DEFAULT
来指定,以便将列显式设置为其默认值。The WHERE
clause, if given, specifies the conditions that identify which rows to update. WHERE
子句(如果给定)指定标识要更新的行的条件。With no 如果没有WHERE
clause, all rows are updated. WHERE
子句,则所有行都将更新。If the 如果指定了ORDER BY
clause is specified, the rows are updated in the order that is specified. ORDER BY
子句,则按指定的顺序更新行。The LIMIT
clause places a limit on the number of rows that can be updated.LIMIT
子句限制可以更新的行数。
For the multiple-table syntax, 对于多表语法,UPDATE
updates rows in each table named in table_references
that satisfy the conditions. UPDATE
更新在table_references
中指定的每个表中满足条件的行。Each matching row is updated once, even if it matches the conditions multiple times. 每个匹配行更新一次,即使它多次匹配条件。For multiple-table syntax, 对于多表语法,不能使用ORDER BY
and LIMIT
cannot be used.ORDER BY
和LIMIT
。
For partitioned tables, both the single-single and multiple-table forms of this statement support the use of a 对于分区表,此语句的单个和多个表形式都支持将PARTITION
clause as part of a table reference. PARTITION
子句用作表引用的一部分。This option takes a list of one or more partitions or subpartitions (or both). 此选项获取一个或多个分区或子分区(或两者)的列表。Only the partitions (or subpartitions) listed are checked for matches, and a row that is not in any of these partitions or subpartitions is not updated, whether it satisfies the 只检查列出的分区(或子分区)是否匹配,不在这些分区或子分区中的行不更新,无论它是否满足where_condition
or not.where_condition
。
Unlike the case when using 与将PARTITION
with an INSERT
or REPLACE
statement, an otherwise valid UPDATE ... PARTITION
statement is considered successful even if no rows in the listed partitions (or subpartitions) match the where_condition
.PARTITION
与INSERT
或REPLACE
语句一起使用不同,其他有效的UPDATE ... PARTITION
语句即使列出的分区(或子分区)中没有与where_condition
匹配的行,它也被认为是成功的。
For more information and examples, see Section 24.5, “Partition Selection”.有关更多信息和示例,请参阅第24.5节,“分区选择”。
where_condition
is an expression that evaluates to true for each row to be updated. For expression syntax, see Section 9.5, “Expressions”.where_condition
是一个表达式,对于要更新的每一行,它的计算结果都为true
。有关表达式语法,请参阅第9.5节,“表达式”。
table_references
and where_condition
are specified as described in Section 13.2.10, “SELECT Statement”.table_references
和where_condition
被指定为如第13.2.10节,“SELECT语句”所述。
You need the 只有在实际更新的更新中引用的列才需要UPDATE
privilege only for columns referenced in an UPDATE
that are actually updated. UPDATE
权限。You need only the 对于已读取但未修改的任何列,您只需要SELECT
privilege for any columns that are read but not modified.SELECT
权限。
The UPDATE
statement supports the following modifiers:UPDATE
语句支持以下修饰符:
With the 使用LOW_PRIORITY
modifier, execution of the UPDATE
is delayed until no other clients are reading from the table. LOW_PRIORITY
修饰符,UPDATE
的执行会延迟,直到没有其他客户机从表中读取数据为止。This affects only storage engines that use only table-level locking (such as 这只影响仅使用表级锁定的存储引擎(如MyISAM
, MEMORY
, and MERGE
).MyISAM
、MEMORY
和MERGE
)。
With the 使用IGNORE
modifier, the update statement does not abort even if errors occur during the update. IGNORE
修饰符,即使在更新期间发生错误,更新语句也不会中止。Rows for which duplicate-key conflicts occur on a unique key value are not updated. 不会更新在唯一键值上发生重复键冲突的行。Rows updated to values that would cause data conversion errors are updated to the closest valid values instead. 更新为可能导致数据转换错误的值的行将更新为最接近的有效值。For more information, see The Effect of IGNORE on Statement Execution.有关详细信息,请参阅IGNORE对语句执行的影响。
UPDATE IGNORE
statements, including those having an ORDER BY
clause, are flagged as unsafe for statement-based replication. UPDATE IGNORE
语句(包括具有ORDER BY
子句的语句)对于基于语句的复制被标记为不安全的。(This is because the order in which the rows are updated determines which rows are ignored.) (这是因为行的更新顺序决定了忽略哪些行。)Such statements produce a warning in the error log when using statement-based mode and are written to the binary log using the row-based format when using 当使用基于语句的模式时,此类语句在错误日志中生成警告,当使用MIXED
mode. MIXED
模式时,将使用基于行的格式写入二进制日志。(Bug #11758262, Bug #50439) See Section 17.2.1.3, “Determination of Safe and Unsafe Statements in Binary Logging”, for more information.有关更多信息,请参阅第17.2.1.3节,“确定二进制日志记录中的安全和不安全语句”。
If you access a column from the table to be updated in an expression, 如果访问要在表达式中更新的表中的列,UPDATE
uses the current value of the column. UPDATE
将使用该列的当前值。For example, the following statement sets 例如,以下语句将col1
to one more than its current value:col1
设置为比其当前值多一个:
UPDATE t1 SET col1 = col1 + 1;
The second assignment in the following statement sets 下面语句中的第二个赋值将col2
to the current (updated) col1
value, not the original col1
value. col2
设置为当前(更新的)col1
值,而不是原始的col1
值。The result is that 结果是col1
and col2
have the same value. col1
和col2
具有相同的值。This behavior differs from standard SQL.此行为与标准SQL不同。
UPDATE t1 SET col1 = col1 + 1, col2 = col1;
Single-table 单表UPDATE
assignments are generally evaluated from left to right. UPDATE
分配通常从左到右进行计算。For multiple-table updates, there is no guarantee that assignments are carried out in any particular order.对于多个表更新,不能保证按任何特定顺序执行分配。
If you set a column to the value it currently has, MySQL notices this and does not update it.如果将列设置为当前的值,MySQL会注意到这一点,并且不会更新它。
If you update a column that has been declared 如果通过设置为NOT NULL
by setting to NULL
, an error occurs if strict SQL mode is enabled; otherwise, the column is set to the implicit default value for the column data type and the warning count is incremented. NULL
来更新已声明为NOT NULL
的列,则在启用严格SQL模式时会发生错误;否则,列将被设置为列数据类型的隐式默认值,并且警告计数将递增。The implicit default value is 对于数值类型,隐式默认值为0
for numeric types, the empty string (''
) for string types, and the “zero” value for date and time types. 0
;对于字符串类型,隐式默认值为空字符串(''
);对于日期和时间类型,隐式默认值为“0”。See Section 11.6, “Data Type Default Values”.请参阅第11.6节,“数据类型默认值”。
If a generated column is updated explicitly, the only permitted value is 如果显式更新生成的列,则唯一允许的值是DEFAULT
. DEFAULT
。For information about generated columns, see Section 13.1.20.8, “CREATE TABLE and Generated Columns”.有关生成列的信息,请参阅第13.1.20.8节,“创建表和生成列”。
UPDATE
returns the number of rows that were actually changed. UPDATE
返回实际更改的行数。The mysql_info()
C API function returns the number of rows that were matched and updated and the number of warnings that occurred during the UPDATE
.mysql_info()
C API函数返回匹配和更新的行数以及UPDATE
过程中出现的警告数。
You can use 可以使用LIMIT
to restrict the scope of the row_count
UPDATE
. LIMIT
来限制row_count
UPDATE
的作用域。A LIMIT
clause is a rows-matched restriction. LIMIT
子句是行匹配的限制。The statement stops as soon as it has found 语句在找到满足row_count
rows that satisfy the WHERE
clause, whether or not they actually were changed.WHERE
子句的row_count
行后立即停止,无论它们是否实际被更改。
If an 如果UPDATE
statement includes an ORDER BY
clause, the rows are updated in the order specified by the clause. UPDATE
语句包含ORDER BY
子句,则按该子句指定的顺序更新行。This can be useful in certain situations that might otherwise result in an error. 这在某些可能导致错误的情况下非常有用。Suppose that a table 假设表t
contains a column id
that has a unique index. t
包含具有唯一索引的列id
。The following statement could fail with a duplicate-key error, depending on the order in which rows are updated:根据行的更新顺序,以下语句可能会因重复键错误而失败:
UPDATE t SET id = id + 1;
For example, if the table contains 1 and 2 in the 例如,如果表的id
column and 1 is updated to 2 before 2 is updated to 3, an error occurs. id
列中包含1和2,并且在将2更新为3之前将1更新为2,则会发生错误。To avoid this problem, add an 要避免此问题,请添加ORDER BY
clause to cause the rows with larger id
values to be updated before those with smaller values:ORDER BY
子句,以使id
值较大的行在id
值较小的行之前更新:
UPDATE t SET id = id + 1 ORDER BY id DESC;
You can also perform 您还可以执行覆盖多个表的UPDATE
operations covering multiple tables. UPDATE
操作。However, you cannot use 但是,不能对多表更新使用ORDER BY
or LIMIT
with a multiple-table UPDATE
. ORDER BY
或LIMIT
。The table_references
clause lists the tables involved in the join. table_references
子句列出了联接中涉及的表。Its syntax is described in Section 13.2.10.2, “JOIN Clause”. 其语法在第13.2.10.2节,“JOIN子句”中描述。Here is an example:举个例子:
UPDATE items,month SET items.price=month.price WHERE items.id=month.id;
The preceding example shows an inner join that uses the comma operator, but multiple-table 前面的示例显示了使用逗号运算符的内部联接,但是多个表UPDATE
statements can use any type of join permitted in SELECT
statements, such as LEFT JOIN
.UPDATE
语句可以使用SELECT
语句中允许的任何类型的联接,例如LEFT JOIN
。
If you use a multiple-table 如果您使用一个涉及UPDATE
statement involving InnoDB
tables for which there are foreign key constraints, the MySQL optimizer might process tables in an order that differs from that of their parent/child relationship. InnoDB
表的多表UPDATE
语句,其中有外键约束,那么MySQL优化器可能会按照不同于表的父/子关系的顺序来处理表。In this case, the statement fails and rolls back. 在这种情况下,语句失败并回滚。Instead, update a single table and rely on the 相反,更新一个表并依赖ON UPDATE
capabilities that InnoDB
provides to cause the other tables to be modified accordingly. InnoDB
提供的ON UPDATE
功能来相应地修改其他表。See Section 13.1.20.5, “FOREIGN KEY Constraints”.请参阅第13.1.20.5节,“外键约束”。
You cannot update a table and select directly from the same table in a subquery. 不能更新表并直接从子查询中的同一表中进行选择。You can work around this by using a multi-table update in which one of the tables is derived from the table that you actually wish to update, and referring to the derived table using an alias. 您可以通过使用多表更新来解决此问题,其中一个表是从实际要更新的表派生的,并使用别名引用派生表。Suppose you wish to update a table named 假设您希望更新名为items
which is defined using the statement shown here:items
的表,该表是使用以下语句定义的:
CREATE TABLE items ( id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, wholesale DECIMAL(6,2) NOT NULL DEFAULT 0.00, retail DECIMAL(6,2) NOT NULL DEFAULT 0.00, quantity BIGINT NOT NULL DEFAULT 0 );
To reduce the retail price of any items for which the markup is 30% or greater and of which you have fewer than one hundred in stock, you might try to use an 要降低任何商品的零售价,如果这些商品的加价是30%或更高,并且您的库存少于100个,您可以尝试使用UPDATE
statement such as the one following, which uses a subquery in the WHERE
clause. UPDATE
语句,例如下面的语句,它在WHERE
子句中使用子查询。As shown here, this statement does not work:如图所示,此语句不起作用:
mysql>UPDATE items
>SET retail = retail * 0.9
>WHERE id IN
>(SELECT id FROM items
>WHERE retail / wholesale >= 1.3 AND quantity > 100);
ERROR 1093 (HY000): You can't specify target table 'items' for update in FROM clause
Instead, you can employ a multi-table update in which the subquery is moved into the list of tables to be updated, using an alias to reference it in the outermost 相反,您可以使用多表更新,其中子查询被移动到要更新的表列表中,使用别名在最外层的WHERE
clause, like this:WHERE
子句中引用它,如下所示:
UPDATE items, (SELECT id FROM items WHERE id IN (SELECT id FROM items WHERE retail / wholesale >= 1.3 AND quantity < 100)) AS discounted SET items.retail = items.retail * 0.9 WHERE items.id = discounted.id;
Because the optimizer tries by default to merge the derived table 因为优化器在默认情况下会尝试将派生表discounted
into the outermost query block, this works only if you force materialization of the derived table. discounted
到最外层的查询块中,所以只有在强制对派生表进行物化时,这种方法才有效。You can do this by setting the 您可以在运行更新之前将derived_merge
flag of the optimizer_switch
system variable to off
before running the update, or by using the NO_MERGE
optimizer hint, as shown here:optimizer_switch
系统变量的derived_merge
标志设置为off
,或者使用NO_MERGE
优化器提示来完成此操作,如下所示:
UPDATE /*+ NO_MERGE(discounted) */ items, (SELECT id FROM items WHERE retail / wholesale >= 1.3 AND quantity < 100) AS discounted SET items.retail = items.retail * 0.9 WHERE items.id = discounted.id;
The advantage of using the optimizer hint in such a case is that it applies only within the query block where it is used, so that it is not necessary to change the value of 在这种情况下使用优化器提示的优点是,它只应用于使用它的查询块中,因此在执行更新后不必再次更改optimizer_switch
again after executing the UPDATE
.optimizer_switch
的值。
Another possibility is to rewrite the subquery so that it does not use 另一种可能是重写子查询,w从而它不使用IN
or EXISTS
, like this:IN
或EXISTS
,如下所示:
UPDATE items, (SELECT id, retail / wholesale AS markup, quantity FROM items) AS discounted SET items.retail = items.retail * 0.9 WHERE discounted.markup >= 1.3 AND discounted.quantity < 100 AND items.id = discounted.id;
In this case, the subquery is materialized by default rather than merged, so it is not necessary to disable merging of the derived table.在这种情况下,子查询在默认情况下是具体化的,而不是合并的,因此不必禁用派生表的合并。