Skip to content

SQL Glossary

Every term you will meet while learning SQL, defined in plain language. Where this site has a full tutorial on a term, the entry links to it — and everything here can be tried immediately in the playground.

A

Aggregate function
A function that folds many rows into one value: COUNT, SUM, AVG, MIN and MAX are the core five. Usually paired with GROUP BY to produce one value per group. Full guide: Aggregate functions →
SELECT COUNT(*) AS employees, AVG(salary) AS avg_salary, MAX(salary) AS top_salary
FROM Employees;
employeesavg_salarytop_salary
12101000156000

● 1 row · produced by running this query on the sample database

Common mistake

Mixing an aggregate with an ordinary column and no GROUP BY. SELECT first_name, MAX(salary) FROM Employees asks for one row and twelve rows at the same time. PostgreSQL, SQL Server, Oracle and MySQL in its default mode reject it; SQLite, which runs this playground, fills first_name from a single row, and the playground flags it with a warning. Either aggregate everything, or add GROUP BY for the plain column.

Alias
A temporary name given with AS - to a column (SELECT salary * 12 AS annual) or a table (FROM Employees e). Aliases exist only for the duration of the query. Full guide: The SELECT guide →
SELECT e.first_name, e.salary * 12 AS annual_salary
FROM Employees e
ORDER BY annual_salary DESC;
first_nameannual_salary
Chen1872000
Ananya1704000
Tomas1572000
Marcus1416000
Priya1260000
Leila1152000
Isabela1104000
Grace1074000
Sofia948000
Hiroshi894000
Daniel816000
Omar732000

● 12 rows · produced by running this query on the sample database

Common mistake

Using a column alias inside WHERE. WHERE is evaluated before the SELECT list, so WHERE annual_salary > 1000000 is an error in PostgreSQL, MySQL, SQL Server and Oracle. SQLite, which runs this playground, accepts it as an extension, so a query that works here can fail elsewhere; repeat the expression, or filter in an outer query.

B

BETWEEN
A range test: WHERE price BETWEEN 10 AND 20 is shorthand for price >= 10 AND price <= 20, inclusive on both ends. For dates, a half-open range is usually safer. Full guide: Date functions →
SELECT name, unit_price
FROM Products
WHERE unit_price BETWEEN 100 AND 500;
nameunit_price
Nimbus Docking Hub189.5
Vertex Monitor 27"449.99
Quill Keyboard119
Harbor Support Plan400

● 4 rows · produced by running this query on the sample database

Common mistake

Forgetting that BETWEEN includes both ends. BETWEEN 100 AND 500 keeps a price of exactly 500; to stop short of it, write unit_price >= 100 AND unit_price < 500.

C

CASE
SQL's conditional expression. It tests conditions in order and produces the value of the first match, anywhere a value can appear - SELECT lists, ORDER BY, even inside aggregates. Full guide: CASE WHEN explained →
SELECT name, unit_price,
       CASE WHEN unit_price >= 500 THEN 'premium' ELSE 'standard' END AS band
FROM Products;
nameunit_priceband
Aurora Laptop 14"1299premium
Nimbus Docking Hub189.5standard
Vertex Monitor 27"449.99standard
Quill Keyboard119standard
Atlas Cloud Suite899premium
Beacon Analytics1450premium
Harbor Support Plan400standard

● 7 rows · produced by running this query on the sample database

Common mistake

Leaving out ELSE. A row that matches no WHEN branch becomes NULL, silently, and then drops out of counts and comparisons.

COALESCE
Returns the first non-NULL of its arguments. The standard way to swap a NULL for a readable fallback, as in COALESCE(manager_name, 'No manager'). Full guide: String functions →
SELECT e.first_name, COALESCE(m.first_name, 'no manager') AS reports_to
FROM Employees e
LEFT JOIN Employees m ON m.emp_id = e.manager_id;
first_namereports_to
Ananyano manager
MarcusAnanya
LeilaAnanya
Tomasno manager
GraceTomas
HiroshiTomas
Priyano manager
DanielPriya
Sofiano manager
OmarSofia
Chenno manager
IsabelaChen

