Skip to main content
An expression is any combination of values, operators, column references, and function calls that Turso evaluates to produce a single value. Expressions appear in SELECT column lists, WHERE conditions, ORDER BY, GROUP BY, HAVING, CHECK constraints, DEFAULT values, and more.

Literals

Integer and real literals

SELECT 42;          -- integer literal
SELECT -17;         -- negative integer
SELECT 3.14;        -- real (floating-point) literal
SELECT 2.5e10;      -- scientific notation → 25000000000.0
SELECT 0xFF;        -- hexadecimal integer → 255

String literals

String literals use single quotes. To embed a single quote, double it:
SELECT 'hello world';      -- text literal
SELECT 'it''s a test';     -- embedded single quote
SELECT '';                 -- empty string
Double-quoted identifiers ("column_name") are not string literals. Use single quotes for string values.

Blob literals

Blob literals are hexadecimal strings prefixed with x or X:
SELECT x'CAFEBABE';         -- blob literal (4 bytes)
SELECT X'48454C4C4F';       -- blob literal: 'HELLO' as raw bytes

NULL literal

SELECT NULL;   -- the null value

Column references

Refer to a column by name, or qualify it with a table name to avoid ambiguity in joins:
SELECT name FROM users;               -- unqualified column
SELECT users.name FROM users;         -- table-qualified column
SELECT u.name FROM users AS u;        -- alias-qualified column

-- Qualification is required when two joined tables share a column name
SELECT orders.id, users.name
FROM orders
JOIN users ON orders.user_id = users.id;
Schema-qualified references (schema.table.column) are not supported in Turso.

Operators

Arithmetic operators

OperatorDescriptionExampleResult
+Addition3 + 47
-Subtraction10 - 37
*Multiplication3 * 412
/Division10 / 33
- (unary)Negation-5-5
Division between two integers performs integer (truncating) division. Use a real operand or CAST for floating-point division:
SELECT 10 / 3;                    -- 3  (integer division)
SELECT 10 / 3.0;                  -- 3.3333333333333335
SELECT CAST(10 AS REAL) / 3;      -- 3.3333333333333335

Comparison operators

OperatorDescription
= or ==Equal
!= or <>Not equal
<Less than
>Greater than
<=Less than or equal
>=Greater than or equal
All comparison operators return 1 (true), 0 (false), or NULL if either operand is NULL.
SELECT 1 = 1;     -- 1
SELECT 1 != 2;    -- 1
SELECT NULL = 1;  -- NULL  (not 0!)

IS and IS NOT

IS and IS NOT work like = and != but treat NULL as an ordinary comparable value:
SELECT NULL IS NULL;      -- 1
SELECT NULL IS NOT NULL;  -- 0
SELECT 1 IS 1;            -- 1
SELECT 1 IS NOT 2;        -- 1
IS DISTINCT FROM and IS NOT DISTINCT FROM are SQL-standard aliases for the same behaviour:
SELECT NULL IS DISTINCT FROM NULL;  -- 0  (both NULL → not distinct)
SELECT NULL IS DISTINCT FROM 1;     -- 1  (NULL vs non-NULL → distinct)
SELECT 1 IS NOT DISTINCT FROM 1;    -- 1

Logical operators

OperatorDescription
ANDTrue if both operands are true
ORTrue if at least one operand is true
NOTInverts a boolean value
Logical operators follow three-valued logic: NULL AND 1 is NULL, NULL OR 1 is 1.
SELECT 1 AND 1;      -- 1
SELECT 1 AND 0;      -- 0
SELECT NULL AND 1;   -- NULL
SELECT NULL OR 1;    -- 1
SELECT NOT 0;        -- 1

String concatenation

SELECT 'hello' || ' ' || 'world';   -- 'hello world'
SELECT 'Count: ' || 42;             -- 'Count: 42'

Bitwise operators

OperatorDescriptionExampleResult
&Bitwise AND5 & 31
|Bitwise OR5 | 37
~Bitwise NOT~5-6
<<Left shift1 << 416
>>Right shift16 >> 24
SELECT 5 & 3;    -- 1  (0101 & 0011 = 0001)
SELECT 5 | 3;    -- 7  (0101 | 0011 = 0111)
SELECT 1 << 3;   -- 8

