CREATE TABLE reference

To create a new table in the database, the CREATE TABLE keywords followed by column definitions are used.

CREATE TABLE my_table(symb SYMBOL, price DOUBLE, ts TIMESTAMP, s STRING)
timestamp(ts);

Syntax#

To create a table by manually entering parameters and settings:

Flow chart showing the syntax of the CREATE TABLE keyword

info

Checking table metadata can be done via the tables() and table_columns() functions which are described in the meta functions documentation page.

To create a table by cloning the metadata of an existing table:

Flow chart showing the syntax of the CREATE TABLE LIKE keyword

IF NOT EXISTS#

An optional IF NOT EXISTS clause may be added directly after the CREATE TABLE keywords to indicate that a new table should be created if one with the desired table name does not already exist.

CREATE TABLE IF NOT EXISTS test_table(price DOUBLE, ts TIMESTAMP) timestamp(ts);

Table name#

Internally the table name is used as a directory name on the file system. It can contain both ASCII and Unicode characters. The table name must be unique and an error is returned if a table already exists with the requested name. Table names containing spaces or period . character must be enclosed in double quotes, for example:

CREATE TABLE "example out of.space" (a INT);
INSERT INTO "example out of.space" values (1);

Column name#

As with table names, the column name is used for file names internally. Although it does support both ASCII and Unicode characters, character restrictions specific to the file system still apply. Tables may have up to 2,147,483,647 columns.

note

Column names must be unique within each table and must not contain a period . character.

Type definition#

When specifying a column, a name and type definition must be provided. The symbol type may have additional optional parameters applied.

Flow chart showing the syntax of the different column types

Symbols#

Optional keywords and parameters may follow the symbol type which allow for further optimization on the handling of this type. For more information on the benefits of using this type, see the symbol overview.

Symbol capacity#

CAPACITY is an optional keyword used when defining a symbol type on table creation to indicate how many distinct values this column is expected to have. When distinctValueEstimate is not explicitly specified, a default value of cairo.default.symbol.capacity is used.

distinctValueEstimate - the value used to size data structures for symbols.

CREATE TABLE my_table(symb SYMBOL CAPACITY 128, price DOUBLE, ts TIMESTAMP),
INDEX (symb) timestamp(ts);

The symbol capacity is not to be confused with index capacity described in column indexes below.

CREATE TABLE my_table
(symb SYMBOL capacity 128 NOCACHE INDEX capacity 256, price DOUBLE, ts TIMESTAMP)
timestamp(ts);

Symbol caching#

CACHE | NOCACHE is used to specify whether a symbol should be cached. The default value is CACHE unless otherwise specified.

CREATE TABLE my_table
(symb SYMBOL CAPACITY 128 NOCACHE, price DOUBLE, ts TIMESTAMP)
timestamp(ts);

Casting types#

castDef - casts the type of a specific column. columnRef must reference existing column in the selectSql

Flow chart showing the syntax of the cast function

CREATE TABLE test AS (SELECT CAST(x as DOUBLE) x FROM long_sequence(10));

Column indexes#

Index definitions (indexDef) are used to create an index for a table column. The referenced table column must be of type symbol.

Flow chart showing the syntax of the index function

CREATE TABLE my_table(symb SYMBOL, price DOUBLE, ts TIMESTAMP),
INDEX (symb) TIMESTAMP(ts);

An index capacity may be provided for the index by defining the index storage parameter, valueBlockSize:

CREATE TABLE my_table(symb SYMBOL, price DOUBLE, ts TIMESTAMP),
INDEX (symb CAPACITY 128) TIMESTAMP(ts);
-- equivalent to
CREATE TABLE my_table(symb SYMBOL INDEX CAPACITY 128, price DOUBLE, ts TIMESTAMP),
TIMESTAMP(ts);

See Index for more information about index capacity.

CREATE TABLE AS#

When SQL (selectSQL) is SELECT * FROM tab or any arbitrary SQL result, the selected column names and their data type will be cloned to the new table.