● 12 rows · produced by running this query on the sample database

Common mistake

Expecting COALESCE to replace an empty string. It only steps past NULL; '' is a value, so it is returned as it is.

Column
One named field of a table, holding the same kind of value for every row - an email, a price, a date. Queries choose columns in the SELECT list. Full guide: The SELECT guide →
SELECT first_name, hire_date
FROM Employees;
first_namehire_date
Ananya2018-03-12
Marcus2019-07-01
Leila2021-01-18
Tomas2017-11-05
Grace2020-06-22
Hiroshi2022-02-14
Priya2019-09-30
Daniel2023-04-03
Sofia2020-01-09
Omar2021-08-16
Chen2016-05-20
Isabela2022-10-11

● 12 rows · produced by running this query on the sample database

Common mistake

Quoting a column name like text. 'first_name' in single quotes is a string, not a column, so every row shows the word first_name. Write the name bare.

Correlated subquery
A subquery that references a column from the outer query, so it is logically evaluated once per outer row. Powerful for per-row comparisons; often slower than a set-based rewrite. Full guide: Subqueries guide →
SELECT e.first_name, e.salary
FROM Employees e
WHERE e.salary > (SELECT AVG(x.salary) FROM Employees x WHERE x.dept_id = e.dept_id);
first_namesalary
Ananya142000
Marcus118000
Tomas131000
Priya105000
Chen156000

● 5 rows · produced by running this query on the sample database

Common mistake

Dropping the condition that ties the inner query to the outer row. Without x.dept_id = e.dept_id the subquery averages the whole company once, and every employee is compared to the same number.

CROSS JOIN
A join with no condition: every row on the left pairs with every row on the right. Occasionally wanted for building grids; more often the accidental result of a forgotten ON. Full guide: JOINs explained →
SELECT d.dept_name, p.category
FROM Departments d
CROSS JOIN Products p;

Common mistake

Producing one by accident. A JOIN with no ON clause, or two tables after FROM with no WHERE linking them, multiplies the tables together; if a query returns far more rows than either table has, look for a missing join condition.

CTE (Common Table Expression)
A named, temporary result set defined with WITH at the top of a query and used below by name. It structures multi-step logic so it reads top to bottom. Full guide: CTEs explained →
WITH big_orders AS (
  SELECT customer_id, order_total FROM Orders WHERE order_total > 3000
)
SELECT c.company, b.order_total
FROM big_orders b
JOIN Customers c ON c.customer_id = b.customer_id;
companyorder_total
Meridian Trading Co.15588
Sakura Logistics3599.92
Meridian Trading Co.4760
Acme Robotics6495
Cedar Health4949.89
Fjord Analytics8091
Andes Textiles5685
Fjord Analytics5800
Cedar Health9093

● 9 rows · produced by running this query on the sample database

Common mistake

Putting a semicolon after the CTE's closing parenthesis. The WITH block and the query that uses it are one statement; a semicolon between them ends the statement before the CTE is used.

D

DDL and DML
Two families of SQL statements: DDL (Data Definition Language) shapes structure - CREATE, ALTER, DROP - while DML (Data Manipulation Language) works with rows - SELECT, INSERT, UPDATE, DELETE. Full guide: DDL, DML, DCL and TCL →
CREATE TABLE Suppliers (supplier_id INT PRIMARY KEY, name VARCHAR(100));  -- DDL
INSERT INTO Suppliers VALUES (1, 'Aurora Parts');                         -- DML
SELECT * FROM Suppliers;
supplier_idname
1Aurora Parts

● 1 row · produced by running this query on the sample database

Common mistake

Assuming DDL can be rolled back like DML. MySQL and Oracle commit CREATE, ALTER and DROP immediately, so there a DROP TABLE inside a transaction is still gone after ROLLBACK. PostgreSQL, SQL Server and SQLite can roll most DDL back.

