What is SQL, and how is it different from MySQL?
SQL is the language for defining, reading and changing data in a relational database; MySQL is one database server that runs it, like PostgreSQL, SQL Server, Oracle and SQLite. The core (
SELECT,JOIN,GROUP BY) is the same everywhere, while date functions, pagination and upserts differ by dialect.What are DDL, DML, DCL and TCL commands in SQL?
They group SQL statements by what they act on: structure, data, permissions or transactions.
Group Stands for Commands DDL Data Definition Language CREATE,ALTER,DROP,TRUNCATEDML Data Manipulation Language INSERT,UPDATE,DELETEDCL Data Control Language GRANT,REVOKETCL Transaction Control Language COMMIT,ROLLBACK,SAVEPOINTFollow-up: can you roll back a
DROP TABLE? Not in MySQL or Oracle, where DDL commits the open transaction; in PostgreSQL and SQL Server, yes.What is the difference between a primary key and a unique key?
Both reject duplicates. A table has one primary key, which is never NULL and identifies the row; it can have many unique keys, which usually allow NULL.
SQLCREATE TABLE users (id INTEGER PRIMARY KEY, email TEXT UNIQUE); INSERT INTO users VALUES (1, NULL), (2, NULL), (3, 'asha@example.com'); SELECT COUNT(*) AS total_rows, COUNT(email) AS emails FROM users;The trap is NULL: two NULLs are not equal, so both NULL emails are accepted and the result is
3 | 1. PostgreSQL, MySQL, Oracle and SQLite allow many NULLs in a unique column by default; SQL Server allows one. See unique constraints.Practice it: Contains Duplicate
What is a foreign key, and what does ON DELETE CASCADE do?
A foreign key is a column whose values must exist in another table's primary or unique key, so a child row never points at a missing parent.
ON DELETE CASCADEdeletes the child rows when their parent is deleted.SQLPRAGMA foreign_keys = ON; CREATE TABLE departments (id INTEGER PRIMARY KEY, name TEXT); CREATE TABLE employees ( id INTEGER PRIMARY KEY, name TEXT, dept_id INTEGER REFERENCES departments(id) ON DELETE CASCADE ); INSERT INTO departments VALUES (1, 'Engineering'), (2, 'Sales'); INSERT INTO employees VALUES (1, 'Asha', 1), (2, 'John', 2), (3, 'Priya', 2); DELETE FROM departments WHERE id = 2; SELECT id, name FROM employees;Deleting Sales removes John and Priya, leaving
1 | Asha; withoutCASCADEthe delete would fail. SQLite enforces foreign keys only afterPRAGMA foreign_keys = ON. More in foreign keys.What are the different types of keys in SQL?
A candidate key is a minimal set of columns that identifies a row. The primary key is the candidate key you choose (never NULL); the others are alternate keys, enforced with
UNIQUE. A super key is any unique column set, a composite key spans several columns, and a foreign key references another table's key.Follow-up: natural or surrogate key? Most schemas use a generated
idas the primary key and keep the natural key (email, PAN number) as aUNIQUEalternate key, because natural keys can change.What is the difference between DELETE, TRUNCATE and DROP?
DELETEremoves rows (optionally filtered byWHERE),TRUNCATEremoves every row at once, andDROPremoves the table itself.DELETE TRUNCATE DROP Type DML DDL DDL Speed on big tables Slow, logged per row Fast Fast Fires DELETEtriggersYes No No Resets identity No Yes in MySQL and SQL Server Table is gone Can roll back Yes PostgreSQL and SQL Server: yes; MySQL and Oracle: no Same as TRUNCATE SQLite has no
TRUNCATE;DELETE FROM twithout aWHEREdoes the same job fast.What is the difference between WHERE and HAVING?
WHEREfilters rows before grouping;HAVINGfilters groups afterGROUP BY, so onlyHAVINGcan use aggregates such asCOUNT(*).SQLCREATE TABLE employees (id INTEGER PRIMARY KEY, name TEXT, dept TEXT, salary INTEGER, manager_id INTEGER); INSERT INTO employees VALUES (1, 'Asha', 'Engineering', 120000, NULL), (2, 'Ravi', 'Engineering', 90000, 1), (3, 'Meera', 'Engineering', 90000, 1), (4, 'John', 'Sales', 70000, 1), (5, 'Priya', 'Sales', 82000, 4), (6, 'Karan', 'HR', 60000, 1); SELECT dept, COUNT(*) AS people, SUM(salary) AS payroll FROM employees WHERE salary > 60000 GROUP BY dept HAVING COUNT(*) >= 2 ORDER BY dept;WHEREdrops Karan before grouping, so HR disappears, andHAVINGkeeps Engineering and Sales. Put any condition that needs no aggregate inWHERE, so fewer rows get grouped. More in GROUP BY and HAVING.In what order does SQL execute the clauses of a SELECT query?
Logically:
FROMandJOIN,WHERE,GROUP BY,HAVING,SELECT(window functions included),DISTINCT,ORDER BY, thenLIMIT. The order explains the classic errors: an aggregate or a window function cannot go inWHERE, and aSELECTalias works inORDER BYbut not inWHERE(SQLite allows it as an extension). The optimizer may execute in another physical order with the same result.What does
NULL = NULLreturn in SQL?SQLSELECT NULL = NULL, NULL IS NULL, NULL <> 1;Any comparison with NULL is NULL (unknown), so
NULL = NULLandNULL <> 1are both NULL; onlyIS NULLtests for a missing value. InWHERE, unknown drops the row, soWHERE manager_id = NULLreturns nothing. To treat NULLs as equal, useIS NOT DISTINCT FROM(PostgreSQL, SQLite 3.39+, SQL Server 2022+, see the SQL Server docs) or<=>in MySQL. See operators and NULL.How does
COUNT(*)differ fromCOUNT(column)when the column has NULLs?SQLCREATE TABLE employees (id INTEGER, dept TEXT, bonus INTEGER); INSERT INTO employees VALUES (1, 'Sales', 500), (2, 'Sales', NULL), (3, 'HR', 300), (4, 'HR', NULL), (5, NULL, 200); SELECT COUNT(*), COUNT(bonus), COUNT(DISTINCT dept) FROM employees;COUNT(*)counts rows,COUNT(column)counts non-NULL values, andCOUNT(DISTINCT column)counts distinct non-NULL values: 5 rows, 3 bonuses, 2 departments.COUNT(1)is the same asCOUNT(*)in every major database, with no speed difference.Does
BETWEEN 2 AND 4include its endpoints?SQLCREATE TABLE t (x INTEGER); INSERT INTO t VALUES (1), (2), (3), (4), (5); SELECT COUNT(*) FROM t WHERE x BETWEEN 2 AND 4;BETWEENincludes both ends, so it matches 2, 3 and 4. The trap is timestamps:created_at BETWEEN '2026-01-01' AND '2026-01-31'misses everything after midnight on the 31st. Usecreated_at >= '2026-01-01' AND created_at < '2026-02-01'.What does
SELECT 7 / 2return?SQLSELECT 7 / 2, 7 / 2.0, 7 % 2;With two integers,
/drops the fraction, so7 / 2is 3; make either side a decimal (2.0,x * 1.0) to get 3.5. That holds in SQLite, PostgreSQL and SQL Server; MySQL and Oracle return a decimal. It bites in ratios: write100.0 * COUNT(*) / total.What is the difference between CHAR and VARCHAR?
CHAR(n)is fixed length and pads shorter values with spaces;VARCHAR(n)stores only what you give it, up to n. UseCHARfor fixed-size codes likeINR.SQLCREATE TABLE countries (code VARCHAR(3)); INSERT INTO countries VALUES ('INDIA'); SELECT code, length(code) FROM countries;SQLite prints
INDIA | 5because it never enforces a declared length; evenSTRICTtables only check the base type, and they rejectVARCHARas a column type. PostgreSQL, SQL Server, Oracle and strict-mode MySQL reject the insert. More on type affinity.How do auto-increment ids work in MySQL, PostgreSQL, SQL Server and SQLite?
Each database has its own syntax for a column that numbers new rows:
-- MySQL CREATE TABLE orders (id INT AUTO_INCREMENT PRIMARY KEY, item VARCHAR(50)); -- PostgreSQL 10+ and Oracle 12c+ (standard); older PostgreSQL used SERIAL CREATE TABLE orders (id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, item TEXT); -- SQL Server CREATE TABLE orders (id INT IDENTITY(1, 1) PRIMARY KEY, item VARCHAR(50));In SQLite an
INTEGER PRIMARY KEYis the row id and gets the largest id plus one, so withoutAUTOINCREMENTit can reuse a deleted last id; see the SQLite AUTOINCREMENT docs. The others do not reuse a value (MySQL before 8.0 could after a restart) but leave gaps (a rolled-back insert burns its number), so never count rows withMAX(id).How do you replace NULL with a default value in SQL?
Use
COALESCE(a, b, ...), which returns its first non-NULL argument in every database.SQLCREATE TABLE contacts (name TEXT, phone TEXT, email TEXT); INSERT INTO contacts VALUES ('Asha', NULL, 'asha@example.com'), ('Ravi', '98450 12345', NULL), ('Meera', NULL, NULL); SELECT name, COALESCE(phone, email, 'no contact') AS contact FROM contacts;Two-argument versions:
IFNULL(MySQL, SQLite),ISNULL(SQL Server),NVL(Oracle). The reverse,NULLIF(a, b), returns NULL whena = b, which avoids division by zero:total / NULLIF(count, 0).How do the LIKE wildcards % and _ work?
%matches any run of characters, including none, and_matches exactly one, so'_a%'means "second letter is a".SQLCREATE TABLE employees (id INTEGER PRIMARY KEY, name TEXT, dept TEXT, salary INTEGER, manager_id INTEGER); INSERT INTO employees VALUES (1, 'Asha', 'Engineering', 120000, NULL), (2, 'Ravi', 'Engineering', 90000, 1), (3, 'Meera', 'Engineering', 90000, 1), (4, 'John', 'Sales', 70000, 1), (5, 'Priya', 'Sales', 82000, 4), (6, 'Karan', 'HR', 60000, 1); SELECT name FROM employees WHERE name LIKE '_a%' ORDER BY name;The result is Karan and Ravi. PostgreSQL and Oracle
LIKEis case-sensitive (PostgreSQL addsILIKE); SQLite (ASCII letters only), MySQL and SQL Server ignore case by default. A leading%cannot use a B-tree index; a prefix like'kum%'can.What constraints can you put on a column in SQL?
NOT NULL,UNIQUE,PRIMARY KEY,FOREIGN KEY,CHECKandDEFAULT. They make the database reject bad data whichever application writes it.SQL-- fails on purpose: the CHECK constraint rejects a negative price CREATE TABLE products ( id INTEGER PRIMARY KEY, name TEXT NOT NULL, price REAL CHECK (price >= 0), stock INTEGER DEFAULT 0 ); INSERT INTO products (name, price) VALUES ('Pen', 20); INSERT INTO products (name, price) VALUES ('Refund', -5);The second insert fails with
CHECK constraint failed: price >= 0; the first getsstock = 0from the default. MySQL parsed and ignoredCHECKbefore 8.0.16; see the MySQL CHECK docs.What is a view in SQL, and why would you use one?
A view is a saved
SELECTyou query like a table. It stores the query, not the data, so it always shows current rows.SQLCREATE TABLE employees (id INTEGER PRIMARY KEY, name TEXT, dept TEXT, salary INTEGER, manager_id INTEGER); INSERT INTO employees VALUES (1, 'Asha', 'Engineering', 120000, NULL), (2, 'Ravi', 'Engineering', 90000, 1), (3, 'Meera', 'Engineering', 90000, 1), (4, 'John', 'Sales', 70000, 1), (5, 'Priya', 'Sales', 82000, 4), (6, 'Karan', 'HR', 60000, 1); CREATE VIEW high_earners AS SELECT name, dept, salary FROM employees WHERE salary > 85000; SELECT * FROM high_earners ORDER BY salary DESC, name;Use one to hide a complex join behind a name or to expose only some columns. A materialized view (PostgreSQL, Oracle) stores the result and must be refreshed; an indexed view in SQL Server stores it too and is updated on every write. See views.
Where do NULLs land when you
ORDER BYa column ascending?SQLCREATE TABLE t (x INTEGER); INSERT INTO t VALUES (3), (NULL), (1); SELECT x FROM t ORDER BY x LIMIT 1;SQLite, MySQL and SQL Server sort NULL first in ascending order, so the first row is NULL; PostgreSQL and Oracle put NULLs last. Say what you want:
ORDER BY x NULLS LAST(PostgreSQL, Oracle, SQLite 3.30+), orORDER BY CASE WHEN x IS NULL THEN 1 ELSE 0 END, xanywhere.How do you return only the first N rows (LIMIT, TOP, FETCH FIRST)?
Sort with
ORDER BY, then cut:LIMIT nin MySQL, PostgreSQL and SQLite,TOP nin SQL Server, and the standardFETCH FIRST n ROWS ONLYin PostgreSQL, Oracle 12c+ and SQL Server (afterOFFSET 0 ROWS).SQLCREATE TABLE employees (id INTEGER PRIMARY KEY, name TEXT, dept TEXT, salary INTEGER, manager_id INTEGER); INSERT INTO employees VALUES (1, 'Asha', 'Engineering', 120000, NULL), (2, 'Ravi', 'Engineering', 90000, 1), (3, 'Meera', 'Engineering', 90000, 1), (4, 'John', 'Sales', 70000, 1), (5, 'Priya', 'Sales', 82000, 4), (6, 'Karan', 'HR', 60000, 1); SELECT name, salary FROM employees ORDER BY salary DESC, name LIMIT 3;The result is Asha, Meera and Ravi. Without
ORDER BYyou get any 3 rows, and since Ravi and Meera tie at 90000,nameis what fixes the order. More in LIMIT and OFFSET.
SQL Basics Interview Questions
Keys, constraints, NULL, filtering and the basic commands, with several predict-the-output questions.