# CREATE

The CREATE statement can be used to add a record to the database if it does not already exist.

The `CREATE` statement can be used to add a record to the database. If the record already exists, the statement will give an error.

> [!NOTE]
> This statement can not be used to create graph relationships. For that, use the [`RELATE`](/docs/reference/query-language/statements/relate.md) statement.

### Statement syntax

**SurrealQL Syntax**

```syntax title="SurrealQL Syntax"
CREATE [ ONLY ] @targets
	[ CONTENT @value
	  | SET @field = @value ...
	]
	[ RETURN NONE | RETURN BEFORE | RETURN AFTER | RETURN DIFF | RETURN @statement_param, ... | RETURN VALUE @statement_param ]
	[ TIMEOUT @duration ]
;
```

## Creating a table record

`CREATE` can be used with just a table name, in which case its ID will be generated randomly.

```surql
-- Create a new record
CREATE person;
```

```surql title="Response"
[
    {
        "id": "person:2vvgzt6m24s952yiy7x8"
    }
]
```

To specify a specific ID for a table instead, use `:` followed by a value.

```surql
CREATE person:one;
```

```surql title="Response"
[
	{
		id: person:one
	}
]
```

The table name and ID together form the full [record ID](/docs/reference/query-language/language-primitives/data-types/record-ids.md) which can be used to query the created data or by using the [`SELECT`](/docs/reference/query-language/statements/select.md) statement. See the [record ID](/docs/reference/query-language/language-primitives/data-types/record-ids.md) page to learn more about what counts as a valid record identifier.