DELETE
Removes rows matched by its WHERE clause. Without a WHERE it empties the entire table, immediately and without confirmation - which is why you SELECT with the same WHERE first. Full guide: Changing data safely →
DELETE FROM Orders WHERE status = 'Cancelled';
SELECT COUNT(*) AS remaining FROM Orders;
remaining
13

● 1 row · produced by running this query on the sample database

Common mistake

A DELETE with no WHERE. It removes every row in the table, asks nothing, and has no undo outside a transaction. Run a SELECT with the same WHERE first and count what comes back.

DISTINCT
Removes duplicate rows from a result. It applies to the whole selected row, not just the column it happens to sit beside - SELECT DISTINCT a, b de-duplicates combinations of a and b. Full guide: SELECT DISTINCT →
SELECT DISTINCT category FROM Products;
category
Hardware
Accessories
Software
Services

● 4 rows · produced by running this query on the sample database

Common mistake

Expecting DISTINCT to apply to one column. It de-duplicates whole rows, so SELECT DISTINCT country, city returns every unique country/city pair, not each country once.

F

Foreign key
A column that references the primary key of another table, expressing a relationship - Employees.dept_id pointing at Departments.dept_id. Joins follow these references. Full guide: Primary key vs foreign key →
CREATE TABLE Reviews (
  review_id  INT PRIMARY KEY,
  product_id INT,
  stars      INT,
  FOREIGN KEY (product_id) REFERENCES Products (product_id)
);
INSERT INTO Reviews VALUES (1, 201, 5);
SELECT * FROM Reviews;
review_idproduct_idstars
12015

● 1 row · produced by running this query on the sample database

Common mistake

Declaring the column but not the constraint. A plain product_id column accepts 999 even though no such product exists; only the FOREIGN KEY line makes the database refuse it. Try inserting a review for product 999 in the playground and read the error. One SQLite caveat: it enforces foreign keys only after PRAGMA foreign_keys = ON has been run on the connection, and that setting is off by default. The playground switches it on for you.

FULL OUTER JOIN
A join that keeps every row from both tables, matching where possible and filling the gaps with NULL on whichever side has no partner. Full guide: JOINs explained →
SELECT e.first_name, d.dept_name
FROM Employees e
FULL OUTER JOIN Departments d ON d.dept_id = e.dept_id;

Common mistake

Reaching for FULL OUTER JOIN when a LEFT JOIN answers the question. It is the right tool only when unmatched rows on both sides matter - and MySQL does not support it, so there it is written as a LEFT JOIN, UNION, a RIGHT JOIN.

G

GROUP BY
Collapses rows into one row per unique value (or combination) of the named columns, so aggregate functions can summarise each group. Full guide: GROUP BY vs HAVING →
SELECT dept_id, COUNT(*) AS headcount
FROM Employees
GROUP BY dept_id;
dept_idheadcount
105
204
301
502

● 4 rows · produced by running this query on the sample database

Common mistake

Selecting a column that is neither grouped nor aggregated. SELECT dept_id, first_name, COUNT(*) ... GROUP BY dept_id has no single first_name to show per group. PostgreSQL, SQL Server, Oracle and MySQL in its default mode reject it; SQLite, which runs this playground, accepts it and shows the first_name of an arbitrary row in each group; the playground flags that with a warning. Group by the column or aggregate it.

H

HAVING
WHERE's counterpart for groups: it filters after GROUP BY has run, so it can test aggregate values like COUNT(*) > 2, which WHERE cannot see. Full guide: GROUP BY vs HAVING →
SELECT dept_id, COUNT(*) AS headcount
FROM Employees
GROUP BY dept_id
HAVING COUNT(*) >= 3;
dept_idheadcount
105
204

● 2 rows · produced by running this query on the sample database

Common mistake

Using HAVING for a row-level condition. HAVING salary > 50000 runs after grouping, when there is no single salary left to test. PostgreSQL and SQL Server reject it; SQLite, which runs this playground, runs it without complaint and tests the salary of one arbitrary row in each group, which is worse than an error. Conditions on individual rows belong in WHERE, before the groups are formed.

