# Optionals

Optional patterns can be used in `match` stages to optionally match a pattern, or in `insert` stages to insert a pattern **if** all the variables involved are bound.

Schema for the following examples

```typeql
#!test[schema, commit]
define
    attribute email, value string;
    attribute phone, value string;
    attribute username, value string;
    relation friendship, relates friend @card(0..2);
    relation marriage, relates spouse @card(0..2);
    relation policy, relates covered @card(0..);
    entity user,
        owns username, owns email, owns phone,
        plays friendship:friend;
    entity person, plays marriage:spouse, plays policy:covered;
```

## [](#_syntax_basic_behavior)Syntax & Basic behavior

```typeql
try { <pattern> };
```

### [](#_match)match

Variables which are present only in the `try` block are considered optional. If the **entire** optional pattern matches the data, it returns an answer per match. If it has no matches, it produces a single answer with all optional variables bound to `None`.

```typeql
#!test[read]
match
    $person isa person;
    try {
        $_ isa marriage, links (spouse: $person, spouse: $spouse);
    };
```

Here, `$spouse` is bound to the spouse if `$person` is in a `marriage`. Else, `$spouse` is bound to `None`

### [](#_insert_update_delete)insert, update, & delete

Optional patterns in insert, update, or delete stages execute only if ALL the variables present in them are bound.

```typeql
match
    $person isa person;
    try {
        $_ isa marriage, links (spouse: $person, spouse: $spouse);
    };
insert
    $policy isa policy;
    $policy links (covered: $person);
    try { $policy links (covered: $spouse); };
```

If `$person` is in a marriage, the match stage binds `$spouse` and the insert stage adds them to the policy.

### [](#_put)put

Because a put stage only inserts data if no existing data matches the body of the put, the patterns in a `try` block of a put stage only attempt to insert data if the mandatory patterns (i.e. those outside `try` blocks) fail to produce a match. When inserting data, put behaves identically to an insert stage in that a `try` block only executes if all referenced variables are bound.

```typeql
#!test[write, rollback]
match
  $person isa person;
  $spouse isa person;
  try {
    $policy isa policy, links (covered: $person);
  };
put
  $_ isa marriage, links (spouse: $person, spouse: $spouse);
  try {
    $policy links (covered: $spouse);
  };
```

In this example, if the marriage relation already exists, the put stage does not attempt to add `$spouse` to the optionally bound `$policy`.

If this behavior is not desirable, the `try` block should be put in a separate insert stage instead.

```typeql
#!test[write, rollback]
match
  $person isa person;
  $spouse isa person;
  try {
    $policy isa policy, links (covered: $person);
    not { $policy links (covered: $spouse); };
  };
put
  $_ isa marriage, links (spouse: $person, spouse: $spouse);
insert
  try {
    $policy links (covered: $spouse);
  };
```

In this pipeline, the `marriage` relation is created if it does not already exist, and `$spouse` is always inserted as a roleplayer in `$policy` provided it is bound.

In particular, a put stage with only `try` blocks never inserts any data!

```typeql
#!test[write, rollback]
match
  $_ isa marriage, links (spouse: $person, spouse: $spouse);
  try {
    $policy isa policy, links (covered: $person);
  };
put
  try {
    $policy links (covered: $spouse);
  };
```

In this example the `$policy` is bound only if `$person` plays a role in it, but if it doesn’t also link `$spouse`, that link is not inserted.

## [](#_behavior_in_match_clauses)Behavior in match clauses

### [](#_single_origin)Single origin

In the stage that it first occurs, An optional variable may only occur in a single try-block.

```typeql
#!test[read, fail_at=runtime]
match
    $person isa person;
    try {
        $_ isa marriage, links (spouse: $person, spouse: $spouse);
    };
    try {
        $policy isa policy, links (covered: $spouse); # Invalid
    };
```

### [](#_optional_variables_in_subsequent_stages)Optional variables in subsequent stages

An optional variable can be used in subsequent stages. An unbound optional variable causes the pattern to fail.

The following is a valid way to express the intent of the example above:

```typeql
#!test[read]
match
    $person isa person;
    try {
        $_ isa marriage, links (spouse: $person, spouse: $spouse);
    };
match
    try {
        $policy isa policy, links (covered: $spouse);
    };
```

### [](#_nested_try_blocks)Nested try blocks

Optional patterns can be nested. This is also an option for the previous example

```typeql
#!test[read]
match
    $person isa person;
    try {
        $_ isa marriage, links (spouse: $person, spouse: $spouse);
        try {
            $policy isa policy, links (covered: $spouse); # Ok
        };
    };
```

### [](#_disallowed_in_negations)Disallowed in negations

Optional patterns may not occur in negations, as they can have no effect on the result of the query - they can neither fail the pattern, nor bind any variables for use outside the negation.

[Negations](../negations/index.md) [Statements](../../statements/index.md)

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