How do I combine two UPDATE statements in one MySQL query?

后端 未结 6 1324
野的像风
野的像风 2020-12-18 11:44

Greetings,

How would one go about performing two UPDATE statements in one query, for example:

UPDATE albums SET isFeatured = \'0\' WHERE isFeatured          


        
6条回答
  •  执笔经年
    2020-12-18 11:53

    MySQL is unable to use the index when it is inside an if function: You need an index on the function which is not possible in MySQL.

    see also: How does one create an index on the date part of DATETIME field in MySql

    I am using the employee test database http://dev.mysql.com/doc/employee/en/employee.html

    mysql> describe employees;
    +------------+---------------+------+-----+---------+-------+
    | Field      | Type          | Null | Key | Default | Extra |
    +------------+---------------+------+-----+---------+-------+
    | emp_no     | int(11)       | NO   | PRI | NULL    |       |
    | birth_date | date          | NO   |     | NULL    |       |
    | first_name | varchar(14)   | NO   |     | NULL    |       |
    | last_name  | varchar(16)   | NO   |     | NULL    |       |
    | gender     | enum('M','F') | NO   |     | NULL    |       |
    | hire_date  | date          | NO   |     | NULL    |       |
    +------------+---------------+------+-----+---------+-------+
    6 rows in set (0.01 sec)
    
    mysql> select count(*) from employees;
    +----------+
    | count(*) |
    +----------+
    |   300024 |
    +----------+
    1 row in set (0.37 sec)
    

    Set all genders to male so it mimics the question.

    mysql> update employees set gender = 'M';
    Query OK, 1 row affected (9.11 sec)
    Rows matched: 300024  Changed: 1  Warnings: 0
    
    mysql>  select emp_no, gender from employees order by emp_no limit 2;
    +--------+--------+
    | emp_no | gender |
    +--------+--------+
    |  10001 | M      |
    |  10002 | M      |
    +--------+--------+
    2 rows in set (0.00 sec)
    

    Set one employee to female. (Notice it uses the index and is almost instant.)

    mysql> update employees set gender = 'F' where emp_no = 10001;
    Query OK, 1 row affected (0.14 sec)
    Rows matched: 1  Changed: 1  Warnings: 0
    

    Now we use the suggested answer. (Notice it does not use the index and touches every row.)

    mysql> update employees set gender = if(emp_no=10002, 'F', 'M');
    Query OK, 2 rows affected (10.67 sec)
    Rows matched: 300024  Changed: 2  Warnings: 0
    

    Will an index help?

    > mysql> create index employees_gender_idx  on employees(gender);
    Query OK, 300024 rows affected (21.61 sec)
    Records: 300024  Duplicates: 0  Warnings: 0
    
    > mysql> update employees set gender = if(emp_no=10001, 'F', 'M');
    Query OK, 2 rows affected (9.02 sec)
    Rows matched: 300024  Changed: 2  Warnings: 0
    
    Nope.
    

    It was also said that MySQL is only going to look at the rows that need to be changed.

    mysql> update employees set gender = 'M';
    Query OK, 1 row affected (8.78 sec)
    Rows matched: 300024  Changed: 1  Warnings: 0
    

    Guess not. What if use a WHERE clause?

    mysql> update employees set gender = 'M' where gender ='F';
    Query OK, 0 rows affected (0.03 sec)
    Rows matched: 0  Changed: 0  Warnings: 0
    

    Gee that fast, now it used the index.

    Mysql has no idea what the IF function will return and must do a full table scan. Notice that WHERE really does mean where and SET really does mean set. You can't expect the DB to just arrange all your clauses to get good performance.

    The correct solution is to issue two updates (which if use indexes will be almost instant.)

    Notice, it was said elsewhere that MySQL will magically know only update the rows it needs to change.

提交回复
热议问题