I

IN and NOT IN
IN tests whether a value matches any item in a list, either written out - category IN ('Hardware', 'Software') - or returned by a subquery. NOT IN is its negation, with one trap: if the list contains a NULL, NOT IN matches nothing. Full guide: EXISTS vs IN →
SELECT first_name
FROM Employees
WHERE emp_id IN (SELECT manager_id FROM Employees)
ORDER BY emp_id;
first_name
Ananya
Tomas
Priya
Sofia
Chen

● 5 rows · produced by running this query on the sample database

Common mistake

Flipping that to NOT IN to find the employees who manage nobody. The five people at the top have a NULL manager_id, so the list holds NULLs, and emp_id NOT IN (SELECT manager_id FROM Employees) returns no rows at all instead of seven. Use NOT EXISTS, or add WHERE manager_id IS NOT NULL inside the subquery.

Index
A database structure that makes lookups on a column fast, at the cost of storage and slower writes - the reason WHERE email = ... can be instant on a million rows. Queries never name indexes; the database chooses to use them. Full guide: SQL indexes →
CREATE INDEX idx_employees_dept ON Employees (dept_id);
SELECT first_name FROM Employees WHERE dept_id = 10;
first_name
Ananya
Marcus
Leila
Sofia
Omar

● 5 rows · produced by running this query on the sample database

Common mistake

Indexing everything. Each index speeds up the reads it matches and slows down every INSERT, UPDATE and DELETE that has to maintain it. Index the columns you filter and join on, not every column.

INNER JOIN
The default join: returns only the row pairs where the ON condition matches on both sides. Rows with no partner are dropped. Full guide: JOINs explained →
SELECT e.first_name, d.dept_name
FROM Employees e
INNER JOIN Departments d ON d.dept_id = e.dept_id;
first_namedept_name
AnanyaEngineering
MarcusEngineering
LeilaEngineering
TomasSales
GraceSales
HiroshiSales
PriyaSales
DanielMarketing
SofiaEngineering
OmarEngineering
ChenFinance
IsabelaFinance

● 12 rows · produced by running this query on the sample database

Common mistake

Forgetting that unmatched rows vanish. An employee with no department, or a department with no employees, is simply not in the result. If that is a surprise, you wanted a LEFT JOIN.

INSERT
Adds new rows to a table. Naming the columns - INSERT INTO t (a, b) VALUES (...) - keeps the statement working when the table later gains columns. Full guide: Changing data safely →
INSERT INTO Departments (dept_id, dept_name, location, budget)
VALUES (60, 'Legal', 'Pune', 300000);
SELECT * FROM Departments;
dept_iddept_namelocationbudget
10EngineeringBengaluru2400000
20SalesLondon980000
30MarketingNew York640000
40SupportBerlin410000
50FinanceSingapore520000
60LegalPune300000

● 6 rows · produced by running this query on the sample database

Common mistake

Omitting the column list. INSERT INTO t VALUES (...) depends on the table's column order and breaks the day a column is added; naming the columns keeps the statement correct.

IS NULL
The only correct way to test for NULL. Comparing with = NULL never matches anything, because NULL means unknown and nothing is known to equal an unknown. Full guide: The WHERE guide →
SELECT first_name FROM Employees WHERE manager_id IS NULL;
first_name
Ananya
Tomas
Priya
Sofia
Chen

● 5 rows · produced by running this query on the sample database

Common mistake

Writing = NULL. Nothing equals NULL, not even NULL, so WHERE manager_id = NULL matches no rows at all. IS NULL and IS NOT NULL are the only tests that work.

J

JOIN
The operation that combines rows from two tables by matching a condition, usually a foreign key against a primary key. Written alone, JOIN means INNER JOIN. Full guide: JOINs explained →
SELECT o.order_id, c.company
FROM Orders o
JOIN Customers c ON c.customer_id = o.customer_id;

Common mistake

