Skip to Content
SQL ReferenceTable DDL

Table DDL

KalamDB supports three application table types: USER, SHARED, and STREAM. For the full architecture, access matrices, storage behavior, and when to choose each type, see /docs/server/architecture/table-types.

CREATE TABLE

Syntax

SQL
CREATE [USER|SHARED|STREAM] TABLE [IF NOT EXISTS] [<namespace>.]<table_name> (  <column_name> <data_type> [NOT NULL|NULL] [DEFAULT <expr>] [PRIMARY KEY],  ...,  [CONSTRAINT <name> PRIMARY KEY (<column_name>)])[WITH (  TYPE = '<USER|SHARED|STREAM>',  STORAGE_ID = '<storage_id>',  USE_USER_STORAGE = <TRUE|FALSE>,  FLUSH_POLICY = '<rows:N|interval:N|rows:N,interval:N>',  TTL_SECONDS = <seconds>,  ACCESS_LEVEL = '<PUBLIC|PRIVATE|RESTRICTED|DBA>',  EVICTION_STRATEGY = '<time_based|size_based|hybrid>',  MAX_STREAM_SIZE_BYTES = <bytes>,  COMPRESSION = '<none|snappy|zstd>')];

Table options are type-specific:

  • USER: STORAGE_ID, USE_USER_STORAGE, FLUSH_POLICY, COMPRESSION
  • SHARED: STORAGE_ID, ACCESS_LEVEL, FLUSH_POLICY, COMPRESSION
  • STREAM: TTL_SECONDS, EVICTION_STRATEGY, MAX_STREAM_SIZE_BYTES

ACCESS_LEVEL is enforced only on SHARED tables. PUBLIC allows regular users to read but not write; PRIVATE and RESTRICTED allow service, dba, and system roles; DBA allows only dba and system roles. The canonical shared-table access matrix is maintained at /docs/server/architecture/table-types.

For storage-specific options such as STORAGE_ID and USE_USER_STORAGE, see /docs/server/sql-reference/storage-id-usage. For flush behavior, see /docs/server/architecture/storage-tiers.

COMPRESSION accepts only none, snappy, and zstd, and is valid only for USER and SHARED tables. It controls the Apache Parquet codec used when table data is flushed or compacted into cold-storage segments. none writes uncompressed Parquet pages, snappy is the default and optimizes for low CPU overhead, and zstd uses Zstandard level 1 for better compression density with modest extra CPU. This option is not WebSocket gzip and does not change RocksDB hot-tier compression. STREAM tables use hot stream log storage and do not accept table Parquet compression.

Examples

User table (per-user isolated):

SQL
CREATE TABLE app.messages (  id BIGINT PRIMARY KEY DEFAULT SNOWFLAKE_ID(),  conversation_id BIGINT NOT NULL,  sender TEXT NOT NULL,  role TEXT NOT NULL DEFAULT 'user',  content TEXT NOT NULL,  created_at TIMESTAMP NOT NULL DEFAULT NOW()) WITH (  TYPE = 'USER',  STORAGE_ID = 'local',  USE_USER_STORAGE = false,  FLUSH_POLICY = 'rows:1000,interval:60',  COMPRESSION = 'snappy');

Shared table (global access):

SQL
CREATE SHARED TABLE app.config (  key TEXT PRIMARY KEY,  value TEXT NOT NULL,  updated_at TIMESTAMP DEFAULT NOW()) WITH (  ACCESS_LEVEL = 'PUBLIC',  COMPRESSION = 'zstd');

Stream table (ephemeral with TTL):

SQL
CREATE STREAM TABLE app.events (  event_id TEXT PRIMARY KEY,  payload TEXT,  created_at TIMESTAMP DEFAULT NOW()) WITH (  TTL_SECONDS = 30,  EVICTION_STRATEGY = 'hybrid',  MAX_STREAM_SIZE_BYTES = 1048576);

ALTER TABLE

SQL
-- Add a columnALTER TABLE [<namespace>.]<table_name>  ADD COLUMN <name> <type> [NOT NULL|NULL] [DEFAULT <value>]; -- Drop a columnALTER TABLE [<namespace>.]<table_name>  DROP COLUMN <name>; -- Modify a column typeALTER TABLE [<namespace>.]<table_name>  MODIFY COLUMN <name> <type> [NOT NULL|NULL]; -- Change table propertiesALTER TABLE [<namespace>.]<table_name>  SET TBLPROPERTIES (<table_option> = <value>, ...); -- Equivalent shorthand for shared access changesALTER TABLE [<namespace>.]<table_name>  SET ACCESS LEVEL <public|private|restricted|dba>; -- Create a vector index on an embedding columnALTER TABLE [<namespace>.]<table_name>  CREATE INDEX <embedding_column> USING COSINE;

SET TBLPROPERTIES supports the same type-specific persisted options as CREATE TABLE. Use FLUSH_POLICY = NULL to clear a user/shared flush policy.

Examples:

SQL
ALTER TABLE app.config  SET TBLPROPERTIES (ACCESS_LEVEL = 'PUBLIC', COMPRESSION = 'zstd'); ALTER TABLE app.messages  SET TBLPROPERTIES (FLUSH_POLICY = 'rows:5000', USE_USER_STORAGE = true); ALTER TABLE app.events  SET TBLPROPERTIES (    TTL_SECONDS = 3600,    EVICTION_STRATEGY = 'size_based',    MAX_STREAM_SIZE_BYTES = 1048576  );

Vector index example

SQL
CREATE TABLE rag.documents_vectors (  id BIGINT PRIMARY KEY,  embedding EMBEDDING(384)) WITH (TYPE = 'USER'); ALTER TABLE rag.documents_vectors  CREATE INDEX embedding USING COSINE;

After the index exists, rank nearest rows with:

SQL
SELECT idFROM rag.documents_vectorsORDER BY COSINE_DISTANCE(embedding, '[0.12,0.03,0.98]')LIMIT 10;

DROP TABLE

SQL
DROP TABLE [IF EXISTS] [<namespace>.]<table_name>;DROP USER TABLE [IF EXISTS] [<namespace>.]<table_name>;DROP SHARED TABLE [IF EXISTS] [<namespace>.]<table_name>;DROP STREAM TABLE [IF EXISTS] [<namespace>.]<table_name>;

CREATE VIEW

SQL
CREATE VIEW [<namespace>.]<view_name> AS <select_query>;CREATE VIEW [<namespace>.]<view_name> (<column1>, <column2>, ...) AS <select_query>;

Example:

SQL
CREATE VIEW chat.recent_messages AS  SELECT id, sender, content, created_at  FROM chat.messages  WHERE created_at > NOW() - INTERVAL '1 hour'  ORDER BY created_at DESC;

SHOW TABLES

SQL
SHOW TABLES;SHOW TABLES IN <namespace>;SHOW TABLES IN NAMESPACE <namespace>;

DESCRIBE TABLE

SQL
DESCRIBE TABLE [<namespace>.]<table_name>;DESC TABLE [<namespace>.]<table_name>; -- Show table historyDESCRIBE TABLE [<namespace>.]<table_name> HISTORY;

SHOW STATS

SQL
SHOW STATS FOR TABLE [<namespace>.]<table_name>;

More Table Architecture

Last updated on