SELECT without FROM
A SELECT without a FROM clause evaluates its projection list against one
synthetic row. Without filtering or pagination, it returns one row:
SELECT 1 + 1;
You probably use this form without thinking about it, for example in:
- Connection health probes.
- Cast checks.
- Utility SQL that an ORM emits on its own.
It is also the shortest way to ask the database a yes-or-no question:
SELECT EXISTS (SELECT 1 FROM accounts WHERE email = @email);
Supported forms
Evaluate a scalar expression:
SELECT 1 + 1;
SELECT upper('abc');
SELECT CAST('5' AS INT64);
SELECT CASE WHEN 1 = 1 THEN 'ok' ELSE 'fail' END;
SELECT regexp_split_to_array('one,two,three', ',');
Bind a parameter:
SELECT @value;
Return several projections:
SELECT 41 + 1 AS answer, 'ok' AS status;
Projections without an alias get ordinal column names, such as 0, 1, and
2.
Literal projections declare their SQL type in result metadata and copied-table
schemas: SELECT 1 AS id has an INT64 output column. You can combine these
queries with set operations:
SELECT 1 AS id UNION ALL SELECT 2 ORDER BY 1;
Here ORDER BY applies to the combined result.
Use LIMIT and OFFSET to keep or skip the single synthetic row:
SELECT 1 LIMIT 0;
SELECT 1 LIMIT 1 OFFSET 1;
Both examples return zero rows.
Filter the synthetic row
A WHERE clause keeps the row when its condition is TRUE; FALSE or NULL returns no rows. Use this for conditional probes or inserts based on an existence check:
SELECT 'ready' WHERE TRUE;
SELECT 'ready' WHERE FALSE; -- no rows
SELECT 'seed' WHERE NOT EXISTS (SELECT 1 FROM accounts);
The condition must be boolean or NULL; SELECT 5 WHERE 1 and
SELECT 5 WHERE 'true' fail with CADB0400. Projection expressions do not run
when the filter drops the row. However, constant division by zero is checked
before execution: SELECT 1 / 0 WHERE FALSE fails with CADB0400. See
statement checks.
With WHERE, the query uses a one-row source, supports EXPLAIN (ANALYZE), and
can be an INSERT ... SELECT or CTAS source or a set-operation operand.
Sequence calls in this form are refused with CADB0547 unless the filter drops
the row before the call runs; SELECT nextval('s') WHERE FALSE draws nothing.
Subqueries in the projection
When a SELECT without a FROM clause has a subquery in its projection,
CamusDB evaluates the subquery first and replaces it with its scalar result.
The EXISTS example at the top of this page works that way, and NOT EXISTS
works too:
SELECT NOT EXISTS (
SELECT 1
FROM accounts
WHERE email = 'nobody@example.com'
);
You can compare a scalar subquery or return it directly:
SELECT (SELECT COUNT(*) FROM accounts) > 0;
SELECT (SELECT COUNT(*) FROM accounts);
The subquery can also read from a derived table:
SELECT (
SELECT COUNT(*)
FROM (
SELECT 1
FROM accounts
WHERE email = @email
) AS matched
) > 0;
A top-level SELECT without a FROM clause has no outer row, so these subqueries are
never correlated. A SELECT with a FROM clause also supports uncorrelated
projection subqueries. When used inside another statement, a FROM-less
subquery can read outer columns too; see subquery positions.
Inside another statement
A SELECT without FROM also works as a scalar or IN subquery, a derived table, or a stored view body:
SELECT (SELECT 1); -- 1
SELECT (SELECT 1 WHERE FALSE); -- NULL
SELECT x FROM (SELECT 5 AS x) d; -- 5
CREATE VIEW readiness AS SELECT 'ready' AS status;
The same WHERE, LIMIT, and OFFSET rules apply. Aggregates and ORDER BY remain
unsupported, and a sequence call in a nested SELECT is refused with CADB0547.
A FROM-less subquery can reference an outer column in supported correlated
positions, for example SELECT u.id FROM app_users u WHERE EXISTS (SELECT 1 WHERE u.active = true).
CREATE VIEW binds a plain expression without evaluating it: a body such as
SELECT 1 / 0 AS x is accepted, and reading the view fails. Subqueries in the
body are also bound without execution; unknown names and known type errors
still fail CREATE VIEW. A materialized view executes its body during its
separate data-population step, unless WITH NO DATA is specified.
Rejected shapes
A SELECT without a FROM clause is limited by design: it evaluates a
projection and accepts optional WHERE, LIMIT, and OFFSET clauses.
| Query shape | Result |
|---|---|
SELECT * | CamusDB rejects it, because * needs a table source. |
SELECT COUNT(*) | CamusDB rejects it, because an aggregate needs a table source. Use a scalar subquery instead, such as SELECT (SELECT COUNT(*) FROM accounts). |
SELECT 1 GROUP BY ... | CamusDB rejects it. An aggregation needs a table source. |
SELECT 1 HAVING ... | CamusDB rejects it. An aggregation needs a table source. |
SELECT 1 ORDER BY ... | CamusDB rejects it. There is only one synthetic row. |
SELECT * WHERE ... or SELECT COUNT(*) WHERE ... | Refused for the same reasons as their unfiltered forms. |
SELECT missing_name | It fails with UnknownColumn, because CamusDB cannot resolve the identifier. |
EXPLAIN
Without WHERE, a plain EXPLAIN of a SELECT without FROM returns a fixed plan shape:
EXPLAIN SELECT 41 + 1 AS answer;
Typical output:
physical project answer
physical constant-source 1 row
The plan includes a limit node when the query has a LIMIT or an OFFSET.
Without WHERE, EXPLAIN (ANALYZE) is refused. With WHERE, the one-row source
appears as function-scan (*single_row*), and ANALYZE executes the filter and
projection.