How to Write a FOR Loop in BigQuery

Last updated August 23, 2026 · By the SaturnSQL team

BigQuery scripting supports FOR record IN (SELECT ...) DO ... END FOR. It only runs inside a multi-statement script, and set-based SQL is usually faster.

The loop variable is a struct holding one row of the query, and its fields are reached with dot notation. Every statement in the body is a separate query with its own overhead, so a loop over a thousand rows means a thousand queries.

FOR rec IN (SELECT table_name FROM analytics.INFORMATION_SCHEMA.TABLES)
DO
  SELECT rec.table_name;
END FOR;

Running dynamic SQL per row

The reason to loop at all is usually to build and run statements that cannot be expressed as one query, such as touching a list of tables. EXECUTE IMMEDIATE runs the assembled string.

FOR rec IN (
  SELECT table_name
  FROM analytics.INFORMATION_SCHEMA.TABLES
  WHERE table_name LIKE 'staging_%'
)
DO
  EXECUTE IMMEDIATE FORMAT('DROP TABLE analytics.%s', rec.table_name);
END FOR;

WHILE, BREAK and CONTINUE

WHILE covers the cases where the exit condition is not a row set. BREAK leaves the loop and CONTINUE skips to the next iteration; LEAVE and ITERATE are accepted as synonyms.

DECLARE i INT64 DEFAULT 0;
WHILE i < 10 DO
  SET i = i + 1;
  IF MOD(i, 2) = 0 THEN CONTINUE; END IF;
  SELECT i;
END WHILE;

Prefer set-based SQL

Most loops people write are a row-by-row version of something the engine can do in one pass. A loop that inserts one row at a time should be a single INSERT with a SELECT; a loop that updates rows conditionally should be a MERGE. Reach for scripting when the work is genuinely procedural, such as iterating over table names or draining a queue in batches.

Run this in SaturnSQL

SaturnSQL is a browser-based SQL editor for teams: shared query library, schema-aware autocomplete, and scheduled exports to Google Sheets and Slack.

Try it free

Do more with BigQuery

Related BigQuery guides