Create, show, and drop constraints
This page describes how to create, list, and drop constraints. The following constraint types are available in Neo4j:
-
Property existence constraints Enterprise Edition
-
Property type constraints Introduced in 5.9 Enterprise Edition
-
Key constraints Enterprise Edition
CREATE CONSTRAINT
Constraints are created with the CREATE CONSTRAINT
command.
When creating a constraint, it is recommended to provide a constraint name.
This name must be unique among both indexes and constraints.
If a name is not explicitly given, a unique name will be auto-generated.
Creating a constraint requires the CREATE CONSTRAINT privilege.
|
Adding constraints is an atomic operation that can take a while — all existing data has to be scanned before a Neo4j DBMS can use a constraint. |
Create property uniqueness constraints
Property uniqueness constraints ensure that the property values are unique for all nodes with a specific label or all relationships with a specific type. For composite property uniqueness constraints on multiple properties, it is the combination of property values that must be unique. Queries that try to add duplicated property values will fail.
Property uniqueness constraints do not require all nodes or relationships to have values for the properties listed in the constraint. Only nodes or relationships that contain all properties specified in the constraint are subject to the uniqueness rule. Nodes or relationships missing one or more of the specified properties are not subject to this rule.
Create a single property uniqueness constraint
Single property uniqueness constraints are created with the following commands:
-
Node property uniqueness constraints:
CREATE CONSTRAINT constraint_name FOR (n:Label) REQUIRE n.property IS UNIQUE
. -
Relationship property uniqueness constraints:
CREATE CONSTRAINT constraint_name FOR ()-[r:REL_TYPE]-() REQUIRE r.property IS UNIQUE
. Introduced in 5.7
For the full command syntax to create a property uniqueness constraint, see Syntax → Create property uniqueness constraints.
Book
nodes to have unique isbn
propertiesCREATE CONSTRAINT book_isbn
FOR (book:Book) REQUIRE book.isbn IS UNIQUE
Added 1 constraint.
The detailed statistics view currently says Unique constraints added: 1 .
It will be updated to say Node property uniqueness constraints added: 1 in a future version of Neo4j.
|
SEQUEL_OF
relationships to have unique order
propertiesCREATE CONSTRAINT sequels
FOR ()-[sequel:SEQUEL_OF]-() REQUIRE sequel.order IS UNIQUE
Added 1 constraint.
The detailed statistics view currently says Relationship uniqueness constraints added: 1 .
It will be updated to say Relationship property uniqueness constraints added: 1 in a future version of Neo4j.
|
Create a composite property uniqueness constraint
Constraints created for multiple properties are called composite constraints. Note that the constrained properties must be parenthesized when creating composite property uniqueness constraints.
-
Node property uniqueness constraints:
CREATE CONSTRAINT constraint_name FOR (n:Label) REQUIRE (n.propertyName_1, …, n.propertyName_n) IS UNIQUE
. -
Relationship property uniqueness constraints:
CREATE CONSTRAINT constraint_name FOR ()-[r:REL_TYPE]-() REQUIRE (r.propertyName_1, …, r.propertyName_n) IS UNIQUE
. Introduced in 5.7
For the full command syntax to create a property uniqueness constraint, see Syntax → Create property uniqueness constraints.
Book
nodes to have unique combinations of title
and publicationYear
propertiesCREATE CONSTRAINT book_title_year
FOR (book:Book) REQUIRE (book.title, book.publicationYear) IS UNIQUE
Added 1 constraint.
PREQUEL_OF
relationships to have unique combinations of order
and author
propertiesCREATE CONSTRAINT prequels
FOR ()-[prequel:PREQUEL_OF]-() REQUIRE (prequel.order, prequel.author) IS UNIQUE
Added 1 constraint.
Create data that complies with existing property uniqueness constraints
Book
node with a unique isbn
propertyCREATE (book:Book {isbn: '1449356265', title: 'Graph Databases'})
Added 1 label, created 1 node, set 2 properties
SEQUEL_OF
relationship with a unique order
propertyCREATE (:Book {title: 'Spirit Walker'})-[:SEQUEL_OF {order: 1, seriesTitle: 'Chronicles of Ancient Darkness'}]->(:Book {title: 'Wolf Brother'})
Added 2 labels, created 2 nodes, set 4 properties, created 1 relationship.
Create property existence constraints
Property existence constraints ensure that a property exists either for all nodes with a specific label or for all relationships with a specific type. Queries that try to create new nodes of the specified label, or relationships of the specified type, without the constrained property will fail. The same is true for queries that try to remove the mandatory property.
Create a single property existence constraint
Property existence constraints on single properties are created with the following commands:
-
Node property existence constraint:
CREATE CONSTRAINT constraint_name FOR (n:Label) REQUIRE n.property IS NOT NULL
. -
Relationship property existence constraint:
CREATE CONSTRAINT constraint_name FOR ()-[r:REL_TYPE]-() REQUIRE r.property IS NOT NULL
.
For the full command syntax to create an existence constraint, see Syntax → Create property existence constraints.
It is not possible to create composite existence constraints on several properties. |
Author
nodes to have a name
propertyCREATE CONSTRAINT author_name
FOR (author:Author) REQUIRE author.name IS NOT NULL
Added 1 constraint.
WROTE
relationships to have a year
propertyCREATE CONSTRAINT wrote_year
FOR ()-[wrote:WROTE]-() REQUIRE wrote.year IS NOT NULL
Added 1 constraint.
Create data that complies with existing property existence constraints
Author
node with a name
property:CREATE (author:Author {name:'Virginia Woolf', surname: 'Woolf'})
Added 1 label, created 1 node, set 2 properties
WROTE
relationship with a year
propertyCREATE (author:Author {name: 'Emily Brontë', surname: 'Brontë'})-[wrote:WROTE {year: 1847, location: 'Haworth, United Kingdom', published: true}]->(book:Book {title:'Wuthering Heights', isbn: 9789186579296})
Added 2 labels, created 2 nodes, set 7 properties, created 1 relationship
Create property type constraints
Property type constraints ensure that a property has the required data type for all nodes with a specific label or for all relationships with a specific type. Queries that attempt to add this property with the wrong data type or modify this property in a way that changes its data type for nodes of the specified label or relationships of the specified type will fail.
Property type constraints do not require all nodes or relationships to have the property. Nodes or relationships without the constrained property are not subject to this rule.
Create a single property type constraint
Property type constraints are created with the following commands:
-
Node property type constraints:
CREATE CONSTRAINT constraint_name FOR (n:Label) REQUIRE n.property IS :: <TYPE>
. -
Relationship property type constraints:
CREATE CONSTRAINT constraint_name FOR ()-[r:REL_TYPE]-() REQUIRE r.property IS :: <TYPE>
.
<TYPE>
refers to a specific Cypher® data type, such as STRING
or INTEGER
.
For the types that properties can be constrained by, see Allowed types, and for information about different data types in Cypher, see Values and types.
For the full command syntax to create a property type constraint, see Syntax → Create property type constraints.
It is not possible to create composite property type constraints on several properties. |
title
properties on Movie
nodes to be of type STRING
CREATE CONSTRAINT movie_title
FOR (movie:Movie) REQUIRE movie.title IS :: STRING
Added 1 constraint.
order
properties on PART_OF
relationships to be of type INTEGER
CREATE CONSTRAINT part_of
FOR ()-[part:PART_OF]-() REQUIRE part.order IS :: INTEGER
Added 1 constraint.
Create property type constraints with a union type
A closed dynamic union allows a node or relationship property to maintain some type flexibility whilst preventing unexpected values from being stored.
tagline
properties on Movie
nodes to be either of type STRING
or LIST<STRING NOT NULL>
CREATE CONSTRAINT movie_tagline
FOR (movie:Movie) REQUIRE movie.tagline IS :: STRING | LIST<STRING NOT NULL>
Added 1 constraint.
tags
properties on PART_OF
relationships to either of type STRING
or LIST<STRING NOT NULL>
CREATE CONSTRAINT part_of_tags
FOR ()-[part:PART_OF]-() REQUIRE part.tags IS :: STRING | LIST<STRING NOT NULL>
Added 1 constraint.
Allowed types
The allowed property types for property type constraints are:
-
BOOLEAN
-
STRING
-
INTEGER
-
FLOAT
-
DATE
-
LOCAL TIME
-
ZONED TIME
-
LOCAL DATETIME
-
ZONED DATETIME
-
DURATION
-
POINT
-
LIST<BOOLEAN NOT NULL>
Introduced in 5.10 -
LIST<STRING NOT NULL>
Introduced in 5.10 -
LIST<INTEGER NOT NULL>
Introduced in 5.10 -
LIST<FLOAT NOT NULL>
Introduced in 5.10 -
LIST<DATE NOT NULL>
Introduced in 5.10 -
LIST<LOCAL TIME NOT NULL>
Introduced in 5.10 -
LIST<ZONED TIME NOT NULL>
Introduced in 5.10 -
LIST<LOCAL DATETIME NOT NULL>
Introduced in 5.10 -
LIST<ZONED DATETIME NOT NULL>
Introduced in 5.10 -
LIST<DURATION NOT NULL>
Introduced in 5.10 -
LIST<POINT NOT NULL>
Introduced in 5.10 -
Any closed dynamic union of the above types, e.g.
INTEGER | FLOAT | STRING
. Introduced in 5.11
For a complete reference describing all types available in Cypher, see the section on types and their synonyms.
Creating property type constraints on invalid types will fail
imdbScore
properties on Movie
nodes to be of type MAP
CREATE CONSTRAINT score FOR (movie:Movie) REQUIRE movie.imdbScore IS :: MAP
Failed to create node property type constraint: Invalid property type `MAP`.
Create data that complies with existing property type constraints
Movie
node with a STRING
title
propertyCREATE (movie:Movie {title:'Iron Man'})
Added 1 label, created 1 node, set 1 properties
PART_OF
relationship with an INTEGER
order
propertyMATCH (movie:Movie {title:'Iron Man'})
CREATE (movie)-[part:PART_OF {order: 3}]->(franchise:Franchise {name:'MCU'})
Added 1 label, added 1 node, created 1 relationship, set 2 properties
Create key constraints
Key constraints ensure that the property exist and the property value is unique for all nodes with a specific label or all relationships with a specific type. For composite key constraints on multiple properties, all properties must exists and the combination of property values must be unique.
Queries that try to create new nodes of the specified label, or relationships of the specified type, without the constrained property will fail. The same is true for queries that try to remove the mandatory property or add duplicated property values.
Create a single property key constraint
Single property key constraints are created with the following commands:
-
Node key constraints:
CREATE CONSTRAINT constraint_name FOR (n:Label) REQUIRE n.property IS NODE KEY
. -
Relationship key constraints:
CREATE CONSTRAINT constraint_name FOR ()-[r:REL_TYPE]-() REQUIRE r.property IS RELATIONSHIP KEY
. Introduced in 5.7
For the full command syntax to create a key constraint, see Syntax → Create key constraints.
Director
nodes to have a unique imdbId
property as a node key.CREATE CONSTRAINT director_imdbId
FOR (director:Director) REQUIRE (director.imdbId) IS NODE KEY
Added 1 constraint.
OWNS
relationships to have a unique ownershipId
property as a relationship keyCREATE CONSTRAINT ownershipId
FOR ()-[owns:OWNS]-() REQUIRE owns.ownershipId IS RELATIONSHIP KEY
Added 1 constraint.
Create a composite key constraint
Constraints created for multiple properties are called composite constraints. Note that the constrained properties must be parenthesized when creating composite key constraints.
Composite key constraints are created with the following commands:
-
Node key constraints:
CREATE CONSTRAINT constraint_name FOR (n:Label) REQUIRE (n.propertyName_1, …, n.propertyName_n) IS NODE KEY
. -
Relationship key constraints:
CREATE CONSTRAINT constraint_name FOR ()-[r:REL_TYPE]-() REQUIRE (r.propertyName_1, …, r.propertyName_n) IS RELATIONSHIP KEY
. Introduced in 5.7
For the full command syntax to create a key constraint, see Syntax → Create key constraints.
Actor
nodes to have a unique combination of firstname
and surname
properties as a node keyCREATE CONSTRAINT actor_fullname
FOR (actor:Actor) REQUIRE (actor.firstname, actor.surname) IS NODE KEY
Added 1 constraint.
KNOWS
relationships to have a unique combination of since
and how
properties as a relationship keyCREATE CONSTRAINT knows_since_how
FOR ()-[knows:KNOWS]-() REQUIRE (knows.since, knows.how) IS RELATIONSHIP KEY
Added 1 constraint.
Create data that complies with existing key constraints
Actor
node with unique firstname
and surname
propertiesCREATE (actor:Actor {firstname: 'Keanu', surname: 'Reeves'})
Added 1 label, created 1 node, set 2 properties.
KNOWS
relationship with unique since
and how
propertiesCREATE (:Actor {firstname: 'Jensen', surname: 'Ackles'})-[:KNOWS {since: 2008, how: 'coworkers', friend: true}]->(:Actor {firstname: 'Misha', surname: 'Collins'})
Added 2 labels, created 2 nodes, set 7 properties, created 1 relationship.
Create a constraint with a parameter
All constraint types can be created with a parameterized name.
{
"name": "node_uniqueness_param"
}
CREATE CONSTRAINT $name
FOR (book:Book) REQUIRE book.prop1 IS UNIQUE
Added 1 constraint.
{
"name": "rel_exist_param"
}
CREATE CONSTRAINT $name
FOR ()-[wrote:WROTE]-() REQUIRE wrote.published IS NOT NULL
Added 1 constraint.
Handling multiple constraints
Creating an already existing constraint will fail. This includes the following scenarios:
-
Creating a constraint identical to an already existing constraint.
-
Creating a constraint with a different name but on the same constraint type and same label/relationship type and property combination as an already existing constraint. For property type constraints the property type also needs to be the same.
-
Creating a constraint with the same name as an already existing constraint, regardless of what that constraint is.
Additionally, some constraints cannot coexist and attempting to create them together will therefore fail as well. This includes:
-
Property type constraints on the same label/relationship type and property but with different property types.
-
Property uniqueness and key constraints on the same label/relationship type and property combination.
However, some constraint types are allowed on the same label/relationship type and property combination. For example, it is possible to have a property uniqueness and a property existence constraint on the same label/relationship type and property combination, though this would be the equivalent of having a node or relationship key constraint. A more useful example would be to combine a property type and a property existence constraint to ensure that the property exists and has the given type.
Handling existing constraints when creating a constraint
To avoid failing on existing constraints, IF NOT EXISTS
can be added to the CREATE
command.
This will ensure that no error is thrown and that no constraint is created if any other constraint with the given name, or another constraint on the same constraint type and schema, or both, already exists.
For property type constraints the property type also needs to be the same.
As of Neo4j 5.17, an informational notification is instead returned showing the existing constraint which blocks the creation.
SEQUEL_OF
relationships to have unique order
propertiesCREATE CONSTRAINT sequels IF NOT EXISTS
FOR ()-[sequel:SEQUEL_OF]-() REQUIRE sequel.order IS UNIQUE
Because the same constraint already exists, nothing will happen:
(no changes, no records)
`CREATE CONSTRAINT sequels IF NOT EXISTS FOR ()-[e:SEQUEL_OF]-() REQUIRE (e.order) IS UNIQUE` has no effect.
`CONSTRAINT sequels FOR ()-[e:SEQUEL_OF]-() REQUIRE (e.order) IS UNIQUE` already exists.
SEQUEL_OF
relationships to have unique order
propertiesCREATE CONSTRAINT new_sequels IF NOT EXISTS
FOR ()-[sequel:SEQUEL_OF]-() REQUIRE sequel.order IS UNIQUE
Because a constraint with a different name (sequels
) on the same schema exists, nothing will happen:
(no changes, no records)
`CREATE CONSTRAINT new_sequels IF NOT EXISTS FOR ()-[e:SEQUEL_OF]-() REQUIRE (e.order) IS UNIQUE` has no effect.
`CONSTRAINT sequels FOR ()-[e:SEQUEL_OF]-() REQUIRE (e.order) IS UNIQUE` already exists.
AUTHORED
relationships to have unique name
propertiesCREATE CONSTRAINT author_name IF NOT EXISTS
FOR ()-[a:AUTHORED]-() REQUIRE a.name IS UNIQUE
Because a node property existence constraint named author_name
already exists, nothing will happen:
(no changes, no records)
`CREATE CONSTRAINT author_name IF NOT EXISTS FOR ()-[e:AUTHORED]-() REQUIRE (e.name) IS UNIQUE` has no effect.
`CONSTRAINT author_name FOR (e:Author) REQUIRE (e.name) IS NOT NULL` already exists.
Creating an already existing constraint will fail
Creating a constraint with the same name or on the same node label or relationship type and properties that are already constrained by a constraint of the same type will fail. Property uniqueness and key constraints are also not allowed on the same schema.
SEQUEL_OF
relationships to have unique order
properties, given an identical constraint already existsCREATE CONSTRAINT sequels
FOR ()-[sequel:SEQUEL_OF]-() REQUIRE sequel.order IS UNIQUE
An equivalent constraint already exists, 'Constraint( id=5, name='sequels', type='RELATIONSHIP UNIQUENESS', schema=()-[:SEQUEL_OF {order}]-(), ownedIndex=4 )'.
The constraint type will be updated to say RELATIONSHIP PROPERTY UNIQUENESS in a future version of Neo4j.
|
Book
nodes to have unique isbn
properties, given that a constraint on that schema already existsCREATE CONSTRAINT new_book_isbn
FOR (book:Book) REQUIRE book.isbn IS UNIQUE
Constraint already exists: Constraint( id=3, name='book_isbn', type='UNIQUENESS', schema=(:Book {isbn}), ownedIndex=2 )
The constraint type will be updated to say NODE PROPERTY UNIQUENESS in a future version of Neo4j.
|
AUTHORED
relationships to have unique name
properties, given that a constraint on a different schema with the same name already existsCREATE CONSTRAINT author_name
FOR ()-[a:AUTHORED]-() REQUIRE a.name IS UNIQUE
There already exists a constraint called 'author_name'.
order
properties on PART_OF
relationships to be of type FLOAT
, given a constraint requiring the same properties to be of type INTEGER
already existsCREATE CONSTRAINT new_part_of
FOR ()-[part:PART_OF]-() REQUIRE part.order IS :: FLOAT
Conflicting constraint already exists: Constraint( id=21, name='part_of', type='RELATIONSHIP PROPERTY TYPE', schema=()-[:PART_OF {order}]-(), propertyType=INTEGER )
title
and publicationYear
on nodes with the Book
label, when a property uniqueness constraint already exists on the same label and property combinationCREATE CONSTRAINT book_titles FOR (book:Book) REQUIRE (book.title, book.publicationYear) IS NODE KEY
Constraint already exists: Constraint( id=7, name='book_title_year', type='UNIQUENESS', schema=(:Book {title, publicationYear}), ownedIndex=6 )
Constraints and indexes
Constraints and backing indexes
Property uniqueness constraints and key constraints are backed by range indexes. This means that creating a property uniqueness or key constraint will create a range index with the same name, node label/relationship type and property combination as its owning constraint. Single property constraints will create single property indexes and multiple property composite constraints will create composite indexes.
Indexes of the same index type, label/relationship type, and property combination cannot be added separately. However, dropping a property uniqueness or key constraint will also drop its backing index. If the backing index is still required, the index needs to be explicitly re-created. |
Property uniqueness and key constraints require an index because it allows the system to quickly check if a node with the same label and property value or a relationship with the same type and property value already exists. Without an index, the system would need to scan all nodes with the same label, which would be slow and inefficient, especially as the graph grows. The index makes these checks much faster by enabling direct lookups instead of scanning the entire graph. Cypher will use the indexes with an owning constraint in the same way that it utilizes other search-performance indexes. For more information about how indexes impact query performance, see The impact of indexes on query performance.
These indexes are listed in the owningConstraint
column returned by the SHOW INDEX
command, and the ownedIndex
column returned by the SHOW CONSTRAINT
command.
SHOW CONSTRAINTS WHERE ownedIndex IS NOT NULL
+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| id | name | type | entityType | labelsOrTypes | properties | ownedIndex | propertyType |
+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| 21 | "actor_fullname" | "NODE_KEY" | "NODE" | ["Actor"] | ["firstname", "surname"] | "actor_fullname" | NULL |
| 3 | "book_isbn" | "UNIQUENESS" | "NODE" | ["Book"] | ["isbn"] | "book_isbn" | NULL |
| 7 | "book_title_year" | "UNIQUENESS" | "NODE" | ["Book"] | ["title", "publicationYear"] | "book_title_year" | NULL |
| 17 | "director_imdbId" | "NODE_KEY" | "NODE" | ["Director"] | ["imdbId"] | "director_imdbId" | NULL |
| 23 | "knows_since_how" | "RELATIONSHIP_KEY" | "RELATIONSHIP" | ["KNOWS"] | ["since", "how"] | "knows_since_how" | NULL |
| 25 | "node_uniqueness_param" | "UNIQUENESS" | "NODE" | ["Book"] | ["prop1"] | "node_uniqueness_param" | NULL |
| 19 | "ownershipId" | "RELATIONSHIP_KEY" | "RELATIONSHIP" | ["OWNS"] | ["ownershipId"] | "ownershipId" | NULL |
| 9 | "prequels" | "RELATIONSHIP_UNIQUENESS" | "RELATIONSHIP" | ["PREQUEL_OF"] | ["order", "author"] | "prequels" | NULL |
| 5 | "sequels" | "RELATIONSHIP_UNIQUENESS" | "RELATIONSHIP" | ["SEQUEL_OF"] | ["order"] | "sequels" | NULL |
+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+
SHOW INDEXES WHERE owningConstraint IS NOT NULL
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| id | name | state | populationPercent | type | entityType | labelsOrTypes | properties | indexProvider | owningConstraint | lastRead | readCount |
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| 20 | "actor_fullname" | "ONLINE" | 100.0 | "RANGE" | "NODE" | ["Actor"] | ["firstname", "surname"] | "range-1.0" | "actor_fullname" | 2024-10-07T12:12:51.893Z | 3 |
| 2 | "book_isbn" | "ONLINE" | 100.0 | "RANGE" | "NODE" | ["Book"] | ["isbn"] | "range-1.0" | "book_isbn" | 2024-10-07T11:58:09.252Z | 2 |
| 6 | "book_title_year" | "ONLINE" | 100.0 | "RANGE" | "NODE" | ["Book"] | ["title", "publicationYear"] | "range-1.0" | "book_title_year" | NULL | 0 |
| 16 | "director_imdbId" | "ONLINE" | 100.0 | "RANGE" | "NODE" | ["Director"] | ["imdbId"] | "range-1.0" | "director_imdbId" | NULL | 0 |
| 22 | "knows_since_how" | "ONLINE" | 100.0 | "RANGE" | "RELATIONSHIP" | ["KNOWS"] | ["since", "how"] | "range-1.0" | "knows_since_how" | 2024-10-07T12:12:51.894Z | 1 |
| 24 | "node_uniqueness_param" | "ONLINE" | 100.0 | "RANGE" | "NODE" | ["Book"] | ["prop1"] | "range-1.0" | "node_uniqueness_param" | NULL | 0 |
| 18 | "ownershipId" | "ONLINE" | 100.0 | "RANGE" | "RELATIONSHIP" | ["OWNS"] | ["ownershipId"] | "range-1.0" | "ownershipId" | NULL | 0 |
| 8 | "prequels" | "ONLINE" | 100.0 | "RANGE" | "RELATIONSHIP" | ["PREQUEL_OF"] | ["order", "author"] | "range-1.0" | "prequels" | NULL | 0 |
| 4 | "sequels" | "ONLINE" | 100.0 | "RANGE" | "RELATIONSHIP" | ["SEQUEL_OF"] | ["order"] | "range-1.0" | "sequels" | 2024-10-07T11:57:12.999Z | 1 |
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
Property existence and property type constraints are not backed by indexes. |
Constraint failures and indexes
Attempting to create any type of constraint with the same name as an existing index will fail.
directors
CREATE INDEX directors FOR (director:Director) ON (director.name)
directors
CREATE CONSTRAINT directors FOR (movie:Movie) REQUIRE movie.director IS :: STRING
There already exists an index called 'directors'.
Creating key or property uniqueness constraints on the same schema as an existing index will fail.
wordCount
properties on Book
nodesCREATE INDEX book_word_count FOR (book:Book) ON (book.wordCount)
Book
nodes to have unique wordCount
propertiesCREATE CONSTRAINT word_count FOR (book:Book) REQUIRE book.wordCount IS UNIQUE
There already exists an index (:Book {wordCount}).
A constraint cannot be created until the index has been dropped.
Constraints and data violation scenarios
Creating data that violates existing constraints will fail
Constraint type | Create nodes and relationships without an existence constrained property | Create nodes and relationships with non-unique properties/property combinations | Create nodes and relationships with the wrong property type |
---|---|---|---|
Property uniqueness constraint |
❌ |
||
Property existence constraint |
❌ |
||
Property type constraint |
❌ |
||
Key constraint |
❌ |
❌ |
Book
node with an isbn
property that already existsCREATE (book:Book {isbn: '1449356265', title: 'Graph Databases'})
Node(0) already exists with label `Book` and property `isbn` = '1449356265'
Author
node without a name
property, given a property existence constraint on :Author(name)
CREATE (author:Author {surname: 'Austen'})
Node(0) with label `Author` must have the property `name`
PART_OF
relationship with a STRING
order
property, given a property type constraint on the relationship type PART_OF
restricting the order
property to INTEGER
valuesMATCH (movie:Movie {title:'Iron Man'}), (franchise:Franchise {name:'MCU'})
CREATE (movie)-[part:PART_OF {order: '1'}]->(franchise)
Relationship(0) with type `PART_OF` has property `order` of wrong type `String`. Allowed types: INTEGER
Actor
node without a firstname
property, given a node key constraint on :Actor(firstname, surname)
CREATE (actor:Actor {surname: 'Wood'})
Node(0) with label `Actor` must have the properties (`firstname`, `surname`)
Removing existence and key constrained properties will fail
name
property from an existing Author
node, given a property existence constraint on :Author(name)
MATCH (author:Author {name: 'Virginia Woolf'})
REMOVE author.name
Node(0) with label `Author` must have the property `name`
firstname
property from an existing node Actor
, given a node key constraint on :Actor(firstname, surname)
MATCH (actor:Actor {firstname: 'Keanu', surname: 'Reeves'})
REMOVE actor.firstname
Node(0) with label `Actor` must have the properties (`firstname`, `surname`)
Modifying type constrained properties will fail
title
for the Movie
'Iron Man' to an INTEGER
value, given a constraint requiring title
properties to be of type STRING
MATCH (m:Movie {title: 'Iron Man'})
SET m.title = 13
Node(9) with label `Movie` required the property `title` to be of type `STRING`, but was of type `INTEGER`.
Creating constraints when there exists conflicting data will fail
Constraint type | Non-existing property | Non-unique property/property combination | Property of wrong type |
---|---|---|---|
Property uniqueness constraint |
❌ |
||
Property existence constraint |
❌ |
||
Property type constraint |
❌ |
||
Key constraint |
❌ |
❌ |
Book
nodes with the same name
property valueCREATE (:Book {isbn: '9780393972832', title: 'Moby Dick'}),
(:Book {isbn: '9780763630188', title: 'Moby Dick'})
Book
nodes to have unique title
properties, when there already exists two Book
nodes with the same title
CREATE CONSTRAINT book_title FOR (book:Book) REQUIRE book.title IS UNIQUE
In this case, the constraint cannot be created because it is in conflict with the existing graph. Either use indexes instead, or remove/correct the offending nodes and then re-apply the constraint.
Unable to create Constraint( name='book_title', type='UNIQUENESS', schema=(:Book {title}) ):
Both Node(0) and Node(1) have the label `Book` and property `title` = 'Moby Dick'
The constraint creation fails on the first offending nodes that are found. This does not guarantee that there are no other offending nodes in the graph. Therefore, all the data should be checked and cleaned up before re-attempting the constraint creation.
MATCH (book1:Book), (book2:Book)
WHERE book1.title = book2.title AND NOT book1 = book2
RETURN book1, book2
WROTE
relationships to have a language
property, when there already exists a WROTE
relationship without a language
propertyCREATE CONSTRAINT wrote_language FOR ()-[wrote:WROTE]-() REQUIRE wrote.language IS NOT NULL
In this case, the constraint cannot be created because it is in conflict with the existing graph. Remove or correct the offending relationships and then re-apply the constraint.
Unable to create Constraint( type='RELATIONSHIP PROPERTY EXISTENCE', schema=()-[:WROTE {language}]-() ):
Relationship(0) with type `WROTE` must have the property `language`. Note that only the first found violation is shown.
The constraint creation fails on the first offending relationship that is found. This does not guarantee that there are no other offending relationships in the graph. Therefore, all the data should be checked and cleaned up before re-attempting the constraint creation.
MATCH ()-[wrote:WROTE]-()
WHERE wrote.language IS NULL
RETURN wrote
Constraint | Query |
---|---|
Node property uniqueness constraint |
|
Relationship property uniqueness constraint |
|
Node property existence constraint |
|
Relationship property existence constraint |
|
Node property type constraint |
|
Relationship property type constraint |
|
Node key constraint |
|
Relationship key constraint |
|
SHOW CONSTRAINTS
To list all constraints with the default output columns, use SHOW CONSTRAINTS
.
If all columns are required, use SHOW CONSTRAINTS YIELD *
.
For the full command syntax to list constraints, see Syntax → SHOW CONSTRAINTS.
One of the output columns from SHOW CONSTRAINTS
is the name of the constraint.
This can be used to drop the constraint with the DROP CONSTRAINT
command.
Listing constraints requires the SHOW CONSTRAINTS privilege.
|
SHOW CONSTRAINTS
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| id | name | type | entityType | labelsOrTypes | properties | ownedIndex | propertyType |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| 21 | "actor_fullname" | "NODE_KEY" | "NODE" | ["Actor"] | ["firstname", "surname"] | "actor_fullname" | NULL |
| 10 | "author_name" | "NODE_PROPERTY_EXISTENCE" | "NODE" | ["Author"] | ["name"] | NULL | NULL |
| 3 | "book_isbn" | "UNIQUENESS" | "NODE" | ["Book"] | ["isbn"] | "book_isbn" | NULL |
| 7 | "book_title_year" | "UNIQUENESS" | "NODE" | ["Book"] | ["title", "publicationYear"] | "book_title_year" | NULL |
| 17 | "director_imdbId" | "NODE_KEY" | "NODE" | ["Director"] | ["imdbId"] | "director_imdbId" | NULL |
| 23 | "knows_since_how" | "RELATIONSHIP_KEY" | "RELATIONSHIP" | ["KNOWS"] | ["since", "how"] | "knows_since_how" | NULL |
| 14 | "movie_tagline" | "NODE_PROPERTY_TYPE" | "NODE" | ["Movie"] | ["tagline"] | NULL | "STRING | LIST<STRING NOT NULL>" |
| 12 | "movie_title" | "NODE_PROPERTY_TYPE" | "NODE" | ["Movie"] | ["title"] | NULL | "STRING" |
| 25 | "node_uniqueness_param" | "UNIQUENESS" | "NODE" | ["Book"] | ["prop1"] | "node_uniqueness_param" | NULL |
| 19 | "ownershipId" | "RELATIONSHIP_KEY" | "RELATIONSHIP" | ["OWNS"] | ["ownershipId"] | "ownershipId" | NULL |
| 13 | "part_of" | "RELATIONSHIP_PROPERTY_TYPE" | "RELATIONSHIP" | ["PART_OF"] | ["order"] | NULL | "INTEGER" |
| 15 | "part_of_tags" | "RELATIONSHIP_PROPERTY_TYPE" | "RELATIONSHIP" | ["PART_OF"] | ["tags"] | NULL | "STRING | LIST<STRING NOT NULL>" |
| 9 | "prequels" | "RELATIONSHIP_UNIQUENESS" | "RELATIONSHIP" | ["PREQUEL_OF"] | ["order", "author"] | "prequels" | NULL |
| 26 | "rel_exist_param" | "RELATIONSHIP_PROPERTY_EXISTENCE" | "RELATIONSHIP" | ["WROTE"] | ["published"] | NULL | NULL |
| 5 | "sequels" | "RELATIONSHIP_UNIQUENESS" | "RELATIONSHIP" | ["SEQUEL_OF"] | ["order"] | "sequels" | NULL |
| 11 | "wrote_year" | "RELATIONSHIP_PROPERTY_EXISTENCE" | "RELATIONSHIP" | ["WROTE"] | ["year"] | NULL | NULL |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
To return the full details of the constraints on a database, use SHOW CONSTRAINTS YIELD *
YIELD *
SHOW CONSTRAINTS YIELD *
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| id | name | type | entityType | labelsOrTypes | properties | ownedIndex | propertyType | options | createStatement |
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| 21 | "actor_fullname" | "NODE_KEY" | "NODE" | ["Actor"] | ["firstname", "surname"] | "actor_fullname" | NULL | {indexConfig: {}, indexProvider: "range-1.0"} | "CREATE CONSTRAINT `actor_fullname` FOR (n:`Actor`) REQUIRE (n.`firstname`, n.`surname`) IS NODE KEY" |
| 10 | "author_name" | "NODE_PROPERTY_EXISTENCE" | "NODE" | ["Author"] | ["name"] | NULL | NULL | NULL | "CREATE CONSTRAINT `author_name` FOR (n:`Author`) REQUIRE (n.`name`) IS NOT NULL" |
| 3 | "book_isbn" | "UNIQUENESS" | "NODE" | ["Book"] | ["isbn"] | "book_isbn" | NULL | {indexConfig: {}, indexProvider: "range-1.0"} | "CREATE CONSTRAINT `book_isbn` FOR (n:`Book`) REQUIRE (n.`isbn`) IS UNIQUE" |
| 7 | "book_title_year" | "UNIQUENESS" | "NODE" | ["Book"] | ["title", "publicationYear"] | "book_title_year" | NULL | {indexConfig: {}, indexProvider: "range-1.0"} | "CREATE CONSTRAINT `book_title_year` FOR (n:`Book`) REQUIRE (n.`title`, n.`publicationYear`) IS UNIQUE" |
| 17 | "director_imdbId" | "NODE_KEY" | "NODE" | ["Director"] | ["imdbId"] | "director_imdbId" | NULL | {indexConfig: {}, indexProvider: "range-1.0"} | "CREATE CONSTRAINT `director_imdbId` FOR (n:`Director`) REQUIRE (n.`imdbId`) IS NODE KEY" |
| 23 | "knows_since_how" | "RELATIONSHIP_KEY" | "RELATIONSHIP" | ["KNOWS"] | ["since", "how"] | "knows_since_how" | NULL | {indexConfig: {}, indexProvider: "range-1.0"} | "CREATE CONSTRAINT `knows_since_how` FOR ()-[r:`KNOWS`]-() REQUIRE (r.`since`, r.`how`) IS RELATIONSHIP KEY" |
| 14 | "movie_tagline" | "NODE_PROPERTY_TYPE" | "NODE" | ["Movie"] | ["tagline"] | NULL | "STRING | LIST<STRING NOT NULL>" | NULL | "CREATE CONSTRAINT `movie_tagline` FOR (n:`Movie`) REQUIRE (n.`tagline`) IS :: STRING | LIST<STRING NOT NULL>" |
| 12 | "movie_title" | "NODE_PROPERTY_TYPE" | "NODE" | ["Movie"] | ["title"] | NULL | "STRING" | NULL | "CREATE CONSTRAINT `movie_title` FOR (n:`Movie`) REQUIRE (n.`title`) IS :: STRING" |
| 25 | "node_uniqueness_param" | "UNIQUENESS" | "NODE" | ["Book"] | ["prop1"] | "node_uniqueness_param" | NULL | {indexConfig: {}, indexProvider: "range-1.0"} | "CREATE CONSTRAINT `node_uniqueness_param` FOR (n:`Book`) REQUIRE (n.`prop1`) IS UNIQUE" |
| 19 | "ownershipId" | "RELATIONSHIP_KEY" | "RELATIONSHIP" | ["OWNS"] | ["ownershipId"] | "ownershipId" | NULL | {indexConfig: {}, indexProvider: "range-1.0"} | "CREATE CONSTRAINT `ownershipId` FOR ()-[r:`OWNS`]-() REQUIRE (r.`ownershipId`) IS RELATIONSHIP KEY" |
| 13 | "part_of" | "RELATIONSHIP_PROPERTY_TYPE" | "RELATIONSHIP" | ["PART_OF"] | ["order"] | NULL | "INTEGER" | NULL | "CREATE CONSTRAINT `part_of` FOR ()-[r:`PART_OF`]-() REQUIRE (r.`order`) IS :: INTEGER" |
| 15 | "part_of_tags" | "RELATIONSHIP_PROPERTY_TYPE" | "RELATIONSHIP" | ["PART_OF"] | ["tags"] | NULL | "STRING | LIST<STRING NOT NULL>" | NULL | "CREATE CONSTRAINT `part_of_tags` FOR ()-[r:`PART_OF`]-() REQUIRE (r.`tags`) IS :: STRING | LIST<STRING NOT NULL>" |
| 9 | "prequels" | "RELATIONSHIP_UNIQUENESS" | "RELATIONSHIP" | ["PREQUEL_OF"] | ["order", "author"] | "prequels" | NULL | {indexConfig: {}, indexProvider: "range-1.0"} | "CREATE CONSTRAINT `prequels` FOR ()-[r:`PREQUEL_OF`]-() REQUIRE (r.`order`, r.`author`) IS UNIQUE" |
| 26 | "rel_exist_param" | "RELATIONSHIP_PROPERTY_EXISTENCE" | "RELATIONSHIP" | ["WROTE"] | ["published"] | NULL | NULL | NULL | "CREATE CONSTRAINT `rel_exist_param` FOR ()-[r:`WROTE`]-() REQUIRE (r.`published`) IS NOT NULL" |
| 5 | "sequels" | "RELATIONSHIP_UNIQUENESS" | "RELATIONSHIP" | ["SEQUEL_OF"] | ["order"] | "sequels" | NULL | {indexConfig: {}, indexProvider: "range-1.0"} | "CREATE CONSTRAINT `sequels` FOR ()-[r:`SEQUEL_OF`]-() REQUIRE (r.`order`) IS UNIQUE" |
| 11 | "wrote_year" | "RELATIONSHIP_PROPERTY_EXISTENCE" | "RELATIONSHIP" | ["WROTE"] | ["year"] | NULL | NULL | NULL | "CREATE CONSTRAINT `wrote_year` FOR ()-[r:`WROTE`]-() REQUIRE (r.`year`) IS NOT NULL" |
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
The type column returns UNIQUENESS for the node property uniqueness constraint and RELATIONSHIP_UNIQUENESS for the relationship property uniqueness constraint.
This will be updated in a future version of Neo4j.
Node property uniqueness constraints will be updated to NODE_PROPERTY_UNIQUENESS and relationship property uniqueness constraints to RELATIONSHIP_PROPERTY_UNIQUENESS .
|
Listing constraints with filtering
The SHOW CONSTRAINTS
command can be filtered in various ways.
The filtering of rows can be done using constraint type keywords or a WHERE
clause, while filtering of columns is achieved by specifying the desired columns in a YIELD
clause.
SHOW KEY CONSTRAINTS
+--------------------------------------------------------------------------------------------------------------------------------------------------------------+
| id | name | type | entityType | labelsOrTypes | properties | ownedIndex | propertyType |
+--------------------------------------------------------------------------------------------------------------------------------------------------------------+
| 21 | "actor_fullname" | "NODE_KEY" | "NODE" | ["Actor"] | ["firstname", "surname"] | "actor_fullname" | NULL |
| 17 | "director_imdbId" | "NODE_KEY" | "NODE" | ["Director"] | ["imdbId"] | "director_imdbId" | NULL |
| 23 | "knows_since_how" | "RELATIONSHIP_KEY" | "RELATIONSHIP" | ["KNOWS"] | ["since", "how"] | "knows_since_how" | NULL |
| 19 | "ownershipId" | "RELATIONSHIP_KEY" | "RELATIONSHIP" | ["OWNS"] | ["ownershipId"] | "ownershipId" | NULL |
+--------------------------------------------------------------------------------------------------------------------------------------------------------------+
For a full list of all the constraint types (and synonyms) available in this command see Syntax → SHOW CONSTRAINTS.
WHERE
clauseRELATIONSHIP
entityType
SHOW CONSTRAINTS
WHERE entityType = 'RELATIONSHIP'
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| id | name | type | entityType | labelsOrTypes | properties | ownedIndex | propertyType |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| 23 | "knows_since_how" | "RELATIONSHIP_KEY" | "RELATIONSHIP" | ["KNOWS"] | ["since", "how"] | "knows_since_how" | NULL |
| 19 | "ownershipId" | "RELATIONSHIP_KEY" | "RELATIONSHIP" | ["OWNS"] | ["ownershipId"] | "ownershipId" | NULL |
| 13 | "part_of" | "RELATIONSHIP_PROPERTY_TYPE" | "RELATIONSHIP" | ["PART_OF"] | ["order"] | NULL | "INTEGER" |
| 15 | "part_of_tags" | "RELATIONSHIP_PROPERTY_TYPE" | "RELATIONSHIP" | ["PART_OF"] | ["tags"] | NULL | "STRING | LIST<STRING NOT NULL>" |
| 9 | "prequels" | "RELATIONSHIP_UNIQUENESS" | "RELATIONSHIP" | ["PREQUEL_OF"] | ["order", "author"] | "prequels" | NULL |
| 26 | "rel_exist_param" | "RELATIONSHIP_PROPERTY_EXISTENCE" | "RELATIONSHIP" | ["WROTE"] | ["published"] | NULL | NULL |
| 5 | "sequels" | "RELATIONSHIP_UNIQUENESS" | "RELATIONSHIP" | ["SEQUEL_OF"] | ["order"] | "sequels" | NULL |
| 11 | "wrote_year" | "RELATIONSHIP_PROPERTY_EXISTENCE" | "RELATIONSHIP" | ["WROTE"] | ["year"] | NULL | NULL |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
It is possible to return only specific columns of the available constraints using the YIELD
clause:
name
, type
, and createStatement
columnsSHOW CONSTRAINTS
YIELD name, type, createStatement
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| name | type | createStatement |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| "actor_fullname" | "NODE_KEY" | "CREATE CONSTRAINT `actor_fullname` FOR (n:`Actor`) REQUIRE (n.`firstname`, n.`surname`) IS NODE KEY" |
| "author_name" | "NODE_PROPERTY_EXISTENCE" | "CREATE CONSTRAINT `author_name` FOR (n:`Author`) REQUIRE (n.`name`) IS NOT NULL" |
| "book_isbn" | "UNIQUENESS" | "CREATE CONSTRAINT `book_isbn` FOR (n:`Book`) REQUIRE (n.`isbn`) IS UNIQUE" |
| "book_title_year" | "UNIQUENESS" | "CREATE CONSTRAINT `book_title_year` FOR (n:`Book`) REQUIRE (n.`title`, n.`publicationYear`) IS UNIQUE" |
| "constraint_with_provider" | "NODE_KEY" | "CREATE CONSTRAINT `constraint_with_provider` FOR (n:`Actor`) REQUIRE (n.`surname`) IS NODE KEY" |
| "director_imdbId" | "NODE_KEY" | "CREATE CONSTRAINT `director_imdbId` FOR (n:`Director`) REQUIRE (n.`imdbId`) IS NODE KEY" |
| "knows_since_how" | "RELATIONSHIP_KEY" | "CREATE CONSTRAINT `knows_since_how` FOR ()-[r:`KNOWS`]-() REQUIRE (r.`since`, r.`how`) IS RELATIONSHIP KEY" |
| "movie_tagline" | "NODE_PROPERTY_TYPE" | "CREATE CONSTRAINT `movie_tagline` FOR (n:`Movie`) REQUIRE (n.`tagline`) IS :: STRING | LIST<STRING NOT NULL>" |
| "movie_title" | "NODE_PROPERTY_TYPE" | "CREATE CONSTRAINT `movie_title` FOR (n:`Movie`) REQUIRE (n.`title`) IS :: STRING" |
| "node_uniqueness_param" | "UNIQUENESS" | "CREATE CONSTRAINT `node_uniqueness_param` FOR (n:`Book`) REQUIRE (n.`prop1`) IS UNIQUE" |
| "ownershipId" | "RELATIONSHIP_KEY" | "CREATE CONSTRAINT `ownershipId` FOR ()-[r:`OWNS`]-() REQUIRE (r.`ownershipId`) IS RELATIONSHIP KEY" |
| "part_of" | "RELATIONSHIP_PROPERTY_TYPE" | "CREATE CONSTRAINT `part_of` FOR ()-[r:`PART_OF`]-() REQUIRE (r.`order`) IS :: INTEGER" |
| "part_of_tags" | "RELATIONSHIP_PROPERTY_TYPE" | "CREATE CONSTRAINT `part_of_tags` FOR ()-[r:`PART_OF`]-() REQUIRE (r.`tags`) IS :: STRING | LIST<STRING NOT NULL>" |
| "prequels" | "RELATIONSHIP_UNIQUENESS" | "CREATE CONSTRAINT `prequels` FOR ()-[r:`PREQUEL_OF`]-() REQUIRE (r.`order`, r.`author`) IS UNIQUE" |
| "rel_exist_param" | "RELATIONSHIP_PROPERTY_EXISTENCE" | "CREATE CONSTRAINT `rel_exist_param` FOR ()-[r:`WROTE`]-() REQUIRE (r.`published`) IS NOT NULL" |
| "sequels" | "RELATIONSHIP_UNIQUENESS" | "CREATE CONSTRAINT `sequels` FOR ()-[r:`SEQUEL_OF`]-() REQUIRE (r.`order`) IS UNIQUE" |
| "wrote_year" | "RELATIONSHIP_PROPERTY_EXISTENCE" | "CREATE CONSTRAINT `wrote_year` FOR ()-[r:`WROTE`]-() REQUIRE (r.`year`) IS NOT NULL" |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
Result columns for listing constraints
Column | Description | Type | ||
---|---|---|---|---|
|
The id of the constraint. Default Output |
|
||
|
Name of the constraint (explicitly set by the user or automatically assigned). Default Output |
|
||
|
The ConstraintType of this constraint (
|
|
||
|
Type of entities this constraint represents ( |
|
||
|
The labels or relationship types of this constraint. The list returned will only include a single value (the name of the constrained node label or relationship type). Default Output |
|
||
|
The properties of this constraint. Default Output |
|
||
|
The name of the index associated with the constraint or |
|
||
|
The property type the property is restricted to for property type constraints, or |
|
||
|
The options passed to |
|
||
|
Statement used to create the constraint. |
|
DROP CONSTRAINT
Constraints are dropped using the DROP CONSTRAINT
command.
For the full command syntax to drop constraints, see Syntax → DROP CONSTRAINT.
Dropping a constraint requires the DROP CONSTRAINT privilege.
|
Drop a constraint by name
A constraint can be dropped using the name with the DROP CONSTRAINT constraint_name
command.
It is the same command for all constraint types.
The name of the constraint can be found using the SHOW CONSTRAINTS
command, given in the output column name
.
book_isbn
DROP CONSTRAINT book_isbn
Removed 1 constraint.
Drop a constraint with a parameter
Constraints can be dropped with a parameterized name.
{
"name": "actor_fullname"
}
DROP CONSTRAINT $name
Removed 1 constraint.
Drop a non-existing constraint
If it is uncertain if any constraint with a given name exists and you want to drop it if it does but not get an error should it not, use IF EXISTS
.
This will ensure that no error is thrown.
As of Neo4j 5.17, an informational notification is returned stating that the constraint does not exist.
missing_constraint_name
DROP CONSTRAINT missing_constraint_name IF EXISTS
(no changes, no records)
`DROP CONSTRAINT missing_constraint_name IF EXISTS` has no effect. `missing_constraint_name` does not exist.