Skip to main content

Tables And Schema

Table DDL runs inside an existing database. Create or select the database first, then create tables, alter columns, rename schema objects, or drop tables.

Create Tables

CREATE TABLE robots (
id OID PRIMARY KEY NOT NULL DEFAULT (gen_id()),
name STRING NOT NULL,
year INT64 DEFAULT (2024),
active BOOL DEFAULT (true)
);

Create a table only when it does not exist:

CREATE TABLE IF NOT EXISTS robots (
id OID PRIMARY KEY NOT NULL DEFAULT (gen_id()),
name STRING NOT NULL
);

Inline constraints can define primary keys and unique columns directly in the column list:

CREATE TABLE app_users (
id STRING PRIMARY KEY NOT NULL,
email STRING UNIQUE NOT NULL,
display_name STRING NOT NULL
);

Use CHECK constraints when a column or row must satisfy a predicate before it can be inserted or updated:

CREATE TABLE products (
id OID PRIMARY KEY NOT NULL DEFAULT (gen_id()),
name STRING NOT NULL,
price FLOAT64 NOT NULL CHECK (price > 0),
discounted_price FLOAT64,
CONSTRAINT valid_discount CHECK (discounted_price IS NULL OR price > discounted_price)
);

See Check Constraints for naming, ALTER TABLE, NULL behavior, and supported expressions.

Declare a composite primary key after the column list:

CREATE TABLE readings (
sensor_id STRING NOT NULL,
ts INT64 NOT NULL,
value FLOAT64 NOT NULL
) PRIMARY KEY (sensor_id ASC, ts DESC);

CamusDB also accepts inline index-style constraints inside CREATE TABLE:

CREATE TABLE robots (
id OID NOT NULL DEFAULT (gen_id()),
code STRING NOT NULL,
name STRING,
PRIMARY KEY (id),
UNIQUE KEY code_uk (code),
KEY name_idx (name),
KEY code_lookup_idx (code) INCLUDE (name)
);

Inline KEY ... INCLUDE (...) creates a covering secondary index. See Indexes for when included columns help a query avoid fetching the primary row.

Schema Comments

Use inline COMMENT '<text>' clauses to document tables, columns, and inline secondary indexes when creating a table:

CREATE TABLE users (
id OID PRIMARY KEY NOT NULL COMMENT 'Internal user identifier',
email STRING NOT NULL COMMENT 'Unique login email address',
KEY email_idx (email) COMMENT 'Lookup by login email'
) COMMENT 'Application users';

You can also set or remove comments later with COMMENT ON:

COMMENT ON TABLE users IS 'Application users';
COMMENT ON COLUMN users.email IS 'Unique login email address';
COMMENT ON INDEX users.email_idx IS 'Lookup by login email';

See Schema Comments for database comments, removal with IS NULL, limits, and introspection behavior.

Column Defaults

Use DEFAULT (...) to define a value CamusDB applies when an insert omits the column or uses the DEFAULT keyword.

CREATE TABLE events (
id UUID PRIMARY KEY NOT NULL DEFAULT (gen_uuid_v7()),
event_name STRING NOT NULL,
priority INT64 DEFAULT (0)
);

INSERT INTO events (event_name)
VALUES ("robot-created");

INSERT INTO events (id, event_name, priority)
VALUES (DEFAULT, "robot-updated", DEFAULT);

Constant defaults are stored in the schema. Supported volatile generator defaults are evaluated once per inserted row, including each row in a multi-row INSERT.

Default expressionColumn typeUse case
DEFAULT (gen_id())OIDGenerate an ObjectId when the row is inserted.
DEFAULT (gen_uuid_v4())UUID / GUIDGenerate a random UUID when the row is inserted.
DEFAULT (gen_uuid_v7())UUID / GUIDGenerate a time-ordered UUID when the row is inserted.

Function defaults must be bare zero-argument calls. CamusDB rejects mismatched defaults such as DEFAULT (gen_id()) on a UUID column.

Column Types

