Query parameters
A comment at the top of the tab declares a typed parameter and its value. The editor types every @name, the run sends real BigQuery query parameters, and the values travel with the SQL in share links, history and git.
-- querylab:param start_date DATE = '2025-09-01' -- querylab:param makes ARRAY<STRING> = ['FORD', 'VOLKSWAGEN'] SELECT make, COUNT(*) AS tests FROM `ace-analytics.warehouse.fact_mot_test` WHERE completed_date >= @start_date AND make IN UNNEST(@makes) GROUP BY make
Declaring a parameter
One line per parameter, anywhere in the tab:
-- querylab:param <name> <type> = <value>
- The type is any BigQuery parameter type, including
ARRAY<…>,STRUCT<…>,RANGE<…>andINTERVAL. Type parameters are the one thing that isn’t allowed: a query parameter is aSTRING, never aSTRING(10). - The value is a GoogleSQL literal, checked against the type as you type.
NULLis a valid value for any type, and[]is a real empty array. - Spacing and case of
querylab:paramdon’t matter, and parameter names match the query case-insensitively, as they do in BigQuery. Declaring the same name twice is an error on the second line.
Typing -- opens completions for querylab:, then the directive name. After @ in the query, completions offer the declared names; after @person., the fields of a STRUCT parameter.
What the editor knows
A declared @name has the declared type everywhere Prism looks at the query: hover shows it, type checks use it, and a comparison against the wrong type is flagged like any other type mismatch.
An @name that no directive declares is an error, and the run is blocked with the same message:
SELECT make FROM `ace-analytics.warehouse.fact_mot_test` WHERE completed_date >= @start_date
The quick fix Declare parameter @start_date inserts the directive at the top of the tab. The type is prefilled when the query gives it away (completed_date >= @start_date makes it a DATE, IN UNNEST(@makes) an array, LIMIT @n an INT64); otherwise it is STRING = ''.
What happens at run time
Every run and every cost estimate sends the declared parameters as typed BigQuery query parameters (parameterMode: NAMED, with arrayType, structTypes and nested values where the type needs them). The directive lines stay in the SQL as comments, which BigQuery ignores.
Running a selection keeps the parameters: the directives the selection references are carried along, so a highlighted fragment runs like the whole tab.
Because the values live in the SQL, nothing is hidden in tab state. A share link, a history entry, a pasted snippet or a committed file carries its parameters with it.
Editing values from the status bar
Click the ⚙ at the left of the status bar. The Parameters section lists each declared parameter with its type, its line, and an editable value. Editing a value rewrites just that part of the directive line, as its own undo step. A value that comes from a Jinja template can’t be edited here; the panel says so and points you at the SQL.
Why not DECLARE?
DECLARE start_date DATE DEFAULT '2025-09-01'; works, but it turns the query into a multi-statement script, and that costs you three things:
- A script’s results never come from BigQuery’s result cache, so repeat runs are billed again.
- The estimate for a script is a lower bound, not the price of the run.
- The SQL can’t be pasted into code that binds parameters;
@start_datecan, unchanged.
A parameter directive keeps the query a single statement and matches what your application sends in production.
Parameters in notebooks
A SQL cell can declare parameters with the same directive lines, and they flow to the cells below it, like notebook variables do. A cell lower in the notebook can redeclare a name to override the value from above. Plain assignments (name = 'x';) keep working and feed @name as a STRING; the editor offers Convert to typed parameter on assignments used that way.