Joining on a column that is not unique on either side, which multiplies rows. If the joined result has more rows than you expected, check which side is supposed to have one row per key.

L

LEFT JOIN
Keeps every row from the left table; where the right table has no match, its columns come back NULL. The join to reach for when unmatched rows still matter. Full guide: JOINs explained →
SELECT d.dept_name, COUNT(e.emp_id) AS headcount
FROM Departments d
LEFT JOIN Employees e ON e.dept_id = d.dept_id
GROUP BY d.dept_name;
dept_nameheadcount
Engineering5
Finance2
Marketing1
Sales4
Support0

● 5 rows · produced by running this query on the sample database

Common mistake

Filtering the right-hand table in WHERE. WHERE e.active = 1 throws away the NULL rows the LEFT JOIN kept, turning it back into an INNER JOIN; put that condition in the ON clause instead.

LIKE
Pattern matching for text: % stands for any run of characters, _ for exactly one. WHERE name LIKE 'A%' finds names starting with A. Full guide: The WHERE guide →
SELECT company FROM Customers WHERE company LIKE '%Systems%';
company
Baltic Systems

● 1 row · produced by running this query on the sample database

Common mistake

Forgetting the wildcards: LIKE 'Systems' with no % matches only that exact word. Case is the other surprise, because it depends on the database: PostgreSQL and Oracle compare case-sensitively, while MySQL and SQL Server with their default collations, and SQLite for ASCII letters, ignore case. So in this playground, which runs SQLite, LIKE '%systems%' still finds Baltic Systems, but = 'baltic systems' finds nothing.

LIMIT
Caps how many rows come back. Meaningful only with an ORDER BY - otherwise it returns an arbitrary handful. SQL Server spells it TOP; Oracle uses FETCH FIRST. Full guide: ORDER BY and LIMIT →
SELECT first_name, salary
FROM Employees
ORDER BY salary DESC
LIMIT 3;
first_namesalary
Chen156000
Ananya142000
Tomas131000

● 3 rows · produced by running this query on the sample database

Common mistake

LIMIT without ORDER BY. Without an order, "the first three rows" means whichever three the engine reached first, which can change between runs.

N

NULL
The marker for a missing or unknown value. It is not zero and not an empty string, it fails every ordinary comparison, and aggregate functions skip it. Handle it with IS NULL and COALESCE. Full guide: The WHERE guide →
SELECT first_name, manager_id FROM Employees WHERE manager_id IS NULL;
first_namemanager_id
AnanyaNULL
TomasNULL
PriyaNULL
SofiaNULL
ChenNULL

● 5 rows · produced by running this query on the sample database

Common mistake

Treating NULL as zero or as an empty string. salary + NULL is NULL, COUNT(manager_id) skips NULLs, and NULL = NULL is not true: every operation on an unknown value stays unknown.

O

ORDER BY
Sorts the final result by one or more columns or expressions, ascending by default, DESC for descending. Without it, row order is never guaranteed. Full guide: ORDER BY and LIMIT →
SELECT first_name, salary
FROM Employees
ORDER BY salary DESC, first_name;
first_namesalary
Chen156000
Ananya142000
Tomas131000
Marcus118000
Priya105000
Leila96000
Isabela92000
Grace89500
Sofia79000
Hiroshi74500
Daniel68000
Omar61000

● 12 rows · produced by running this query on the sample database

Common mistake

Assuming rows come back sorted without ORDER BY. They come back in whatever order was cheapest to produce, which may look sorted today and not tomorrow.

P

PARTITION BY
Inside a window function's OVER clause, splits rows into independent windows - the non-destructive cousin of GROUP BY, computing per group while keeping every row. Full guide: Window functions →
SELECT first_name, dept_id, salary,
       AVG(salary) OVER (PARTITION BY dept_id) AS dept_avg
FROM Employees;
first_namedept_idsalarydept_avg
Ananya1014200099200
Marcus1011800099200
Leila109600099200
Sofia107900099200
Omar106100099200
Tomas20131000100000
Grace2089500100000
Hiroshi2074500100000
Priya20105000100000
Daniel306800068000
Chen50156000124000
Isabela5092000124000

