mysqlupdate语句分区更新_MySQL的SQL语句-数据操作语句
(15)-UPDATE语句
UPDATE 语句
UPDATE 是修改表中⾏的 DML 语句。
UPDATE 语句可以⽤ WITH ⼦句开头,定义在 UPDATE 中可访问的公共表表达式。
单表语法:
1. UPDATE [LOW_PRIORITY] [IGNORE] table_reference
2. SET assignment_list
3. [WHERE where_condition]
4. [ORDER BY ...]
5. [LIMIT row_count]
6.
7. value:
8. {expr | DEFAULT}
9.
10. assignment:
11. col_name = value
12.
13. assignment_list:
14. assignment [, assignment] ...
多表语法:
1. UPDATE [LOW_PRIORITY] [IGNORE] table_references
2. SET assignment_list
3. [WHERE where_condition]
对于单表语法,UPDATE 语句⽤新值更新命名表中现有⾏的列。SET ⼦句指⽰要修改的列及其应给定的值。每个值可以⽤表达式给定,也可以使⽤关键字 DEFAULT 将列显式设置为其默认值。WHERE ⼦句(如果给定)指定要更新哪些⾏。如果没有 WHERE ⼦句,所有⾏都将更新。如果指定了 ORDER BY ⼦句,则按指定的顺序更新⾏。LIMIT ⼦句对可以更新的⾏数进⾏了限制。
对于多表语法,UPDATE 更新 table_references 中每个表中满⾜条件的⾏。每个匹配的⾏都会更新⼀次,即使它与条件匹配多次。对于多表语法,不能使⽤ ORDER BY 和 LIMIT。
对于分区表,此语句的单表和多表形式都⽀持使⽤ PARTITION 选项⽤作表引⽤的⼀部分。此选项接受分区或⼦分区列表。只检查列出的分区(或⼦分区)是否匹配,不在这些分区或⼦分区中的⾏不会更新,⽆论它是否满⾜ where_condition 条件。
注意
与在 INSERT 或 REPLACE 语句中使⽤ PARTITION 的情况不同,即使列出的分区(或⼦分区)中没有与 where_condition 匹配的
⾏,UPDATE ... PARTITION 语句也被认为是成功的。
where_condition 是⼀个表达式,要更新的每⼀⾏都必须满⾜此表达式的条件。
只需要拥有在 UPDATE 语句实际更新引⽤的列的 UPDATE 权限。对于任何已读取但未修改的列,只需要 SELECT 权限。
UPDATE 语句⽀持以下修饰符:
● 使⽤ LOW_PRIORITY 修饰符,UPDATE 的执⾏将被延迟,直到没有其他客户端从表中读取数据。这只影响只使⽤表级锁定的存储引擎(如 MyISAM、MEMORY 和 MERGE)。
● 使⽤ IGNORE 修饰符,即使在更新过程中发⽣错误,更新语句也不会中⽌。不会更新在唯⼀键值上引发重复键冲突的⾏。可能导致数据转换错误的值的⾏将更新为最接近的有效值。
包括 ORDER BY ⼦句的 UPDATE IGNORE 语句被标记为不安全的基于语句的复制。(这是因为⾏的更新顺序决定了哪些⾏被忽略。)当使⽤基于语句的模式时,这些语句在错误⽇志中⽣成警告,在使⽤ MIXED 模式时,这些语句将使⽤基于⾏的格式写⼊⼆进制⽇志。
如果从要在表达式中更新的表中访问列,则 UPDATE 将使⽤该列的当前值。例如,下⾯的语句将 col1 设置为⽐当前值多1:
1. UPDATE t1 SET col1 = col1 + 1;
下⾯语句中的第⼆个赋值将 col2 设置为当前(更新的)col1 值,⽽不是原始 col1 值。结果是 col1 和 col2 的值相同。此⾏为与标准 SQL 不同。
1. UPDATE t1 SET col1 = col1 + 1, col2 = col1;
单表 UPDATE 分配通常从左到右进⾏计算。对于多表更新,不能保证以任何特定的顺序执⾏分配。
如果将列设置为当前的值,MySQL 会注意到这⼀点,并且不会更新它。
如果把已声明为 NOT NULL 的列设置为 NULL,则在启⽤了严格 SQL 模式会出错;否则,该列将设置为列数据类型的隐式默认值,并且警告计数将递增。对于数值类型,隐式默认值为0;对于字符串类型,隐式默认值为空字符串(''),对于⽇期和时间类型,默认值为“零”。
如果显式更新⽣成列,则唯⼀允许的值是 DEFAULT。
UPDATE 返回实际更改的⾏数。mysql_info() C API 函数返回匹配和更新的⾏数以及更新过程中出现的警告数。
可以使⽤ LIMIT row_count 来限制 UPDATE 的范围。LIMIT ⼦句是匹配⾏的限制。只要到满⾜ WHERE ⼦句的 row_count ⾏,语句就会⽴即停⽌,⽽不管这些⾏是否实际被更改。
如果 UPDATE 语句包含 ORDER BY ⼦句,则按该⼦句指定的顺序更新⾏。这在某些可能导致错误的情况下⾮常有⽤。假设表 t 包含⼀个具有唯⼀索引的列 id。以下语句可能会出现重复键错误⽽失败,这取决于⾏的更新顺序:
1. UPDATE t SET id = id + 1;
例如,如果表在 id 列中包含值 1 和 2,并且在 2 更新为 3 之前 1 先更新为2,则会发⽣错误。若要避免此问题,请添加 ORDER BY ⼦句,使 id 值较⼤的⾏在值较⼩的⾏之前更新:
1. UPDATE t SET id = id + 1 ORDER BY id DESC;
还可以执⾏覆盖多个表的 UPDATE 操作。但是,不能将 ORDER BY 或 LIMIT ⽤于多表更新。table_references ⼦句列出了连接中涉及的表。
1. UPDATE items,month SET items.price=month.price
2. WHERE items.id=month.id;
前⾯的⽰例显⽰了使⽤逗号运算符的内部联接,但多表更新语句可以使⽤ SELECT 语句中允许的任何类型的联接,例如 LEFT JOIN。
如果使⽤包含 InnoDB 表且有外键约束的多表 UPDATE 语句,那么 MySQL 优化器可能会按照与⽗/⼦关系不同的顺序处理表。在本例中,语句失败并回滚。相反,更新⼀个表并依赖 InnoDB 提供的 ON UPDATE 功能来相应地修改其他表。
不能在更新⼀个表的同时直接从⼦查询中对同⼀表进⾏选择。可以通过使⽤多表更新来解决此问题,其中⼀个表是从实际要更新的表派⽣的,并使⽤别名引⽤派⽣表。假设希望更新⼀个名为 items 的表,该表是使⽤以下语句定义的:
1. CREATE TABLE items (
2. id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
3. wholesale DECIMAL(6,2) NOT NULL DEFAULT 0.00,
4. retail DECIMAL(6,2) NOT NULL DEFAULT 0.00,
5. quantity BIGINT NOT NULL DEFAULT 0
6. );
若要降低利润为30%或更⾼并且库存少于100的商品的零售价,可以尝试使⽤如下所⽰的 UPDATE 语句,该语句在 WHERE ⼦句中使⽤⼦查询。如下所⽰,此语句不起作⽤:
1. mysql> UPDATE items
2. > SET retail = retail * 0.9
3. > WHERE id IN
4. > (SELECT id FROM items
5. > WHERE retail / wholesale >= 1.3 AND quantity > 100);
6. ERROR 1093 (HY000): You can't specify target table 'items' for update in FROM clause
替代⽅法是可以使⽤多表更新,其中⼦查询被移动到要更新的表列表中,使⽤别名在最外层的 WHERE ⼦句中引⽤它,如下所⽰:
1. UPDATE items,
2. (SELECT id FROM items
3. WHERE id IN
4. (SELECT id FROM items
5. WHERE retail / wholesale >= 1.3 AND quantity < 100))
6. AS discounted
7. ail = ail * 0.9
8. WHERE items.id = discounted.id;
因为默认情况下,优化器会尝试将派⽣表 discounted 合并到最外层的查询块中,只有在强制物化派⽣表时,这才有效。可以在运⾏更新之前将 optimizer_switch 系统变量的 derived_merge 标志设置为 off,或使⽤ NO_MERGE 优化器提⽰来执⾏此操作,如下所⽰:
1. UPDATE /*+ NO_MERGE(discounted) */ items,
2. (SELECT id FROM items
数据库优化sql语句
3. WHERE retail / wholesale >= 1.3 AND quantity < 100)
4. AS discounted
5. ail = ail * 0.9
6. WHERE items.id = discounted.id;
在这种情况下使⽤优化器提⽰的好处是,它只适⽤于使⽤它的查询块中,因此在执⾏ UPDATE 之后,不必再次更改 optimizer_switch 的值。
另⼀种可能是重写⼦查询,使其不使⽤ IN 或 EXISTS,如下所⽰:
1. UPDATE items,
2. (SELECT id, retail / wholesale AS markup, quantity FROM items)
3. AS discounted
4. ail = ail * 0.9
5. WHERE discounted.markup >= 1.3
6. AND discounted.quantity < 100
7. AND items.id = discounted.id;
在这种情况下,⼦查询默认情况下是物化的,⽽不是合并的,因此不需要禁⽤派⽣表的合并。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论