Operator precedence

Operators are evaluated in this order (highest precedence first):
PrecedenceOperators
1 (highest)~ (unary), + (unary), - (unary)
2|| (concatenation)
3*, /
4+, -
5<<, >>, &, |
6<, <=, >, >=
7=, ==, !=, <>, IS, IS NOT, IS DISTINCT FROM, IN, LIKE, GLOB, REGEXP, BETWEEN
8NOT
9AND
10 (lowest)OR
Use parentheses to override precedence:
SELECT 2 + 3 * 4;    -- 14  (multiplication first)
SELECT (2 + 3) * 4;  -- 20  (parentheses override)

CAST expression

CAST converts a value to a specified type.
CAST(expression AS type-name)
SELECT CAST(3.7 AS INTEGER);     -- 3  (truncates toward zero)
SELECT CAST(42 AS TEXT);          -- '42'
SELECT CAST('123' AS INTEGER);    -- 123
SELECT CAST('abc' AS INTEGER);    -- 0  (non-numeric text)
SELECT CAST(NULL AS INTEGER);     -- NULL
The target type name follows the same affinity rules as column declarations — CAST(x AS VARCHAR(10)) applies TEXT affinity, and CAST(x AS NUMERIC) applies NUMERIC affinity.

CASE expression

The CASE expression provides conditional logic inside SQL.

Simple CASE

Compares a single expression against a list of values:
CASE expression
    WHEN value1 THEN result1
    WHEN value2 THEN result2
    ...
    [ELSE default_result]
END
SELECT name,
    CASE status
        WHEN 'A' THEN 'Active'
        WHEN 'I' THEN 'Inactive'
        ELSE 'Unknown'
    END AS status_label
FROM users;

Searched CASE

Evaluates arbitrary boolean conditions:
CASE
    WHEN condition1 THEN result1
    WHEN condition2 THEN result2
    ...
    [ELSE default_result]
END
SELECT name, score,
    CASE
        WHEN score >= 90 THEN 'A'
        WHEN score >= 80 THEN 'B'
        WHEN score >= 70 THEN 'C'
        ELSE 'F'
    END AS grade
FROM students;
If no WHEN clause matches and there is no ELSE clause, the CASE expression returns NULL.

Pattern matching

LIKE

LIKE performs case-insensitive pattern matching for ASCII characters. % matches any sequence of zero or more characters; _ matches any single character.
expression [NOT] LIKE pattern [ESCAPE escape-char]
SELECT 'Hello World' LIKE 'hello%';          -- 1  (case-insensitive)
SELECT 'Hello World' LIKE 'H_llo%';          -- 1  (_ matches 'e')
SELECT 'Hello World' LIKE '%World';           -- 1
SELECT '10% off' LIKE '10\% off' ESCAPE '\'; -- 1  (literal %)

SELECT name FROM products WHERE name LIKE '%widget%';

GLOB

GLOB performs case-sensitive Unix-style pattern matching. * matches any sequence; ? matches a single character; [...] matches a character class.
expression [NOT] GLOB pattern
SELECT 'Hello' GLOB 'H*';       -- 1
SELECT 'Hello' GLOB 'h*';       -- 0  (case-sensitive)
SELECT 'Hello' GLOB 'H?llo';    -- 1
SELECT 'Hello' GLOB 'H[a-z]*';  -- 1  (character class)

REGEXP

REGEXP performs regular expression matching. The regexp extension is loaded by default in Turso.
expression [NOT] REGEXP pattern
SELECT 'Hello123' REGEXP '[A-Za-z]+[0-9]+';           -- 1
SELECT '[email protected]' REGEXP '^[^@]+@[^@]+\.[^@]+$'; -- 1
SELECT 'abc' NOT REGEXP '[0-9]+';                       -- 1

BETWEEN expression

BETWEEN tests whether a value falls within an inclusive range. It is equivalent to expression >= low AND expression <= high.
expression [NOT] BETWEEN low AND high
SELECT 5 BETWEEN 1 AND 10;       -- 1
SELECT 5 NOT BETWEEN 1 AND 3;    -- 1
SELECT 'b' BETWEEN 'a' AND 'c';  -- 1

