# SET
{bdg-primary-line}`GQL clause`
Changes the properties of vertices and edges the query has bound.
## Synopsis
SET { target = expression | target += expression } [, ...]
bold keywords · italic placeholders you supply · [ ] optional · ... repeatable. See Syntax conventions.
## Description
`SET` writes properties onto elements already bound by an earlier clause. The
effect depends on what is on the left of the operator and which operator you use:
| Written as | Effect |
| --- | --- |
| `n.key = expression` | Sets one property, adding the key if it is not there. |
| `n.key = NULL` | Removes that key. |
| `n = {…}` | **Replaces** the whole property bag with the map. Keys not in the map are lost. |
| `n = other` | Replaces `n`'s bag with `other`'s. |
| `n += {…}` | **Merges** the map into the bag: listed keys are set, the rest are kept. |
- Assignments in one `SET` are separated by commas and applied left to right.
- `SET` runs once per incoming row, so a `MATCH` that finds 10 vertices updates
10 of them.
- `SET` needs a bound variable. It cannot introduce one, and it cannot lead a
query. It always follows a `MATCH`, a `MERGE` or another clause that binds
something.
- `SET` may end a query. Add a [`RETURN`](return.md) to see the result.
- `SET` writes properties only. It cannot add or change a label.
- `ON CREATE SET` and `ON MATCH SET` on a [`MERGE`](merge.md) take this same
assignment syntax.
## Parameters
target
: A property reference, `variable.key`, optionally nested as
`variable.key.subkey`; or a bare element variable when you are replacing or
merging the whole bag.
expression
: The value to store. Any Cypher expression: a literal, a property of another
element, an arithmetic or `CASE` expression, a list, a map. For `+=`, and for
`=` against a bare variable, it must be a map or another graph element.
## Examples
Every example runs against [the example dataset](../../get_started/example-dataset.md).
The last example undoes them.
### Set one property
```cypher
CREATE (:movie {title: 'Tenet', year: 2020, genre: 'Action'});
```
```
UPDATE 1
```
```cypher
MATCH (m:movie {title: 'Tenet'})
SET m.runtime = 150
RETURN properties(m) AS props;
```
```
props
---------------------------------------------------------------------
{"year": 2020, "genre": "Action", "title": "Tenet", "runtime": 150}
(1 row)
```
`properties()` returns the whole bag, which is the easiest way to see what a
`SET` did.
### Set several properties in one clause
```cypher
MATCH (m:movie {title: 'Tenet'})
SET m.genre = 'Sci-Fi', m.runtime = 151
RETURN properties(m) AS props;
```
```
props
---------------------------------------------------------------------
{"year": 2020, "genre": "Sci-Fi", "title": "Tenet", "runtime": 151}
(1 row)
```
### Remove a property with NULL
Assigning null deletes the key rather than storing a null:
```cypher
MATCH (m:movie {title: 'Tenet'})
SET m.runtime = NULL
RETURN properties(m) AS props;
```
```
props
-----------------------------------------------------
{"year": 2020, "genre": "Sci-Fi", "title": "Tenet"}
(1 row)
```
[`REMOVE`](remove.md) says the same thing more plainly.
### Merge a map with +=
`+=` sets the keys the map lists and leaves the others alone:
```cypher
MATCH (m:movie {title: 'Tenet'})
SET m += {runtime: 150, imax: true}
RETURN properties(m) AS props;
```
```
props
-----------------------------------------------------------------------------------
{"imax": true, "year": 2020, "genre": "Sci-Fi", "title": "Tenet", "runtime": 150}
(1 row)
```
### Replace the whole bag with =
`=` against a bare variable throws away everything not in the map. `genre`,
`runtime` and `imax` are gone:
```cypher
MATCH (m:movie {title: 'Tenet'})
SET m = {title: 'Tenet', year: 2020}
RETURN properties(m) AS props;
```
```
props
----------------------------------
{"year": 2020, "title": "Tenet"}
(1 row)
```
This is the difference between the two operators, and the one to be careful
about: `=` is a replacement, `+=` is an update.
### Copy one element's properties to another
The right-hand side can be another element, which copies its whole bag:
```cypher
CREATE (:person {name: 'Stand-in'});
```
```
UPDATE 1
```
```cypher
MATCH (p:person {name: 'Stand-in'}), (k:person {name: 'Keanu Reeves'})
SET p = k
RETURN properties(p) AS props;
```
```
props
----------------------------------------
{"born": 1964, "name": "Keanu Reeves"}
(1 row)
```
There are now two vertices whose `name` is `Keanu Reeves`:
```cypher
MATCH (p:person {name: 'Keanu Reeves'}) RETURN count(*) AS keanus;
```
```
keanus
--------
2
(1 row)
```
Copying a bag copies the identifying properties too. It does not copy edges, and
it does not merge the two vertices.
### Set a property on an edge
An edge takes properties exactly as a vertex does:
```cypher
MATCH (:person {name: 'Keanu Reeves'})-[r:acted_in]->(:movie {title: 'The Matrix'})
SET r.credited = true
RETURN properties(r) AS props;
```
```
props
-----------------------------------
{"role": "Neo", "credited": true}
(1 row)
```
```cypher
MATCH (:person {name: 'Keanu Reeves'})-[r:acted_in]->(:movie {title: 'The Matrix'})
SET r.credited = NULL
RETURN properties(r) AS props;
```
```
props
-----------------
{"role": "Neo"}
(1 row)
```
The `MATCH` finds the one edge that belongs to the original Keanu Reeves, because
the copy created above has no edges.
### Empty a bag
An empty map removes every property, leaving the element in place:
```cypher
MATCH (m:movie {title: 'Tenet'})
SET m = {}
RETURN properties(m) AS props;
```
```
props
-------
{}
(1 row)
```
The vertex is now unreachable by any property. The cleanup below therefore looks
for a missing `title` rather than for `Tenet`.
### Undo the examples
```cypher
MATCH (m:movie) WHERE m.title IS NULL DETACH DELETE m;
MATCH (p:person) WHERE p.name = 'Keanu Reeves' AND NOT EXISTS { MATCH (p)-[]->() } DETACH DELETE p;
```
```
UPDATE 1
UPDATE 1
```
## Notes
The default setting `allow_null_properties = off` makes `SET n.key = NULL` a
deletion. Turn it on and the key is kept with a JSON null value instead:
```cypher
SET allow_null_properties = true;
CREATE (m:movie {title: 'Tenet', year: 2020})
SET m.runtime = NULL
RETURN properties(m) AS props;
```
```
SET
props
---------------------------------------------------
{"year": 2020, "title": "Tenet", "runtime": null}
(1 row)
```
```cypher
SET allow_null_properties = false;
MATCH (m:movie {title: 'Tenet'}) DETACH DELETE m;
```
```
SET
UPDATE 1
```
A stored null is not the same as an absent key: `m.runtime IS NULL` is true
either way, but the key shows up in `properties()` and in a `jsonb` key test.
## Compatibility
### Setting a label (ISO/IEC 39075 §13.3)
The standard's `` adds a label to an element, written
`SET n:blockbuster` or `SET n IS blockbuster`. AgensGraph accepts neither:
```cypher
MATCH (m:movie {title: 'Inception'}) SET m:blockbuster RETURN m.title;
```
```
ERROR: syntax error at or near ":"
LINE 1: MATCH (m:movie {title: 'Inception'}) SET m:blockbuster RETUR...
^
```
An element's label is the table it lives in, so it is fixed when the element is
created. To move a vertex to another label, create it there and delete the
original.
## See also
- [`REMOVE`](remove.md) — remove properties by name
- [`MERGE`](merge.md) — `ON CREATE SET` and `ON MATCH SET`
- [`MATCH`](match.md) — binding the elements a `SET` writes to
- [`DELETE`](delete.md) — remove elements rather than properties