13.2.8 REPLACE 구문
REPLACE [LOW_PRIORITY | DELAYED] [INTO]tbl_name
[PARTITION (partition_name
,...)] [(col_name
,...)] {VALUES | VALUE} ({expr
| DEFAULT},...),(...),...
또는 :
REPLACE [LOW_PRIORITY | DELAYED] [INTO]tbl_name
[PARTITION (partition_name
...) SETcol_name
= {expr
| DEFAULT}, ...
또는 :
REPLACE [LOW_PRIORITY | DELAYED] [INTO]tbl_name
[PARTITION (partition_name
...) [(col_name
, ...)] SELECT ...
REPLACE
은 INSERT
와 똑같이 작동합니다. 그러나 테이블의 이전 행에 PRIMARY KEY
또는 UNIQUE
인덱스에 대해 새로운 행과 동일한 값이 포함되어 있으면 이전 행은 새 행이 삽입되기 전에 삭제됩니다. 섹션 13.2.5 "INSERT 구문" 을 참조하십시오.
REPLACE
는 SQL 표준에 대한 MySQL 확장입니다. 이것은 삽입을 수행하거나 삭제 및 삽입합니다. 표준 SQL에 다른 MySQL 확장 (삽입 또는 업데이트합니다) 내용은 섹션 13.2.5.3 "INSERT ... ON DUPLICATE KEY UPDATE 구문" 을 참조하십시오.
테이블에 PRIMARY KEY
또는 UNIQUE
인덱스가 존재하지 않는 한, REPLACE
문을 사용하여도 아무 의미가 없습니다. 새로운 행이 다른 행을 복제했는지 여부를 판정하기 위해서 사용되는 인덱스가 존재하지 않기 때문에 그것은 INSERT
와 동등합니다.
모든 컬럼의 값이 REPLACE
문에 지정된 값에서 가져옵니다. 열이 없으면 INSERT
에서의 처리뿐만 아니라 그 열은 기본값으로 설정됩니다. 현재 행의 값을 참조하고 그것을 새로운 행에서 사용할 수 없습니다. SET
등의 대입을 사용하면 오른쪽에있는 컬럼 이름에 대한 참조는 col_name
= col_name
+ 1DEFAULT(
로 처리되기 때문에 대입이 col_name
)SET
과 동일합니다. col_name
= DEFAULT( col_name
) + 1
REPLACE
를 사용하려면이 테이블에 대한 INSERT
권한과 DELETE
권한이 모두 필요합니다.
MySQL 5.6.2에서 REPLACE
는 파티션 서브 파티션 또는 두 이름의 쉼표로 구분 된 목록을 포함 PARTITION
옵션을 사용하여 명시 적 파티션 선택을 지원하고 있습니다. INSERT
와 마찬가지로 이들 중 하나의 파티션 또는 서브 파티션에 새 행을 삽입 할 수없는 경우 REPLACE
문은 Found a row not matching the given partition set 오류로 실패합니다. 자세한 내용은 섹션 19.5 "파티션 선택" 을 참조하십시오.
REPLACE
는 영향을받은 행 수를 나타내는 숫자를 반환합니다. 이것은 삭제 된 행과 삽입 된 행의 합계입니다. 이 숫자는 한 줄의 REPLACE
에 대해 1 인 경우 행이 삽입되고 삭제 된 행이 없습니다. 이 값이 1보다 큰 경우, 새로운 행이 삽입되기 전에 하나 이상의 기존 행이 삭제되었습니다. 테이블에 여러 개의 고유 인덱스가 존재하면 새로운 행이 다른 고유 인덱스의 다른 오래된 행의 값을 복제 한 경우는 단 일행이 여러 오래된 줄을 바꿀 수 있습니다.
영향을받은 행 수에 따라 REPLACE
이 행을 추가했을뿐하거나 행의 대체도 행했는지를 판정하는 것이 용이합니다. 그 수가 1 (추가) 또는 그것보다 큰 (대체) 여부를 확인합니다.
C API를 사용하는 경우 mysql_affected_rows()
함수를 사용하여 영향을받은 행 수를 얻을 수 있습니다.
현재 테이블에 대체를 실시하여 하위 쿼리 같은 테이블에서 선택 할 수 없습니다.
MySQL은 REPLACE
(및 LOAD DATA ... REPLACE
)에 다음의 알고리즘을 사용합니다.
테이블에 새로운 행 삽입을 시도합니다
기본 키 또는 고유 인덱스에 중복 키 오류가 발생했기 때문에 삽입이 실패하는 동안 다음을 수행합니다.
중복 키 값을 포함 충돌하는 행을 테이블에서 제거합니다
테이블에 새로운 행 삽입을 시도합니다
중복 키 에러가 발생했을 경우, 스토리지 엔진이 삭제 및 삽입이 아니라 업데이트로 REPLACE
를 실행할 수 있지만 그 의미는 동일합니다. 스토리지 엔진이 Handler_
상태 변수를 증가하는 방법이 다를 수있다를 제외하고 사용자에게 보이는 영향은 없습니다. xxx
REPLACE ... SELECT
문의 결과는 SELECT
에서 행의 순서에 따라, 또한이 순서를 항상 보장 할 수 없기 때문에 로깅시에 이러한 문이 마스터와 슬레이브로 다를 수 있습니다. 따라서 MySQL 5.6.4 이후에서는 REPLACE ... SELECT
문에는 문 기반 복제는 안전하지 않은 플래그가 지정됩니다. 이러한 변경으로 인해 이러한 문은 STATEMENT
바이너리 로깅 모드를 사용하는 경우에는 로그에 경고를 생성하고 MIXED
모드를 사용하는 경우 행 기반 형식을 사용하여 기록됩니다 . 섹션 17.1.2.1 "문 기반 및 열 기반 리플리케이션의 장점과 단점" 을 참조하십시오.
분할되지 않은 기존 테이블을 파티셔닝을 지원하도록 변경하고 있거나 이미 분할 된 테이블의 파티션을 변경하는 경우 해당 테이블의 기본 키의 변경을 검토하는 수 있습니다 ( 섹션 19.6.1 "파티셔닝 키, 기본 키 및 고유 키" 를 참조하십시오). 이렇게하면 분할되지 않은 테이블의 기본 키를 변경 한 경우와 마찬가지로, REPLACE
문의 결과에 영향을 줄 수 있습니다. 다음의 CREATE TABLE
문에 의해 생성 된 테이블을 생각해 보겠습니다.
CREATE TABLE test ( id INT UNSIGNED NOT NULL AUTO_INCREMENT, data VARCHAR (64) DEFAULT NULL, ts TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (id) );
이 테이블을 만들고 mysql 클라이언트에 표시된 문을 실행하면 결과는 다음과 같습니다.
mysql>REPLACE INTO test VALUES (1, 'Old', '2014-08-20 18:47:00');
Query OK, 1 row affected (0.04 sec) mysql>REPLACE INTO test VALUES (1, 'New', '2014-08-20 18:47:42');
Query OK, 2 rows affected (0.04 sec) mysql>SELECT * FROM test;
+----+------+---------------------+ | id | data | ts | +----+------+---------------------+ | 1 | New | 2014-08-20 18:47:42 | +----+------+---------------------+ 1 row in set (0.00 sec)
여기에서 다음과 같이 (강조 표시된 텍스트) 기본 키가 두 개의 열이있는 점을 제외하고 첫 번째 테이블과 거의 동일한 두 번째 테이블을 만듭니다.
CREATE TABLE test2 ( id INT UNSIGNED NOT NULL AUTO_INCREMENT, data VARCHAR (64) DEFAULT NULL, ts TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (id, ts) );
원래 test
테이블에 대해 실행 한 것과 동일한 2 개의 REPLACE
문을 test2
에 대해 실행하면 다른 결과를 얻을 수 있습니다.
mysql>REPLACE INTO test2 VALUES (1, 'Old', '2014-08-20 18:47:00');
Query OK, 1 row affected (0.05 sec) mysql>REPLACE INTO test2 VALUES (1, 'New', '2014-08-20 18:47:42');
Query OK, 1 row affected (0.06 sec) mysql>SELECT * FROM test2;
+----+------+---------------------+ | id | data | ts | +----+------+---------------------+ | 1 | Old | 2014-08-20 18:47:00 | | 1 | New | 2014-08-20 18:47:42 | +----+------+---------------------+ 2 rows in set (0.00 sec)
이것은 test2
에서 수행 한 경우 id
컬럼과 ts
된 컬럼의 값이 대체 행에 대한 기존 행의 값과 일치해야하고, 그렇지 않으면 행이 삽입되기 때문입니다 .
MySQL 5.6.6 이전에는 테이블 수준의 잠금을 채용 한 MyISAM
등의 스토리지 엔진을 사용하는 파티션 된 테이블에 영향을 미칠 REPLACE
의해 그 테이블의 모든 파티션이 잠겨있었습니다. 이것은 REPLACE ... PARTITION
문에도 적용되었습니다. (이것은 행 레벨 락을 채용 한 InnoDB
등의 스토리지 엔진에서 발생하지 않았고 현재도 발생하지 않습니다.) MySQL 5.6.6 이후에서는, MySQL은 파티션 잠금 가지 치기를 사용합니다. 이렇게하면 그 테이블의 모든 파티션 컬럼이 업데이트되지 않는 한, REPLACE
문 WHERE
절에 일치하는 행을 포함하는 파티션 만 실제로 잠기도록합니다. 그렇지 않으면 전체 테이블이 잠겨 있습니다. 자세한 내용은 섹션 19.6.4 "파티셔닝 및 잠금" 을 참조하십시오.