How do you declare a composite FOREIGN KEY with ON DELETE CASCADE in CREATE TABLE?
answer
- no inline form exists for this one
- two parenthesised lists, one correspondence rule
- position decides the pairing, not the names
- delete and update are separate clauses
- an omitted action is not cascade
basics
~20 sAs a table constraint: FOREIGN KEY (a, b) REFERENCES parent (x, y) ON DELETE CASCADE. The two column lists correspond by position, the referenced columns must carry a PRIMARY KEY or UNIQUE declaration, and ON UPDATE is a separate clause.
solid answer
~50 sA composite foreign key has no inline form, so it goes in the table-constraint list: ```sql CONSTRAINT fk_section_course FOREIGN KEY (dept_code, course_no) REFERENCES course (dept_code, course_no) ON DELETE CASCADE ``` The child list after `FOREIGN KEY` and the parent list after `REFERENCES` correspond **by position**, not by name — the first child column is compared with the first referenced column, and the lists must have the same length and comparable types. The referenced columns have to be declared as the parent's primary key or a unique key; a plain column list is not a legal target. `ON DELETE` and `ON UPDATE` are two independent, optional clauses that may be written in either order after `REFERENCES`. Each takes one referential action — `NO ACTION`, `RESTRICT`, `CASCADE`, `SET NULL` or `SET DEFAULT`. Omitting a clause is not the same as choosing cascade: the standard's default is `NO ACTION`.
code
sql · 12 linesCREATE TABLE course_section (
dept_code CHAR(4) NOT NULL,
course_no INTEGER NOT NULL,
section_no INTEGER NOT NULL,
CONSTRAINT pk_course_section
PRIMARY KEY (dept_code, course_no, section_no),
CONSTRAINT fk_course_section_course
FOREIGN KEY (dept_code, course_no)
REFERENCES course (dept_code, course_no)
ON DELETE CASCADE
ON UPDATE NO ACTION
);go deeper
Be able to write a foreign key from a schema description without looking it up: FOREIGN KEY (cols) REFERENCES parent (cols), placed after the column list.
Explain the positional correspondence of the two column lists, what the referenced side must already declare, and that ON DELETE and ON UPDATE are independent clauses defaulting to NO ACTION.
Demonstrate declaration judgment: which action each relationship deserves, why SET NULL forces nullable child columns, and why explicit referenced column lists survive schema change better than the implicit form.
Own the schema-wide convention — where foreign keys are declared, which actions are permitted by default, and how create-order or add-afterwards is standardised across migrations.
## Anatomy of the declaration A foreign key declaration has up to four parts, in this order: ```sql [ CONSTRAINT <name> ] FOREIGN KEY ( <child columns> ) REFERENCES <parent table> [ ( <parent columns> ) ] [ MATCH { SIMPLE | PARTIAL | FULL } ] [ ON DELETE <action> ] [ ON UPDATE <action> ] ``` Only `FOREIGN KEY (...) REFERENCES parent` is mandatory. Everything else is optional, and the optional pieces are where most of the interview questions live. A single-column foreign key may also be written inline on the column, with the `FOREIGN KEY` keyword dropped: `order_id INTEGER NOT NULL REFERENCES orders (id)`. A **composite** foreign key has no inline form at all, because inline syntax offers no place to list two child columns. It must be a table constraint. ## The two column lists correspond by position ```sql CREATE TABLE course_section ( dept_code CHAR(4) NOT NULL, course_no INTEGER NOT NULL, section_no INTEGER NOT NULL, room VARCHAR(20), CONSTRAINT pk_course_section PRIMARY KEY (dept_code, course_no, section_no), CONSTRAINT fk_course_section_course FOREIGN KEY (dept_code, course_no) REFERENCES course (dept_code, course_no) ON DELETE CASCADE ON UPDATE NO ACTION ); ``` The engine pairs child column 1 with parent column 1, child column 2 with parent column 2, and so on. Names are irrelevant to the pairing — they happen to match here, but `FOREIGN KEY (dept, num) REFERENCES course (dept_code, course_no)` would be equally valid, and `FOREIGN KEY (course_no, dept_code) REFERENCES course (dept_code, course_no)` would silently compare the wrong things (or, more likely, fail on type mismatch). The lists must be the same length and pairwise comparable in type. ## The referenced column list can be omitted `REFERENCES course` with no column list means "the parent's declared primary key". The columns are resolved when the constraint is created, so a later change to the parent's key does not quietly retarget an existing constraint. Spelling the columns out is still better practice: it documents which key you meant, and the statement fails loudly if the parent's key is not what you assumed. The target has to be a **declared** primary key or unique key on the parent, over exactly those columns. A column list that merely happens to hold distinct values is not a legal target. ## Referential actions are two independent clauses `ON DELETE` fires when a parent row is deleted; `ON UPDATE` fires when a referenced key value in the parent is changed. They are separate clauses, may appear in either order, and each takes exactly one action: - `NO ACTION` - `RESTRICT` - `CASCADE` - `SET NULL` - `SET DEFAULT` The two most common mistakes are assuming that `ON DELETE CASCADE` implies anything about updates — it does not — and assuming that omitting a clause means cascade. Omitting it means `NO ACTION`, the standard's default: the operation is rejected if it would leave a child row pointing at nothing. Two declaration-level requirements follow from the actions you choose. `SET NULL` requires the child columns to be nullable, so it cannot be combined with `NOT NULL` on those columns. `SET DEFAULT` requires the child columns to have defaults, and those default values must themselves exist in the parent. ## Self-references and forward references A foreign key may reference the table being created — an adjacency list is the classic case: ```sql CREATE TABLE employee ( id INTEGER NOT NULL, manager_id INTEGER, CONSTRAINT pk_employee PRIMARY KEY (id), CONSTRAINT fk_employee_manager FOREIGN KEY (manager_id) REFERENCES employee (id) ON DELETE SET NULL ); ``` Note that `manager_id` is deliberately nullable — the root of the hierarchy has no manager, and `ON DELETE SET NULL` would be illegal on a `NOT NULL` column anyway. Referencing a table that does not exist yet is a different matter: the parent must exist when the constraint is created, so either order your `CREATE TABLE` statements parent-first, or create the tables and add the foreign keys afterwards. ## Frequent declaration errors - Writing a composite foreign key inline on one of the two columns — there is no such form. - Column lists of different lengths, or written in mismatched order. - Targeting parent columns that carry no primary key or unique declaration. - `ON DELETE SET NULL` on child columns declared `NOT NULL`. - Expecting `ON UPDATE` behaviour from an `ON DELETE` clause. - Assuming an omitted action clause means cascade rather than `NO ACTION`.
- If you write no ON DELETE clause at all, what does the standard say applies?`NO ACTION` — the delete is rejected if it would orphan a child row. Nothing is cascaded and nothing is nulled. `ON UPDATE` defaults the same way and independently, so a key declared `ON DELETE CASCADE` still has `NO ACTION` behaviour for updates to the parent key.
- May you omit the referenced column list and just write REFERENCES course?Yes — it means the parent's declared primary key, resolved when the constraint is created. Spelling the columns out is better practice: it documents which key you meant and fails loudly if the parent's key is not what you assumed, rather than binding to something unexpected.
- Do the child column names have to match the parent's key column names?No. The lists correspond strictly by position: first with first, second with second. Names may differ freely, but the lists must be the same length with pairwise comparable types. A mis-ordered list either fails on type mismatch or silently compares the wrong pair of columns.
- Can a foreign key reference the table currently being created?Yes — a self-reference such as `FOREIGN KEY (manager_id) REFERENCES employee (id)` is legal inside the same CREATE TABLE. Keep the referencing column nullable so the root row can exist, and note that `ON DELETE SET NULL` would be illegal on a NOT NULL column anyway.
saying these in an interview costs you the question
- Writes a composite foreign key inline on one column
- Assumes the referenced columns need no primary key or unique declaration
- Thinks omitting ON DELETE means CASCADE
- Matches the two column lists by name rather than position
- Believes ON DELETE CASCADE also governs parent key updates