SQL for Data Analysis

Creating Tables and Changing Data

Lesson 11 of 13

So far you have only read data. Analysts also create tables for their own work and occasionally correct data.

CREATE TABLE

A table definition lists each column, its type and its rules.

CREATE TABLE reviews (
    review_id   INTEGER PRIMARY KEY,
    product_id  INTEGER NOT NULL REFERENCES products(product_id),
    rating      INTEGER NOT NULL CHECK (rating BETWEEN 1 AND 5),
    comment     TEXT,
    review_date TEXT NOT NULL DEFAULT CURRENT_DATE
);

SELECT name FROM sqlite_master WHERE type = 'table';

Constraints

Constraints are rules the database enforces on every row.

Constraint Rule
PRIMARY KEY Identifies each row. Unique and not null
FOREIGN KEY / REFERENCES The value must exist in another table
NOT NULL A value is required
UNIQUE No two rows may share the value
CHECK The value must satisfy a condition
DEFAULT The value used when none is given

Constraints stop bad data at the door, which is far cheaper than cleaning it later.

Data types

Common types are INTEGER, REAL or DECIMAL for numbers, TEXT or VARCHAR for text, DATE and TIMESTAMP for dates and times, and BOOLEAN. SQLite is flexible about types and stores dates as text; most other databases enforce types strictly.

INSERT

CREATE TABLE reviews (
    review_id  INTEGER PRIMARY KEY,
    product_id INTEGER NOT NULL,
    rating     INTEGER NOT NULL CHECK (rating BETWEEN 1 AND 5),
    comment    TEXT
);

INSERT INTO reviews (product_id, rating, comment)
VALUES (1, 5, 'Fast and light'),
       (1, 4, 'Good value'),
       (4, 2, 'Stopped working');

SELECT * FROM reviews;

Always list the columns. The statement then keeps working if someone adds a column to the table. Try changing a rating to 9 and run it again: the CHECK constraint rejects the row.

You can also insert the result of a query with INSERT INTO ... SELECT ....

UPDATE

UPDATE products
SET price = ROUND(price * 1.10, 2)
WHERE category = 'Accessories';

SELECT name, category, price FROM products;

An UPDATE without a WHERE clause changes every row in the table.

DELETE

DELETE FROM orders
WHERE status = 'cancelled';

SELECT order_id, status FROM orders;

A DELETE without WHERE removes every row. Before running an update or delete, run a SELECT with the same WHERE clause to see exactly which rows will be affected.

Transactions

A transaction groups statements so that they all succeed or all fail. COMMIT makes the changes permanent and ROLLBACK undoes them.

BEGIN;

UPDATE products SET price = 0;
SELECT name, price FROM products;

ROLLBACK;

SELECT name, price FROM products;

The first result shows every price at zero. After ROLLBACK, the prices are back. Wrapping risky changes in a transaction lets you check the result before you commit.

Views

A view is a saved query that you can use like a table. It stores the definition, not the data.

CREATE VIEW order_totals AS
SELECT oi.order_id,
       SUM(oi.quantity * p.price) AS order_total
FROM order_items AS oi
JOIN products AS p ON p.product_id = oi.product_id
GROUP BY oi.order_id;

SELECT * FROM order_totals ORDER BY order_total DESC LIMIT 3;

Views give a team one agreed definition of a calculation such as order total.

Changing and removing tables

ALTER TABLE reviews ADD COLUMN verified INTEGER; adds a column. DROP TABLE reviews; deletes the table and all its data.

Practice

Create a table suppliers with an id, a required name and a country that defaults to ‘Unknown’. Insert two rows and select them.