SELECT * FROM orders WHERE amount BETWEEN 100 AND 500;

IN expression

IN tests whether a value matches any value in a list or subquery result.
expression [NOT] IN (value1, value2, ...)
expression [NOT] IN (select-statement)
SELECT 3 IN (1, 2, 3, 4, 5);             -- 1
SELECT 'red' NOT IN ('blue', 'green');    -- 1

-- IN with a subquery
SELECT name FROM users
WHERE id IN (
    SELECT user_id FROM orders WHERE total > 100
);

EXISTS / NOT EXISTS

EXISTS returns 1 if the subquery produces at least one row, and 0 otherwise. It is commonly used as a correlated subquery in WHERE clauses.
[NOT] EXISTS (select-statement)
-- Does any user named Alice exist?
SELECT EXISTS (SELECT 1 FROM users WHERE name = 'Alice');  -- 1 or 0

-- Departments that have at least one employee
SELECT name FROM departments d
WHERE EXISTS (
    SELECT 1 FROM employees e
    WHERE e.department_id = d.id
);

-- Departments with no employees
SELECT name FROM departments d
WHERE NOT EXISTS (
    SELECT 1 FROM employees e
    WHERE e.department_id = d.id
);

Scalar subqueries

A subquery enclosed in parentheses that returns exactly one column and at most one row can be used as a scalar expression. If the subquery returns no rows, it evaluates to NULL.
SELECT name,
    (SELECT COUNT(*) FROM orders WHERE orders.user_id = users.id) AS order_count
FROM users;

SELECT * FROM products
WHERE price > (SELECT AVG(price) FROM products);
Turso supports scalar subqueries. Multi-column subquery comparisons such as (x, y) = (SELECT ...) are not supported.

NULL handling

Any arithmetic or comparison with NULL returns NULL. Use dedicated operators and functions to handle NULL explicitly.

IS NULL / IS NOT NULL

expression IS NULL
expression IS NOT NULL
SELECT NULL IS NULL;      -- 1
SELECT NULL = NULL;       -- NULL  (not 1!)
SELECT 42 IS NOT NULL;    -- 1
SELECT NULL IS NOT NULL;  -- 0

COALESCE

COALESCE(x, y, ...) returns the first non-NULL argument:
SELECT COALESCE(NULL, NULL, 'fallback');  -- 'fallback'
SELECT COALESCE(NULL, 42);               -- 42
SELECT COALESCE(1, 2, 3);               -- 1

-- Provide a default when a column may be NULL
SELECT name, COALESCE(phone, 'no phone') AS phone FROM users;

IFNULL

IFNULL(x, y) is equivalent to COALESCE(x, y) — returns x if it is not NULL, otherwise returns y:
SELECT IFNULL(NULL, 'default');  -- 'default'
SELECT IFNULL(42, 0);            -- 42

NULLIF

NULLIF(x, y) returns NULL if x = y, otherwise returns x. Useful for avoiding division by zero:
SELECT NULLIF(5, 5);   -- NULL
SELECT NULLIF(5, 3);   -- 5

-- Avoid division by zero
SELECT total / NULLIF(count, 0) AS average FROM stats;

Function calls

Functions are called with a comma-separated argument list. Most scalar functions, aggregate functions, and table-valued functions follow the same call syntax:
function-name(argument1, argument2, ...)
SELECT length('hello');          -- 5
SELECT upper('hello');           -- 'HELLO'
SELECT round(3.14159, 2);        -- 3.14
SELECT abs(-42);                 -- 42
SELECT coalesce(NULL, 0);        -- 0

-- Aggregate functions in SELECT
SELECT COUNT(*), SUM(amount), AVG(amount) FROM orders;

-- Window function with OVER clause
SELECT name, salary,
    AVG(salary) OVER (PARTITION BY department) AS dept_avg
FROM employees;
See Scalar Functions, Aggregate Functions, and Window Functions for the complete function references.

See also

  • Data Types — storage classes, type affinity, and CAST behaviour
  • Scalar Functions — built-in string, numeric, and utility functions
  • SELECT — using expressions in queries, joins, and aggregations

Build docs developers (and LLMs) love