● 12 rows · produced by running this query on the sample database

Common mistake

Confusing PARTITION BY with GROUP BY. GROUP BY collapses each group to one row; PARTITION BY keeps every row and adds the group's value alongside it.

Primary key
The column (or columns) that uniquely identifies each row of a table - order_id, emp_id. Foreign keys in other tables point at it. Full guide: Primary key vs foreign key →
CREATE TABLE Suppliers (
  supplier_id INT PRIMARY KEY,
  name        VARCHAR(100) NOT NULL
);
INSERT INTO Suppliers VALUES (1, 'Aurora Parts');
SELECT * FROM Suppliers;
supplier_idname
1Aurora Parts

● 1 row · produced by running this query on the sample database

Common mistake

Choosing a key that can change, such as an email address. When it changes, every row that referenced it must change too. An id that means nothing on its own is the safer choice.

Q

Query
A request for data written in SQL - most often a SELECT statement. The database plans how to execute it and returns a result table. Full guide: The beginner guide →
SELECT first_name, last_name
FROM Employees
WHERE active = 1
ORDER BY last_name;
first_namelast_name
MarcusBennett
DanielCruz
LeilaHaddad
SofiaLindqvist
PriyaMenon
IsabelaMoreira
TomasNowak
GraceOkafor
AnanyaRao
HiroshiTanaka
ChenWei

● 11 rows · produced by running this query on the sample database

Common mistake

Writing the clauses out of order. SQL requires SELECT, FROM, WHERE, GROUP BY, HAVING, ORDER BY in that sequence; a WHERE after ORDER BY is a syntax error, not a style choice.

R

RIGHT JOIN
The mirror of LEFT JOIN: keeps every row from the right table. Rarely written in practice, because swapping the table order turns it into the easier-to-read LEFT JOIN. Full guide: JOINs explained →
SELECT e.first_name, d.dept_name
FROM Employees e
RIGHT JOIN Departments d ON d.dept_id = e.dept_id;

Common mistake

Using RIGHT JOIN where swapping the tables and writing LEFT JOIN says the same thing more readably. Nearly every RIGHT JOIN in the wild is a LEFT JOIN written backwards.

ROW_NUMBER
A window function that hands out 1, 2, 3... down a specified order, turning position into a value you can filter on - the engine behind pagination and top-N-per-group. Full guide: Window functions →
SELECT first_name, salary,
       ROW_NUMBER() OVER (ORDER BY salary DESC) AS rank_by_pay
FROM Employees
ORDER BY rank_by_pay;
first_namesalaryrank_by_pay
Chen1560001
Ananya1420002
Tomas1310003
Marcus1180004
Priya1050005
Leila960006
Isabela920007
Grace895008
Sofia790009
Hiroshi7450010
Daniel6800011
Omar6100012

● 12 rows · produced by running this query on the sample database

Common mistake

Filtering on the number in the same query. Window functions are computed after WHERE, so WHERE rank_by_pay <= 3 is not allowed; wrap the query in a CTE or subquery and filter there.

S

Schema
The structure of a database: which tables exist, their columns and types, and how they relate. Reading a schema is the first step of writing a query against unfamiliar data. Full guide: Designing tables (normalization) →
CREATE TABLE Suppliers (
  supplier_id INT PRIMARY KEY,
  name        VARCHAR(100) NOT NULL,
  country     VARCHAR(60)
);
SELECT * FROM Suppliers;

● 0 rows · the query ran, and nothing in the sample database matched it

Common mistake

Guessing column names and types instead of reading the schema. Most "column does not exist" errors are a schema nobody looked at. This playground shows it beside the editor.

