BigQuery SQL style and best practices: a short, tested standard
A short standard for BigQuery SQL that a team can adopt in one meeting: names, layout, reserved keywords and backticks, the three comment styles, raw and triple-quoted strings, SAFE functions, and the cost rules that matter most. Every syntax point was checked in BigQuery, including what fails, such as EXPLAIN.
A code standard is worth having when two people read each other’s queries. It does not need to be long. This page is a standard that fits on one screen, with each syntax rule checked in BigQuery, so it can be adopted as is or used as a starting point.
| Area | Rule |
|---|---|
| Names | snake_case, singular tables, plural only for arrays |
| Layout | one clause per line, one column per line, keywords in capitals |
| Reserved words | avoid them as names; when unavoidable, backtick them |
| Comments | -- for notes, /* */ for blocks |
| Strings | raw strings for regex, triple quotes for multi-line text |
| Errors | SAFE. and SAFE_ functions only where a NULL is acceptable |
| Cost | name columns, filter partitions, check the estimate |
| Logic | one definition per metric, shared, not copied |
Note: Rewritten in October 2026. Every query and error message below was produced in BigQuery on 16 October 2026.
Names
snake_casefor everything: datasets, tables, columns, CTEs. BigQuery column names are not case-sensitive, soOrderDateandorderdatecollide.- Datasets by stage and domain:
raw_google_ads,staging_crm,reporting_marketing. The prefix says how far the data has been processed; the rest says what it is. - Tables singular, by grain:
order,session,daily_channel_spend. The name answers “one row is one what”. - Columns say their unit:
amount_usd,cost_micros,duration_seconds,is_paidfor booleans,_atfor TIMESTAMP and_datefor DATE. - IDs end in
_idand keep the same name in every table, so a join readsUSING (customer_id).
Reserved words and backticks
SELECT 1 AS order;
fails with “Syntax error: Unexpected keyword ORDER”. ORDER, SELECT, GROUP, FROM and other reserved keywords cannot be used as plain names. With backticks they can: SELECT 1 AS `order` runs.
Not every SQL keyword is reserved in BigQuery. SELECT 2 AS date, 3 AS record ran without backticks. The safe rule is still to avoid them: a column called date reads ambiguously next to the DATE type and function. Use order_date, event_date.
Project IDs with a hyphen are a special case. In FROM, BigQuery accepts them unquoted: FROM my-project.dataset.table passed a dry run in our test. Outside FROM the same path fails with a syntax error, and other names with a hyphen need quoting anyway. Backtick the whole path, `my-project.dataset.table`, and the question never comes up.
OWOX Data Marts
See your first report built in real time. 15 minutes.
- Connect your data warehouse
- Pick your metrics
- Get a live Google Sheets report
In the time it takes to write a ticket. Then imagine never writing that ticket again.
Book a DemoWe'll use your actual use case
Layout
SELECT
customer_id,
COUNT(*) AS orders,
SUM(amount_usd) AS revenue_usd
FROM reporting_marketing.order
WHERE order_date >= '2026-09-01'
AND status = 'paid'
GROUP BY customer_id
ORDER BY revenue_usd DESC;
One clause per line, one column per line, trailing commas avoided, conditions aligned under WHERE. The point is diffs: when a column is added, one line changes. Name every aggregate with AS; an unnamed one becomes f0_, which nobody downstream can read. Use CTEs for steps instead of nested subqueries; see the CTE guide.
Comments
All three styles work in BigQuery:
SELECT 1 AS n -- a note at the end of a line
# also a single-line comment
/* a block
comment */
Use -- for single lines; # works but is unusual outside BigQuery and confuses readers coming from other SQL. Comment the why, not the what: -- refunds are excluded because finance books them separately is useful; -- filter status is noise.
Strings
SELECT
"""He said "it's fine"
on two lines""" AS triple,
r'\d+' AS raw_regex;
| triple | raw_regex |
|---|---|
| He said “it’s fine” (new line) on two lines | \d+ |
- Triple quotes hold quotes and line breaks without escaping: useful for JSON, long text and SQL inside SQL.
- Raw strings,
r'...', keep backslashes as typed. Write every regular expression as a raw string, or\dhas to become\\d. The string functions guide has the regex functions.
SAFE functions
| Expression | Result |
|---|---|
SAFE.PARSE_DATE('%Y-%m-%d', '2026-13-01') |
NULL |
SAFE_DIVIDE(1, 0) |
NULL |
The SAFE. prefix turns an error into a NULL for most functions, and SAFE_DIVIDE, SAFE_CAST and others are their own functions. Use them where a NULL is an acceptable answer, and count the NULLs they produce; otherwise a broken input is replaced by silence. Not every function accepts the prefix: SAFE.DATE(string) fails with “SAFE with function … is not supported”. Details are in CAST and SAFE_CAST.
Cost rules
- Name the columns. On-demand queries are billed by the columns read;
SELECT *on a wide table can cost hundreds of times more. - Filter on the partition column with constants, so BigQuery prunes partitions. See partitioned tables.
- Check the estimate the editor shows before running.
LIMITdoes not lower it. - There is no
EXPLAIN.EXPLAIN SELECT 1fails with “Statement not supported: ExplainStatement”. Use the dry-run estimate before, and the job’s Execution details after, to see where time and bytes went.
Prices and the billing model are in BigQuery pricing.
Enforce it with tools
- SQLFluff, with its BigQuery dialect, checks layout and naming in CI.
- Version control for every query a report depends on, so a change has a diff and an author.
- A review rule: no query reaches a shared report without a second reader.
One definition per metric
Style makes a query readable. It does not stop two readable queries from defining “active customer” differently, and that is what makes reports disagree. The last rule of a standard is about ownership: each metric is written once and read everywhere. In OWOX Data Marts that query is a Data Mart with an owner and a description per column, and every sheet and dashboard reads it. OWOX Data Marts runs your SQL as written, in your own BigQuery project, and does not transform the data. More SQL foundations are in the BigQuery SQL guide.
Turn your data into decisions.
Governed data marts give you the clean foundation ML needs to actually work.
- No AI hallucinations
- Analyst-governed definitions
- Every number traces to SQL
Frequently Asked Questions
Which words are reserved in BigQuery?
SQL keywords such as SELECT, FROM, ORDER and GROUP cannot be used as plain names: SELECT 1 AS order fails with 'Unexpected keyword ORDER'. Wrap them in backticks to use them anyway. Some keywords are not reserved, such as DATE and RECORD, but naming a column date is still unclear.
Does BigQuery have EXPLAIN?
No. EXPLAIN SELECT 1 fails with 'Statement not supported: ExplainStatement'. Use the dry-run estimate before running a query and the job's Execution details afterwards to see where time and bytes went.
How do I write comments in BigQuery SQL?
Three styles work: -- and # for a single line, and /* ... */ for a block. Use -- for single lines, since # is unusual outside BigQuery, and comment why a rule exists rather than what the line does.
When should I use SAFE functions in BigQuery?
Where a NULL is an acceptable answer for a bad input: SAFE.PARSE_DATE returns NULL for an invalid date, SAFE_DIVIDE for a division by zero. Count the NULLs they produce. Not every function takes the SAFE. prefix: SAFE.DATE(string) fails.
How should I format BigQuery SQL for readability?
One clause per line, one column per line, keywords in capitals, every aggregate named with AS, and CTEs instead of nested subqueries. A one-line change then shows as a one-line diff.
What tools help keep BigQuery SQL consistent?
SQLFluff with its BigQuery dialect checks layout and naming in CI; version control gives every query a history; and a review rule that every query feeding a shared report has a second reader.
What naming conventions should I use in BigQuery?
snake_case everywhere, datasets named by stage and domain (raw_google_ads, reporting_marketing), tables named for their grain, columns that state their unit (amount_usd, cost_micros), and IDs with the same name in every table.
What are BigQuery code standards?
A team's agreed rules for writing BigQuery SQL: names, layout, comments, string literals, error handling and cost habits, so that anyone can read and review anyone else's query.

