📌 Snapshot
- SQL in one chapter: create tables, add keys, insert, query, group and join, with the result of every query shown.
- How to read a SELECT query clause by clause, and why WHERE cannot filter groups but HAVING can.
- Data types, constraints, ALTER variants and the string, math, date and aggregate functions in comparison tables.
- Worked queries on the EMPLOYEE, SALE and INVENTORY tables, plus UNION, Cartesian product and JOIN traces.
📖 Detailed Notes
Written and reviewed by Rohit Singh, Computer Science & Commerce faculty at UniDrill (MCA, Osmania University · 6 years teaching). Based on NCERT Computer Science Class XII, Chapter 9.
Why can you ask a database "what" and not "how"?
In a file system you write a program that loops through records. With a database you write one line, such as "give me the names of employees earning more than 45,000", and the DBMS works out how to find them. That is the big idea behind SQL (Structured Query Language): you state what you want, not how to get it. SQL is the most popular query language of relational DBMS software such as MySQL, Oracle and SQL Server. The name says "query", but SQL also defines the structure of data, inserts and changes data, and declares constraints.
In MySQL, three habits matter. SQL keywords are not case sensitive (salary and SALARY are the same column). Every statement ends with a semicolon. A statement can run over several lines: the prompt changes from mysql> to -> and you put the ; only after the last line. Text and date values go in single quotes.
Data types and constraints
Each column has a data type, which decides what values it holds and what operations are allowed. Arithmetic works on numbers but not on text.
| Data type | What it stores | Key facts |
|---|---|---|
| CHAR(n) | Fixed length text, n from 0 to 255 | CHAR(10) always reserves 10 characters; 'city' (4 characters) is padded with 6 spaces |
| VARCHAR(n) | Variable length text, n up to 65535 | VARCHAR(30) allows at most 30 characters but 'city' uses space for only 4 |
| INT | Whole numbers | 4 bytes; unsigned range 0 to 4,294,967,295; for larger values use BIGINT (8 bytes) |
| FLOAT | Numbers with a decimal point | 4 bytes |
| DATE | A date | Format 'YYYY-MM-DD'; range '1000-01-01' to '9999-12-31' |
Pick CHAR for data of fixed length that you will never calculate with, such as a 12 digit guardian ID or a 10 digit phone number, and VARCHAR for names and addresses whose length varies.
Constraints are restrictions on the values a column can take, so the data stays correct.
| Constraint | What it ensures |
|---|---|
| NOT NULL | The column can never be NULL (missing, unknown or not applicable) |
| UNIQUE | All values in the column are different |
| DEFAULT | A fallback value is used when none is supplied |
| PRIMARY KEY | Uniquely identifies each row (combines NOT NULL with UNIQUE) |
| FOREIGN KEY | The column must hold a value that exists as a primary key in another table |
By default every column accepts NULL, except the primary key.
SQL is made of two languages: DDL and DML
| Language | Full form | Purpose | Statements |
|---|---|---|---|
| DDL | Data Definition Language | Define, change and remove the structure (schema) | CREATE, ALTER, DROP |
| DML | Data Manipulation Language | Insert, retrieve, change and delete data | INSERT, SELECT, UPDATE, DELETE |
A quick test: if the statement changes the shape of the table, it is DDL. If it changes or reads the rows, it is DML.
DDL: creating the database and tables
First create the database, select it, and look inside.
| Code |
|---|
CREATE DATABASE StudentAttendance; |
USE StudentAttendance; |
SHOW DATABASES; |
SHOW TABLES; |
SHOW DATABASES lists the databases and SHOW TABLES lists the tables of the selected one (empty at first). Next, create the STUDENT table. The roll number fits in 3 digits so INT is enough, a name is at most 20 characters so VARCHAR(20), and the guardian ID is 12 digits that we never add up, so CHAR(12).
| Code |
|---|
CREATE TABLE STUDENT( |
RollNumber INT, |
SName VARCHAR(20), |
SDateofBirth DATE, |
GUID CHAR(12), |
PRIMARY KEY (RollNumber)); |
Notice that columns are separated by commas and the statement ends with a semicolon. The number of columns is the degree of the table. To see its structure use DESCRIBE STUDENT; (or DESC STUDENT;). MySQL leaves the empty cells blank; a dash is shown here:
| Field | Type | Null | Key | Default | Extra |
|---|---|---|---|---|---|
| RollNumber | int | NO | PRI | NULL | - |
| SName | varchar(20) | YES | - | NULL | - |
| SDateofBirth | date | YES | - | NULL | - |
| GUID | char(12) | YES | - | NULL | - |
The key column shows PRI for the primary key, and Null shows NO only for it, which confirms the rule that primary keys cannot be NULL while other columns can.
ALTER TABLE: changing a table that already exists
After a table is made, you may need a key, a new column or a different data type. All of these use ALTER TABLE.
| Task | Statement |
|---|---|
| Add a primary key | ALTER TABLE GUARDIAN ADD PRIMARY KEY (GUID); |
| Add a composite primary key | ALTER TABLE ATTENDANCE ADD PRIMARY KEY (AttendanceDate, RollNumber); |
| Add a foreign key | ALTER TABLE STUDENT ADD FOREIGN KEY (GUID) REFERENCES GUARDIAN(GUID); |
| Add UNIQUE | ALTER TABLE GUARDIAN ADD UNIQUE (GPhone); |
| Add a new column | ALTER TABLE GUARDIAN ADD income INT; |
| Change a data type or size | ALTER TABLE GUARDIAN MODIFY GAddress VARCHAR(40); |
| Make a column NOT NULL | ALTER TABLE STUDENT MODIFY SName VARCHAR(20) NOT NULL; |
| Set a default value | ALTER TABLE STUDENT MODIFY SDateofBirth DATE DEFAULT '2000-05-15'; |
| Remove a column | ALTER TABLE GUARDIAN DROP income; |
| Remove the primary key | ALTER TABLE GUARDIAN DROP PRIMARY KEY; |
Three rules are tested. To add a foreign key, the referenced table must already exist, the referenced column must be a primary key of that table, and the two columns must have the same data type and size. With MODIFY you must repeat the data type, even when you only want to add NOT NULL or DEFAULT. And a table should always have a primary key, so if you drop it you add it back.
DROP removes a table or a whole database permanently, and it cannot be undone.
| Code |
|---|
DROP TABLE tablename; |
DROP DATABASE databasename; |
Dropping a database removes every table inside it.
DML: inserting rows
INSERT INTO adds a row. If you give a value for every column, in the same order as the columns, you need not name them.
| Code |
|---|
INSERT INTO STUDENT |
VALUES (1, 'Atharv Ahuja', '2003-05-15', '444444444444'); |
If you have values for only some columns, name those columns, and the others get NULL or their default.
| Code |
|---|
INSERT INTO GUARDIAN (GUID, GName, GAddress) |
VALUES ('333333333333', 'Danny Dsouza', 'S -13, Ashok Village, Daman'); |
Here GPhone is skipped and is stored as NULL. When the order of values is not known, or only some are supplied, use the form that names the columns. When a column is NULL and you are not naming columns, you must write NULL yourself:
| Code |
|---|
INSERT INTO STUDENT |
VALUES (3, 'Taleem Shah', '2002-02-28', NULL); |
One more rule: insert into the referenced table first. A student row refers to a guardian row through GUID, so the GUARDIAN table is filled before STUDENT. And two rows cannot share a roll number, because it is the primary key.
DML: updating and deleting rows
UPDATE changes values, and DELETE removes rows. Both need a WHERE clause to say which rows.
| Code |
|---|
UPDATE STUDENT |
SET GUID = '101010101010' |
WHERE RollNumber = 3; |
| Code |
|---|
DELETE FROM STUDENT |
WHERE RollNumber = 2; |
Common wrong step. Leaving out WHERE. An UPDATE without WHERE changes the column in every row (every student would get the same GUID), and a DELETE without WHERE removes every row of the table, although the table itself remains. Compare this with DROP, which removes the table as well, and with ALTER, which changes the structure, while UPDATE changes the data.
| Statement | Acts on | Effect |
|---|---|---|
| ALTER | Structure of a table | Adds, removes or changes columns and constraints |
| UPDATE | Values in rows | Changes the data in chosen rows |
| DELETE | Rows | Removes chosen rows; the table stays |
| DROP | Table or database | Removes it completely and permanently |
Querying with SELECT
SELECT retrieves data, and the answer comes back as a table. The pattern is:
| Code |
|---|
SELECT column1, column2 |
FROM table_name |
WHERE condition; |
FROM is always written with SELECT, and WHERE is optional. Use * to get all columns. The queries below use the EMPLOYEE table of an office database.
| EmpNo | Ename | Salary | Bonus | DeptId |
|---|---|---|---|---|
| 101 | Aaliya | 10000 | 234 | D02 |
| 102 | Kritika | 60000 | 123 | D01 |
| 103 | Shabbir | 45000 | 566 | D01 |
| 104 | Gurpreet | 19000 | 565 | D04 |
| 105 | Joseph | 34000 | 875 | D03 |
| 106 | Sanya | 48000 | 695 | D02 |
| 107 | Vergese | 15000 | NULL | D01 |
| 108 | Nachaobi | 29000 | NULL | D05 |
| 109 | Daribha | 42000 | NULL | D04 |
| 110 | Tanya | 50000 | 467 | D05 |
Aliases and DISTINCT
AS renames a column in the output only; the table is not changed. A name containing a space needs quotes. Expressions such as Salary*12 can be calculated in the SELECT list.
| Code |
|---|
SELECT Ename AS Name, Salary*12 AS 'Annual Income' |
FROM EMPLOYEE; |
The first rows of the result are:
| Name | Annual Income |
|---|---|
| Aaliya | 120000 |
| Kritika | 720000 |
| Shabbir | 540000 |
| Gurpreet | 228000 |
DISTINCT removes repeated values. Because many employees share a department, SELECT DISTINCT DeptId FROM EMPLOYEE; returns five values instead of ten:
| DeptId |
|---|
| D02 |
| D01 |
| D04 |
| D03 |
| D05 |
WHERE with relational and logical operators
WHERE accepts =, <, <=, >, >= and !=, and combines conditions with AND, OR and NOT. AND needs both conditions true, OR needs at least one, and NOT reverses a condition. Text values such as 'D04' need quotes.
| Code |
|---|
SELECT * FROM EMPLOYEE |
WHERE Salary > 5000 AND DeptId = 'D04'; |
| EmpNo | Ename | Salary | Bonus | DeptId |
|---|---|---|---|---|
| 104 | Gurpreet | 19000 | 565 | D04 |
| 109 | Daribha | 42000 | NULL | D04 |
BETWEEN gives a range including both ends, and IN tests membership in a list. Each of these has an equivalent long form.
| Short form | Long form | Rows returned |
|---|---|---|
WHERE Salary BETWEEN 20000 AND 50000 |
WHERE Salary>=20000 AND Salary<=50000 |
Shabbir, Joseph, Sanya, Nachaobi, Daribha, Tanya (6 rows) |
WHERE DeptId IN ('D01','D02','D04') |
WHERE DeptId='D01' OR DeptId='D02' OR DeptId='D04' |
7 rows |
WHERE DeptId NOT IN ('D01','D02') |
WHERE NOT (DeptId='D01' OR DeptId='D02') |
Gurpreet, Joseph, Nachaobi, Daribha, Tanya (5 rows) |
ORDER BY
ORDER BY sorts the output. The default is ascending; add DESC for descending. With two columns, the second breaks ties in the first.
| Code |
|---|
SELECT Ename, Salary FROM EMPLOYEE |
ORDER BY Salary DESC; |
The top rows of the result:
| Ename | Salary |
|---|---|
| Kritika | 60000 |
| Tanya | 50000 |
| Sanya | 48000 |
| Shabbir | 45000 |
NULL: not zero, not blank
NULL means missing or unknown. It is different from 0, and any arithmetic with NULL gives NULL (so 5 + NULL is NULL). You test for it with IS NULL or IS NOT NULL, never with =.
| Code |
|---|
SELECT Ename, Bonus FROM EMPLOYEE |
WHERE Bonus IS NULL; |
| Ename | Bonus |
|---|---|
| Vergese | NULL |
| Nachaobi | NULL |
| Daribha | NULL |
Beyond the textbook. For the exam: use IS NULL to find missing values. In reality: writing WHERE Bonus = NULL is not an error, but it returns no rows at all, because comparing anything with an unknown value gives "unknown" rather than true. Many beginners spend an hour wondering why the table looks empty.
LIKE: matching patterns
When you do not know the exact text, LIKE searches for a pattern with two wildcards. % stands for zero, one or many characters, and _ (underscore) stands for exactly one character.
| Pattern | Meaning | Names returned |
|---|---|---|
'K%' |
Starts with K | Kritika |
'%a' |
Ends with a | Aaliya, Kritika, Sanya, Daribha, Tanya |
'_ANYA' |
Any one letter, then ANYA (exactly 5 letters) | Sanya, Tanya |
'%se%' |
Contains se anywhere | Joseph, Vergese |
'_a%' |
Second letter is a | Aaliya, Sanya, Nachaobi, Daribha, Tanya |
Adding AND Salary > 45000 to the '%a' query keeps Kritika, Sanya and Tanya. In MySQL's default setting, text comparison ignores case, which is why '_ANYA' still matches Sanya and Tanya. The trap is to use = with a wildcard: Ename = 'K%' matches only a name that is literally "K%".
Pause and predict: SELECT COUNT(*) FROM EMPLOYEE; returns 10. What does SELECT COUNT(Bonus) FROM EMPLOYEE; return?
Check your answer: 7. COUNT(*) counts all rows, while COUNT(column) counts only the values that are not NULL, and three employees have NULL bonus.
Functions in SQL
A function does one job and returns a value. SQL has two kinds, and the difference is a favourite question.
| Single row function (scalar) | Multiple row function (aggregate) |
|---|---|
| Works on one row at a time | Works on a group of rows |
| One result per row | One result for the whole group |
| Can be used in SELECT, WHERE and ORDER BY | Used in the SELECT clause (the HAVING clause works with it too) |
| Math, string and date functions | MAX, MIN, AVG, SUM, COUNT(*), COUNT(column) |
Single row functions
| Category | Function | What it does | Example and result |
|---|---|---|---|
| Math | POWER(X, Y) | X to the power Y | SELECT POWER(2,3); gives 8 |
| Math | ROUND(N, D) | Round N to D decimal places (D = 0: nearest integer) | ROUND(2912.564, 1) gives 2912.6; ROUND(283.2) gives 283 |
| Math | MOD(A, B) | Remainder of A divided by B | MOD(21, 2) gives 1 |
| String | UCASE(s) or UPPER(s) | Convert to capitals | UCASE('Informatics') gives INFORMATICS |
| String | LCASE(s) or LOWER(s) | Convert to small letters | LOWER('Informatics Practices') gives informatics practices |
| String | MID(s, pos, n) (also SUBSTRING, SUBSTR) | Substring of n characters from position pos; without n, to the end | MID('Informatics',3,4) gives form; MID('Informatics',7) gives atics |
| String | LENGTH(s) | Number of characters | LENGTH('Informatics') gives 11 |
| String | LEFT(s, N) | First N characters | LEFT('Computer',4) gives Comp |
| String | RIGHT(s, N) | Last N characters | RIGHT('SCIENCE',3) gives NCE |
| String | INSTR(s, sub) | Position of the first occurrence of sub; 0 if absent | INSTR('Informatics','ma') gives 6 |
| String | LTRIM, RTRIM, TRIM | Remove leading, trailing, or both leading and trailing spaces | A string of 9 characters with 2 spaces on each side becomes 5 under TRIM |
| Date | NOW() | Current system date and time | SELECT NOW(); gives a value such as 2019-07-11 19:41:17 |
| Date | DATE(), MONTH(), MONTHNAME(), YEAR(), DAY(), DAYNAME() | Parts of a date | MONTHNAME('2003-11-28') gives November; YEAR('2003-10-03') gives 2003; DAY('2003-03-24') gives 24; DAYNAME('2019-07-11') gives Thursday |
Position counting in MID and INSTR starts at 1, not 0. So MID('Informatics',3,4) starts at the third letter, f, and takes 4: f, o, r, m.
Worked example: a GST column. A car dealer wants the GST (12 per cent of the price) rounded to one decimal place.
| Code |
|---|
SELECT CarId, Price, ROUND(12/100*Price, 1) AS GST |
FROM INVENTORY; |
For the first three cars:
| CarId | Price | GST |
|---|---|---|
| D001 | 582613.00 | 69913.6 |
| D002 | 673112.00 | 80773.4 |
| B001 | 567031.00 | 68043.7 |
Step by step, for D001: $0.12 \times 582613 = 69913.56$, which rounds to 69913.6. The wrong step is to use ROUND(..., 0) and expect a decimal.
Worked example: the part of an email before the @ sign. From a CUSTOMER table with an Email column, take the user name from addresses such as [email protected]:
| Code |
|---|
SELECT LEFT(Email, INSTR(Email, '@') - 1) |
FROM CUSTOMER; |
INSTR(Email, '@') returns the position of @, which is 10 here, so subtracting 1 gives 9, and LEFT(Email, 9) returns amitsaha2. Without the minus one, the @ would be included.
Aggregate functions
On the INVENTORY table of eight cars:
| Function | Query | Result |
|---|---|---|
| MAX | SELECT MAX(Price) FROM INVENTORY; |
673112.00 |
| MIN | SELECT MIN(Price) FROM INVENTORY; |
355205.00 |
| AVG | SELECT AVG(Price) FROM INVENTORY; |
576091.625 |
| SUM | SELECT SUM(Price) FROM INVENTORY; |
4608733.00 |
| COUNT(*) with WHERE | SELECT COUNT(*) FROM INVENTORY WHERE Model='VXI'; |
2 |
| COUNT(DISTINCT) | SELECT COUNT(DISTINCT Model) FROM INVENTORY; |
6 |
| AVG with WHERE | SELECT AVG(Price) FROM INVENTORY WHERE Model='LXI'; |
548306.5 |
On the EMPLOYEE table: COUNT(*) is 10 but COUNT(Bonus) is 7, because COUNT(column) ignores NULL. Aggregate functions skip NULL values, so AVG(Bonus) is the average of the seven bonuses, 3525 / 7 = 503.57, not 3525 / 10.
GROUP BY and HAVING
GROUP BY puts rows with the same value in a column into one group, and aggregate functions then work on each group. HAVING filters the groups.
| Code |
|---|
SELECT DeptId, COUNT(*), MAX(Salary) |
FROM EMPLOYEE |
GROUP BY DeptId; |
| DeptId | COUNT(*) | MAX(Salary) |
|---|---|---|
| D01 | 3 | 60000 |
| D02 | 2 | 48000 |
| D03 | 1 | 34000 |
| D04 | 2 | 42000 |
| D05 | 2 | 50000 |
Add HAVING COUNT(*) > 2 and only D01 survives. The difference between WHERE and HAVING comes from the order in which SQL works: FROM picks the table, WHERE filters individual rows, GROUP BY forms groups, HAVING filters groups, SELECT picks the columns, and ORDER BY sorts. A row filter is applied before groups exist, so WHERE cannot use an aggregate like SUM(Salary).
Worked example: WHERE and HAVING together. Which departments have a total salary above 60000, counting only employees who earn more than 20000?
| Code |
|---|
SELECT DeptId, SUM(Salary) |
FROM EMPLOYEE |
WHERE Salary > 20000 |
GROUP BY DeptId |
HAVING SUM(Salary) > 60000 |
ORDER BY DeptId; |
| Step | What happens | Result |
|---|---|---|
| FROM, WHERE | Keep rows with Salary > 20000 | Kritika, Shabbir (D01); Sanya (D02); Joseph (D03); Daribha (D04); Nachaobi, Tanya (D05) |
| GROUP BY | One group per DeptId, then SUM(Salary) | D01 = 105000, D02 = 48000, D03 = 34000, D04 = 42000, D05 = 79000 |
| HAVING | Keep groups with sum above 60000 | D01 and D05 |
| ORDER BY | Sort by DeptId | D01 then D05 |
Final output:
| DeptId | SUM(Salary) |
|---|---|
| D01 | 105000 |
| D05 | 79000 |
A common wrong step is to move the salary condition into HAVING: then Aaliya (10000) would be counted in D02's group before filtering, and D02's total would change.
Pause and predict: On the SALE table of a car showroom (customers C0001 and C0002 bought two cars each, C0003 and C0004 one each), what does SELECT CustId, COUNT(*) FROM SALE GROUP BY CustId HAVING COUNT(*) > 1; return?
Check your answer: Two rows: C0001 with 2 and C0002 with 2. Groups for C0003 and C0004 have a count of 1, so HAVING removes them.
Operations on relations
Three operations merge the rows of two tables. They are binary operations, and they need the two tables to have the same number of attributes with matching domains. We use two tables of students in dance and music.
| DANCE: SNo | Name | Class |
|---|---|---|
| 1 | Aastha | 7A |
| 2 | Mahira | 6A |
| 3 | Mohit | 7B |
| 4 | Sanjay | 7A |
| MUSIC: SNo | Name | Class |
|---|---|---|
| 1 | Mehak | 8A |
| 2 | Mahira | 6A |
| 3 | Lavanya | 7A |
| 4 | Sanjay | 7A |
| 5 | Abhay | 8A |
| Operation | Symbol | Result | Rows for DANCE and MUSIC |
|---|---|---|---|
| UNION | ∪ | All rows of either table; duplicates shown once | 7 rows: Aastha, Mahira, Mohit, Sanjay, Mehak, Lavanya, Abhay |
| INTERSECT | ∩ | Rows common to both | 2 rows: Mahira (6A) and Sanjay (7A) |
| MINUS (set difference) | - | Rows in the first table but not in the second | DANCE minus MUSIC: Aastha (7A) and Mohit (7B). MUSIC minus DANCE: Mehak, Lavanya, Abhay |
Two students (Mahira and Sanjay) are in both lists, so UNION lists them once. Sums to check: 4 + 5 = 9 rows altogether, minus the 2 repeated ones, gives the 7 rows of the union. Rows are compared as a whole: (1, Aastha, 7A) and (1, Mehak, 8A) are different rows, even though SNo is 1 in both.
Beyond the textbook. For the exam: UNION, INTERSECT and MINUS are the three operations on relations. In reality: MySQL has long supported UNION directly, but MINUS is the Oracle spelling. Recent MySQL versions provide INTERSECT and EXCEPT, with EXCEPT doing what MINUS does. The idea is the same in each system; only the keyword changes.
Cartesian product (×) pairs every row of one table with every row of the other. If one relation has degree $d_1$ and cardinality $c_1$, and the other has $d_2$ and $c_2$, the product has degree $d_1 + d_2$ and cardinality $c_1 \times c_2$.
| Relation | Degree | Cardinality |
|---|---|---|
| DANCE | 3 | 4 |
| MUSIC | 3 | 5 |
| DANCE × MUSIC | $3 + 3 = 6$ | $4 \times 5 = 20$ |
Listing two tables in FROM, separated by a comma, makes MySQL form the Cartesian product first: SELECT * FROM DANCE, MUSIC; returns all 20 rows. Adding a condition keeps only the meaningful pairs, and table aliases (D, M) shorten the names:
| Code |
|---|
SELECT * FROM DANCE D, MUSIC M |
WHERE D.Name = M.Name; |
| SNo | Name | Class | SNo | Name | Class |
|---|---|---|---|---|---|
| 2 | Mahira | 6A | 2 | Mahira | 6A |
| 4 | Sanjay | 7A | 4 | Sanjay | 7A |
An alias is valid only for the query in which it is defined, and once a table has an alias you cannot use its original name in that query.
JOIN: combining related tables
A Cartesian product followed by a condition is wasteful, so SQL provides JOIN, which combines rows of two tables on a condition. The condition usually matches a primary key in one table with a foreign key in the other. Take UNIFORM(UCode, UName, UColor) and COST(UCode, Size, Price):
| UCode | UName | UColor |
|---|---|---|
| 1 | Shirt | White |
| 2 | Pant | Grey |
| 3 | Tie | Blue |
| UCode | Size | Price |
|---|---|---|
| 1 | L | 580 |
| 1 | M | 500 |
| 2 | L | 890 |
| 2 | M | 810 |
The same result can be written three ways.
| Style | Query |
|---|---|
| Condition in WHERE | SELECT * FROM UNIFORM U, COST C WHERE U.UCode = C.UCode; |
| Explicit JOIN with ON | SELECT * FROM UNIFORM U JOIN COST C ON U.UCode = C.UCode; |
| NATURAL JOIN | SELECT * FROM UNIFORM NATURAL JOIN COST; |
The first two return six columns, with UCode shown twice. NATURAL JOIN removes the repeated column and returns five:
| UCode | UName | UColor | Size | Price |
|---|---|---|---|---|
| 1 | Shirt | White | L | 580 |
| 1 | Shirt | White | M | 500 |
| 2 | Pant | Grey | L | 890 |
| 2 | Pant | Grey | M | 810 |
The Tie (UCode 3) does not appear, since COST has no row for it. Because UCode is in both tables, an unqualified UCode would be ambiguous, so use U.UCode and C.UCode. To join N tables on equality, you need N - 1 joins. With JOIN you may use other relational operators, not only equals.
Exam traps
| The trap | Why it's tempting | The truth |
|---|---|---|
"WHERE Bonus = NULL finds missing bonuses." |
It reads naturally | Use IS NULL; the equality version returns nothing |
| "WHERE and HAVING are interchangeable." | Both filter | WHERE filters rows before grouping; HAVING filters groups and can use aggregates |
| "BETWEEN 20000 AND 50000 excludes the ends." | Range questions often exclude ends | Both ends are included |
"LIKE '_a%' means the first letter is a." |
The a comes first in the pattern | The underscore is one unknown letter, so the second letter is a |
| "COUNT(Bonus) and COUNT(*) always match." | Both count | COUNT(column) skips NULL values |
| "DELETE FROM STUDENT; removes the table." | Both remove things | It removes all rows; the empty table stays. DROP removes the table |
| "UPDATE without WHERE changes one row." | Updating feels targeted | Every row of the table is changed |
| "CHAR(10) uses space only for the characters entered." | It sounds like VARCHAR | CHAR is fixed length and pads with spaces; VARCHAR is variable length |
60-second revision
| Topic | Lock this in |
|---|---|
| SQL | Not case sensitive; end with ;; text and dates in single quotes |
| DDL / DML | CREATE, ALTER, DROP / INSERT, SELECT, UPDATE, DELETE |
| Data types | CHAR(n) fixed, VARCHAR(n) variable, INT 4 bytes, FLOAT, DATE as YYYY-MM-DD |
| Constraints | NOT NULL, UNIQUE, DEFAULT, PRIMARY KEY, FOREIGN KEY |
| ALTER | ADD, MODIFY (repeat the data type), DROP column, DROP PRIMARY KEY |
| Safety | UPDATE and DELETE without WHERE hit every row |
| SELECT clauses | DISTINCT, AS, WHERE, BETWEEN, IN, ORDER BY (DESC), LIKE (% and _) |
| NULL | Not zero; test with IS NULL; arithmetic gives NULL |
| Functions | Single row: math, string, date. Aggregate: MAX, MIN, AVG, SUM, COUNT |
| Order of work | FROM, WHERE, GROUP BY, HAVING, SELECT, ORDER BY |
| Set operations | UNION, INTERSECT, MINUS need the same number of attributes and domains |
| Product and join | Cartesian: degree adds, cardinality multiplies. N tables need N - 1 joins. NATURAL JOIN drops the repeated column |
Where this chapter connects
- Previous: Database Concepts explains the keys and relations that these statements create.
- Next: Computer Networks moves from storing data to moving it between computers.
- Same skills elsewhere: Querying and SQL Functions goes further into functions and queries, and Introduction to Structured Query Language (SQL) is the Class XI starting point.
🎯 Practice MCQs
First 3 questions free · create a free account to unlock the rest — answers & explanations included, no payment needed
Q1. Which of the following is a DDL statement?
▸ Show answer & explanation
Answer: C
DDL defines or changes structure, and CREATE, ALTER and DROP belong to it. INSERT, UPDATE and SELECT work on the data in the table, so they are DML.
Q2. A column is declared CHAR(10), and the value 'city' is stored in it. Which statement is correct?
▸ Show answer & explanation
Answer: B
CHAR is a fixed length type, so MySQL fills the remaining 6 characters with spaces on the right. A VARCHAR column would use only the space needed for 4 characters.
Q3. Which statement correctly makes the existing column SName of STUDENT not accept NULL values?
▸ Show answer & explanation
Answer: B
With MODIFY the data type must be written together with the constraint. Option C leaves it out, and options A and D are not valid ways to add a constraint.
🔒 12 more practice MCQs
Create a free account to unlock every MCQ in this chapter — answers and explanations included. No payment needed.
Already registered? Just log in and they'll all appear here.
Q4. The table EMPLOYEE has 10 rows. Exactly 3 rows have NULL in the column Bonus. What does SELECT COUNT(Bonus) FROM EMPLOYEE return?
▸ Show answer & explanation
Answer: C
COUNT(column) counts only values that are not NULL, so 10 minus 3 gives 7. Counting all rows would give 10, and the number 3 is the count of NULL values.
Q5. How many employees satisfy: SELECT Ename FROM EMPLOYEE WHERE Ename LIKE '_a%', in the EMPLOYEE table with names Aaliya, Kritika, Shabbir, Gurpreet, Joseph, Sanya, Vergese, Nachaobi, Daribha and Tanya?
▸ Show answer & explanation
Answer: C
The pattern asks for names whose second letter is a: Aaliya, Sanya, Nachaobi, Daribha and Tanya. None of the other five names has a as the second letter.
Q6. In the same table, the salaries are 10000, 60000, 45000, 19000, 34000, 48000, 15000, 29000, 42000 and 50000. How many rows does WHERE Salary BETWEEN 20000 AND 50000 return?
▸ Show answer & explanation
Answer: B
BETWEEN includes both end values. The salaries 45000, 34000, 48000, 29000, 42000 and 50000 fall in the range, which gives 6. The values 10000, 60000, 19000 and 15000 are outside it.
Q7. SELECT Ename FROM EMPLOYEE WHERE Bonus = NULL; What is the result?
▸ Show answer & explanation
Answer: C
A comparison with NULL using = is never true, so no row is returned, and the statement is still valid SQL. The correct test is Bonus IS NULL.
Q8. Which clause is used to place a condition on the result of an aggregate function applied to groups?
▸ Show answer & explanation
Answer: C
HAVING filters groups formed by GROUP BY, so it can use aggregate functions like COUNT. WHERE filters individual rows before grouping and cannot use aggregates.
Q9. What does SELECT LEFT('Computer', 4), RIGHT('SCIENCE', 3), MID('Informatics', 3, 4); display?
▸ Show answer & explanation
Answer: A
LEFT gives the first 4 letters, Comp. RIGHT gives the last 3 letters, NCE. MID starts at position 3, the letter f, and takes 4 characters, form. Option C starts one position too early.
Q10. Relation R1 has degree 3 and cardinality 4. Relation R2 has degree 3 and cardinality 5. What are the degree and cardinality of the Cartesian product of R1 and R2?
▸ Show answer & explanation
Answer: C
The degree of a Cartesian product is the sum of the degrees (3 + 3 = 6), and the cardinality is the product of the cardinalities (4 x 5 = 20). Options A, B and D mix up the sum and the product.
Q11. Match List I with List II. List I: (i) MOD (ii) INSTR (iii) COUNT (iv) DAYNAME. List II: (p) Date function (q) Aggregate function (r) Math function (s) String function
▸ Show answer & explanation
Answer: A
MOD is a math function, INSTR is a string function, COUNT is an aggregate function and DAYNAME is a date function. The other options misplace at least two of them.
Q12. Assertion (A): A DELETE statement without a WHERE clause removes all rows of a table but not the table itself. Reason (R): DELETE changes the data in a table, whereas DROP changes the structure by removing the table.
▸ Show answer & explanation
Answer: A
DELETE works on rows, so even when it removes all of them the empty table remains. DROP removes the table itself. R correctly explains A.
Q13. In the EMPLOYEE table, the departments are D01 (3 employees), D02 (2), D03 (1), D04 (2) and D05 (2). What does SELECT DeptId, COUNT(DeptId) FROM EMPLOYEE GROUP BY DeptId HAVING COUNT(DeptId) > 2; return?
▸ Show answer & explanation
Answer: A
Only D01 has more than 2 employees. Option B is the answer for a condition greater than 1, option C ignores HAVING, and option D is wrong since D01 qualifies.
Q14. Statement I: UNION shows rows that appear in both tables only once. Statement II: INTERSECT returns the rows that are in the first table but not in the second. Which is correct?
▸ Show answer & explanation
Answer: A
UNION removes duplicates, so a row present in both tables is listed once. The description in Statement II belongs to MINUS (set difference), while INTERSECT returns the rows common to both tables.
Q15. UNIFORM(UCode, UName, UColor) has 3 rows and COST(UCode, Size, Price) has 4 rows, and the UCode values of 4 COST rows match rows of UNIFORM. How many columns and rows does a query selecting all columns from UNIFORM NATURAL JOIN COST return?
▸ Show answer & explanation
Answer: B
NATURAL JOIN keeps matching rows only, giving 4 rows, and shows the common column UCode once, so there are 3 + 3 - 1 = 5 columns. A plain Cartesian product would have 6 columns and 12 rows.
📊 Previous-Year Questions
Practise with real CUET Computer Science previous-year papers — every question solved, with the correct answer and a step-by-step explanation.
View solved CUET PYQ papers →Ready to drill Computer Science?
Unlock all MCQs, chapter tests, mocks & PYQs for ₹199/year.
Get UniDrill Pro