The default random ID can be generated in different ways (such as a ULID) using the [built-in ID generation functions](/docs/reference/query-language/language-primitives/data-types/record-ids.md#generating-record-ids).

It is also possible to specify the ID of the record you want to create using a string or any of the supported formats for [record IDs](/docs/reference/query-language/language-primitives/data-types/record-ids.md).

```surql
-- Use the type::record() function to provide a record's table and id separately
CREATE type::record("person", "one");
```

## Adding record data

When creating a record, you can specify the record data using the `SET` clause, or the `CONTENT` clause. The `SET` clause is used to specify record data one field at a time, while the `CONTENT` clause is used to specify record data using a SurrealQL object. The `CONTENT` clause is useful when the record data is already in the form of a SurrealQL or JSON object.

```surql
-- Create a new record with a text id
CREATE person:tobie SET
    name = 'Tobie',
    company = 'SurrealDB',
    skills = ['Rust', 'Go', 'JavaScript'];
```

The above will create a new record with the ID `person:tobie` and the specified data.

```surql title="Response"
[
	{
		"id": "person:tobie",
		"name": "Tobie",
		"company": "SurrealDB",
		"skills": ["Rust", "Go", "JavaScript"]
	}
]
```

Specifing record data using the `CONTENT` keyword:

```surql
-- Create a new record with a numeric id
CREATE person:100 CONTENT {
	name: 'Tobie',
	company: 'SurrealDB',
	skills: ['Rust', 'Go', 'JavaScript'],
};
```

## Options and clauses

### Creating multiple records

Multiple records or even multiple record types can be created by separating table names by commas.

```surql
-- Note: record::tb(id) returns just the table name portion of a record ID
CREATE townsperson, cat, dog SET
    created_at = time::now(),
    name = "Just a " + record::tb(id);
```

```surql title="Response"
[
    {
        "created_at": "2024-03-19T03:12:05.079Z",
        "id": "townsperson:p37ha2lngckp3v8tvf2j",
        "name": "Just a townsperson"
    },
    {
        "created_at": "2024-03-19T03:12:05.080Z",
        "id": "cat:p1pwbjaq96nhhnuohjtc",
        "name": "Just a cat"
    },
    {
        "created_at": "2024-03-19T03:12:05.080Z",
        "id": "dog:01vcxgdpuctdk354hzkp",
        "name": "Just a dog"
    }
]
```

The `| |` syntax is another way to create multiple records in a single execution. This syntax can be used in two ways.

One is by including a table name, a `:` (a colon), and then a number. This will create a quantity of records equal to the number after the table name. The records created will have random IDs.

```surql
-- Creates three townperson records with a random ID
CREATE |townsperson:3|;
```

```surql title="Response"
[
	{
		id: townsperson:hzkt0piy3f72xo5dl2jf
	},
	{
		id: townsperson:k0mujrohm8qe2txz5pnz
	},
	{
		id: townsperson:pwumqelrsi1qt0jmihwh
	}
]
```

The other method is by using the `..` range syntax after the `:` instead of a single number. This will create records with specific IDs that span across the range indicated.

```surql
-- Note: 1..4 used to be inclusive until SurrealDB 3.0.0
-- Now creates 1 up to but not including 4
CREATE |townsperson:1..4|;
```

```surql title="Response"
[
	{
		id: townsperson:1
	},
	{
		id: townsperson:2
	},
	{
		id: townsperson:3
	}
]
```

All of these methods can be combined to create multiple records at the same time.

```surql
CREATE dog, |cat:2|, |townsperson:1..3| SET
    created_at = time::now(),
    name = "Just a " + record::tb(id);
```

```surql title="Response"
[
	{
		created_at: '2024-08-13T04:14:44.135Z',
		id: dog:u3fzmqvg3yq9mo3o6z2s,
		name: 'Just a dog'
	},
	{
		created_at: '2024-08-13T04:14:44.137Z',
		id: cat:n6x3caiiazucslfs7rpm,
		name: 'Just a cat'
	},
	{
		created_at: '2024-08-13T04:14:44.137Z',
		id: cat:rnvhxgjhsbea5u58s0wu,
		name: 'Just a cat'
	},
	{
		created_at: '2024-08-13T04:14:44.137Z',
		id: townsperson:1,
		name: 'Just a townsperson'
	},
	{
		created_at: '2024-08-13T04:14:44.137Z',
		id: townsperson:2,
		name: 'Just a townsperson'
	},
	{
		created_at: '2024-08-13T04:14:44.137Z',
		id: townsperson:3,
		name: 'Just a townsperson'
	}
]
```

### ONLY

When creating a single record, the `ONLY` clause can be used to return the record object on its own instead of inside an array.

```surql
-- Returns an array with a single record inside
CREATE person:tobie SET
    name = 'Tobie',
    company = 'SurrealDB',
    skills = ['Rust', 'Go', 'JavaScript'];

-- Returns just a single record
CREATE ONLY person:tobie SET
    name = 'Tobie',
    company = 'SurrealDB',
    skills = ['Rust', 'Go', 'JavaScript'];
```

```surql title="Response"
-------- Query --------

[
	{
		company: 'SurrealDB',
		id: person:tobie,
		name: 'Tobie',
		skills: [
			'Rust',
			'Go',
			'JavaScript'
		]
	}
]

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

{
	company: 'SurrealDB',
	id: person:tobieagain,
	name: 'Tobie',
	skills: [
		'Rust',
		'Go',
		'JavaScript'
	]
}
```

### Return values

By default, the create statement returns the record once it has been created. To change what is returned, we can use the `RETURN` clause, specifying either `NONE`, `BEFORE`, `AFTER`, `DIFF`, or a comma-separated list of specific fields to return.

`RETURN NONE` can be useful to avoid excess output:

```surql
-- Create 10000 records but don't show any of them
CREATE |person:10000| SET age = 46, username = "john-smith" RETURN NONE;
```

`RETURN DIFF` returns the changeset diff:

```surql
CREATE person SET age = 46, username = "john-smith" RETURN DIFF;
```

```surql title="Response"
[
	[
		{
			op: 'replace',
			path: '/',
			value: {
				age: 46,
				id: person:h84x4k5kh2m6cjf1vvza,
				username: 'john-smith'
			}
		}
	]
]
```

`RETURN BEFORE` inside a `CREATE` statement is essentially a synonym for `RETURN NONE`, while `RETURN AFTER` is the default behaviour for create.

```surql
-- Will always return NONE
CREATE person SET age = 46, username = "john-smith" RETURN BEFORE;
```

```surql
-- Return the record after creation
CREATE person SET age = 46, username = "john-smith" RETURN AFTER;
```

You can also return specific fields from a created record, the value of a single field using `VALUE`, as well as ad-hoc fields to modify the output as needed.

```surql
CREATE person
    SET age = 46,
    username = "john-smith",
    interests = ['skiing', 'music']
RETURN
    age,
    interests,
    age + 1 AS age_next_year;

CREATE |person:5|
    SET age = 20
RETURN VALUE age;
```

```surql title="Response"
-------- Query --------

[
	{
		age: 46,
		age_next_year: 47,
		interests: [
			'skiing',
			'music'
		]
	}
]

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

[
	20,
	20,
	20,
	20,
	20
]
```

### Timeout

The `TIMEOUT` clause can be used to specify the maximum time the statement should take to execute. This is useful when you want more control such as controlling compute costs or making sure queries succeed or fail within tight latency boundaries to not have a big query queue forming.

The value for `TIMEOUT` is specified in seconds or milliseconds.

```surql
-- Query attempting to create half a million `person` records
CREATE |person:500000| SET age = 46, username = "john-smith" TIMEOUT 500ms;
```

## Implicit statement behaviour

While a number of definitions need to be in place for a `CREATE` statement to happen, SurrealDB will handle them automatically by default. This behaviour is best seen by starting a new database.

While a connection to SurrealDB via SurrealDB Studio or the [surreal sql](/docs/reference/cli/surrealdb-cli/commands/sql.md) command can include a defined namespace and database, the namespace and database names do not exist upon creation. At this point, they are only held inside the pre-defined [$session](/docs/reference/query-language/language-primitives/parameters.md#session) parameter. This can be seen through the [INFO](/docs/reference/query-language/statements/info.md) statements, which will show no definitions at all inside a new database.

```surql
INFO FOR ROOT;
INFO FOR NS;
INFO FOR DB;
RETURN $session;
```

```surql title="Response"
-------- Query --------

{
	accesses: {},
	namespaces: {},
	nodes: {},
	system: {
		available_parallelism: 0,
		cpu_usage: 0,
		load_average: [
			0,
			0,
			0
		],
		memory_allocated: 0,
		memory_usage: 0,
		physical_cores: 0,
		threads: 0
	},
	users: {}
}

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

{
	accesses: {},
	analyzers: {},
	apis: {},
	configs: {},
	functions: {},
	models: {},
	params: {},
	tables: {},
	users: {}
}

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

{
	analyzers: {},
	functions: {},
	models: {},
	params: {},
	scopes: {},
	tables: {},
	tokens: {},
	users: {}
}

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

{
	ac: NONE,
	db: 'sandbox',
	exp: NONE,
	id: NONE,
	ip: NONE,
	ns: 'sandbox',
	or: NONE,
	rd: NONE,
	tk: NONE
}
```

This is to allow the chance to [define](/docs/reference/query-language/statements/define/database.md) them manually, such as by including a comment.

```surql
DEFINE DATABASE my_database COMMENT "Some important info that I prefer to add manually";
```

However, once the first record is created or inserted, SurrealDB will access the session data to execute a number of definition statements for the namespace, database, and then add a definition for the desired table name in order to allow the operation to proceed.

```surql
-- Three DEFINE statements will happen to allow this operation
CREATE person;

INFO FOR ROOT;
INFO FOR NS;
INFO FOR DB;
```

```surql title="Response"
-------- Query --------

{
	accesses: {},
	namespaces: {
		sandbox: 'DEFINE NAMESPACE sandbox'
	},
	nodes: {},
	system: {
		available_parallelism: 0,
		cpu_usage: 0,
		load_average: [
			0,
			0,
			0
		],
		memory_allocated: 0,
		memory_usage: 0,
		physical_cores: 0,
		threads: 0
	},
	users: {}
}

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

{
	accesses: {},
	databases: {
		sandbox: 'DEFINE DATABASE sandbox'
	},
	users: {}
}

-------- Query 7 --------

{
	accesses: {},
	analyzers: {},
	apis: {},
	configs: {},
	functions: {},
	models: {},
	params: {},
	tables: {
		person: 'DEFINE TABLE person TYPE ANY SCHEMALESS PERMISSIONS NONE'
	},
	users: {}
}
```

To disallow this behaviour, you can [define a database](/docs/reference/query-language/statements/define/database.md) using the `STRICT` keyword. In strict mode, any resource must first be explicitly defined before it can be used.

```surql
ns/db> CREATE person;
[[{ id: person:epgvviec00l4pnmhtt5n }]]

ns/db> DEFINE DB strict_db STRICT;
[NONE]

ns/db> USE DB strict_db;
[NONE]

ns/strict_db> CREATE person;
["Thrown error: The table 'person' does not exist"]

ns/strict_db> DEFINE TABLE person;
[NONE]

ns/strict_db> CREATE person;
[[{ id: person:c76lfw6n4yb1z2dj9xaj }]]
```

## Learn more

To learn more about SurrealDB, check out the following resources:
- [Getting started guide](/docs)
- [Select statement](/docs/reference/query-language/statements/select.md)
- [Update statement](/docs/reference/query-language/statements/update.md)
- [Insert statement](/docs/reference/query-language/statements/insert.md)
- [Delete statement](/docs/reference/query-language/statements/delete.md)
- [Relate statement](/docs/reference/query-language/statements/relate.md)
