如何在一个MySQL查询中组合两个UPDATE语句?

时间:2011-01-09 21:33:57

标签: mysql sql-update

问候,

如何在一个查询中执行两个UPDATE语句,例如:

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

结合

UPDATE albums SET isFeatured = '1' WHERE id = '$id'

基本上,当推出新专辑时,先前推荐的专辑将恢复正常,新功能的专辑将设置为有效。

谢谢!

6 个答案:

答案 0 :(得分:7)

试试这个:

UPDATE albums SET isFeatured = IF(id!='$id', '0','1')

答案 1 :(得分:7)

当你必须做这种事情时,它表明你的数据模型是错误的,可以做一些修复。

所以,我建议添加一个单独的表featured_albums(FK:int id_album)并使用它来确定相册是否有特色。

您的更新

DELETE FROM featured_album; INSERT INTO featured_album SET id_album = $id;

选择加入表格时

SELECT album.id,
       album.name, 
       ( id_album IS NOT NULL ) AS isfeatured
FROM   album
LEFT JOIN featured_album ON id_album = album.id 

根据要求扩展以上基本上我建议添加一个表格,其中包含一行表示当前所选专辑。这是1对1关系,即专辑表中的一个记录在feature_albums表中有一个相关记录。请参阅Types of Relationship

Album Schema Diagram

从相册表中删除isFeatured字段并添加新表。

CREATE TABLE `featured_album` (
    `id_album` INTEGER NOT NULL,
    FOREIGN KEY (id_album) REFERENCES `album` (`id`)
);

DELETE FROM .. INSERT INTO行通过在表格中创建条目来设置精选相册。

带有LEFT JOIN的SELECT语句将从专辑表中提取记录并从feature_album表中加入匹配的记录,在我们的例子中只有一个记录匹配,因为feature_album表中有一个字段它将返回除精选专辑外的所有记录均为NULL。

所以,如果我们做了

SELECT album.id, album.name, featured_album.id_album as isFeatured0
FROM   album
LEFT JOIN featured_album ON id_album = album.id 

我们会得到以下内容:

+----+----------------+------------+
| id | name           | isFeatured |
+----+----------------+------------+
|  1 | Rumours        |       NULL |
|  2 | Snowblind      |       NULL |
|  3 | Telegraph road |          3 |
+----+----------------+------------+

即。 isFeatured为NULL或ID。

添加( id_album IS NOT NULL ) AS isfeatured并使用我们获得的第一个查询

+----+----------------+------------+
| id | name           | isfeatured |
+----+----------------+------------+
|  1 | Rumours        |          0 |
|  2 | Snowblind      |          0 |
|  3 | Telegraph road |          1 |
+----+----------------+------------+

即。 0/1 for isfeatured使事情更具可读性,但如果你在PHP中处理结果,它将不会对你的代码产生影响。

答案 2 :(得分:4)

您可以使用CASE WHEN语句并记住在必要时设置原始值(下面的ELSE子句)并根据需要订购CASE条件(如果具有请求id的行也具有isFeatured = 1,则在下面的语句中isFeatured将为0,改变它交换WHEN条款)。

UPDATE albums 
SET isFeatured = CASE 
  WHEN isFeatured = '1' THEN '0' 
  WHEN id = '$id' THEN '1'
  ELSE isFeatured
END

答案 3 :(得分:1)

你不能。您只能选择一组应更新的记录,然后只能对所有记录执行一次操作。

是不可能的
 UPDATE x SET col1 = 1 WHERE col1 = 0 AND col1 = 0 WHERE col1 = 1;

使用函数解决这个问题时要小心,因为需要对每一行进行评估,这可能会变得非常昂贵。

答案 4 :(得分:1)

MySQL在if函数中时无法使用索引: 您需要一个函数索引,这在MySQL中是不可能的。

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

我正在使用员工测试数据库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)

将所有性别设置为男性,以便模仿问题。

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)

将一名员工设为女性。 (注意它使用索引并且几乎是即时的。)

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

现在我们使用建议的答案。 (注意它不使用索引并触及每一行。)

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

索引有帮助吗?

> 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.

还有人说MySQL只会查看需要更改的行。

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

不要猜。如果使用WHERE子句会怎么样?

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

快,现在它使用了索引。

Mysql不知道IF函数将返回什么,必须执行全表扫描。请注意,WHERE确实意味着在哪里,SET确实意味着设置。您不能指望DB只是安排所有条款以获得良好的性能。

正确的解决方案是发出两个更新(如果使用索引几乎是即时的。)

注意,有人在其他地方说过MySQL会神奇地知道只更新它需要更改的行。

答案 5 :(得分:0)

我认为你不能,或者至少不能以一种整洁或实际的方式。

如果您想从php /中进行一次调用,那么您可以用分号分隔它们:

UPDATE albums SET isFeatured = '0' WHERE isFeatured = '1';UPDATE albums SET isFeatured = '1' WHERE id = '$id';