2011-01-09 146 views
2

問候,如何在一個MySQL查詢中結合兩個UPDATE語句?

一個會如何在一個查詢執行兩個UPDATE語句,例如:

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

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

基本上,在功能的新專輯,組合之前的精選專輯將切換回正常,並將新功能專輯設置爲有效。

謝謝!

回答

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語句將從專輯表中拉入記錄並加入與featured_album表匹配的記錄,在我們的例子中,只有一個記錄匹配,因此在featured_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或ID的NULL。

通過添加(id_album IS NOT NULL) AS isfeatured並使用第一查詢,我們得到

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

即0/1用於isfeatured這使事情變得更加可讀,但如果你在PHP處理結果也不會做與您的代碼不同。

7

試試這個:

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

+1。你太快了:) – a1ex07 2011-01-09 21:38:22

+0

@Richo如果old_value等於new,Mysql不更新該行。 – a1ex07 2011-01-09 21:44:15

+0

看起來這對我來說非常活潑,容易理解和簡短。謝謝:) – NightMICU 2011-01-09 22:04:17

1

你就不能。您只能選擇一組應該更新的記錄,然後只能對它們進行一項操作。這是不可能做到

UPDATE x SET col1 = 1 WHERE col1 = 0 AND col1 = 0 WHERE col1 = 1; 

使用功能來解決這個時要小心,因爲他們需要爲每一行進行評估,這可以成爲真貴。

0

我不認爲你可以,或者至少不是以一種整潔或實用的方式。

如果你想這樣做從PHP的一個呼叫/什麼,那麼你可以用分號因此它們分開:

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

您可以使用CASE WHEN聲明,記得設置初始值在必要時(ELSE條款如下)並根據需要命令CASE條件(在以下語句中,如果具有請求的id的行也具有isFeatured = 1,則將其更改爲交換WHEN子句),則Feature將爲0。

UPDATE albums 
SET isFeatured = CASE 
    WHEN isFeatured = '1' THEN '0' 
    WHEN id = '$id' THEN '1' 
    ELSE isFeatured 
END 
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確實的確表示確實意味着設置。你不能指望數據庫只安排你的所有條款來獲得好的表現。

正確的解決方案是發出兩個更新(如果使用索引將幾乎瞬間。)

注意,這是在別的地方說,MySQL將奇蹟般地只知道更新需要改變的行。

相關問題