CREATE can be used with just a table name, in which case its ID will be generated randomly.
-- Create a new record CREATEperson;
Response
[ { "id": "person:2vvgzt6m24s952yiy7x8" } ]
To specify a specific ID for a table instead, use : followed by a value.
CREATEperson:one;
Response
[ { id: person:one } ]
The table name and ID together form the full record ID which can be used to query the created data or by using the SELECT statement. See the record ID page to learn more about what counts as a valid record identifier.
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.
-- Use the type::record() function to provide a record's table and id separately CREATEtype::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.
-- Create a new record with a text id CREATEperson:tobieSET name='Tobie', company='SurrealDB', skills=['Rust', 'Go', 'JavaScript'];
The above will create a new record with the ID person:tobie and the specified data.
-- Create a new record with a numeric id CREATEperson:100CONTENT{ 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.
-- Note: record::tb(id) returns just the table name portion of a record ID CREATEtownsperson, cat, dogSET created_at=time::now(), name="Just a "+record::tb(id);
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.
-- Creates three townperson records with a random ID CREATE |townsperson:3|;
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.
-- 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|;
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:
-- Create 10000 records but don't show any of them CREATE |person:10000| SETage=46, username="john-smith"RETURNNONE;
RETURN BEFORE inside a CREATE statement is essentially a synonym for RETURN NONE, while RETURN AFTER is the default behaviour for create.
-- Will always return NONE CREATEpersonSETage=46, username="john-smith"RETURNBEFORE;
-- Return the record after creation CREATEpersonSETage=46, username="john-smith"RETURNAFTER;
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.
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.
-- Query attempting to create half a million `person` records CREATE |person:500000| SETage=46, username="john-smith"TIMEOUT500ms;
VERSION
If you are using SurrealKV as the storage engine with versioning enabled, when creating a record you can specify a version for each record. This is useful for time-travel queries. You can query a specific version of a record by using the VERSION clause.
The VERSION clause is always followed by a datetime and when the specified timestamp does not exist, an empty array is returned.
Note
The VERSION clause is currently in alpha and is subject to change. We do not recommend this for production.
-- Create a record for user:john at 8:00AM CREATEuser:johnSETname='John' VERSION d'2024-08-19T08:00:00Z'; [[{id: user:john, name: 'John'}]]
-- Return the record for user:john at 8:00AM SELECT * FROMuser:johnVERSIONd'2024-08-19T08:00:00Z'; [[{id: user:john, name: 'John'}]]
-- Create a record for user:john at 8:01AM CREATEuser:johnSETname='John-1' VERSION d'2024-08-19T08:01:00Z'; [[{id: user:john, name: 'John-1'}]]
-- Return the record for user:john at 8:01AM SELECT * FROMuser:johnVERSIONd'2024-08-19T08:01:00Z'; [[{id: user:john, name: 'John-1'}]]
-- Return an empty array because the record at the datetime does not exist SELECT * FROMuser:johnVERSIONd'2024-08-19T07:00:00Z'; [[]]
Another example of how VERSION works with CREATE is by creating records at different times and then querying for them at a specific point in time.
The VERSION clause can also take a dynamic value or parameter that resolves to a datetime.
CREATEuser:johnSETname='John' VERSION time::now();
LET$now = time::now(); CREATEuser:john_the_secondSETname='John' VERSION $now;
DEFINEFUNCTIONfn::yesterday() {time::now() -1d}; CREATEuser:john_the_thirdSETname='John' VERSION fn::yesterday();
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 Surrealist or the surreal sql 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 parameter. This can be seen through the INFO statements, which will show no definitions at all inside a new database.
This is to allow the chance to define them manually, such as by including a comment.
DEFINEDATABASEmy_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.
-- Three DEFINE statements will happen to allow this operation CREATEperson;
{ 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 using the STRICT keyword. In strict mode, any resource must first be explicitly defined before it can be used.