2011-01-09 3 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)을 추가하고이를 사용하여 앨범의 주요 기능을 결정하는 것이 좋습니다. 기본적으로 내가 나타내는 행을 포함하는 테이블을 추가하는 제안하고있어 위의 확장 요청에 따라 테이블

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

가입 선택하면

귀하의 업데이트는

DELETE FROM featured_album; INSERT INTO featured_album SET id_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 

을 한 경우에

그래서 우리는 다음과 같은 무언가를 얻을 것 : 즉 isFeatured 또는 ID에 대한 NULL

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

. 당신이 PHP에서 결과를 처리하는 경우 그것은을하지 않습니다 있지만 첫 번째 쿼리를 (id_album IS NOT NULL) AS isfeatured를 추가하고 사용하여

우리는 일을 더 쉽게 읽을 isfeatured에 대한

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

즉 0/1을 얻을 코드와의 차이.

+0

나는이 코드에 흥미가 없지만 결코 MySQL 전문가 (분명히)는 여기에 일어나고있는 것을 조금 더 설명해 주시겠습니까? 감사합니다 – NightMICU

+1

저는 제 대답을 확장했습니다. 그것이 의미가 있기를 바랍니다. –

+0

대단히 감사합니다! 나는이 시도를 해봐야 할 것 같네. – NightMICU

7

이 시도 :

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

+1. 당신은 너무 빠릅니다 :) – a1ex07

+0

old_value가 new 인 경우 @Richo Mysql은 행을 업데이트하지 않습니다. – a1ex07

+0

내게는 꽤 기분 좋은 것처럼 보입니다. 이해하기 쉽고 짧습니다. 감사합니다 :) – NightMICU

1

당신은 그냥 할 수 없습니다. 업데이트해야하는 레코드 그룹을 하나만 선택할 수 있으며 모든 레코드에 대해 하나의 작업 만 수행 할 수 있습니다.

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

함수를 사용하여 모든 행에 대해 평가해야하므로 비용이 많이 들기 때문에 함수를 사용할 때는주의해야합니다.

+0

+1 : MySQL이 당신의 쿼리를 마침내'if'로 재 작성하지 않고 where 절을 대체합니다. –

0

나는 할 수 있다고 생각하지 않는다. 적어도 깔끔하고 실용적인 방법은 아니다. 당신은 PHP에서 하나의 호출을하고자하는 경우

/어떤 그런 다음 이렇게 세미콜론으로 분리해서 할 수

UPDATE albums SET isFeatured = '0' WHERE isFeatured = '1';UPDATE albums SET isFeatured = '1' WHERE id = '$id'; 
당신은 CASE WHEN 문을 사용하고 필요한 경우 (ELSE 절 아래의 원래 값을 설정 기억할 수
4

)와 순서대로 CASE 조건을 요구합니다 (아래 문에서 isFeatured는 요청 된 ID가있는 행에도 isFeatured = 1이 있으면 WHEN 절을 바꾸기 위해 0이됩니다).

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

이것은 내가 전반적으로 도움이 될 것입니다, 장래에 이것을 사용할 것입니다. 감사합니다 :) – NightMICU

1

MySQL은 if 함수 안에있을 때 인덱스를 사용할 수 없습니다 : 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) 

세트 남성에 대한 모든 성별을 사용하고 How does one create an index on the date part of DATETIME field in MySql

.

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이 마술 만 변경하는 데 필요한 행을 업데이트 아는 것을 다른 곳 말했다.

+0

매우 철저한 설명, 감사합니다. 그래서, 기본적으로, 이런 종류의 것을 결합하려고하는 것은 실제로 두 개의 분리 된 문장을 보내는 것보다 실제로 느린 것입니까? – NightMICU

+0

예. PostgreSQL과 같은 일부 db는 MySQl이 아닌 함수를 색인 할 수 있습니다. 또한 귀하의 테이블이 정규화되지 않았다고 말하는 것이 맞습니다 (Richard Harrisons 대답 참조). 그러면 문제를 해결할 수 있습니다. 나는 단지 잘못된 정보를 정리하고 싶었습니다. –

+0

명확히하기 위해 MySQL이 SET 절을 알아 내기를 기대하는 것에 대해 실제로 추가 한 것은 where 절입니다. –

관련 문제