A writable CTE is a Common Table Expression that allows you to perform INSERT, UPDATE, or DELETE operations inside the CTE and then use the affected rows in the main query.
Click to reveal answer
beginner
How do you use an UPDATE inside a writable CTE?
You write a CTE with the UPDATE statement, then select from it to see the updated rows or use them in further queries.
Click to reveal answer
intermediate
Can you perform multiple writable CTEs in a single query?
Yes, you can chain multiple writable CTEs (INSERT, UPDATE, DELETE) in one query, and each can use the results of the previous ones.
Click to reveal answer
intermediate
What is the benefit of using writable CTEs instead of separate statements?
Writable CTEs let you combine data modification and retrieval in one query, making your code cleaner and sometimes more efficient.
Click to reveal answer
beginner
Give an example of a DELETE operation inside a writable CTE.
WITH deleted_rows AS (DELETE FROM table_name WHERE condition RETURNING *) SELECT * FROM deleted_rows;
Click to reveal answer
What does a writable CTE allow you to do in PostgreSQL?
ACreate temporary tables
BOnly SELECT data inside a CTE
CPerform INSERT, UPDATE, or DELETE inside a CTE
DRun stored procedures
✗ Incorrect
Writable CTEs allow data modification operations like INSERT, UPDATE, and DELETE inside the CTE.
Which keyword is used to get the affected rows from a writable CTE operation?
AINTO
BRETURNING
CFETCH
DOUTPUT
✗ Incorrect
The RETURNING clause returns the rows affected by INSERT, UPDATE, or DELETE.
Can you chain multiple writable CTEs in one query?
AYes, you can chain multiple writable CTEs
BNo, only one writable CTE per query
COnly if they are INSERTs
DOnly if they are SELECTs
✗ Incorrect
PostgreSQL supports chaining multiple writable CTEs in a single query.
What is the main advantage of using writable CTEs?
AMake queries run faster always
BAutomatically backup data
CAvoid using indexes
DCombine data modification and retrieval in one query
✗ Incorrect
Writable CTEs let you modify data and use the results immediately in the same query.
Which statement is NOT valid inside a writable CTE?
ACREATE TABLE
BINSERT
CUPDATE
DSELECT
✗ Incorrect
Writable CTEs support INSERT, UPDATE, DELETE, but not DDL statements like CREATE TABLE.
Explain how writable CTEs work in PostgreSQL and give an example of an UPDATE operation using a writable CTE.
Think about how you can update rows and then select them in one query.
You got /4 concepts.
Describe the benefits of using writable CTEs compared to running separate INSERT, UPDATE, or DELETE statements.
Consider how writable CTEs help organize queries.
You got /4 concepts.
Practice
(1/5)
1. What is the main purpose of using writable CTEs in PostgreSQL?
easy
A. To speed up SELECT queries by caching results
B. To create temporary tables that last beyond the current transaction
C. To perform INSERT, UPDATE, or DELETE operations inside a WITH clause
D. To define functions that return multiple rows
Solution
Step 1: Understand writable CTEs
Writable CTEs allow data modification commands like INSERT, UPDATE, or DELETE inside a WITH clause.
Step 2: Compare options
Options B, C, and D describe other features unrelated to writable CTEs.
Final Answer:
To perform INSERT, UPDATE, or DELETE operations inside a WITH clause -> Option C
Quick Check:
Writable CTEs = Data modification in WITH [OK]
Hint: Writable CTEs = data changes inside WITH clause [OK]
Common Mistakes:
Confusing writable CTEs with temporary tables
Thinking writable CTEs speed up SELECT queries
Mixing writable CTEs with function definitions
2. Which of the following is the correct syntax to update rows using a writable CTE in PostgreSQL?
easy
A. UPDATE employees WITH (salary = salary * 1.1) RETURNING *;
B. WITH updated AS (UPDATE employees SET salary = salary * 1.1) RETURNING *;
C. WITH updated AS (SELECT * FROM employees WHERE salary > 5000) UPDATE updated SET salary = salary * 1.1;
D. WITH updated AS (UPDATE employees SET salary = salary * 1.1 RETURNING *) SELECT * FROM updated;
Solution
Step 1: Review writable CTE update syntax
The correct syntax uses WITH updated AS (UPDATE ... RETURNING *) followed by a SELECT from updated.
Step 2: Analyze options
WITH updated AS (UPDATE employees SET salary = salary * 1.1 RETURNING *) SELECT * FROM updated; matches the correct syntax. Options A, C, and D have syntax errors or misuse RETURNING.
Final Answer:
WITH updated AS (UPDATE employees SET salary = salary * 1.1 RETURNING *) SELECT * FROM updated; -> Option D
4. Identify why this writable CTE query returns an empty result set even if matching rows exist:
WITH deleted AS (DELETE FROM orders WHERE status = 'cancelled') SELECT * FROM deleted;
medium
A. The WHERE clause syntax is incorrect
B. Missing RETURNING clause in DELETE statement
C. SELECT * FROM deleted should be SELECT COUNT(*)
D. DELETE cannot be used inside WITH clause
Solution
Step 1: Check DELETE in writable CTE
DELETE inside WITH must include RETURNING to produce rows for the outer SELECT.
Step 2: Analyze the query
The query lacks RETURNING, so 'deleted' has no rows to select from, resulting in an empty result set.
Final Answer:
Missing RETURNING clause in DELETE statement -> Option B
Quick Check:
Writable CTE DELETE needs RETURNING [OK]
Hint: Always add RETURNING with DELETE in writable CTEs [OK]
Common Mistakes:
Omitting RETURNING after DELETE in CTE
Thinking DELETE can't be in WITH clause
Misunderstanding SELECT after writable CTE
5. You want to insert new users and immediately update their status to 'active' using writable CTEs. Which query correctly does this in one statement?
hard
A. WITH ins AS (INSERT INTO users(name) VALUES ('Alice'), ('Bob') RETURNING id, name) UPDATE users SET status = 'active' FROM ins WHERE users.id = ins.id RETURNING users.*;
B. INSERT INTO users(name) VALUES ('Alice'), ('Bob'); WITH upd AS (UPDATE users SET status = 'active' WHERE name IN ('Alice', 'Bob') RETURNING *) SELECT * FROM upd;
C. WITH ins AS (INSERT INTO users(name) VALUES ('Alice'), ('Bob')) UPDATE users SET status = 'active' WHERE id IN (SELECT id FROM ins);
D. WITH ins AS (INSERT INTO users(name) VALUES ('Alice'), ('Bob')) UPDATE ins SET status = 'active' WHERE name IN ('Alice', 'Bob');
Solution
Step 1: Insert and capture new rows
Use a writable CTE to insert and RETURNING id, name to identify new users.
Step 2: Update using CTE results
Update users joining with inserted rows on id, setting status to 'active', and RETURNING updated rows.
Step 3: Analyze options
WITH ins AS (INSERT INTO users(name) VALUES ('Alice'), ('Bob') RETURNING id, name) UPDATE users SET status = 'active' FROM ins WHERE users.id = ins.id RETURNING users.*; correctly chains insert and update in one statement with proper RETURNING and join. INSERT INTO users(name) VALUES ('Alice'), ('Bob'); WITH upd AS (UPDATE users SET status = 'active' WHERE name IN ('Alice', 'Bob') RETURNING *) SELECT * FROM upd; separates insert and update into multiple statements. WITH ins AS (INSERT INTO users(name) VALUES ('Alice'), ('Bob')) UPDATE users SET status = 'active' WHERE id IN (SELECT id FROM ins); lacks RETURNING so CTE returns no rows and subquery updates nothing. WITH ins AS (INSERT INTO users(name) VALUES ('Alice'), ('Bob')) UPDATE ins SET status = 'active' WHERE name IN ('Alice', 'Bob'); incorrectly attempts to UPDATE the CTE which is invalid.
Final Answer:
WITH ins AS (INSERT INTO users(name) VALUES ('Alice'), ('Bob') RETURNING id, name) UPDATE users SET status = 'active' FROM ins WHERE users.id = ins.id RETURNING users.*; -> Option A
Quick Check:
Writable CTE insert + update with join = WITH ins AS (INSERT INTO users(name) VALUES ('Alice'), ('Bob') RETURNING id, name) UPDATE users SET status = 'active' FROM ins WHERE users.id = ins.id RETURNING users.*; [OK]
Hint: Chain INSERT and UPDATE with RETURNING and FROM join [OK]
Common Mistakes:
Omitting RETURNING clause before using CTE in subquery
Splitting insert and update into separate statements
Omitting RETURNING to get updated rows
Recommended
Ready to prove it?
Pass the test and this pattern moves unknownstrongwhile earning +1 Grip toward your certificate.