# `@card` annotation

The `@card` annotation is used to specify cardinality ranges for roles and ownerships.

## [](#_syntax)Syntax

Range Argument Syntax

```typeql
<type label> <capability> <type label 2> @card(N..M);
<type label> <capability> <type label 2> @card(N..);
```

Single Scalar Argument Syntax

```typeql
<type label> <capability> <type label 2> @card(N);
```

The `@card` annotation can be defined for any `<capability>` of: `owns`, `relates`, or `plays`.

It accepts either a range argument or a single scalar argument. Arguments must be integers.

*   Both bounds are inclusive.
    
*   A partially unbounded range `N..` has an infinite upper bound.
    
*   The minimal lower bound is `0` and must be explicitly specified (e.g., use `0..M` instead of `..M`).
    
*   A single scalar argument `N` is shorthand for `N..N` and means "exactly N".
    

## [](#_usage)Usage

Every capability has a default `cardinality` constraint, accessible in [Default capability cardinalities](#_default_cardinality).

When defined, the `@card` annotation overrides the default `cardinality` with the specified arguments.

The `cardinality` constraint regulates the number of data instances that can appear in a specific context (like owning an attribute). For example, the following definition specifies that an instance of the `page` type must have at least one and no more than three \`name\`s:

```typeql
#!test[schema]
#{{
define
  attribute name value string;
#}}
#!test[schema]
define
  entity page owns name @card(1..3);
```

At the same time, the `page` type can play the `posting:page` role an unlimited number of times:

```typeql
#!test[schema]
#{{
define relation posting relates page;
#}}
#!test[schema, rollback]
define
  page plays posting:page @card(0..);
```

However, an instance of the `posting` relation type can have up to a thousand `page` instances:

```typeql
#!test[schema]
define
  relation posting relates page @card(0..1000);
```

### [](#subtyping)Subtyping

Similarly to inherited type constraints, capability constraints also affect subtypes from both sides. For example, the following query defines that:

*   A `page` instance must have between 1 and 3 names.
    
*   A `profile` instance (subtype of `page`) inherits the same constraint and must have between 1 and 3 names.
    
*   A `user` instance can own exactly 1 first name and up to 2 surnames (`first-name` and `surname` are subtypes of `name`).
    

```typeql
#!test[schema]
define
  entity page owns name @card(1..3);
  entity profile sub page;
  entity user sub profile,
    owns first-name @card(1),
    owns surname @card(0..);
  attribute name @abstract, value string;
  attribute first-name sub name;
  attribute surname sub name;
```

Valid statements based on this schema include:

*   It is impossible to insert a `page`, `profile`, or `user` without a name.
    
*   It is impossible to insert a `page` or `profile` because they do not own non-abstract names.
    
*   A `user` instance can be inserted with just a first name.
    
*   A `user` instance cannot have more than two surnames.
    

## [](#_limitations)Limitations

Cannot be used with the [`@key` annotation](../key/index.md) as they both produce `cardinality` constraints.

## [](#_references)References

### [](#_default_cardinality)Default capability cardinalities

The following `cardinality` constraints are set for capabilities by default if no `@card` annotations are declared:

Table 1. Default capability cardinalities  

capability

Cardinality

`owns`

`card(0..1)`

`relates`

`card(0..1)`

`plays`

`card(0..)`

[Annotations](../index.md) [@cascade](../cascade/index.md)

[Edit on GitHub](https://github.com/typedb/typedb-docs/edit/3.x-development/typeql-reference/modules/ROOT/pages/annotations/card.adoc) Edit this page on GitHub.