Back to The Times of Claw

DuckDB Data Types: Complete Reference Guide

DuckDB data types reference: integers, floats, decimals, strings, dates, timestamps, JSON, arrays, structs, and more. With examples and casting patterns.

Mark Rachapoom
Mark Rachapoom
·7 min read
DuckDB Data Types: Complete Reference Guide

DuckDB Data Types: Complete Reference Guide

DuckDB has a rich type system that covers everything from standard SQL types to nested structures, arrays, and enumerations. Understanding which type to use for each column affects storage efficiency, query performance, and correctness.

This is the reference guide you'll want bookmarked.

Numeric Types#

Integer Types#

TypeAliasesSizeRange
TINYINTINT11 byte-128 to 127
SMALLINTINT2, SHORT2 bytes-32,768 to 32,767
INTEGERINT, INT44 bytes-2.1B to 2.1B
BIGINTINT8, LONG8 bytes-9.2 quintillion to 9.2 quintillion
HUGEINT16 bytes±170 undecillion
UTINYINT1 byte0 to 255
USMALLINT2 bytes0 to 65,535
UINTEGER4 bytes0 to 4.3B
UBIGINT8 bytes0 to 18.4 quintillion
CREATE TABLE metrics (
    id BIGINT,
    count INTEGER,
    small_flag TINYINT,
    large_value HUGEINT
);

Use INTEGER for most row counts. Use BIGINT for IDs in large systems. Use HUGEINT for astronomical calculations or cryptographic hashes.

Floating Point Types#

TypeAliasesSizePrecision
FLOATFLOAT4, REAL4 bytes~7 decimal digits
DOUBLEFLOAT8, NUMERIC8 bytes~15 decimal digits
-- Float precision warning
SELECT 0.1 + 0.2 = 0.3;  -- Returns FALSE due to floating point
SELECT 0.1::DOUBLE + 0.2::DOUBLE;  -- Still FALSE

Don't use FLOAT or DOUBLE for money. Use DECIMAL.

DECIMAL / NUMERIC#

DECIMAL(precision, scale)
-- precision: total number of digits
-- scale: digits after decimal point
 
-- Money: 10 total digits, 2 after decimal
amount DECIMAL(10, 2)  -- Stores up to 99,999,999.99
 
-- Percentage: 5 total digits, 4 after decimal  
rate DECIMAL(5, 4)  -- Stores up to 9.9999

DECIMAL performs exact arithmetic — no floating point errors.

String Types#

TypeDescription
VARCHARVariable-length string, no limit
VARCHAR(n)Variable-length, max n characters
CHAR(n)Fixed-length, n characters (padded with spaces)
TEXTAlias for VARCHAR
BLOBBinary data
-- All of these are essentially equivalent in DuckDB
name VARCHAR,
name VARCHAR(255),
name TEXT,
name STRING

DuckDB doesn't enforce VARCHAR(n) length limits (unlike PostgreSQL). VARCHAR, VARCHAR(255), and TEXT all behave identically. Use VARCHAR for simplicity.

Boolean#

is_active BOOLEAN
 
-- Values
true, false, NULL
 
-- Comparisons
SELECT * FROM users WHERE is_active = true;
SELECT * FROM users WHERE is_active;  -- Same thing
SELECT * FROM users WHERE NOT is_active;

Date and Time Types#

TypeDescriptionExample
DATECalendar date2026-03-26
TIMETime of day14:30:00
TIMESTAMPDate + time (no timezone)2026-03-26 14:30:00
TIMESTAMPTZDate + time (with timezone)2026-03-26 14:30:00+00
INTERVALDurationINTERVAL '3 days'
-- Date literals
SELECT DATE '2026-03-26';
SELECT '2026-03-26'::DATE;
 
-- Timestamp literals
SELECT TIMESTAMP '2026-03-26 14:30:00';
SELECT TIMESTAMPTZ '2026-03-26 14:30:00+00';
 
-- Current values
SELECT CURRENT_DATE, CURRENT_TIME, CURRENT_TIMESTAMP, NOW();
 
-- Interval arithmetic
SELECT DATE '2026-03-26' + INTERVAL '7 days';
SELECT TIMESTAMP '2026-03-26 14:30:00' - INTERVAL '1 hour';
 
-- Date parts
SELECT YEAR(NOW()), MONTH(NOW()), DAY(NOW());
SELECT EXTRACT(HOUR FROM NOW());
SELECT DATE_TRUNC('month', NOW());

Use TIMESTAMP for most datetime storage. Use TIMESTAMPTZ when you need timezone-aware operations.

JSON Type#

DuckDB treats JSON as text but with JSON-specific functions:

-- Store JSON
data JSON,
metadata VARCHAR  -- Also works for JSON
 
-- Query JSON
SELECT data->>'name' FROM records;  -- String extraction
SELECT data->'address'->>'city' FROM records;  -- Nested
 
-- JSON functions
SELECT json_extract(data, '$.name') FROM records;
SELECT json_extract_string(data, '$.name') FROM records;
SELECT json_array_length(data->'items') FROM records;
 
-- Create JSON
SELECT json_object('name', 'DenchClaw', 'version', 1);
SELECT json_array(1, 2, 3);

Arrays#

DuckDB has native array and list types:

-- Fixed-size array (DuckDB 0.10+)
tags INTEGER[3]
 
