---
title: "24: Defining events | SurrealDB University"
description: "Follow along with interactive SurrealDB lessons featuring hands-on exercises, code examples, and step-by-step instructions."
url: https://surrealdb.com/learn/tour/page-24
---

![Course content preview](https://surrealdb.com/assets/static/town.D95IYf2V.avif)

[Back to Courses](https://surrealdb.com/learn)

Course chapters

[Welcome to the Tour of SurrealDB!](https://surrealdb.com/learn/tour) [1: Connecting to a database](https://surrealdb.com/learn/tour/page-01) [2: Creating records](https://surrealdb.com/learn/tour/page-02) [3: Using the ONLY keyword](https://surrealdb.com/learn/tour/page-03) [4: Non-ASCII record IDs](https://surrealdb.com/learn/tour/page-04) [5: Parentheses, indexing, and accessing fields](https://surrealdb.com/learn/tour/page-05) [6: Deleting records](https://surrealdb.com/learn/tour/page-06) [7: Field order in objects](https://surrealdb.com/learn/tour/page-07) [8: Tips when selecting records](https://surrealdb.com/learn/tour/page-08) [9: Casting and aliases](https://surrealdb.com/learn/tour/page-09) [10: Affixes](https://surrealdb.com/learn/tour/page-10) [11: Updating records](https://surrealdb.com/learn/tour/page-11) [12: Linking records](https://surrealdb.com/learn/tour/page-12) [13: Viewing the database as a whole](https://surrealdb.com/learn/tour/page-13) [14: Schemafull and schemaless](https://surrealdb.com/learn/tour/page-14) [15: Viewing the schema](https://surrealdb.com/learn/tour/page-15) [16: Literal types and assertions](https://surrealdb.com/learn/tour/page-16) [17: INSERT and using JSON](https://surrealdb.com/learn/tour/page-17) [18: FOR loops](https://surrealdb.com/learn/tour/page-18) [19: Basic graph relations](https://surrealdb.com/learn/tour/page-19) [20: Creating graph edges](https://surrealdb.com/learn/tour/page-20) [21: Querying graph relations](https://surrealdb.com/learn/tour/page-21) [22: Graph relations at greater depth](https://surrealdb.com/learn/tour/page-22) [23: Adding and improving data](https://surrealdb.com/learn/tour/page-23) [24: Defining events](https://surrealdb.com/learn/tour/page-24) [25: Defining indexes](https://surrealdb.com/learn/tour/page-25) [26: Improving the schema](https://surrealdb.com/learn/tour/page-26) [27: Visualising graph paths](https://surrealdb.com/learn/tour/page-27) [28: Recursive queries: setup](https://surrealdb.com/learn/tour/page-28) [29: Recursive queries](https://surrealdb.com/learn/tour/page-29) [30: More on recursive queries](https://surrealdb.com/learn/tour/page-30) [31: AI vector search](https://surrealdb.com/learn/tour/page-31) [Done the tour!](https://surrealdb.com/learn/tour/page-32)

# 24: Defining events

One of the most convenient parts of SurrealDB is the ability to [define an event](https://surrealdb.com/docs/reference/query-language/statements/define/event) whenever a record is created, updated, or deleted (or any combination of the three).

In the last chapter we created some books using this `CREATE` statement, but we haven't defined any fields yet.

```surql
LET $book = CREATE ONLY book SET
    author = $data.author,
    english_title = $data.english_title,
    language = $data.language,
    published = <datetime>$data.published,
    title = $data.title;
```

Three of those fields should always be present, so let's officially define them now.

```surql
/**
[test]

[[test.results]]
value = "NONE"

[[test.results]]
value = "NONE"

[[test.results]]
value = "NONE"

*/

DEFINE FIELD author   ON book TYPE string;
DEFINE FIELD language ON book TYPE string;
DEFINE FIELD title    ON book TYPE string;
```

An `english_title` should also be present, but we can use an event to fill it out or check to see if it has been entered. This is because:

- If the book is written in English, the `english_title` field should be the same as `title`. We don't want user error to result in `title` and `english_title` being different.
- If the book is written in another language, we should check to see if `english_title` has been filled out. If not, throw an error.

The `DEFINE EVENT` syntax looks like this.

```surql
DEFINE EVENT event_name ON table_name [ WHEN some_expression ] THEN {
   // Write what you want to happen here
};
```

It also gives access to the type of event (either "CREATE", "UPDATE", or "DELETE") through a parameter called `$event`, along with `$before` and `$after` for the record before and after the change was made.

To create our event, we will use the following:

- `WHEN $event = "CREATE"` to do this check when a book is first created,
- Check if `$after.language = 'en'`, and `UPDATE` the `english_title` field with `$after.title` if so,
- If `$after.language` is not equal to `'en'` and there is no `english_title` field filled in, then throw an error using the `THROW` keyword and a custom message.

```surql
/**
[test]

[[test.results]]
value = "NONE"

*/

DEFINE EVENT language_check ON book WHEN $event = "CREATE" THEN {
    IF $after.language = 'en' {
        UPDATE $after SET english_title = $after.title;
    } ELSE IF $after.language != 'en' AND $after.english_title IS NONE {
        THROW "Please enter an English title for " 
            + $after.title + 
            " written in "
            + $after.language;
    }
};
```

With this event defined, we can enter a book without an `english_title` field but the event will fill it in using the `title` field.

```
CREATE book SET title = "The Shadow Rising", author = "Robert Jordan", language = 'en';SELECT * FROM book WHERE title = "The Shadow Rising";
```

![Surrealist Icon](https://surrealdb.com/assets/static/fdfe2c20f5941d5e.D0guSOhZ.webp) Run Query

Note that the first response is the output of the `CREATE` statement, which doesn't include `english_title`. It's at this point that the event jumps in and adds the field.

Response

```surql
-------- Query --------

[
  {
    author: 'Robert Jordan',
    id: book:w8e6dv2db255h27ezrip,
    language: 'en',
    title: 'The Shadow Rising'
  }
]

-------- Query--------

[
  {
    author: 'Robert Jordan',
    english_title: 'The Shadow Rising',
    id: book:w8e6dv2db255h27ezrip,
    language: 'en',
    title: 'The Shadow Rising'
  }
]
```

And if we try to enter this next French book, the query will fail because we forgot to fill out the `english_title`.

```
CREATE book SET    title = "La Détresse et l'enchantement",    author = "Gabrielle Roy",    language = 'fr';SELECT * FROM book WHERE title = "La Détresse et l'enchantement";
```

![Surrealist Icon](https://surrealdb.com/assets/static/fdfe2c20f5941d5e.D0guSOhZ.webp) Run Query

The output this time doesn't show the initial `CREATE` statement before the event, because statements in SurrealDB are [all run within their own transaction](https://surrealdb.com/docs/reference/query-language/language-primitives/transactions), including their events. Since the `CREATE` statement led to an event which failed, the entire statement is rolled back and the book is never created.

Response

```surql
-------- Query --------

"An error occurred: Please enter an English title 
for La Détresse et l'enchantement written in fr"

-------- Query --------

[]
```

Previous

23: Adding and improving data

[Previous](https://surrealdb.com/learn/tour/page-23)

Next lesson

25: Defining indexes

[Next lesson](https://surrealdb.com/learn/tour/page-25)

```json
{"@context":"https://schema.org","@type":"Course","name":"Welcome to the Tour of SurrealDB!","description":"Welcome to the Tour of SurrealDB!","url":"https://surrealdb.com/learn/tour","inLanguage":"en","isAccessibleForFree":true,"provider":{"@type":"Organization","name":"SurrealDB","url":"https://surrealdb.com"},"hasPart":[{"@type":"LearningResource","name":"Welcome to the Tour of SurrealDB!","url":"https://surrealdb.com/learn/tour"},{"@type":"LearningResource","name":"1: Connecting to a database","url":"https://surrealdb.com/learn/tour/page-01"},{"@type":"LearningResource","name":"2: Creating records","url":"https://surrealdb.com/learn/tour/page-02"},{"@type":"LearningResource","name":"3: Using the ONLY keyword","url":"https://surrealdb.com/learn/tour/page-03"},{"@type":"LearningResource","name":"4: Non-ASCII record IDs","url":"https://surrealdb.com/learn/tour/page-04"},{"@type":"LearningResource","name":"5: Parentheses, indexing, and accessing fields","url":"https://surrealdb.com/learn/tour/page-05"},{"@type":"LearningResource","name":"6: Deleting records","url":"https://surrealdb.com/learn/tour/page-06"},{"@type":"LearningResource","name":"7: Field order in objects","url":"https://surrealdb.com/learn/tour/page-07"},{"@type":"LearningResource","name":"8: Tips when selecting records","url":"https://surrealdb.com/learn/tour/page-08"},{"@type":"LearningResource","name":"9: Casting and aliases","url":"https://surrealdb.com/learn/tour/page-09"},{"@type":"LearningResource","name":"10: Affixes","url":"https://surrealdb.com/learn/tour/page-10"},{"@type":"LearningResource","name":"11: Updating records","url":"https://surrealdb.com/learn/tour/page-11"},{"@type":"LearningResource","name":"12: Linking records","url":"https://surrealdb.com/learn/tour/page-12"},{"@type":"LearningResource","name":"13: Viewing the database as a whole","url":"https://surrealdb.com/learn/tour/page-13"},{"@type":"LearningResource","name":"14: Schemafull and schemaless","url":"https://surrealdb.com/learn/tour/page-14"},{"@type":"LearningResource","name":"15: Viewing the schema","url":"https://surrealdb.com/learn/tour/page-15"},{"@type":"LearningResource","name":"16: Literal types and assertions","url":"https://surrealdb.com/learn/tour/page-16"},{"@type":"LearningResource","name":"17: INSERT and using JSON","url":"https://surrealdb.com/learn/tour/page-17"},{"@type":"LearningResource","name":"18: FOR loops","url":"https://surrealdb.com/learn/tour/page-18"},{"@type":"LearningResource","name":"19: Basic graph relations","url":"https://surrealdb.com/learn/tour/page-19"},{"@type":"LearningResource","name":"20: Creating graph edges","url":"https://surrealdb.com/learn/tour/page-20"},{"@type":"LearningResource","name":"21: Querying graph relations","url":"https://surrealdb.com/learn/tour/page-21"},{"@type":"LearningResource","name":"22: Graph relations at greater depth","url":"https://surrealdb.com/learn/tour/page-22"},{"@type":"LearningResource","name":"23: Adding and improving data","url":"https://surrealdb.com/learn/tour/page-23"},{"@type":"LearningResource","name":"24: Defining events","url":"https://surrealdb.com/learn/tour/page-24"},{"@type":"LearningResource","name":"25: Defining indexes","url":"https://surrealdb.com/learn/tour/page-25"},{"@type":"LearningResource","name":"26: Improving the schema","url":"https://surrealdb.com/learn/tour/page-26"},{"@type":"LearningResource","name":"27: Visualising graph paths","url":"https://surrealdb.com/learn/tour/page-27"},{"@type":"LearningResource","name":"28: Recursive queries: setup","url":"https://surrealdb.com/learn/tour/page-28"},{"@type":"LearningResource","name":"29: Recursive queries","url":"https://surrealdb.com/learn/tour/page-29"},{"@type":"LearningResource","name":"30: More on recursive queries","url":"https://surrealdb.com/learn/tour/page-30"},{"@type":"LearningResource","name":"31: AI vector search","url":"https://surrealdb.com/learn/tour/page-31"},{"@type":"LearningResource","name":"Done the tour!","url":"https://surrealdb.com/learn/tour/page-32"}]}
```

```json
{"@context":"https://schema.org","@type":"LearningResource","name":"24: Defining events","description":"Defining events","url":"https://surrealdb.com/learn/tour/page-24","learningResourceType":"lesson","isPartOf":{"@type":"Course","name":"Welcome to the Tour of SurrealDB!","url":"https://surrealdb.com/learn/tour"},"position":25}
```

```json
{"@context":"https://schema.org","@type":"Organization","name":"SurrealDB","url":"https://surrealdb.com","logo":"https://surrealdb.com/assets/static/logo.BG7_TG2b.svg","description":"SurrealDB is the unified data layer for AI. A multi-model database for documents, graphs, vectors, and time-series.","foundingDate":"2022","hasCertification":[{"@type":"Certification","name":"SOC 2 Type 2"},{"@type":"Certification","name":"GDPR"},{"@type":"Certification","name":"Cyber Essentials Plus"},{"@type":"Certification","name":"ISO 27001"}],"owns":[{"@type":"SoftwareApplication","name":"SurrealDB","url":"https://surrealdb.com/surrealdb"},{"@type":"SoftwareApplication","name":"Agent Memory","url":"https://surrealdb.com/agent-memory"}],"knowsAbout":["multi-model databases","document databases","graph databases","vector search","time-series databases","SurrealQL","Agent Memory","real-time databases","embedded databases","context layer","graph ontology","distributed database","knowledge graphs","distributed transaction protocols","highly-scalable databases"],"sameAs":["https://www.wikidata.org/wiki/Q124316308","https://github.com/surrealdb/surrealdb","https://twitter.com/surrealdb","https://www.youtube.com/@surrealdb","https://www.linkedin.com/company/surrealdb","https://discord.gg/surrealdb","https://www.reddit.com/r/surrealdb","https://www.instagram.com/surrealdb","https://medium.com/surrealdb","https://dev.to/surrealdb"]}
```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://surrealdb.com"},{"@type":"ListItem","position":2,"name":"Learn","item":"https://surrealdb.com/learn"},{"@type":"ListItem","position":3,"name":"Page 24","item":"https://surrealdb.com/learn/tour/page-24"}]}
```
