SQL Complete Study Guide
MySQL Server Edition
SELECT • Operators • Constraints • Joins | UMT Lahore — Spring 2026
SECTION 1: SELECT Query & Operators
Source: Lab 09 | Applied in: Task File 04 (DB Super Store)
1.1 SELECT Statement
Definition: Retrieves data from one or more columns of a table. Use * to select all columns.
Syntax:
SELECT column1, column2 FROM table_name;
SELECT * FROM table_name; -- all columns
MySQL Example:
SELECT firstName, lastName
FROM customers;
1.2 WHERE Clause
Definition: Filters rows — only rows where the condition evaluates to TRUE are returned.
Syntax:
SELECT column1, column2
FROM table_name
WHERE condition;
MySQL Example:
SELECT firstName, lastName
FROM customers
WHERE customerID = 1;
1.3 Comparison Operators
Used inside WHERE to compare column values. All standard in MySQL.
Operator Meaning & MySQL Example
= Equal to: WHERE Fruit = 'Oranges'
!= or <> Not equal: WHERE Size != 'Small'
> Greater than: WHERE Price > 800
< Less than: WHERE Quantity < 5
>= Greater or equal: WHERE Price >= 500
<= Less or equal: WHERE Quantity <= 10
1.4 NOT Operator
Definition: Reverses a condition — excludes rows that match.
SELECT * FROM DBSuperStore
WHERE NOT Fruit = 'Apples';
➡ Returns every row except Apples.
1.5 LIKE Operator
Definition: Pattern matching on text columns. MySQL LIKE is case-insensitive by default.
Wildcard Meaning
% Zero or more characters → 'A%' = starts with A
_ Exactly ONE character → 'A_' = A followed by any one char
-- Starts with A
SELECT * FROM DBSuperStore WHERE Fruit LIKE 'A%';
-- Ends with s
SELECT * FROM DBSuperStore WHERE Fruit LIKE '%s';
-- Contains 'ap' anywhere (case-insensitive in MySQL)
SELECT * FROM DBSuperStore WHERE Fruit LIKE '%ap%';
-- Name is exactly 6 characters
SELECT * FROM DBSuperStore WHERE Fruit LIKE '______';
1.6 BETWEEN Operator
Definition: Filters rows within a range. Both boundary values are INCLUSIVE. Works on
numbers, text, and dates.
SELECT * FROM DBSuperStore
WHERE Price BETWEEN 400 AND 900;
-- Equivalent to:
SELECT * FROM DBSuperStore
WHERE Price >= 400 AND Price <= 900;
1.7 IN Operator
Definition: Checks if a value matches any item in a list. Cleaner than writing multiple OR
conditions.
SELECT * FROM DBSuperStore
WHERE Fruit IN ('Oranges', 'Apples');
-- Same as:
SELECT * FROM DBSuperStore
WHERE Fruit = 'Oranges' OR Fruit = 'Apples';
1.8 ORDER BY
Definition: Sorts result rows. ASC = ascending (default), DESC = descending. Can sort by
multiple columns.
-- Single column ascending
SELECT * FROM DBSuperStore ORDER BY Price ASC;
-- Single column descending
SELECT * FROM DBSuperStore ORDER BY Quantity DESC;
-- Multi-column: sort by Fruit name, then by Price within same fruit
SELECT * FROM DBSuperStore ORDER BY Fruit ASC, Price ASC;
1.9 AND / OR Logical Operators
AND: both conditions must be true. OR: at least one condition must be true.
-- AND: Oranges with Large size only
SELECT * FROM DBSuperStore
WHERE Fruit = 'Oranges' AND Size = 'Large';
-- OR: Apples OR anything Medium-sized
SELECT * FROM DBSuperStore
WHERE Fruit = 'Apples' OR Size = 'Medium';
🔗 Task File 04 — DB Super Store (MySQL)
📝 Task 1: Create the Table
Create DBSuperStore with all 5 columns. Use AUTO_INCREMENT for SrNo in MySQL:
CREATE DATABASE IF NOT EXISTS superstore;
USE superstore;
CREATE TABLE DBSuperStore (
SrNo INT AUTO_INCREMENT PRIMARY KEY,
Fruit VARCHAR(50) NOT NULL,
Quantity INT NOT NULL,
Price INT NOT NULL,
Size VARCHAR(20) NOT NULL
);
INSERT INTO DBSuperStore (Fruit, Quantity, Price, Size) VALUES
('Oranges', 10, 500, 'Small'),
('Apples', 5, 1400, 'Large'),
('Grapes', 7, 1200, 'Medium'),
('Pine Apple', 8, 700, 'Small'),
('Oranges', 2, 850, 'Large'),
('Oranges', 7, 650, 'Large'),
('Grapes', 4, 300, 'Medium'),
('Grapes', 10, 200, 'Small'),
('Oranges', 11, 450, 'Large'),
('Apples', 12, 900, 'Small');
📝 Task 2a: Select all Oranges
Basic WHERE with = operator:
SELECT * FROM DBSuperStore WHERE Fruit = 'Oranges';
📝 Task 2b: Price greater than 800
Use > comparison operator:
SELECT * FROM DBSuperStore WHERE Price > 800;
📝 Task 2c: Size is Small
Filter by exact text match:
SELECT * FROM DBSuperStore WHERE Size = 'Small';
📝 Task 2d: Quantity less than 5
Use < operator:
SELECT * FROM DBSuperStore WHERE Quantity < 5;
📝 Task 2e: Sort by Price ascending & Quantity descending
Use ORDER BY with ASC and DESC:
-- Ascending by Price
SELECT * FROM DBSuperStore ORDER BY Price ASC;
-- Descending by Quantity
SELECT * FROM DBSuperStore ORDER BY Quantity DESC;
-- Multi-sort: Fruit name, then Price
SELECT * FROM DBSuperStore ORDER BY Fruit ASC, Price ASC;
📝 Task 2f: Oranges AND Large size
AND requires both conditions to be true:
SELECT * FROM DBSuperStore WHERE Fruit = 'Oranges' AND Size = 'Large';
📝 Task 2g: Price BETWEEN 400 and 900
BETWEEN is inclusive at both ends:
SELECT * FROM DBSuperStore WHERE Price BETWEEN 400 AND 900;
📝 Task 2h: Name starts with A / ends with s / contains ap
LIKE with % wildcard — MySQL LIKE is case-insensitive by default:
SELECT * FROM DBSuperStore WHERE Fruit LIKE 'A%'; -- starts with A
SELECT * FROM DBSuperStore WHERE Fruit LIKE '%s'; -- ends with s
SELECT * FROM DBSuperStore WHERE Fruit LIKE '%ap%'; -- contains ap
📝 Task 2i: Fruits with at least two vowels AND Quantity < 10
MySQL REGEXP matches patterns. [aeiouAEIOU] matches any vowel:
SELECT * FROM DBSuperStore
WHERE Fruit REGEXP '[aeiouAEIOU].*[aeiouAEIOU]'
AND Quantity < 10;
📝 Task 2j: Second highest Price
Subquery: find MAX price that is less than the overall MAX:
SELECT * FROM DBSuperStore
WHERE Price = (
SELECT MAX(Price) FROM DBSuperStore
WHERE Price < (SELECT MAX(Price) FROM DBSuperStore)
);
📝 Task 2k: Oranges or Grapes with Price > average
IN for multiple fruit names + subquery for AVG:
SELECT * FROM DBSuperStore
WHERE Fruit IN ('Oranges', 'Grapes')
AND Price > (SELECT AVG(Price) FROM DBSuperStore);
📝 Task 2l: Price 500–1200 BUT name does NOT contain 'e'
BETWEEN for range + NOT LIKE to exclude names with 'e':
SELECT * FROM DBSuperStore
WHERE Price BETWEEN 500 AND 1200
AND Fruit NOT LIKE '%e%';
SECTION 2: SQL Constraints
Source: Lab 12 | Applied in: Task File 05 (University Database)
Definition: Constraints are rules on table columns that protect data integrity. They are enforced
by MySQL automatically on every INSERT and UPDATE.
2.1 NOT NULL
Definition: Column must always have a value — NULL is not allowed.
CREATE TABLE syntax:
CREATE TABLE Student (
rollNumber INT NOT NULL,
name VARCHAR(50) NOT NULL,
cgpa FLOAT NULL -- NULL allowed here
);
ALTER TABLE syntax (MySQL):
ALTER TABLE Student
MODIFY COLUMN rollNumber INT NOT NULL;
⚠️MySQL Note: MySQL uses MODIFY COLUMN, not ALTER COLUMN, to change a column
definition.
2.2 UNIQUE
Definition: No two rows can store the same value in this column (or combination of columns).
CREATE TABLE Student (
rollNumber INT NOT NULL,
cnic VARCHAR(20) NOT NULL UNIQUE,
email VARCHAR(100) NOT NULL,
UNIQUE (email)
);
Add UNIQUE with ALTER TABLE:
ALTER TABLE Student
ADD CONSTRAINT uq_student_cnic UNIQUE (cnic);
-- Composite unique (combination must be unique):
ALTER TABLE Student
ADD CONSTRAINT uq_cnic_name UNIQUE (cnic, name);
2.3 PRIMARY KEY
Definition: Uniquely identifies every row. Enforces NOT NULL + UNIQUE automatically. One
primary key per table (can span multiple columns = composite PK).
-- Inline definition
CREATE TABLE Student (
rollNumber INT PRIMARY KEY,
name VARCHAR(50) NOT NULL
);
-- Table-level definition
CREATE TABLE Student (
rollNumber INT,
name VARCHAR(50) NOT NULL,
PRIMARY KEY (rollNumber)
);
-- Composite Primary Key
CREATE TABLE Enrollment (
studentID INT,
courseID INT,
PRIMARY KEY (studentID, courseID)
);
Add with ALTER TABLE:
ALTER TABLE Student
MODIFY COLUMN rollNumber INT NOT NULL,
ADD PRIMARY KEY (rollNumber);
2.4 FOREIGN KEY
Definition: Links a column to the PRIMARY KEY of another table. Prevents inserting a value that
doesn't exist in the referenced table.
CREATE TABLE Student (
rollNumber INT PRIMARY KEY,
deptId INT,
FOREIGN KEY (deptId) REFERENCES Department(departmentId)
);
-- With ON DELETE / ON UPDATE actions:
CREATE TABLE Student (
rollNumber INT PRIMARY KEY,
deptId INT,
CONSTRAINT fk_student_dept
FOREIGN KEY (deptId) REFERENCES Department(departmentId)
ON DELETE NO ACTION
ON UPDATE CASCADE
);
Add with ALTER TABLE:
ALTER TABLE Student
ADD CONSTRAINT fk_student_dept
FOREIGN KEY (deptId) REFERENCES Department(departmentId)
ON UPDATE CASCADE ON DELETE NO ACTION;
Action Effect on foreign key when parent row changes
CASCADE FK value updated/deleted automatically to match parent
SET NULL FK set to NULL (column must allow NULL)
NO ACTION Parent row cannot be changed if a child row references it
RESTRICT Same as NO ACTION in MySQL (checked immediately)
2.5 CHECK Constraint
Definition: Restricts the range of values allowed in a column. MySQL 8.0.16+ fully enforces
CHECK constraints.
CREATE TABLE Student (
rollNumber INT,
cgpa FLOAT CHECK (cgpa >= 0.0 AND cgpa <= 4.0),
gender VARCHAR(10) CHECK (gender IN ('Male', 'Female'))
);
Add with ALTER TABLE:
ALTER TABLE Student
ADD CONSTRAINT chk_cgpa CHECK (cgpa >= 0.0 AND cgpa <= 4.0);
⚠️MySQL Note: CHECK constraints are silently ignored in MySQL versions before 8.0.16.
Always use MySQL 8.0.16 or newer for CHECK to work.
2.6 DEFAULT Constraint
Definition: Automatically inserts a preset value when no value is provided during INSERT.
CREATE TABLE Enrollment (
enrollmentID INT AUTO_INCREMENT PRIMARY KEY,
grade VARCHAR(10) DEFAULT 'Pending',
marks INT DEFAULT 0
);
Add / Modify with ALTER TABLE (MySQL):
-- Set a default
ALTER TABLE Student ALTER cgpa SET DEFAULT 0.0;
-- Remove a default
ALTER TABLE Student ALTER cgpa DROP DEFAULT;
2.7 GROUP BY
Definition: Collapses rows that share the same value into one summary row per group. Always
used with aggregate functions.
Aggregate Function What it computes
COUNT(*) Number of rows in the group
SUM(col) Total of all values in the column
AVG(col) Average of all values in the column
MAX(col) Largest value in the column
MIN(col) Smallest value in the column
Syntax:
SELECT column_name, aggregate_function(column_name)
FROM table_name
GROUP BY column_name;
MySQL Example:
SELECT DepartmentID, COUNT(*) AS TeacherCount
FROM Teachers
GROUP BY DepartmentID;
2.8 HAVING Clause
Definition: Filters groups produced by GROUP BY. WHERE filters individual rows before
grouping; HAVING filters groups after grouping.
Syntax:
SELECT column_name, aggregate_function(column_name)
FROM table_name
GROUP BY column_name
HAVING aggregate_condition;
MySQL Example:
SELECT DepartmentID, COUNT(*) AS TeacherCount
FROM Teachers
GROUP BY DepartmentID
HAVING COUNT(*) > 1;
🔗 Task File 05 — University Database (MySQL)
Step 1 — Create the database and tables:
CREATE DATABASE IF NOT EXISTS university;
USE university;
CREATE TABLE Departments (
DepartmentID INT AUTO_INCREMENT PRIMARY KEY,
DepartmentName VARCHAR(100) NOT NULL UNIQUE,
Budget DECIMAL(12,2) CHECK (Budget >= 100000)
);
CREATE TABLE Teachers (
TeacherID INT AUTO_INCREMENT PRIMARY KEY,
FirstName VARCHAR(50) NOT NULL,
LastName VARCHAR(50) NOT NULL,
Gender VARCHAR(10) CHECK (Gender IN ('Male','Female')),
Salary DECIMAL(10,2) CHECK (Salary >= 30000),
Email VARCHAR(100) UNIQUE,
HireDate DATE NOT NULL,
DepartmentID INT,
FOREIGN KEY (DepartmentID) REFERENCES Departments(DepartmentID)
);
CREATE TABLE Students (
StudentID INT AUTO_INCREMENT PRIMARY KEY,
FirstName VARCHAR(50) NOT NULL,
LastName VARCHAR(50) NOT NULL,
Gender VARCHAR(10) CHECK (Gender IN ('Male','Female')),
Age INT CHECK (Age >= 17),
Email VARCHAR(100) UNIQUE,
EnrollmentDate DATE NOT NULL,
DepartmentID INT,
FOREIGN KEY (DepartmentID) REFERENCES Departments(DepartmentID)
);
CREATE TABLE Courses (
CourseID INT AUTO_INCREMENT PRIMARY KEY,
CourseName VARCHAR(100) NOT NULL UNIQUE,
CreditHours INT CHECK (CreditHours BETWEEN 1 AND 4),
DepartmentID INT,
FOREIGN KEY (DepartmentID) REFERENCES Departments(DepartmentID)
);
CREATE TABLE Enrollments (
EnrollmentID INT AUTO_INCREMENT PRIMARY KEY,
Semester VARCHAR(20) NOT NULL,
Marks INT CHECK (Marks BETWEEN 0 AND 100),
Grade VARCHAR(10) DEFAULT 'Pending',
StudentID INT,
CourseID INT,
FOREIGN KEY (StudentID) REFERENCES Students(StudentID),
FOREIGN KEY (CourseID) REFERENCES Courses(CourseID)
);
📝 Task 1: Count students in each department
GROUP BY DepartmentID + COUNT(*). JOIN to Departments to show the name:
SELECT [Link], COUNT([Link]) AS StudentCount
FROM Departments d
LEFT JOIN Students s ON [Link] = [Link]
GROUP BY [Link], [Link];
📝 Task 2: Average teacher salary per department
GROUP BY + AVG() aggregate:
SELECT [Link], AVG([Link]) AS AvgSalary
FROM Teachers t
JOIN Departments d ON [Link] = [Link]
GROUP BY [Link], [Link];
📝 Task 3: Departments with more than 1 teacher
GROUP BY + HAVING COUNT(*) > 1:
SELECT [Link], COUNT([Link]) AS TeacherCount
FROM Teachers t
JOIN Departments d ON [Link] = [Link]
GROUP BY [Link], [Link]
HAVING COUNT([Link]) > 1;
📝 Task 4: Courses where average marks > 75
GROUP BY CourseID + HAVING AVG(Marks) > 75:
SELECT [Link], AVG([Link]) AS AvgMarks
FROM Enrollments e
JOIN Courses c ON [Link] = [Link]
GROUP BY [Link], [Link]
HAVING AVG([Link]) > 75;
📝 Task 5: Highest marks in each course
GROUP BY CourseID + MAX():
SELECT [Link], MAX([Link]) AS HighestMarks
FROM Enrollments e
JOIN Courses c ON [Link] = [Link]
GROUP BY [Link], [Link];
📝 Task 6: Department with highest budget
Subquery finds MAX budget; outer query fetches the matching row:
SELECT *
FROM Departments
WHERE Budget = (SELECT MAX(Budget) FROM Departments);
📝 Task 7: Students enrolled in more than 1 course
GROUP BY StudentID + HAVING COUNT(*) > 1:
SELECT [Link], [Link], COUNT([Link]) AS CourseCount
FROM Enrollments e
JOIN Students s ON [Link] = [Link]
GROUP BY [Link], [Link], [Link]
HAVING COUNT([Link]) > 1;
SECTION 3: SQL Joins
Source: Joins Lab | Applied in: Task File 06 (Shops Database)
Definition: A JOIN merges rows from two or more tables by matching values in related columns
(usually a foreign key to a primary key). Without a JOIN you would need separate queries and
manual matching.
3.0 Shops Database Schema
CREATE DATABASE IF NOT EXISTS shops;
USE shops;
CREATE TABLE customers (
customerID INT AUTO_INCREMENT PRIMARY KEY,
firstName VARCHAR(50) NOT NULL,
lastName VARCHAR(50) NOT NULL,
email VARCHAR(100) NOT NULL,
password VARCHAR(255) NOT NULL
);
CREATE TABLE categories (
categoryID INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(50) NOT NULL
);
CREATE TABLE products (
productID INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
price DECIMAL(10,2) NOT NULL,
categoryID INT NOT NULL,
FOREIGN KEY (categoryID) REFERENCES categories(categoryID)
);
CREATE TABLE orders (
orderID INT AUTO_INCREMENT PRIMARY KEY,
customerID INT NOT NULL,
orderDate DATE NOT NULL,
FOREIGN KEY (customerID) REFERENCES customers(customerID)
);
CREATE TABLE orderDetails (
orderID INT NOT NULL,
productID INT NOT NULL,
quantity INT NOT NULL,
PRIMARY KEY (orderID, productID),
FOREIGN KEY (orderID) REFERENCES orders(orderID),
FOREIGN KEY (productID) REFERENCES products(productID)
);
3.1 INNER JOIN
Definition: Returns ONLY rows with a match in BOTH tables. Non-matching rows are excluded
entirely.
Syntax:
SELECT columns
FROM table1
INNER JOIN table2 ON [Link] = [Link];
MySQL Example:
SELECT [Link], [Link]
FROM customers c
INNER JOIN orders o ON [Link] = [Link];
➡ Customers who have NEVER placed an order will NOT appear.
3.2 LEFT JOIN
Definition: Returns ALL rows from the LEFT table plus matching rows from the right. If no match
exists on the right, those columns show NULL.
SELECT [Link], [Link], [Link]
FROM customers c
LEFT JOIN orders o ON [Link] = [Link];
➡ Every customer appears. Customers with no orders show NULL for orderID and orderDate.
3.3 RIGHT JOIN
Definition: Returns ALL rows from the RIGHT table plus matching rows from the left. If no match
on the left, those columns show NULL.
SELECT [Link], [Link]
FROM customers c
RIGHT JOIN orders o ON [Link] = [Link];
➡ Every order appears. Orders with no matching customer show NULL for firstName.
3.4 FULL OUTER JOIN (MySQL workaround)
MySQL does NOT support FULL OUTER JOIN syntax. Simulate it with UNION of LEFT JOIN
and RIGHT JOIN:
SELECT [Link], [Link]
FROM customers c
LEFT JOIN orders o ON [Link] = [Link]
UNION
SELECT [Link], [Link]
FROM customers c
RIGHT JOIN orders o ON [Link] = [Link];
⚠️MySQL Note: UNION removes duplicate rows automatically. Use UNION ALL to keep
duplicates.
3.5 Join Type Summary
Join Type Rows Returned Unmatched rows
INNER JOIN Matched rows only Excluded completely
LEFT JOIN All LEFT + matched RIGHT RIGHT side → NULL
RIGHT JOIN Matched LEFT + all RIGHT LEFT side → NULL
FULL OUTER JOIN All from both (via UNION) Both sides → NULL
🔗 Task File 06 — Shops Database Join Tasks (MySQL)
📝 Task 1: Customer Orders
Customer name + order ID + order date. Link customers → orders via customerID using INNER
JOIN:
SELECT [Link], [Link],
[Link], [Link]
FROM customers c
INNER JOIN orders o ON [Link] = [Link];
📝 Task 2: Order Details
Order ID + product name + quantity. Link orderDetails → products via productID:
SELECT [Link],
[Link] AS ProductName,
[Link]
FROM orderDetails od
INNER JOIN products p ON [Link] = [Link];
📝 Task 3: Products with Categories
Product name + price + category name. Link products → categories via categoryID:
SELECT [Link] AS ProductName,
[Link],
[Link] AS CategoryName
FROM products p
INNER JOIN categories c ON [Link] = [Link];
📝 Task 4: Product Category Sales
Product Name + Category Name + Quantity Ordered. Chain: orderDetails → products →
categories (3 tables):
SELECT [Link] AS ProductName,
[Link] AS CategoryName,
[Link] AS QuantityOrdered
FROM orderDetails od
INNER JOIN products p ON [Link] = [Link]
INNER JOIN categories c ON [Link] = [Link];
📝 Task 5: Products Never Ordered (LEFT JOIN)
Include products with NO orders. LEFT JOIN from products to orderDetails — unordered
products get NULL in orderDetails columns:
SELECT [Link] AS ProductName,
[Link],
[Link]
FROM products p
LEFT JOIN orderDetails od ON [Link] = [Link];
-- To show ONLY products never ordered:
SELECT [Link] AS ProductName
FROM products p
LEFT JOIN orderDetails od ON [Link] = [Link]
WHERE [Link] IS NULL;
📝 Task 6: Ordered Products Report (RIGHT JOIN)
Show ALL order details even if product info is missing. RIGHT JOIN ensures every orderDetails
row appears:
SELECT [Link] AS ProductName,
[Link],
[Link]
FROM products p
RIGHT JOIN orderDetails od ON [Link] = [Link];
📝 Task 7: Complete Order Report
Customer Name + Order ID + Order Date + Product Name + Quantity. Chain all 4 tables:
customers → orders → orderDetails → products:
SELECT [Link], [Link],
[Link], [Link],
[Link] AS ProductName,
[Link]
FROM customers c
INNER JOIN orders o ON [Link] = [Link]
INNER JOIN orderDetails od ON [Link] = [Link]
INNER JOIN products p ON [Link] = [Link];
📝 Task 8: Order Cost Report
Order ID + Product Name + Quantity + Price + Total Cost. Computed column: [Link] *
[Link] AS TotalCost:
SELECT [Link],
[Link] AS ProductName,
[Link],
[Link],
([Link] * [Link]) AS TotalCost
FROM orders o
INNER JOIN orderDetails od ON [Link] = [Link]
INNER JOIN products p ON [Link] = [Link];
Quick Reference — MySQL
Clause Execution Order in MySQL
-- Written order: Execution order:
SELECT -- 6. SELECT (columns evaluated here)
FROM -- 1. FROM (identify tables)
JOIN ... ON -- 2. JOIN (combine tables)
WHERE -- 3. WHERE (filter rows)
GROUP BY -- 4. GROUP BY (create groups)
HAVING -- 5. HAVING (filter groups)
ORDER BY -- 7. ORDER BY (sort results)
LIMIT -- 8. LIMIT (restrict row count)
WHERE vs HAVING — Key Difference
WHERE HAVING
Filters Individual rows Groups (after GROUP BY)
Uses agg? ❌ Cannot use COUNT/SUM ✅ Can use COUNT/SUM
Runs when? Before grouping After grouping
Example WHERE Salary > 30000 HAVING COUNT(*) > 2
MySQL-Specific Reminders
Topic MySQL Behaviour
ALTER COLUMN MySQL uses MODIFY COLUMN, not ALTER COLUMN
FULL OUTER JOIN Not supported — use LEFT JOIN UNION RIGHT JOIN
CHECK constraint Only enforced in MySQL 8.0.16+
AUTO_INCREMENT MySQL keyword for auto-incrementing primary keys
LIKE case LIKE is case-insensitive by default in MySQL
String quotes Use single quotes '' for strings — double quotes work but '' is
standard SQL
DROP CONSTRAINT MySQL: ALTER TABLE t DROP FOREIGN KEY fk_name
REGEXP MySQL supports REGEXP for regex pattern matching in WHERE
— End of Study Guide (MySQL Edition) —