{#alter-label-alter-vlabel-and-alter-elabel} # ALTER VLABEL과 ALTER ELABEL 레이블의 이름을 바꾸고, 저장 방식을 바꾸고, 부모를 붙이거나 떼고, 인덱스를 끄고, 승격된 타입 컬럼을 추가하거나 제거합니다. {#alter-label-synopsis} ## 개요
ALTER VLABEL [ IF EXISTS ] label_name action [, ... ]
ALTER VLABEL [ IF EXISTS ] label_name RENAME TO new_label_name

ALTER ELABEL [ IF EXISTS ] label_name action [, ... ]
ALTER ELABEL [ IF EXISTS ] label_name RENAME TO new_label_name

where action is one of:

    ADD [ COLUMN ] promoted_property
    DROP [ COLUMN ] column_name [ CASCADE | RESTRICT ]
    DISABLE INDEX
    SET STORAGE { PLAIN | EXTERNAL | EXTENDED | MAIN }
    SET TABLESPACE tablespace_name
    SET { LOGGED | UNLOGGED }
    CLUSTER ON index_name
    SET WITHOUT CLUSTER
    INHERIT parent_label
    NO INHERIT parent_label
    REPLICA IDENTITY { DEFAULT | USING INDEX index_name | FULL | NOTHING }
    OWNER TO role_specification

굵게 키워드 · 기울임 직접 채우는 자리 · [ ] 생략 가능 · ... 반복 가능. 구문 표기 규약을 참고하십시오.

{#alter-label-description} ## 설명 `ALTER VLABEL`은 정점 레이블에, `ALTER ELABEL`은 간선 레이블에 작용합니다. 키워드를 빼면 두 문장은 같습니다. **위에 나열한 모든 동작이 두 종류 모두에서 받아들여집니다.** 다른 것은 그 동작이 작용할 대상을 각 레이블 종류가 무엇으로 갖고 있는가입니다. - 레이블이 만들어질 때 함께 생기는 인덱스가 다릅니다. 정점 레이블에는 `id`에 대한 기본 키가 생기고, 간선 레이블에는 `(start, "end")`와 `("end", start)`에 걸린 btree 인덱스와 `id`에 걸린 BRIN 인덱스가 생깁니다. `DISABLE INDEX`는 어느 쪽이든 그 레이블의 모든 인덱스를 무효로 만들므로, 갓 만든 정점 레이블에서는 무효로 만들 것이 하나이고 간선 레이블에서는 셋입니다. `CLUSTER ON`도 고를 수 있는 이름이 다릅니다. - `DROP COLUMN`이 거부하는 구조 컬럼은 정점 레이블에서 `id`와 `properties`이고, 간선 레이블에는 `start`와 `end`가 더해집니다. - `INHERIT`와 `NO INHERIT`는 그 레이블과 같은 종류이고 같은 그래프에 있는 부모를 요구합니다. 레이블은 `graph_path`가 지정한 그래프에서 찾습니다. 그 이름은 수식할 수 없습니다. - `RENAME TO`는 그 자체로 하나의 형태입니다. 다른 어떤 동작과도 함께 쓸 수 없고, 여러 동작을 나열한 목록에 들어갈 수도 없습니다. - 한 문장의 여러 동작은 쉼표로 구분하며 적은 순서대로 적용됩니다. - 기반 레이블인 `ag_vertex`와 `ag_edge`는 아예 변경할 수 없습니다. - `ALTER VLABEL`은 간선 레이블을 거부하고 `ALTER ELABEL`은 정점 레이블을 거부합니다. 대신 `ALTER TABLE`로 레이블의 모양을 바꾸는 것은 `enable_graph_ddl`을 켜 두지 않으면 거부됩니다. 그래프 카탈로그가 레이블의 컬럼을 설명하는데, `ALTER TABLE`은 그것을 갱신하지 않습니다. 그 관문에 대해서는 [그래프가 어떻게 저장되는가](#graph-on-postgresql-what-is-deliberately-closed-off)가 다룹니다. {#alter-label-parameters} ## 매개변수 IF EXISTS : 그 레이블이 없을 때 오류가 아니라 알림을 냅니다. label_name : 변경할 레이블이며, `graph_path`가 지정한 그래프 안에서 찾습니다. RENAME TO new_label_name : 레이블에 새 이름을 줍니다. 정점과 간선은 자기 id를 유지하므로, 이름을 바꾸기 전에 만든 행에 대해서도 `label()`이 새 이름을 보고합니다. 그 테이블의 시퀀스와 인덱스는 처음 받은 이름을 유지하므로, `CLUSTER ON`을 쓰기 전에 그것을 확인하십시오. ADD [ COLUMN ] promoted_property : 승격된 타입 컬럼을 추가하고 이미 있는 행에서 그것을 채웁니다. `promoted_property`는 [`CREATE VLABEL`](#create-vlabel-promoted-properties)과 같은 세 형태를 받고 제한도 같습니다. 그 레이블에서 이미 승격된 속성은 거부되며, 한 문장에서 같은 키를 두 번 승격하는 것도 거부됩니다. DROP [ COLUMN ] column_name [ CASCADE | RESTRICT ] : 컬럼을 지우고, 승격된 속성이라면 그 대응 관계도 잊습니다. 레이블의 구조 컬럼은 거부됩니다. 지운 컬럼에 걸려 있던 인덱스도 함께 사라집니다. DISABLE INDEX : 그 레이블의 모든 인덱스를 무효로 표시해, 대량 적재가 그것을 유지하지 않게 합니다. 읽기와 쓰기는 계속 동작하고 플래너는 무효 인덱스를 무시합니다. `ENABLE INDEX`는 없습니다. 되돌아가는 길은 [`REINDEX VLABEL`](reindex.md)입니다. SET STORAGE { PLAIN | EXTERNAL | EXTENDED | MAIN } : 레이블의 `properties` 컬럼의 저장 방식을 정합니다. 이 방식이 큰 속성 맵을 인라인으로 둘지 그 테이블의 TOAST 관계에 둘지, 그리고 압축할지를 결정합니다. 레이블은 `EXTENDED`로 시작하며, 그것은 인라인이 아니면서 압축하는 방식입니다. 이 문장은 이후 쓰기에 대한 전략을 바꿀 뿐, 이미 저장된 것을 다시 쓰지는 않습니다. SET TABLESPACE tablespace_name : 레이블의 테이블을 다른 테이블스페이스로 옮깁니다. 그 인덱스는 있던 자리에 남습니다. SET { LOGGED | UNLOGGED } : 레이블 테이블의 미리 쓰기 로깅을 켜거나 끕니다. 그 레이블의 id 시퀀스도 함께 영속성이 바뀝니다. CLUSTER ON index_name : 나중의 `CLUSTER`가 쓸 인덱스로 어떤 인덱스를 기록해 둡니다. 지금 무언가를 재배열하지는 않습니다. SET WITHOUT CLUSTER : 그 기록을 잊습니다. INHERIT parent_label : 그 레이블을 같은 그래프의 같은 종류 레이블의 자식으로 붙여, 부모에 대한 패턴이 이 레이블의 행에도 일치하기 시작하게 합니다. NO INHERIT parent_label : 그 관계를 제거합니다. REPLICA IDENTITY { DEFAULT | USING INDEX index_name | FULL | NOTHING } : 논리 복제를 위해, 쓰기가 행을 식별하려고 WAL에 기록하는 이전 값을 무엇으로 할지 고릅니다. OWNER TO role_specification : 그 레이블을 다른 롤에게 넘깁니다. 롤 이름, `CURRENT_ROLE`, `CURRENT_USER`, `SESSION_USER` 중 하나를 씁니다. {#alter-label-examples} ## 예제 예제는 [예제 데이터셋](../../get_started/example-dataset.md)을 쓰지 않고 자체 그래프인 `catalogue`를 만들고, 끝에서 그것을 지웁니다. ```cypher CREATE GRAPH catalogue; SET graph_path = catalogue; CREATE VLABEL film; CREATE (:film {title: 'Arrival', year: 2016}), (:film {title: 'Dune', year: 2021}); ``` {#alter-label-rename-a-label} ### 레이블 이름 바꾸기 ```cypher ALTER VLABEL film RENAME TO movie; ``` ```psql \dGl catalogue.mov* ``` ``` List of labels Graph | Name | Type | Owner -----------+-------+--------+------- catalogue | movie | vertex | agens (1 row) ``` 행도 함께 따라왔습니다: ```cypher MATCH (m:movie) RETURN count(m) AS movies; ``` ``` movies -------- 2 (1 row) ``` 시퀀스와 기본 키는 여전히 옛 이름을 지니고 있습니다: ```psql \d catalogue.movie ``` ``` Table "catalogue.movie" Column | Type | Collation | Nullable | Default ------------+---------+-----------+----------+---------------------------------------------------------------------------------------------- id | graphid | | not null | graphid(graph_labid('catalogue.movie'::cstring), nextval('catalogue.film_id_seq'::regclass)) properties | jsonb | | not null | jsonb_build_object() Indexes: "film_pkey" PRIMARY KEY, btree (id) Inherits: catalogue.ag_vertex ``` 그래서 `ALTER VLABEL movie CLUSTER ON movie_pkey`는 `index "movie_pkey" for table "movie" does not exist`로 실패하고, 써야 할 이름은 `film_pkey`입니다. {#alter-label-turn-a-labels-indexes-off-for-a-bulk-load} ### 대량 적재를 위해 레이블의 인덱스 끄기 ```cypher ALTER VLABEL movie DISABLE INDEX; ``` ```psql \d catalogue.movie ``` ``` Table "catalogue.movie" Column | Type | Collation | Nullable | Default ------------+---------+-----------+----------+---------------------------------------------------------------------------------------------- id | graphid | | not null | graphid(graph_labid('catalogue.movie'::cstring), nextval('catalogue.film_id_seq'::regclass)) properties | jsonb | | not null | jsonb_build_object() Indexes: "film_pkey" PRIMARY KEY, btree (id) INVALID Inherits: catalogue.ag_vertex ``` 행을 적재하고, 그다음 인덱스를 다시 만듭니다: ```cypher REINDEX VLABEL movie; ``` ``` REINDEX ``` {#alter-label-promote-a-property-on-a-label-that-already-holds-rows} ### 행이 이미 있는 레이블에서 속성 승격하기 ```cypher ALTER VLABEL movie ADD COLUMN year int GENERATED; ``` ```psql \d catalogue.movie ``` ``` Table "catalogue.movie" Column | Type | Collation | Nullable | Default ------------+---------+-----------+----------+----------------------------------------------------------------------------------------------- id | graphid | | not null | graphid(graph_labid('catalogue.movie'::cstring), nextval('catalogue.film_id_seq'::regclass)) properties | jsonb | | not null | jsonb_build_object() year | integer | | | generated always as (ag_property_text(properties, 'year'::text, 'n'::"char")::integer) stored Indexes: "film_pkey" PRIMARY KEY, btree (id) Inherits: catalogue.ag_vertex ``` 이미 있는 행이 채워지므로, 그 문장이 돌아오는 순간 컬럼은 이미 완전합니다: ```sql SELECT year FROM catalogue.movie ORDER BY year; ``` ``` year ------ 2016 2021 (2 rows) ``` {#alter-label-look-up-what-a-label-promotes} ### 레이블이 무엇을 승격했는지 조회하기 `ag_label_property`가 속성 키를 그것을 대신해 답하는 컬럼에 대응시킵니다: ```cypher ALTER VLABEL movie ADD COLUMN released text GENERATED (releaseDate); ``` ```sql SELECT p.propname, p.attnum FROM pg_catalog.ag_label_property p JOIN pg_catalog.ag_label l ON l.oid = p.laboid JOIN pg_catalog.ag_graph g ON g.oid = l.graphid WHERE g.graphname = 'catalogue' AND l.labname = 'movie' ORDER BY p.attnum; ``` ``` propname | attnum -------------+-------- year | 3 releasedate | 4 (2 rows) ``` `attnum`은 그 테이블에서 컬럼의 위치입니다. 컬럼 이름까지 원한다면 그것으로 `pg_attribute`와 조인하십시오. 키를 명시하는 형태를 썼다면 그 둘이 다릅니다. {#alter-label-drop-a-promoted-column} ### 승격된 컬럼 지우기 ```cypher ALTER VLABEL movie DROP COLUMN released; ``` 그 대응 관계도 컬럼과 함께 사라집니다: ```sql SELECT p.propname, p.attnum FROM pg_catalog.ag_label_property p JOIN pg_catalog.ag_label l ON l.oid = p.laboid JOIN pg_catalog.ag_graph g ON g.oid = l.graphid WHERE g.graphname = 'catalogue' AND l.labname = 'movie' ORDER BY p.attnum; ``` ``` propname | attnum ----------+-------- year | 3 (1 row) ``` `releasedate`를 읽으면 `properties`로 돌아갑니다. `properties`에서 지워진 것은 없습니다. {#alter-label-change-how-the-property-map-is-stored} ### 속성 맵의 저장 방식 바꾸기 ```cypher ALTER VLABEL movie SET STORAGE external; ``` 어느 컬럼을 예상했든, 그 방식은 `properties`에 설정됩니다: ```sql SELECT attname, attstorage FROM pg_attribute WHERE attrelid = 'catalogue.movie'::regclass AND attnum > 0 AND NOT attisdropped; ``` ``` attname | attstorage ------------+------------ id | p properties | e year | p (3 rows) ``` {#alter-label-attach-and-detach-a-parent} ### 부모 붙이고 떼기 ```cypher CREATE VLABEL work; ALTER VLABEL movie INHERIT work; ``` ```psql \dGv catalogue.movie ``` ``` List of labels Graph | Name | Type | Owner -----------+-------+--------+------- catalogue | movie | vertex | agens (1 row) Vertex label "catalogue.movie" -- Inherits: catalogue.ag_vertex, catalogue.work ``` 이제 `movie`에는 부모가 둘입니다. 처음부터 있던 기반 레이블과 `work`입니다. 떼어 내도 기반 레이블은 그대로입니다: ```cypher ALTER VLABEL movie NO INHERIT work; ``` ``` ALTER VLABEL ``` {#alter-label-refusals-worth-recognizing} ### 알아 둘 만한 거부 사례 구조 컬럼은 지울 수 없습니다: ```cypher ALTER VLABEL movie DROP COLUMN properties; ``` ``` ERROR: cannot drop column "properties" of graph label "movie" HINT: It is a structural column of the graph label. ``` 추가하는 컬럼은 `properties`에서 생성되는 것이어야 합니다: ```cypher ALTER VLABEL movie ADD COLUMN rank int; ``` ``` ERROR: a non-generated promoted column is not supported yet HINT: Use GENERATED to mirror the property from the jsonb bag. ``` 이미 승격된 속성을 두 번 승격할 수는 없습니다: ```cypher ALTER VLABEL movie ADD COLUMN yr2 int GENERATED (year); ``` ``` ERROR: property "year" is already promoted on graph label "movie" HINT: Drop the existing promoted column first, or promote the property to a different column name. ``` 기반 레이블은 부모로든 대상으로든 손댈 수 없습니다: ```cypher ALTER VLABEL movie INHERIT ag_vertex; ``` ``` ERROR: cannot ALTER inheritance with base label ``` ```cypher ALTER VLABEL ag_vertex SET STORAGE main; ``` ``` ERROR: ALTER base vertex label is prohibited ``` 각 문장은 한 종류의 레이블에만 작용합니다: ```cypher CREATE ELABEL directed; ALTER VLABEL directed RENAME TO helmed; ``` ``` ERROR: RENAME VLABEL cannot RENAME edge label ``` 그리고 `RENAME TO`는 홀로 섭니다: ```cypher ALTER VLABEL movie RENAME TO film, SET STORAGE main; ``` ``` ERROR: syntax error at or near "," LINE 1: ALTER VLABEL movie RENAME TO film, SET STORAGE main; ^ ``` `enable_graph_ddl`이 꺼져 있는 동안에는 SQL로 레이블의 테이블 모양을 바꾸는 것이 거부됩니다: ```sql ALTER TABLE catalogue.movie ADD COLUMN rank int; ``` ``` ERROR: cannot add a column to graph label "movie" with ALTER TABLE HINT: Use ALTER VLABEL or ALTER ELABEL instead, which keeps the graph catalog in step. ``` 마지막으로 예제가 만든 그래프를 지웁니다: ```cypher DROP GRAPH catalogue CASCADE; ``` {#alter-label-notes} ## 참고 `SET STORAGE`는 다섯이 아니라 네 개의 키워드를 받습니다. `DEFAULT`는 예약어이고 여기서는 구문 오류입니다. 레이블이 처음 갖는 방식으로 돌아가려면 `SET STORAGE extended`로 쓰십시오. 알 수 없는 단어는 `invalid storage type "..."`으로 보고됩니다. `IF EXISTS` 알림은 두 형태에서 다릅니다. `RENAME TO`는 `label "nosuch" does not exist, skipping`을, 동작 목록은 `graph label "nosuch" does not exist, skipping`을 냅니다. 그다음 둘 다 성공을 보고하고 아무것도 하지 않습니다. {#alter-label-compatibility} ## 호환성 {#alter-label-isoiec-39075-gql} ### ISO/IEC 39075 (GQL) GQL에는 레이블을 변경하는 문장이 없습니다. 변경할 레이블이 없기 때문입니다. 요소 타입은 그래프 타입에 속하고, 그래프 타입은 통째로 만들어지고 지워집니다(``, §12.6). 레이블 이름 바꾸기, 속성 승격, 인덱스 끄기에 대응하는 것이 GQL에는 없습니다. 그래프 타입은 [GQL 적합성 표](../../appendix/gql-conformance.md)에 계획으로 기록돼 있습니다. {#alter-label-postgresql} ### PostgreSQL 여기 있는 모든 동작은 `ALTER TABLE`의 동작이고, 각각 거기서와 같은 뜻이며 두 가지만 조정됐습니다. `SET STORAGE`는 컬럼을 지정하지 않습니다. 저장 방식을 고를 만한 컬럼은 `properties` 하나뿐이므로 그 컬럼에 적용됩니다. `DISABLE INDEX`에는 `ALTER TABLE` 대응물이 아예 없습니다. 그것은 레이블의 인덱스를 무효로 표시하는데, SQL에서는 `CREATE INDEX CONCURRENTLY`를 중단시키는 것 말고는 그렇게 만들 방법이 없습니다. 반대 방향으로는, 레이블의 테이블에 대한 `ALTER TABLE`이 그 모양을 바꾸는 동작에 대해서는 `enable_graph_ddl`을 켜 두지 않으면 거부됩니다. 컬럼을 추가하거나 지우거나 타입을 바꾸는 것이 그런 동작입니다. 위의 예제가 그 거부를 보여 줍니다. 이 페이지의 동작들은 그 설정을 결코 필요로 하지 않습니다. 그래프 카탈로그를 스스로 갱신하기 때문입니다. {#alter-label-see-also} ## 관련 항목 - [`CREATE VLABEL`](create-vlabel.md) - [`CREATE ELABEL`](create-elabel.md) - [`DROP VLABEL`·`DROP ELABEL`](drop-label.md) - [`REINDEX VLABEL`·`REINDEX ELABEL`](reindex.md) - [속성을 컬럼으로 승격하기](../../querying/typed-columns.md) - [레이블 상속](../../concepts/label-inheritance.md)