SELECT
The statement that reads data. Its clauses - FROM, WHERE, GROUP BY, HAVING, ORDER BY, LIMIT - each answer one question about what comes back. Full guide: The SELECT guide →
SELECT first_name, last_name, salary FROM Employees;
first_namelast_namesalary
AnanyaRao142000
MarcusBennett118000
LeilaHaddad96000
TomasNowak131000
GraceOkafor89500
HiroshiTanaka74500
PriyaMenon105000
DanielCruz68000
SofiaLindqvist79000
OmarFarouk61000
ChenWei156000
IsabelaMoreira92000

● 12 rows · produced by running this query on the sample database

Common mistake

SELECT * in code that other code depends on. It returns whatever columns exist today, in today's order, so adding a column to the table can silently change what the query produces.

Self join
Joining a table to itself, with two aliases telling the two copies apart. The standard way to walk relationships a table has with its own rows, like employee to manager. Full guide: JOINs explained →
SELECT e.first_name AS employee, m.first_name AS manager
FROM Employees e
JOIN Employees m ON m.emp_id = e.manager_id;
employeemanager
MarcusAnanya
LeilaAnanya
GraceTomas
HiroshiTomas
DanielPriya
OmarSofia
IsabelaChen

● 7 rows · produced by running this query on the sample database

Common mistake

Leaving out the aliases. Both copies of the table are called Employees, so without e and m every column reference is ambiguous and the query cannot run.

Subquery
A SELECT nested inside another statement, supplying a value, a list or a derived table to its outer query. The correlated variety re-runs per outer row. Full guide: Subqueries guide →
SELECT first_name, salary
FROM Employees
WHERE salary > (SELECT AVG(salary) FROM Employees);
first_namesalary
Ananya142000
Marcus118000
Tomas131000
Priya105000
Chen156000

● 5 rows · produced by running this query on the sample database

Common mistake

Using = with a subquery that can return more than one row. PostgreSQL, MySQL, SQL Server and Oracle stop with an error when it does; SQLite, which runs this playground, quietly compares against the first row instead, so the mistake can go unnoticed here. If the inner query may produce several values, the outer comparison needs IN or EXISTS, not =.

T

Table
The basic container of a relational database: named columns across the top, one row per record. Everything SQL does starts from tables and produces table-shaped results. Full guide: The beginner guide →
SELECT * FROM Products;
product_idnamecategoryunit_pricein_stock
201Aurora Laptop 14"Hardware129942
202Nimbus Docking HubAccessories189.5130
203Vertex Monitor 27"Hardware449.9968
204Quill KeyboardAccessories119210
205Atlas Cloud SuiteSoftware899999
206Beacon AnalyticsSoftware1450999
207Harbor Support PlanServices400999

● 7 rows · produced by running this query on the sample database

Common mistake

Thinking of a table as having a natural row order. It does not; rows come back in an arbitrary order unless the query says ORDER BY.

Transaction
A group of statements executed all-or-nothing: COMMIT keeps every change, ROLLBACK undoes them all. The mechanism behind the ACID guarantees databases advertise. Full guide: Changing data safely →
BEGIN TRANSACTION;
UPDATE Products SET unit_price = unit_price * 1.1 WHERE category = 'Accessories';
-- look at the result, then either keep it ...
COMMIT;
-- ... or undo it with ROLLBACK;

Common mistake

Leaving a transaction open. Until COMMIT or ROLLBACK, the rows it touched can stay locked for everyone else - and a connection that drops mid-transaction rolls it back, taking the work with it.

TRUNCATE
Empties a table in one fast operation, without a WHERE and typically without firing per-row triggers. For removing specific rows, DELETE is the tool. Full guide: DELETE vs TRUNCATE vs DROP →
-- MySQL, PostgreSQL, SQL Server and Oracle (SQLite has no TRUNCATE)
TRUNCATE TABLE Orders;

SQLite, which runs this playground, has no TRUNCATE statement. Its equivalent is a DELETE with no WHERE, which SQLite can carry out as one fast wipe of the table rather than row by row:

DELETE FROM Orders;
SELECT COUNT(*) AS remaining FROM Orders;
remaining
0

● 1 row · produced by running this query on the sample database

