Inlining mockup data

When prototyping or testing, you often want to run a query without connecting to a real database. FeatureQL lets you inline data directly in the query using several approaches, from quick-and-dirty to production-ready patterns.

Binding inline values directly

The simplest approach binds mockup data directly to inputs with BIND_VALUES(). Every input gets its values in the FOR clause:

WITH
    ID := INPUT(BIGINT),
    NAME := INPUT(VARCHAR),
    HELLO_MESSAGE := 'Hello, ' || NAME || '!',
SELECT
    ID,
    HELLO_MESSAGE
FOR
    (ID, NAME) := BIND_VALUES(ARRAY[ROW(1, 'Alice'), ROW(2, 'Bob'), ROW(3, 'Charlie')]);
sql

This works well for small datasets where every column is an input. For larger datasets or when you need key-value separation, BIND_SQL() offers more flexibility with standard SQL VALUES():

WITH
    ID := INPUT(BIGINT),
    NAME := INPUT(VARCHAR),
    HELLO_MESSAGE := 'Hello, ' || NAME || '!',
SELECT
    ID,
    HELLO_MESSAGE
FOR
    (ID, NAME) := BIND_SQL(SELECT id, name FROM (VALUES(1, 'Alice'), (2, 'Bob'), (3, 'Charlie')) as t(id, name));
sql

Separating keys from values with EXTERNAL_SQL

Both approaches above treat every column as an input. In practice, you usually want to bind only the key (e.g., a customer ID) and look up associated values from a data source. EXTERNAL_SQL() with inline VALUES() mimics this pattern without a real database:

WITH
    ID := INPUT(BIGINT),
    NAME := EXTERNAL_SQL(
        `SELECT id, name FROM (VALUES(1, 'Alice'), (2, 'Bob'), (3, 'Charlie')) as t(id, name)`
        ON `SELF.id = %ID`
        AS ROW(ID BIGINT, NAME VARCHAR)
    )[NAME],
    HELLO_MESSAGE := 'Hello, ' || NAME || '!',
SELECT
    ID,
    HELLO_MESSAGE
FOR
    ID := BIND_VALUES(ARRAY[1,2,3]);
sql

This is the recommended pattern for prototyping because it mirrors how production queries work: keys are bound, values are looked up. When you're ready to connect to a real table, you replace the inline VALUES() with an actual table reference.

Backend differences

The SQL syntax for inline data varies by backend. DuckDB and Trino support VALUES(), while BigQuery uses UNNEST() with arrays. See backend particularities for details.

When to use each approach

ApproachBest forTrade-off
BIND_VALUES()Quick tests with 2-3 rowsAll columns must be inputs
BIND_SQL() with VALUES()Slightly larger inline datasetsAll columns are still inputs
EXTERNAL_SQL() with VALUES()Prototyping production-like queriesMore verbose, but mirrors real data source patterns

See data source mapping for the full reference on connecting features to external data.

Last update at: 2026/03/03 16:47:38
Last updated: 2026-03-03 16:48:19