SQL Quick Reference
This page is a small companion page for SQL practice. It does not replace the course materials, but it is useful when you want to quickly recall the shape of a statement.
Read the Shape First
Before focusing on syntax, ask three small questions:
- What table or tables does the query start from?
- What does one result row represent?
- Which clauses are shaping the result?
That habit becomes especially useful once joins and grouped queries appear.
Basic Read Query
SELECT column1, column2FROM table_nameWHERE conditionORDER BY column1 ASCLIMIT 10;Common notes:
WHEREfilters rows.ORDER BYsorts rows.LIMITkeeps only the first part of the result.- Use
SELECT *mainly for exploration, not as the default teaching or maintenance style.
A More Concrete Read Query
SELECT name, emailFROM usersWHERE name ILIKE '%Ada%'ORDER BY nameLIMIT 5;A useful way to read this is:
- start from
users, - keep only rows whose
namematches the condition, - sort the remaining rows,
- and then keep at most five rows.
Checking for NULL
SELECT id, exercise_id, user_idFROM submissionsWHERE score IS NULL;Use IS NULL or IS NOT NULL, not = NULL.
Insert
INSERT INTO courses (code, title)VALUES ('DB101', 'Introduction to Databases');You can also insert several rows at once:
INSERT INTO courses (code, title)VALUES ('DB101', 'Introduction to Databases'), ('DB102', 'Database Design');Update
UPDATE coursesSET title = 'Databases and Data Management'WHERE code = 'DB101';Delete
DELETE FROM coursesWHERE code = 'DB101';In a real schema, a delete like this may be rejected if other tables still reference the row through foreign keys.
Inner Join
SELECT e.title, c.code AS course_code, ci.term, ci.yearFROM exercises AS eJOIN course_instances AS ci ON ci.id = e.course_instance_idJOIN courses AS c ON c.id = ci.course_id;Read joins as relationship paths. Ask which table you start from, what one result row represents, and which foreign-key path the query follows.
Left Join
SELECT c.code, ci.term, ci.year, e.titleFROM course_instances AS ciINNER JOIN courses AS c ON c.id = ci.course_idLEFT JOIN exercises AS e ON e.course_instance_id = ci.idORDER BY c.code, ci.year, ci.term;Use a LEFT JOIN when rows from the left side should stay visible even if no matching row exists on the right side.
NOT EXISTS
SELECT u.nameFROM users AS uWHERE NOT EXISTS ( SELECT 1 FROM submissions AS s WHERE s.user_id = u.id);This pattern is useful when the question is about missing related rows, such as users with no submissions.
Grouping and Aggregation
SELECT exercise_id, COUNT(*) AS submission_countFROM submissionsGROUP BY exercise_idHAVING COUNT(*) >= 5;Common notes:
WHEREfilters rows before grouping.HAVINGfilters grouped results after grouping.- Always ask what one grouped row represents.
Set Operations
SELECT user_idFROM submissionsWHERE score >= 50
UNION
SELECT user_idFROM enrollments;With UNION, the result sets must have compatible columns. The result combines the rows and removes duplicates.
Create Table
CREATE TABLE courses ( id SERIAL PRIMARY KEY, code TEXT NOT NULL UNIQUE, title TEXT NOT NULL);Add a Foreign Key
CREATE TABLE exercises ( id SERIAL PRIMARY KEY, course_instance_id INTEGER NOT NULL REFERENCES course_instances(id), title TEXT NOT NULL);This is a common pattern in the course: one table stores a foreign key that points to another table.
Clause Order at a Glance
The common written order of a query is:
SELECT ...FROM ...WHERE ...GROUP BY ...HAVING ...ORDER BY ...LIMIT ...This is worth remembering because many common mistakes come from mixing up:
- row filtering with
WHERE, - group filtering with
HAVING, - and result ordering with
ORDER BY.
Parameterized Query in Application Code
In the application parts of the course, values should be passed separately from the SQL structure. With Psycopg t-strings, a safe pattern looks like this:
conn.execute(t""" INSERT INTO tags (name) VALUES ({name})""")The important idea is that user input should not be pasted directly into the SQL text.
Safe SQL Habits
- Start from the question, not from random syntax.
- Read the table or schema before writing the query.
- For
UPDATEandDELETE, run a matchingSELECTfirst. - After write queries, verify the new database state.
- Prefer parameterized queries in application code.
- Keep one eye on meaning: what does one result row represent?