굵게 키워드 · 기울임 직접 채우는 자리 · [ ] 생략 가능 · ... 반복 가능. 구문 표기 규약을 참고하십시오.
{#merge-description}
## 설명
`MERGE`는 [`MATCH`](match.md)와 [`CREATE`](create.md)의 일을 하나의 절이 하는 것입니다. 자기 패턴을
찾고, 그 패턴이 있으면 `MATCH`처럼 동작하고 없으면 `CREATE`처럼 동작합니다. 어느 쪽이든 패턴의
변수는 결국 바인딩되므로, 쿼리의 나머지는 둘 중 무엇이 일어났는지 알 필요가 없습니다.
`MERGE`에 관한 모든 것을 규칙 하나가 결정합니다. 이 절은 **패턴 전체**를 봅니다:
- 패턴 전체가 일치하면 아무것도 쓰이지 않습니다.
- 그중 어느 부분이라도 없으면 **패턴 전체가 만들어집니다.** 그래프의 다른 곳에 이미 있는 부분까지
포함해서입니다. `a`와 `b`는 있고 간선만 없는 상태에서 `(a)-[:e]->(b)`를 merge하면, 간선과 함께
두 번째 `a`와 두 번째 `b`가 만들어집니다.
- 그러므로 이미 무엇이 있는지 확실하지 않을 때는 **요소를 하나씩** merge하십시오. 정점마다 `MERGE`를
쓰고, 그다음 그것들이 바인딩한 변수 사이의 간선에 `MERGE`를 쓰십시오. 그렇게 쓰면 `MERGE`는
멱등합니다.
그 밖의 규칙입니다:
- `MERGE`는 **패턴을 정확히 하나** 받습니다. 쉼표로 구분한 패턴은 구문 오류입니다. `MERGE` 절을
여러 개 쓰십시오.
- `ON CREATE SET`은 패턴이 만들어졌을 때만, `ON MATCH SET`은 일치했을 때만 실행됩니다. 둘 다 어느
순서로든 줄 수 있고, 각각 [`SET`](set.md)의 항목 목록을 받습니다.
- 패턴 안의 속성도 일치 대상의 일부입니다. `MERGE (m:movie {title: 'Tenet'})`는 `title`이 정확히
`Tenet`인 `movie`에만 일치하며, `title`을 갖고 있기만 한 것에는 일치하지 않습니다.
- `MERGE`는 들어오는 행마다 한 번 실행됩니다. 쿼리를 시작하거나, 다른 절 뒤에 오거나, 쿼리를 끝낼
수 있습니다.
{#merge-parameters}
## 매개변수
pattern
: [`MATCH`](match.md) 구문의 경로 패턴 하나입니다. 그 안의 모든 속성은 일치 조건이면서, 만들 때는
설정할 속성이기도 합니다.
ON CREATE SET
: 패턴이 만들어졌을 때만 적용되는 할당입니다.
ON MATCH SET
: 패턴을 찾았을 때만 적용되는 할당입니다.
set_item
: [`SET`](set.md) 구문의 할당입니다. `variable.property = expression`, `variable = map`,
`variable += map` 중 하나입니다.
{#merge-examples}
## 예제
모든 예제는 [예제 데이터셋](../../get_started/example-dataset.md)에서 실행됩니다.
The last example undoes them.
{#merge-create-the-vertex-or-find-it}
### 정점을 만들거나 찾기
첫 실행은 만듭니다:
```cypher
MERGE (m:movie {title: 'Tenet'}) RETURN m.title AS film, m.year AS year;
```
```
film | year
---------+------
"Tenet" |
(1 row)
```
패턴에 `title`만 있었으므로 `year`는 설정되지 않았습니다. 두 번째 실행은 같은 정점을 찾고
아무것도 쓰지 않습니다:
```cypher
MERGE (m:movie {title: 'Tenet'}) RETURN m.title AS film, m.year AS year;
```
```
film | year
---------+------
"Tenet" |
(1 row)
```
```cypher
MATCH (m:movie {title: 'Tenet'}) RETURN count(*) AS rows;
```
```
rows
------
1
(1 row)
```
{#merge-set-different-properties-on-create-and-on-match}
### 만들 때와 일치할 때 서로 다른 속성 설정하기
아무것도 없는 상태에서 시작합니다:
```cypher
MATCH (m:movie {title: 'Tenet'}) DETACH DELETE m;
```
```
UPDATE 1
```
```cypher
MERGE (m:movie {title: 'Tenet'})
ON CREATE SET m.year = 2020, m.source = 'created'
ON MATCH SET m.source = 'matched'
RETURN m.title AS film, m.year AS year, m.source AS source;
```
```
film | year | source
---------+------+-----------
"Tenet" | 2020 | "created"
(1 row)
```
똑같은 문장을 두 번째로 실행하면 다른 분기를 탑니다:
```cypher
MERGE (m:movie {title: 'Tenet'})
ON CREATE SET m.year = 2020, m.source = 'created'
ON MATCH SET m.source = 'matched'
RETURN m.title AS film, m.year AS year, m.source AS source;
```
```
film | year | source
---------+------+-----------
"Tenet" | 2020 | "matched"
(1 row)
```
`year`는 만들기 분기가 준 값을 그대로 유지합니다. `ON MATCH SET`이 그것에 손대지 않았기
때문입니다.
{#merge-see-a-whole-pattern-merge-duplicate-a-vertex}
### 패턴 전체를 MERGE하면 정점이 중복되는 것 보기
Christopher Nolan은 한 명이고, 그는 `Tenet`을 연출하지 않았습니다:
```cypher
MATCH (m:movie {title: 'Tenet'}) DETACH DELETE m;
MATCH (p:person {name: 'Christopher Nolan'}) RETURN count(*) AS nolans;
```
```
UPDATE 1
nolans
--------
1
(1 row)
```
경로 전체를 merge하면 간선이 없으므로 일치하는 것을 찾지 못합니다. 그래서 경로 전체를
만듭니다:
```cypher
MERGE (d:person {name: 'Christopher Nolan'})-[:directed]->(m:movie {title: 'Tenet'})
RETURN d.name AS director, m.title AS film;
```
```
director | film
---------------------+---------
"Christopher Nolan" | "Tenet"
(1 row)
```
```cypher
MATCH (p:person {name: 'Christopher Nolan'}) RETURN count(*) AS nolans;
```
```
nolans
--------
2
(1 row)
```
`born` 속성도 없고 원본의 간선도 하나 없는 두 번째 Christopher Nolan입니다. `MERGE`가 불러들이는
실수가 이것입니다.
{#merge-merge-one-element-at-a-time-instead}
### 대신 요소를 하나씩 merge하기
그것을 되돌리고, 그다음 요소를 하나씩 따로 merge합니다:
```cypher
MATCH (p:person {name: 'Christopher Nolan'})
WHERE NOT EXISTS { MATCH (p)-[:directed]->(:movie {title: 'Inception'}) }
DETACH DELETE p;
MATCH (m:movie {title: 'Tenet'}) DETACH DELETE m;
```
```
UPDATE 2
UPDATE 1
```
```cypher
MERGE (d:person {name: 'Christopher Nolan'})
MERGE (m:movie {title: 'Tenet'})
MERGE (d)-[:directed]->(m)
RETURN d.name AS director, m.title AS film;
```
```
director | film
---------------------+---------
"Christopher Nolan" | "Tenet"
(1 row)
```
```cypher
MATCH (p:person {name: 'Christopher Nolan'}) RETURN count(*) AS nolans;
```
```
nolans
--------
1
(1 row)
```
첫 `MERGE`는 이미 있는 사람을 일치시켰고, 둘째는 영화를 만들었고, 셋째는 간선만 만들었습니다. 같은
세 절을 다시 실행해도 아무것도 바뀌지 않습니다:
```cypher
MATCH (p:person {name: 'Christopher Nolan'})-[:directed]->(m:movie)
RETURN count(*) AS edges;
```
```
edges
-------
3
(1 row)
```
원래 데이터셋의 둘에 merge한 하나를 더한 것이며, 그 문장을 몇 번 실행하든 그대로입니다.
{#merge-reject-more-than-one-pattern}
### 패턴이 둘 이상이면 거부된다
```cypher
MERGE (a:movie {title: 'A'}), (b:movie {title: 'B'});
```
```
ERROR: syntax error at or near ","
LINE 1: MERGE (a:movie {title: 'A'}), (b:movie {title: 'B'});
^
```
`MERGE` 절을 두 개 쓰십시오.
{#merge-undo-the-examples}
### 예제 되돌리기
```cypher
MATCH (m:movie {title: 'Tenet'}) DETACH DELETE m;
```
```
UPDATE 2
```
{#merge-notes}
## 참고
고유성 제약은 중복 위험을 조용한 데이터 오염이 아니라 깔끔한 실패로 바꿔 줍니다. `person`의
`name`에 고유성이 걸려 있으면, 위의 패턴 전체 merge는 두 번째 Nolan을 만들 수 없습니다:
```cypher
CREATE CONSTRAINT unique_person_name ON person ASSERT name IS UNIQUE;
MERGE (d:person {name: 'Christopher Nolan'})-[:directed]->(m:movie {title: 'Tenet'})
RETURN d.name AS director, m.title AS film;
```
```
CREATE CONSTRAINT
ERROR: conflicting key value violates exclusion constraint "unique_person_name"
DETAIL: Key ((properties.'name'))=("Christopher Nolan") conflicts with existing key ((properties.'name'))=("Christopher Nolan").
```
아무것도 만들어지지 않고, 트랜잭션이 그 이유를 보고합니다. merge에 쓰는 키가 무엇이든 그 키에
제약을 선언하십시오.
{#merge-compatibility}
## 호환성
{#merge-merge-is-not-a-gql-clause}
### MERGE는 GQL 절이 아니다
ISO/IEC 39075에는 `MERGE`가 없습니다. 표준의 데이터 변경 문장은 ``(§13.2),
``(§13.3), ``(§13.4), ``(§13.5)입니다. `MERGE`는
Cypher에서 왔고 AgensGraph는 그것을 유지합니다. 표준만으로 같은 일을 하려면
[`CALL { subquery }`](call-subquery.md)를 쓰거나, `EXISTS` 검사 뒤에
[`INSERT`](insert.md)를 쓰십시오.
{#merge-see-also}
## 관련 항목
- [`CREATE`](create.md) — 조건 없이 쓰기
- [`MATCH`](match.md) — 패턴 구문
- [`SET`](set.md) — `ON CREATE SET`과 `ON MATCH SET`이 받는 할당 구문
- [`DELETE`](delete.md) — merge가 만든 것을 지우기