Common mistake

Expecting TRUNCATE to take a WHERE. It cannot; it empties the whole table in one step. To remove some rows, DELETE with a WHERE is the only option.

U

UNION and UNION ALL
Stack two results with the same column shape on top of each other. UNION removes duplicate rows (extra work); UNION ALL keeps everything and is faster. Full guide: UNION vs UNION ALL →
SELECT city AS place FROM Customers
UNION
SELECT location FROM Departments;
place
Arequipa
Arusha
Austin
Beirut
Bengaluru
Bergen
Berlin
Lima
London
New York
Osaka
Singapore

● 12 rows · produced by running this query on the sample database

Common mistake

Reaching for UNION by habit. UNION has to find and remove duplicates, which costs time; when the two sides cannot overlap, or duplicates are wanted, UNION ALL is both faster and correct.

UPDATE
Changes values in existing rows: SET says what changes, WHERE says which rows. Without a WHERE, it changes every row in the table. Full guide: Changing data safely →
UPDATE Products
SET unit_price = unit_price * 1.1
WHERE category = 'Accessories';
SELECT name, unit_price FROM Products WHERE category = 'Accessories';
nameunit_price
Nimbus Docking Hub208.45
Quill Keyboard130.9

● 2 rows · produced by running this query on the sample database

Common mistake

An UPDATE with no WHERE. Every row in the table changes, immediately. Run a SELECT with the intended WHERE first and count what comes back.

V

View
A stored, named query that behaves like a table. Where a CTE lives for one query, a view lives in the database and is shared by every query and user. Full guide: SQL views →
CREATE VIEW active_staff AS
  SELECT first_name, last_name, dept_id FROM Employees WHERE active = 1;
SELECT * FROM active_staff;
first_namelast_namedept_id
AnanyaRao10
MarcusBennett10
LeilaHaddad10
TomasNowak20
GraceOkafor20
HiroshiTanaka20
PriyaMenon20
DanielCruz30
SofiaLindqvist10
ChenWei50
IsabelaMoreira50

● 11 rows · produced by running this query on the sample database

Common mistake

Expecting a view to make a query faster. An ordinary view stores nothing - it re-runs its SELECT every time it is used - so it organises code, not performance.

W

WHERE
Filters rows before anything else happens to them - before grouping, before selecting, before sorting. The workhorse clause of practically every real query. Full guide: The WHERE guide →
SELECT first_name, salary
FROM Employees
WHERE dept_id = 10 AND salary > 90000;
first_namesalary
Ananya142000
Marcus118000
Leila96000

● 3 rows · produced by running this query on the sample database

Common mistake

Mixing AND and OR without parentheses. AND binds tighter, so a OR b AND c means a OR (b AND c); write the parentheses you mean.

Wildcard
A placeholder character in a LIKE pattern: % matches any run of characters (including none), _ matches exactly one. SELECT's * is also loosely called a wildcard - it means every column. Full guide: The WHERE guide →
SELECT first_name FROM Employees WHERE first_name LIKE '_ri%';
first_name
Priya

● 1 row · produced by running this query on the sample database

Common mistake

Using * as a wildcard in LIKE. In SQL the wildcards are % (any run of characters) and _ (exactly one character); LIKE 'A*' looks for a literal asterisk.

Window function
A function that computes a value for each row from a window of related rows - rankings, running totals, per-group averages - without collapsing rows the way GROUP BY does. Full guide: Window functions →
SELECT first_name, salary,
       SUM(salary) OVER () AS total_payroll
FROM Employees;
first_namesalarytotal_payroll
Ananya1420001212000
Marcus1180001212000
Leila960001212000
Tomas1310001212000
Grace895001212000
Hiroshi745001212000
Priya1050001212000
Daniel680001212000
Sofia790001212000
Omar610001212000
Chen1560001212000
Isabela920001212000

● 12 rows · produced by running this query on the sample database

Common mistake

Expecting a window function to reduce the number of rows. It never does; every input row comes back, with the window's value added as a column.