DO blocks for anonymous code in PostgreSQL - Time & Space Complexity
Start learning this pattern below
Jump into concepts and practice - no test required
We want to understand how the time it takes to run a DO block changes as the amount of work inside it grows.
How does the number of operations inside the block affect the total time?
Analyze the time complexity of the following DO block in PostgreSQL.
DO $$
DECLARE
i INTEGER := 1;
BEGIN
WHILE i <= 1000 LOOP
PERFORM pg_sleep(0); -- simulate work
i := i + 1;
END LOOP;
END $$;
This block runs a loop 1000 times, doing a small action each time.
Look for repeated actions inside the block.
- Primary operation: The WHILE loop running the PERFORM statement.
- How many times: The loop runs once for each number from 1 to 1000, so 1000 times.
As the number of loop iterations increases, the total work grows in a straight line.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | 10 |
| 100 | 100 |
| 1000 | 1000 |
Pattern observation: Doubling the number of iterations roughly doubles the total work.
Time Complexity: O(n)
This means the time grows directly in proportion to the number of loop iterations.
[X] Wrong: "The DO block runs instantly no matter how many times the loop runs."
[OK] Correct: Each loop iteration takes some time, so more iterations mean more total time.
Understanding how loops inside anonymous code blocks affect performance helps you write efficient database scripts and answer questions about code speed.
"What if we replaced the WHILE loop with a nested loop inside the DO block? How would the time complexity change?"
Practice
DO block in PostgreSQL?Solution
Step 1: Understand the role of DO blocks
DO blocks allow running procedural code immediately without saving it as a function.Step 2: Compare with other options
Creating tables or functions is done with other commands, and DO blocks do not return query results.Final Answer:
To run anonymous procedural code immediately without creating a permanent function -> Option DQuick Check:
DO blocks = anonymous immediate code execution [OK]
- Thinking DO blocks create permanent functions
- Confusing DO blocks with SELECT queries
- Assuming DO blocks create tables
Solution
Step 1: Recall the correct DO block syntax
The DO block uses dollar quoting $$ to enclose the code, with LANGUAGE plpgsql specified after the block.Step 2: Check each option
DO $$ BEGIN END $$ LANGUAGE plpgsql; correctly places $$ around BEGIN...END and specifies LANGUAGE plpgsql after the block.Final Answer:
DO $$ BEGIN END $$ LANGUAGE plpgsql; -> Option AQuick Check:
DO block syntax = DO $$ code $$ LANGUAGE plpgsql; [OK]
- Placing LANGUAGE plpgsql before BEGIN
- Not using dollar quoting $$
- Misordering keywords in the DO block
DO $$ BEGIN RAISE NOTICE 'Hello, PostgreSQL!'; END $$ LANGUAGE plpgsql;
Solution
Step 1: Understand RAISE NOTICE in DO blocks
RAISE NOTICE outputs a message to the client as an informational notice, not a query result.Step 2: Analyze the DO block behavior
The block runs immediately and prints the notice message but does not return rows or create functions.Final Answer:
It prints 'Hello, PostgreSQL!' as a notice message -> Option AQuick Check:
RAISE NOTICE outputs messages, not query results [OK]
- Expecting query result rows
- Thinking it creates a function
- Confusing notice with error
DO $$ BEGIN PERFORM 1/0; END $$ LANGUAGE plpgsql;
Solution
Step 1: Analyze the code inside DO block
The statement PERFORM 1/0 attempts to divide 1 by zero, which is not allowed.Step 2: Identify the error type
This causes a runtime error (division by zero), not a syntax error or missing keyword.Final Answer:
Division by zero runtime error -> Option BQuick Check:
1/0 causes runtime error, not syntax [OK]
- Confusing runtime error with syntax error
- Ignoring division by zero possibility
- Assuming PERFORM is invalid here
users to set active = false for all users who haven't logged in for over a year. Which DO block correctly performs this task?Solution
Step 1: Check the DO block structure and logic
DO $$ BEGIN UPDATE users SET active = false WHERE last_login < NOW() - INTERVAL '1 year'; END $$ LANGUAGE plpgsql; correctly uses BEGIN...END with an UPDATE statement and the right condition for last_login older than 1 year.Step 2: Verify other options
DO $$ BEGIN SELECT * FROM users WHERE last_login < NOW() - INTERVAL '1 year'; END $$ LANGUAGE plpgsql; only selects rows, no update. DO $$ UPDATE users SET active = false WHERE last_login < NOW() - INTERVAL '1 year'; END $$ LANGUAGE plpgsql; misses BEGIN...END block. DO $$ BEGIN UPDATE users SET active = false WHERE last_login > NOW() - INTERVAL '1 year'; END $$ LANGUAGE plpgsql; uses wrong condition (greater than instead of less than).Final Answer:
DO $$ BEGIN UPDATE users SET active = false WHERE last_login < NOW() - INTERVAL '1 year'; END $$ LANGUAGE plpgsql; -> Option CQuick Check:
Correct DO block with UPDATE and condition [OK]
- Omitting BEGIN...END block
- Using wrong comparison operator in WHERE
- Using SELECT instead of UPDATE