-- Variable-size list
tags INTEGER[]
emails VARCHAR[]
 
-- Array literals
SELECT [1, 2, 3]::INTEGER[];
SELECT ['hello', 'world']::VARCHAR[];
 
-- Array operations
SELECT array_length([1, 2, 3]);
SELECT list_contains([1, 2, 3], 2);  -- Returns true
SELECT list_append([1, 2, 3], 4);
SELECT unnest([1, 2, 3]);  -- Expands to 3 rows
 
-- Query with arrays
SELECT * FROM users WHERE list_contains(tags, 'enterprise');

Structs#

Structs are named collections of fields — like a row within a row:

-- Struct type
address STRUCT(street VARCHAR, city VARCHAR, zip VARCHAR)
 
-- Create structs
SELECT {'street': '123 Main St', 'city': 'San Francisco', 'zip': '94105'}::STRUCT(street VARCHAR, city VARCHAR, zip VARCHAR);
 
-- Access struct fields
SELECT address.city FROM contacts;
 
-- Unnest struct
SELECT unnest(address) FROM contacts;

MAP Type#

Maps are key-value collections with dynamic keys:

metadata MAP(VARCHAR, VARCHAR)
 
-- Create a map
SELECT MAP(['key1', 'key2'], ['val1', 'val2']);
SELECT MAP {'color': 'blue', 'size': 'large'};
 
-- Access map values
SELECT metadata['color'] FROM products;
 
-- Check if key exists
SELECT map_contains(metadata, 'color') FROM products;

ENUM Type#

Enums enforce valid values and are more efficient than VARCHAR for low-cardinality fields:

-- Create an enum type
CREATE TYPE deal_stage AS ENUM ('Lead', 'Qualified', 'Proposal', 'Negotiation', 'Closed Won', 'Closed Lost');
 
-- Use in table
CREATE TABLE deals (
    id VARCHAR,
    stage deal_stage
);
 
-- Insert
INSERT INTO deals VALUES ('d-1', 'Proposal');
 
-- Invalid value raises error
INSERT INTO deals VALUES ('d-2', 'Invalid Stage');  -- Error
 
-- List enum values
SELECT unnest(enum_range(NULL::deal_stage));

Enums use integer storage internally, so they're more efficient than VARCHAR for repeated values.

Type Casting#

-- Explicit cast
SELECT CAST(42 AS VARCHAR);
SELECT 42::VARCHAR;
SELECT '42'::INTEGER;
 
-- Safe cast (returns NULL on failure instead of error)
SELECT TRY_CAST('not a number' AS INTEGER);  -- Returns NULL
SELECT TRY_CAST('42' AS INTEGER);  -- Returns 42
 
-- Implicit casts
SELECT 1 + 1.5;  -- INTEGER + DOUBLE → DOUBLE
SELECT '2026-03-26'::DATE + 7;  -- DATE + INTEGER → DATE

NULL Handling#

-- NULL comparisons
SELECT NULL = NULL;   -- Returns NULL (not TRUE)
SELECT NULL IS NULL;  -- Returns TRUE
SELECT NULL IS NOT NULL;  -- Returns FALSE
 
-- NULL-safe operations
SELECT COALESCE(value, 'default');  -- First non-NULL
SELECT IFNULL(value, 'default');    -- Same as COALESCE with 2 args
SELECT NULLIF(value, '');           -- Return NULL if value = ''
 
-- NULL in aggregates
SELECT AVG(revenue) FROM orders;  -- Ignores NULL rows
SELECT COUNT(*) FROM orders;      -- Counts all rows including NULLs
SELECT COUNT(revenue) FROM orders;  -- Ignores NULL revenue rows

Data Types in DenchClaw#

DenchClaw maps its CRM field types to DuckDB types in the EAV schema:

DenchClaw Field TypeDuckDB Storage Type
textVARCHAR
numberDECIMAL(18, 4)
dateDATE
datetimeTIMESTAMP
emailVARCHAR
phoneVARCHAR
urlVARCHAR
enumVARCHAR (with valid values in field metadata)
tagsVARCHAR[] or stored as JSON
booleanBOOLEAN
richtextTEXT (Markdown)
relationVARCHAR (foreign key UUID)

The entry_fields table stores all values as VARCHAR for schema flexibility. The PIVOT views cast them to the appropriate type when building the v_* views.

Frequently Asked Questions#

Should I use VARCHAR or TEXT for long strings?#

They're identical in DuckDB. Use VARCHAR for clarity.

What's the best type for storing money?#

DECIMAL(10, 2) for most currencies (handles up to $99,999,999.99). Never use FLOAT or DOUBLE for money.

Does DuckDB have a UUID type?#

Yes, UUID stores 16-byte UUIDs efficiently. Use gen_random_uuid() to generate them.

How do I store timezone-aware timestamps?#

Use TIMESTAMPTZ. Values are stored as UTC internally and displayed in the session timezone.

What's the maximum VARCHAR length?#

DuckDB doesn't enforce a maximum length on VARCHAR. The practical limit is memory.

Ready to try DenchClaw? Install in one command: npx denchclaw. Full setup guide →

Mark Rachapoom

Written by

Mark Rachapoom

Building the future of AI CRM software.

Continue reading

DENCH

© 2026 DenchHQ · San Francisco, CA