Introduction to Databases
A database stores related data in an organized form so applications can create, read, update, and protect it reliably.
Lesson content
Introduction to Databases A database stores related data in an organized form so applications can create, read, update, and protect it reliably. Example CREATE DATABASE shop; Key point Use the smallest correct statement, test it with representative data, and verify constraints and performance before production use. Real-life example An online shop stores customers, products, orders, and order items. The schema must prevent duplicate identities, missing required values, and orders that reference customers that do not exist. Advanced example BEGIN; -- Preview the exact target set first. SELECT id FROM orders WHERE status = 'pending'; -- Apply the Introduction to Databases operation, verify affected rows, then commit. COMMIT; Expected result The schema or operation satisfies the stated rule, rejects invalid data, and can be verified with a repeatable query. Production check Test with empty, duplicate, null, and boundary values. Use a transaction for related writes. Inspect the execution plan before adding an index. Use parameterized queries for application input. PicoStore practice database Every lesson in this SQL course uses the same fictional e-commerce database: picostore . Create it once, then reuse its tables throughout the course. CREATE DATABASE picostore; CREATE TABLE customers ( customer_id INTEGER PRIMARY KEY, name VARCHAR(100) NOT NULL, email VARCHAR(255) UNIQUE NOT NULL, city VARCHAR(80), created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE products ( product_id INTEGER PRIMARY KEY, name VARCHAR(120) NOT NULL, category VARCHAR(60), price DECIMAL(10, 2) CHECK (price >= 0), stock INTEGER DEFAULT 0 ); CREATE TABLE orders ( order_id INTEGER PRIMARY KEY, customer_id INTEGER NOT NULL REFERENCES customers(customer_id), status VARCHAR(20) DEFAULT 'pending', total DECIMAL(12, 2) NOT NULL, ordered_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE order_items ( order_id INTEGER REFERENCES orders(order_id), product_id INTEGER REFERENCES products(product_id), quantity INTEGER CHECK (quantity > 0), unit_price DECIMAL(10, 2) NOT NULL, PRIMARY KEY (order_id, product_id) ); CREATE TABLE employees ( employee_id INTEGER PRIMARY KEY, manager_id INTEGER REFERENCES employees(employee_id), name VARCHAR(100) NOT NULL, department VARCHAR(60), salary DECIMAL(12, 2) ); CREATE TABLE accounts ( account_id INTEGER PRIMARY KEY, customer_id INTEGER REFERENCES customers(customer_id), balance DECIMAL(14, 2) NOT NULL ); Starter data INSERT INTO customers (customer_id, name, email, city) VALUES (1, 'Asha', 'asha@example.com', 'Pune'), (2, 'Ravi', 'ravi@example.com', 'Mumbai'), (3, 'Meera', 'meera@example.com', NULL); INSERT INTO products (product_id, name, category, price, stock) VALUES (101, 'Keyboard', 'Accessories', 2499.00, 12), (102, 'Monitor', 'Displays', 14999.00, 5), (103, 'USB Cable', 'Accessories', 499.00, 0); INSERT INTO orders (order_id, customer_id, status, total, ordered_at) VALUES (1001, 1, 'paid', 15498.00, '2026-01-10 10:00:00'), (1002, 1, 'pending', 499.00, '2026-01-12 12:30:00'), (1003, 2, 'shipped', 2499.00, '2026-02-02 09:15:00'); INSERT INTO order_items (order_id, product_id, quantity, unit_price) VALUES (1001, 102, 1, 14999.00), (1001, 103, 1, 499.00), (1002, 103, 1, 499.00), (1003, 101, 1, 2499.00); Another practical example SELECT o.order_id, c.name AS customer, o.status, o.total FROM orders o JOIN customers c ON c.customer_id = o.customer_id WHERE o.total >= 1000 ORDER BY o.ordered_at DESC; Check the result Run the verification query, compare the returned rows with the starter data, and explain why every included or excluded row is correct. Easy example Start with a small customer table and retrieve active customers in a predictable order. SELECT customer_id, name, email FROM customers WHERE status = 'active' ORDER BY name; How to verify the easy example Run it with representative input. Confirm the expected output. Try one missing, invalid, or boundary value. Advanced example Use a CTE and a window function to rank customer revenue while keeping the query readable and testable. WITH customer_revenue AS ( SELECT customer_id, SUM(total_amount) AS revenue FROM orders WHERE order_status = 'completed' GROUP BY customer_id ) SELECT customer_id, revenue, DENSE_RANK() OVER (ORDER BY revenue DESC) AS revenue_rank FROM customer_revenue ORDER BY revenue_rank, customer_id; Advanced review Explain the tradeoffs and assumptions. Test failure, scale, security, and recovery behavior. Capture evidence from tests, execution plans, logs, or review output. Additional practical guidance Introduction to Databases: MySQL and PostgreSQL Model the rule with keys and constraints instead of relying only on application code. MySQL and PostgreSQL support the core relational design, but generated-column, check-constraint, and alteration details can differ by server version. Required verification Run the simple case. Test a NULL, duplicate, empty, or boundary case where relevant. Confirm the affected rows or query result. Use EXPLAIN for performance-sensitive queries.