Introduction to SQL
SQL (Structured Query Language) is the universal language for talking to databases. Whether you are building a web application, analysing business data, or working with any kind of stored information, SQL is the tool you will reach for. This chapter explains what SQL is, how databases work, and gives you your first real queries.
What is SQL and Why Does It Matter?
Imagine you own a library with millions of books. You need to:
- Find all books by a specific author
- List books published after 2010, sorted by title
- Count how many books are in each genre
- Update a book's status when it is checked out
Without a structured way to do this, you would have to manually search through rows of a spreadsheet โ slow, error-prone, and impossible at scale. SQL solves this. It lets you express what data you want in plain, English-like sentences, and the database engine figures out the fastest way to retrieve it.
SQL was developed by IBM researchers in the early 1970s, became an ANSI/ISO standard in 1987, and today powers virtually every application that stores data โ from small mobile apps to the largest enterprise systems in the world.
What is a Relational Database?
Think of a relational database as a collection of spreadsheets that can talk to each other.
In a spreadsheet you have:
- A sheet (tab) โ like a table in a database
- Column headers โ like column definitions
- Rows of data โ like records
The key difference is that in a relational database, tables can be linked together through shared values. This avoids storing the same information in multiple places (known as data redundancy) and makes the data consistent.
Spreadsheet analogy:
| emp_id | name | dept_name | dept_location |
|---|---|---|---|
| 1 | Alice | HR | New York |
| 2 | Bob | IT | London |
| 3 | Carol | IT | London |
Notice that "IT" and "London" are repeated for Bob and Carol. If the IT department moves to Paris, you have to update every row. In a relational database, you split this into two tables:
employees table:
| emp_id | name | dept_id |
|---|---|---|
| 1 | Alice | 10 |
| 2 | Bob | 20 |
| 3 | Carol | 20 |
departments table:
| dept_id | dept_name | location |
|---|---|---|
| 10 | HR | New York |
| 20 | IT | London |
Now if IT moves to Paris, you update one row in departments and every employee automatically reflects the change.
Tables, Rows, Columns โ The Building Blocks
Every relational database stores data in tables. Here is what each term means:
Table โ A named collection of related data, like a spreadsheet tab. Examples: employees, orders, products.
Column (Field) โ A named attribute that defines what type of data is stored. Every column has a data type (text, number, date, etc.). Examples: name, salary, hire_date.
Row (Record) โ One complete entry in the table. A row is one employee, one order, one product.
Cell โ The intersection of a row and a column โ a single piece of data.
TABLE: employees
โโโโโโโโโโโฌโโโโโโโโฌโโโโโโโฌโโโโโโโโโ
โ emp_id โ name โ dept โ salary โ โ COLUMNS (define what data goes here)
โโโโโโโโโโโผโโโโโโโโผโโโโโโโผโโโโโโโโโค
โ 1 โ Alice โ HR โ 60000 โ โ ROW (one complete record)
โ 2 โ Bob โ IT โ 85000 โ โ ROW
โ 3 โ Carol โ IT โ 92000 โ โ ROW
โโโโโโโโโโโดโโโโโโโโดโโโโโโโดโโโโโโโโโ
โ
PRIMARY KEY column (unique identifier)
Primary Keys and Foreign Keys
Primary Key โ A column (or set of columns) whose value uniquely identifies each row. Think of it as the row's ID card number โ no two rows can have the same primary key, and it can never be blank (NULL).
Rules:
- Must be unique across every row
- Cannot be NULL (empty)
- One primary key per table (though it can span multiple columns)
Foreign Key โ A column in one table that holds the primary key value of a row in another table. It is the link that connects two tables.
employees.dept_id โ departments.dept_id
(foreign key) (primary key)
This connection is called referential integrity: the foreign key value must always match a real primary key in the referenced table. You cannot assign an employee to a department that does not exist.
SQL vs NoSQL โ Which Is Which?
You will often hear "NoSQL" mentioned alongside SQL databases. Here is a clear comparison:
| Feature | SQL (Relational) | NoSQL |
|---|---|---|
| Data model | Tables with rows and columns | Documents, key-value pairs, graphs, wide columns |
| Schema | Fixed and predefined | Flexible, schema-less |
| Relationships | Excellent โ joins between tables | Limited or handled in application code |
| ACID transactions | Full support (Atomicity, Consistency, Isolation, Durability) | Varies by system |
| Query language | SQL (standardised) | Varies by product (no universal standard) |
| Scaling | Typically scales vertically (bigger server) | Often designed to scale horizontally (more servers) |
| Best for | Structured data, complex queries, financial systems | Unstructured data, high write volumes, flexible schemas |
| Examples | Oracle, PostgreSQL, MySQL, SQL Server, SQLite | MongoDB, Redis, Cassandra, DynamoDB, Neo4j |
The 5 Types of SQL Commands
SQL commands are grouped into five categories based on what they do. You will eventually use all of them.
DDL โ Data Definition Language
DDL commands define and change the structure of the database โ creating tables, modifying columns, dropping objects.
-- Create a new table
CREATE TABLE departments (
dept_id INT PRIMARY KEY,
dept_name VARCHAR(100) NOT NULL,
location VARCHAR(100)
);
-- Add a column to an existing table
ALTER TABLE departments ADD budget DECIMAL(12,2);
-- Remove a table permanently
DROP TABLE old_archive;
-- Remove all rows but keep the table structure
TRUNCATE TABLE temp_staging;
DML โ Data Manipulation Language
DML commands work with the data inside tables โ adding, changing, removing rows.
-- Insert a new employee
INSERT INTO employees (emp_id, name, dept_id, salary)
VALUES (1, 'Alice', 10, 60000);
-- Give everyone in IT a 10% raise
UPDATE employees
SET salary = salary * 1.10
WHERE dept_id = 20;
-- Remove employees who left before 2020
DELETE FROM employees
WHERE end_date < '2020-01-01';
DQL โ Data Query Language
DQL retrieves data. The entire DQL category is just one command: SELECT โ but it is the most powerful and complex SQL command.
-- Retrieve names and salaries of all employees
SELECT name, salary
FROM employees
ORDER BY salary DESC;
DCL โ Data Control Language
DCL controls who can do what in the database. Administrators use these to grant or revoke access.
-- Allow user 'john' to read the employees table
GRANT SELECT ON employees TO john;
-- Allow 'jane' to insert and update orders
GRANT INSERT, UPDATE ON orders TO jane;
-- Remove john's read access
REVOKE SELECT ON employees FROM john;
TCL โ Transaction Control Language
A transaction is a group of SQL statements that should all succeed or all fail together. Think of a bank transfer: debit one account AND credit another โ if one fails, the other must be undone.
-- Begin a transaction (implicit in most databases)
BEGIN;
UPDATE accounts SET balance = balance - 500 WHERE account_id = 1;
UPDATE accounts SET balance = balance + 500 WHERE account_id = 2;
-- If everything is fine, save the changes permanently
COMMIT;
-- If something went wrong, undo all changes since BEGIN
ROLLBACK;
-- Set a named checkpoint you can roll back to
SAVEPOINT before_update;
UPDATE employees SET salary = 99999 WHERE dept_id = 10;
ROLLBACK TO SAVEPOINT before_update; -- undo just the update above
Popular Databases โ A Comparison
| Database | Key Strengths | Typical Use Case | Cost |
|---|---|---|---|
| Oracle | Enterprise features, PL/SQL, rock-solid ACID, huge scale | Large enterprises, banking, ERP systems | Commercial (expensive) |
| PostgreSQL | Open source, highly standards-compliant, rich features, extensible | Web apps, analytics, GIS data | Free |
| MySQL | Fast reads, huge ecosystem, easy to set up | Web applications, WordPress, e-commerce | Free (MySQL Community) |
| SQL Server | Deep Microsoft integration, great tooling (SSMS), BI features | Microsoft-stack enterprises, .NET apps | Commercial (free Express tier) |
| SQLite | File-based, zero configuration, embedded | Mobile apps, development, small tools | Free |
| MariaDB | MySQL-compatible, open-source fork | Drop-in MySQL replacement | Free |
Data Types โ What Can a Column Store?
Every column in a table has a data type that defines what kind of value it can hold. Choosing the right type matters for storage efficiency, performance, and data validation.
Numeric Types
| Type | Description | Example Values |
|---|---|---|
INT / INTEGER |
Whole numbers | 1, 42, -100, 999999 |
BIGINT |
Very large whole numbers | 9223372036854775807 |
DECIMAL(p,s) / NUMERIC(p,s) |
Exact decimal โ p digits total, s after decimal point | DECIMAL(10,2) โ 12345678.99 |
FLOAT / REAL |
Approximate floating point | 3.14159, 2.71828 |
NUMBER(p,s) |
Oracle's all-purpose numeric | NUMBER(8,2) โ 123456.78 |
Text Types
| Type | Description | Notes |
|---|---|---|
VARCHAR(n) |
Variable-length text, up to n characters | Use for most text columns |
VARCHAR2(n) |
Oracle equivalent of VARCHAR | Oracle prefers VARCHAR2 |
CHAR(n) |
Fixed-length text โ always n characters wide | Padded with spaces; use for fixed codes like 'US', 'GB' |
TEXT |
Unlimited-length text | PostgreSQL/MySQL; use for long descriptions |
CLOB |
Character Large Object | Oracle; large documents, XML |
Date and Time Types
| Type | Description | Example |
|---|---|---|
DATE |
Calendar date (and time in Oracle) | '2024-01-15' |
TIME |
Time of day | '14:30:00' |
TIMESTAMP |
Date + time with fractional seconds | '2024-01-15 14:30:00.000' |
INTERVAL |
A span of time | INTERVAL '3' MONTH |
Other Types
| Type | Description |
|---|---|
BOOLEAN |
True/false (PostgreSQL; Oracle uses NUMBER(1)) |
BLOB |
Binary Large Object โ images, files, binary data |
-- Example table showing common data type choices
CREATE TABLE employees (
emp_id INT PRIMARY KEY, -- whole number ID
name VARCHAR(100) NOT NULL, -- up to 100 chars
email VARCHAR(200) UNIQUE, -- email address
salary DECIMAL(10,2), -- e.g. 75000.00
hire_date DATE, -- e.g. 2021-03-15
is_active BOOLEAN, -- true/false
notes TEXT -- long free-form text
);
Your First SQL Query โ Line by Line
Let us read your first real SQL query carefully. Assume this employees table exists:
| emp_id | name | dept | salary | hire_date |
|---|---|---|---|---|
| 1 | Alice | HR | 60000 | 2020-01-15 |
| 2 | Bob | IT | 85000 | 2019-03-10 |
| 3 | Carol | IT | 92000 | 2018-07-22 |
| 4 | David | HR | 55000 | 2021-09-01 |
| 5 | Eve | Finance | 78000 | 2020-11-30 |
-- Query: Find IT department employees earning above 80,000
SELECT name, -- Which columns do you want to see?
salary -- You can list as many as you need
FROM employees -- Which table holds the data?
WHERE dept = 'IT' -- Filter: only rows where dept equals 'IT'
AND salary > 80000 -- AND another filter: salary must exceed 80000
ORDER BY salary DESC; -- Sort results: highest salary first
Breaking it down:
SELECT name, salaryโ specifies exactly which columns appear in the resultFROM employeesโ tells the database which table to read fromWHERE dept = 'IT'โ a filter; only rows where this condition is TRUE are includedAND salary > 80000โ an additional filter; both conditions must be trueORDER BY salary DESCโ sort the result by salary, largest first (DESC= descending);โ the semicolon marks the end of the statement (required in many tools)
Result:
| name | salary |
|---|---|
| Carol | 92000 |
| Bob | 85000 |
How SQL is Executed โ The Logical Order of Clauses
One of the most important things to understand about SQL is that clauses are written in one order but executed in a different order. Many beginners are confused when they try to use a column alias in a WHERE clause and get an error โ this is why.
Written order (how you type it):
SELECT โ FROM โ WHERE โ GROUP BY โ HAVING โ ORDER BY โ LIMIT
Logical execution order (how the database processes it):
1. FROM โ identify the source table(s)
2. WHERE โ filter individual rows
3. GROUP BY โ group the remaining rows
4. HAVING โ filter the groups
5. SELECT โ calculate the output columns and aliases
6. ORDER BY โ sort the result
7. LIMIT โ restrict the number of output rows
This means:
- You cannot use a SELECT alias in the WHERE clause (WHERE runs before SELECT)
- You can use a SELECT alias in ORDER BY (ORDER BY runs after SELECT)
- HAVING can use aggregate functions; WHERE cannot
-- This is WRONG โ alias used in WHERE (runs before SELECT)
SELECT salary * 12 AS annual_salary
FROM employees
WHERE annual_salary > 900000; -- ERROR: column "annual_salary" does not exist
-- This is CORRECT โ repeat the expression in WHERE
SELECT salary * 12 AS annual_salary
FROM employees
WHERE salary * 12 > 900000;
-- ORDER BY can use aliases (it runs after SELECT)
SELECT salary * 12 AS annual_salary
FROM employees
ORDER BY annual_salary DESC; -- This works fine
How to Read SQL Error Messages
When a SQL query fails, the database gives you an error message. Learning to read these is a crucial skill.
Common error types:
ORA-00942: table or view does not exist
You referenced a table name that does not exist, is misspelled, or is in a different schema.
ORA-00904: "ANNUAL_SALARY": invalid identifier
You used a column name or alias that the database cannot see at that point in the query. Usually caused by using a SELECT alias in a WHERE clause.
ORA-01858: a non-numeric character was found where a numeric was expected
You tried to insert or compare a text value where a number is expected โ for example WHERE salary = 'lots'.
ERROR: syntax error at or near "FORM"
A typo in a keyword (FORM instead of FROM). Check the word just before the error location.
ORA-00001: unique constraint violated
You tried to insert a duplicate value into a PRIMARY KEY or UNIQUE column.
Debugging strategy:
- Read the error message carefully โ it usually tells you the line number or the exact word where SQL got confused
- Check for typos in table and column names (they are case-insensitive in most databases, but must exist)
- Check that string values use single quotes, not double quotes
- Check clause order โ SELECT must come before FROM, WHERE must come before GROUP BY
Putting It All Together โ Your First 5 Queries
-- 1. See everything in a table (exploration query)
SELECT * FROM employees;
-- 2. See specific columns only
SELECT name, salary, hire_date
FROM employees;
-- 3. Filter rows by condition
SELECT name, salary
FROM employees
WHERE dept = 'IT';
-- 4. Sort results
SELECT name, dept, salary
FROM employees
ORDER BY dept ASC, salary DESC;
-- 5. Combine filtering and sorting
SELECT name, salary
FROM employees
WHERE salary > 70000
ORDER BY salary DESC;
These five patterns will cover a large proportion of your daily SQL work. Each subsequent chapter builds on these foundations โ adding more powerful filtering, grouping, joining multiple tables, and beyond.
Common Errors
| Error | Cause | Fix |
|---|---|---|
| ORA-00942 | Table or view does not exist โ wrong schema, typo, or missing synonym | Check SELECT * FROM user_tables WHERE table_name = 'EMPLOYEES'; verify schema prefix |
| ORA-00904 | Invalid identifier โ column name misspelled or not in scope | Double-check the column name against DESCRIBE table_name |
| ORA-01017 | Invalid username/password when connecting | Verify credentials; account may be locked โ check DBA_USERS |
| ORA-12541 | TNS: no listener โ database service unreachable | Confirm listener is running: lsnrctl status; verify tnsnames.ora |
| ORA-01400 | Cannot insert NULL into a NOT NULL column | Provide a value or set a DEFAULT; check which column is constrained |
| ORA-00933 | SQL command not properly ended โ trailing semicolon inside a JDBC call or syntax error | Remove the trailing ; when submitting SQL through JDBC/OCI; check for mismatched keywords |
Interview Corner
โถ Show answer
SQL is a declarative language for querying and manipulating relational data โ you describe what you want, not how to get it. A single SQL statement is sent to the database engine, optimised, and executed.
PL/SQL is Oracle's procedural extension. It wraps SQL inside imperative constructs (IF/THEN, loops, exception handlers, cursors) for multi-step logic that cannot be expressed in a single SQL statement.
Choose SQL when you need to retrieve or change data in a single operation. Choose PL/SQL when you need conditional branching, loops, error handling, or want to bundle multiple SQL statements into a stored procedure or function.
โถ Show answer
| Category | Full name | Purpose | Example |
|---|---|---|---|
| DDL | Data Definition Language | Define/alter schema objects | CREATE TABLE, ALTER TABLE, DROP TABLE |
| DML | Data Manipulation Language | Add/change/remove rows | INSERT, UPDATE, DELETE, MERGE |
| DQL | Data Query Language | Retrieve rows | SELECT |
| TCL | Transaction Control Language | Commit or roll back changes | COMMIT, ROLLBACK, SAVEPOINT |
| DCL | Data Control Language | Grant/revoke permissions | GRANT, REVOKE |
Related Topics
- Basic SQL โ the SELECT statement in depth: columns, aliases, DISTINCT, ORDER BY
- Filtering & Conditions โ WHERE clause operators, NULL handling, pattern matching
- Aggregate Functions โ COUNT, SUM, AVG, GROUP BY, HAVING
- DDL Commands โ CREATE, ALTER, DROP, TRUNCATE
- DML Commands โ INSERT, UPDATE, DELETE, MERGE