SQL typeNotes
OIDNative object id values.
UUIDNative 128-bit UUID values. Also accepted as GUID.
INT64Signed 64-bit integers. Also accepted as SMALLINT.
FLOAT64Double-precision floating point values. Also accepted as FLOAT.
FLOAT32Single-precision floating point values.
BOOLBoolean values.
STRING, STRING(N)Text values, optionally with a maximum length. Also accepted as CHAR, VARCHAR, or TEXT.
DATECalendar dates without time.
DATETIMEUTC instants.
BYTESOpaque byte strings.
ARRAY(T)Ordered lists of scalar values. Arrays are not indexable.

Common aliases include INT / INTEGER / SMALLINT for INT64, FLOAT for FLOAT64, REAL for FLOAT32, TIMESTAMP for DATETIME, BLOB for BYTES, CHAR / VARCHAR / TEXT for STRING, BOOLEAN for BOOL, OBJECT_ID for OID, and GUID for UUID.

See Data Types for length limits, literal formats, casts, storage recommendations, API value encoding, and array rules.

Alter Tables

Add or drop columns:

ALTER TABLE robots ADD COLUMN model STRING NULL;
ALTER TABLE robots ADD COLUMN notes STRING NULL COMMENT 'Operator notes';
ALTER TABLE robots DROP COLUMN model;

Add or drop a primary key:

ALTER TABLE robots ADD PRIMARY KEY (id);
ALTER TABLE robots DROP PRIMARY KEY;

Rename Tables

ALTER TABLE robots RENAME TO machines;

After the rename, the old table name is no longer valid and the new table name resolves to the same table data. Row and index data survive the rename because the storage identity is not the table display name.

Renaming to an existing table name fails with TableAlreadyExists. Renaming a missing table fails with TableDoesntExist.

Rename Columns

ALTER TABLE machines RENAME COLUMN name TO display_name;

Column rename is metadata-only for stored rows. Existing row values remain available under the new column name, and query results no longer include the old column name.

Renaming a missing column fails with UnknownColumn. Renaming to an existing column name fails with DuplicateColumn.

Identifier Case

Schema object names preserve the case you use when creating or renaming them, but name lookup is case-insensitive.

CREATE TABLE Robots (
Id OID PRIMARY KEY NOT NULL,
RobotName STRING NOT NULL
);

INSERT INTO robots (id, robotname) VALUES (GEN_ID(), "R2-D2");
SELECT ROBOTNAME FROM ROBOTS;

SHOW TABLES, SHOW COLUMNS, and SHOW CREATE TABLE display the stored names with their original case. References in SQL can use any case.

Duplicate names that differ only by case are rejected. For example, a table cannot contain both RobotName and robotname, and a database cannot contain both Robots and robots as separate tables.

Table Settings

Use ALTER TABLE ... SET (...) to update table-level settings.

ALTER TABLE application_logs
SET (sql_stats_automatic_collection_enabled = false);

ALTER TABLE application_logs
SET (sql_stats_automatic_collection_enabled = true);

sql_stats_automatic_collection_enabled controls whether automatic analyze may refresh statistics for that table. It defaults to true. Setting it to false opts the table out of background statistics collection, but manual ANALYZE TABLE application_logs still runs.

The setting name is case-insensitive and the value must be boolean. Unknown setting names are rejected.

Drop Tables

DROP TABLE robots;
DROP TABLE IF EXISTS robots;
DROP TABLE robots FORCE;

DROP TABLE removes the table from the active schema immediately, but the table data is retained as a recoverable orphan for the configured retention window. SHOW TABLES no longer lists the table and the name is free to reuse.

Use SHOW ORPHAN TABLES in the current database to inspect recoverable dropped tables, then recover one under a new name:

SHOW ORPHAN TABLES;
CREATE TABLE robots_recovered RELINK TO "A0";

The recovered table keeps its rows, indexes, constraints, and column definitions from the time it was dropped.

Use FORCE only when the table should be physically deleted immediately and permanently:

DROP TABLE robots FORCE;

Forced drops create no orphan and cannot be recovered. See Recover Dropped Objects for retention settings, recovery examples, and limits.