Create table as select
CREATE TABLE new_table AS(
SELECT
rnd_int() a,
rnd_double() b,
rnd_symbol('ABB', 'CDD') c
FROM
long_sequence(100)
WHERE false
);

The data type of a column can be changed:

Clone an existing wide table and change type of cherry-picked columns
CREATE TABLE new_table AS (SELECT * FROM source_table WHERE false),
CAST(price AS LONG),
CAST(instrument as SYMBOL);

Here we changed type of price (assuming it was INT) to LONG and changed type of sym to symbol and created an index.

Designated timestamp#

The timestamp function allows for specifying which column (which must be of timestamp type) should be a designated timestamp for the table. For more information, see the designated timestamp reference.

caution

The designated timestamp column cannot be changed after the table has been created.

Partitioning#

PARTITION BY allows for specifying the partitioning strategy for the table. Tables created via SQL are not partitioned by default and tables can be partitioned by one of the following:

  • YEAR
  • MONTH
  • DAY
  • HOUR
caution

The partitioning strategy cannot be changed after the table has been created.

WITH table parameter#

Flow chart showing the syntax of keyword to specify WITH table parameter

The parameter influences how often commits of out-of-order data occur. It may be set during table creation using the WITH keyword.

  • maxUncommittedRows - equivalent to cairo.max.uncommitted.rows
Setting out-of-order table parameters via SQL
CREATE TABLE my_table (timestamp TIMESTAMP) TIMESTAMP(timestamp)
PARTITION BY DAY WITH maxUncommittedRows=250000;

Checking the values per-table may be done using the tables() function:

List all tables
SELECT id, name, maxUncommittedRows FROM tables();
idnamemaxUncommittedRows
1my_table250000
2device_data10000

QuestDB 6.5.5 and earlier versions#

Flow chart showing the syntax of keyword to specify WITH table commit parameters

From QuestDB 6.6 onwards, the database adjusts relevant settings automatically and provides optimal ingestion speed.

  • commitLag - equivalent to cairo.commit.lag expects a value with a modifier to specify the unit of time for the value:

    unitdescription
    usmicroseconds
    sseconds
    mminutes
    hhours
    ddays

For more information on commit lag and the maximum uncommitted rows, see the guide for out-of-order commits and ILP commit strategy.

CREATE TABLE LIKE#

The LIKE keyword clones the table schema of an existing table without copying the data. Table settings and parameters such as designated timestamp, symbol column indexes, and index capacity will be cloned, too.

Create table like
CREATE TABLE new_table (LIKE my_table);

Examples#

The following examples demonstrate creating tables from basic statements, and introduce features such as partitioning and designated timestamps. For more information on the concepts introduced to below, see

  • designated timestamp reference on electing a timestamp column
  • partition documentation which describes how partitions work in QuestDB
  • symbol reference for using the symbol data type

This example will create a table without a designated timestamp and does not have a partitioning strategy applied.

Basic example
CREATE TABLE my_table(symb SYMBOL, price DOUBLE, ts TIMESTAMP, s STRING);

The same table can be created and a designated timestamp may be specified.

Adding a designated timestamp
CREATE TABLE my_table(symb SYMBOL, price DOUBLE, ts TIMESTAMP, s STRING)
TIMESTAMP(ts);
Adding a partitioning strategy by DAY
CREATE TABLE my_table(symb SYMBOL, price DOUBLE, ts TIMESTAMP, s STRING)
TIMESTAMP(ts)
PARTITION BY DAY;
Adding parameters for symbol type
CREATE TABLE
my_table(symb SYMBOL CAPACITY 256 NOCACHE INDEX CAPACITY 1048576,
price DOUBLE, ts TIMESTAMP, s STRING)
TIMESTAMP(ts)
PARTITION BY DAY;

Let's assume we imported a text file into the table taxi_trips_unordered and now we want to turn this data into time series through ordering trips by pickup_time, assign dedicated timestamp and partition by month:

Create table as select with data manipulation
CREATE TABLE taxi_trips AS(
SELECT * FROM taxi_trips_unordered ORDER BY pickup_time
) TIMESTAMP(pickup_time)
PARTITION BY MONTH;