# CREATE GRAPH
Creates a graph — a schema, the two base labels that every label inherits from, and the
sequence that hands out label ids.
## Synopsis
CREATE GRAPH [ IF NOT EXISTS ] graph_name [ AUTHORIZATION role_specification ]
CREATE GRAPH ONLY graph_name
bold keywords · italic placeholders you supply · [ ] optional · ... repeatable. See Syntax conventions.
## Description
A graph is a schema. `CREATE GRAPH` creates that schema and puts three objects in it:
- `ag_vertex`, the base vertex label,
- `ag_edge`, the base edge label,
- `ag_label_seq`, the sequence that assigns label ids.
Every label you create afterwards inherits from `ag_vertex` or `ag_edge`. That inheritance
gives an unlabelled pattern like `MATCH (n)` its meaning.
[How a graph is stored](../../concepts/graph-on-postgresql.md) describes the
objects and the identifier scheme in full.
- The name has to be free as a graph name and as a schema name, because the graph owns a
schema of that name.
- If the session's `graph_path` is empty, `CREATE GRAPH` sets it to the new graph. A
`graph_path` that is already set is left alone.
- `CREATE GRAPH ONLY` creates the schema and the catalog row and nothing else. It is the
form `pg_dump` emits, so that a restore can recreate the base labels itself with their
original label ids. A graph created this way cannot hold a label until those base labels
exist.
## Parameters
IF NOT EXISTS
: Issue a notice instead of an error when a graph of that name already exists. Nothing is
created and nothing existing is changed.
graph_name
: Name of the graph to create.
AUTHORIZATION role_specification
: Role that owns the graph and the objects created with it. Write a role name,
`CURRENT_ROLE`, `CURRENT_USER` or `SESSION_USER`. Without this clause the graph belongs to
the role that runs the statement.
ONLY
: Create the schema and the catalog row without `ag_vertex`, `ag_edge` or `ag_label_seq`.
Unlike the plain form, it does not touch `graph_path`.
## Examples
The examples build their own graph, `boxoffice`, rather than using
[the example dataset](../../get_started/example-dataset.md), and drop it at the end.
### Create a graph
```cypher
CREATE GRAPH boxoffice;
```
```
CREATE GRAPH
```
The statement claimed an empty `graph_path`:
```sql
SHOW graph_path;
```
```
graph_path
------------
boxoffice
(1 row)
```
The graph is listed by `\dG`:
```psql
\dG boxoffice
```
```
List of graphs
Name | Owner
-----------+-------
boxoffice | agens
(1 row)
```
And it already holds the two base labels:
```psql
\dGl boxoffice.*
```
```
List of labels
Graph | Name | Type | Owner
-----------+-----------+--------+-------
boxoffice | ag_edge | edge | agens
boxoffice | ag_vertex | vertex | agens
(2 rows)
```
### Create a graph only if it is not there
```cypher
CREATE GRAPH IF NOT EXISTS boxoffice;
```
```
NOTICE: graph "boxoffice" already exists, skipping
CREATE GRAPH
```
The existing graph is untouched. This is not a "create or replace".
### Create a graph owned by another role
```sql
CREATE ROLE curator;
```
```cypher
CREATE GRAPH festival AUTHORIZATION curator;
```
```
CREATE GRAPH
```
```psql
\dG festival
```
```
List of graphs
Name | Owner
----------+---------
festival | curator
(1 row)
```
### Create the schema without the base labels
```cypher
CREATE GRAPH ONLY skeleton;
```
```
CREATE GRAPH
```
The graph exists but holds nothing:
```psql
\dGl skeleton.*
```
```
No matching labels found.
```
Because `ag_vertex` is missing, a label cannot be created in it:
```cypher
SET graph_path = skeleton;
CREATE VLABEL film;
```
```
ERROR: relation "skeleton.ag_vertex" does not exist
```
Clean up the three graphs and the role:
```cypher
DROP GRAPH boxoffice CASCADE;
DROP GRAPH festival CASCADE;
DROP GRAPH skeleton;
```
```sql
DROP ROLE curator;
```
`skeleton` needs no `CASCADE` because nothing was created inside it. A graph made by the
plain form always does. See [`DROP GRAPH`](drop-graph.md).
## Notes
`graph_path` names the graph that unqualified label names belong to. It is a per-session
setting; set it in each new session, or attach it to a database or a role:
```sql
ALTER DATABASE SET graph_path = boxoffice;
```
Two more statements act on a graph as a whole. Neither has an `IF EXISTS` form:
```cypher
CREATE GRAPH receipts;
ALTER GRAPH receipts RENAME TO takings;
ALTER GRAPH takings OWNER TO CURRENT_USER;
SHOW graph_path;
```
```
graph_path
------------
takings
(1 row)
```
A rename moves the underlying schema with the graph, and the session's `graph_path` follows
it. So it reads `takings` above rather than `receipts`.
```cypher
DROP GRAPH takings CASCADE;
```
## Compatibility
### ISO/IEC 39075 (GQL)
GQL defines `` (§12.4) as
`CREATE [PROPERTY] GRAPH { | }`. A graph is created
either as `ANY`, which accepts any content, or against a *graph type* that constrains its
node types, edge types and properties. AgensGraph's graphs are always open, so no graph type
is written and none can be. The `PROPERTY` spelling is not accepted:
`CREATE PROPERTY GRAPH boxoffice` is a syntax error. Graph types are tracked as planned in
the [GQL conformance matrix](../../appendix/gql-conformance.md).
`AUTHORIZATION` and `ONLY` are AgensGraph's own; GQL has neither. GQL's `OR REPLACE` form is
not accepted either.
### PostgreSQL
`CREATE GRAPH` corresponds to `CREATE SCHEMA`, and `IF NOT EXISTS` and `AUTHORIZATION` mean
what they mean there. The difference is the contents. `CREATE SCHEMA` creates an empty
schema. `CREATE GRAPH` also creates the base labels and the label-id sequence, and registers
the schema in `ag_graph` so that Cypher can find it. `CREATE SCHEMA` on its own does not
produce a graph.
## See also
- [`DROP GRAPH`](drop-graph.md)
- [`CREATE VLABEL`](create-vlabel.md)
- [`CREATE ELABEL`](create-elabel.md)
- [How a graph is stored](../../concepts/graph-on-postgresql.md)