LogIn
I don't have account.

Foreign Key in SQL

DevSniper

194 Views

A foreign key is a column (or a set of columns) in one table (child table) that uniquely identifies a row in another table(parent table). Foreign keys play a critical role for establishing and maintaining relationships between tables. They enforce referential integrity, ensuring the consistency and accuracy of data relationships.

A foreign key establishes a link between two tables by referencing the primary key (or a unique key) in another table. The table that contains the primary key is called the parent table, and the table that contains the foreign key is known as the child table. In this article, we will explore all aspects of foreign keys. By the end, you will have a clear understanding of foreign keys, including their syntax, use cases and key concepts etc.

Syntax

CREATE TABLE TableName (
    Column1 DataType,
    Column2 DataType,
    FOREIGN KEY (Column1 ) REFERENCES ParentTableName(ParentColumnName)
);
ALTER TABLE TableName
ADD CONSTRAINT ConstraintName
FOREIGN KEY (ColumnName) REFERENCES ParentTableName(ParentColumnName);

1. Defining a Foreign Key During Table Creation

a. Without Naming the Constraint

CREATE TABLE TableName (
    Column1 DataType,
    Column2 DataType,
    FOREIGN KEY (Column1 ) REFERENCES ParentTableName(ParentColumnName)
);

  • Foreign key constraint is automatically assigned by a system-generated name.
  • b. With Naming the Constraint

    CREATE TABLE TableName (
        Column1 DataType,
        Column2 DataType,
        CONSTRAINT FK_Name FOREIGN KEY (Column1 ) REFERENCES ParentTableName(ParentColumnName)
    );
    • Explicitly assigns a user-defined name to the foreign key constraint.
    • This is useful for referencing the constraint later, such as when altering or dropping the constraint.

    Example

    Let’s create two table Departments and Employees. Crate Departments table query :-

    CREATE TABLE Departments ( 
    Id INT PRIMARY KEY, 
    Name VARCHAR(100) 
    );

    Create Employees table query with foreign key on Departments table on column DepartmentId

    CREATE TABLE Employees (
        EmployeeId INT PRIMARY KEY,
        Name VARCHAR(100),
        Mobile VARCHAR(15),
        DepartmentId INT,
        JobTitle VARCHAR(50),
        Salary DECIMAL(10, 2),
        CONSTRAINT FK_Department FOREIGN KEY (DepartmentId) REFERENCES Departments(Id)
    );

    Verification

    We have created a Foreign Key Constraint on a column DepartmentId in the Employees table that references the column named Id of the Departments table. So if you attempt to drop table Departments before dropping table Employees, the database will throw an error

    DROP TABLE Departments;
    Error Code: 3730. Cannot drop table 'Departments' referenced by 
    a foreign key constraint 'FK_Department' on table 'Employees'. 0.000 sec

    2. Adding a Foreign Key to an Existing Table

    ALTER TABLE TableName
    ADD CONSTRAINT ConstraintName
    FOREIGN KEY (ColumnName) REFERENCES ParentTableName(ParentColumnName);

    Example

    Consider a case, if Employees table already exists and you need to add Foreign Key Constraint on DepartmentId then the query would be as follows

    ALTER TABLE Employees
    ADD CONSTRAINT FK_DepartmentId
    FOREIGN KEY (DepartmentId) REFERENCES Departments (Id);
    

    Indexes with Foreign Key

    Different database systems handle the creation of indexes for foreign keys in different ways. In some databases, the index may be automatically created when you add the foreign key constraint. However, if it's not created automatically, you can manually create an index on the foreign key column for better performance.

    MySQL and SQL Server automatically create indexes for foreign keys, while PostgreSQL, Oracle and SQLite do not. You need to create the index manually if required for performance.

    Q. Is it possible to use a column of the parent table, which is neither a primary key nor a unique key, as a foreign key in the child table?

    Ans. No, you can not use a column in the parent table that is neither a primary key nor a unique key as a foreign key in the child table. Because if the parent column is not unique, it could have multiple rows with the same value, leading to ambiguity and breaking referential integrity. Therefore, only columns with a primary key or unique constraint can be referenced by foreign keys. If you attempt to add , the database will throw an error.

    Example

    CREATE TABLE Departments ( 
    Id INT PRIMARY KEY, 
    Name VARCHAR(100) 
    );
    CREATE TABLE Employees (
        EmployeeId INT PRIMARY KEY,
        Name VARCHAR(100),
        Mobile VARCHAR(15),
        DepartmentId INT,
        JobTitle VARCHAR(50),
        Salary DECIMAL(10, 2),
        CONSTRAINT FK_Department FOREIGN KEY (Name) REFERENCES Departments(Name)
    );
    Error Code: 1822. Failed to add the foreign key constraint. Missing index 
    for constraint 'FK_Department' in the referenced table 'departments'. 0.016 sec

    Key Points of Foreign Key

    • Foreign keys can be defined at the time of table creation or added later to an existing table.
    • Foreign keys enforce referential integrity. This ensures that relationships between data are valid and consistent.
    • The foreign key column in the child table points to the primary key or a unique key in the parent table. This key is usually the primary key of the parent table but can also be a unique key if needed.
    • While a foreign key can reference any unique field (including a unique key), it's typically used to reference a primary key in relational databases.
    • A table can have multiple foreign keys, each referencing different tables or columns within same table, It is useful for establishing many relationships with other tables
    • While foreign keys are essential for data integrity but they can introduce some performance overhead during insert, update and delete operations due to the need to check the foreign key constraints.
    • Proper indexing and foreign key management can significantly improve data consistency and query performance.
    • Primarily for Foreign Keys: CASCADE, SET NULL, NO ACTION and RESTRICT are options used within foreign key constraints to manage the behavior when the parent record is updated or deleted.

    ON DELETE / ON UPDATE Options

    These options control what happens to the child table when the parent row is deleted or updated.

    Option What It Does (Simplified) Example Scenario
    CASCADE Automatically deletes or updates related child rows. If a user is deleted from the Users table, all their posts in the Posts table will also be deleted.
    SET NULL Sets the foreign key in the child table to NULL. If a manager is removed from the Employees table, the manager_id in the Departments table becomes NULL.
    RESTRICT Blocks the delete/update if any related child rows exist. You can’t delete a category from the Categories table if any products are still linked to it in the Products table.
    NO ACTION Like RESTRICT, but the check is deferred (happens at the end of the transaction in some databases). Similar to RESTRICT, but may allow complex logic in a single transaction before enforcing rules.

    Quick Explanation

    • Use CASCADE when you want related rows to follow the parent automatically (good for things like user posts, orders etc.).
    • Use SET NULL when it's okay for child rows to exist without a parent (like optional relationships).
    • Use RESTRICT or NO ACTION when you want to protect child data from being orphaned or invalid.

    SQL Syntax Example

    -- CASCADE Example
    FOREIGN KEY (user_id) REFERENCES users(id)
    ON DELETE CASCADE
    ON UPDATE CASCADE;
    
    -- SET NULL Example
    FOREIGN KEY (manager_id) REFERENCES employees(id)
    ON DELETE SET NULL;
    
    -- RESTRICT Example
    FOREIGN KEY (category_id) REFERENCES categories(id)
    ON DELETE RESTRICT;

    FAQs

    Q1. What is the purpose of a foreign key?

    A foreign key ensures referential integrity between two tables by linking the child table to a primary or unique key in the parent table. It ensures that the value in the child column exists in the parent column.

    Q2. Can a table have more than one foreign key?

    Yes. A table can have multiple foreign keys, each referencing a different table or even different columns in the same table.

    Q3. Can a foreign key reference a non-primary key column?

    Yes, but only if that column has a UNIQUE constraint. A foreign key must reference a column that is either a primary key or unique key to ensure unambiguous relationships.

    Q4. What happens if I try to insert a value in the child table that doesn’t exist in the parent table?

    The insert will fail with a referential integrity constraint violation. The database will not allow orphan records that don’t have corresponding entries in the parent table.

    Q5. How can I remove a foreign key constraint?

    Use the ALTER TABLE statement with DROP CONSTRAINT

    ALTER TABLE TableName
    DROP FOREIGN KEY ConstraintName; -- MySQL
    
    -- or
    
    ALTER TABLE TableName
    DROP CONSTRAINT ConstraintName;  -- SQL Server, PostgreSQL

    Q6. Do foreign keys automatically create indexes?

    It depends on the database system you are using. Here is how some major databases handle it

    Database Creates Index Automatically? Explanation
    MySQL ✅ Yes When you create a foreign key, MySQL automatically creates an index on the foreign key column (if it doesn't already exist).
    SQL Server ✅ Yes SQL Server also automatically creates an index to support the foreign key constraint.
    PostgreSQL ❌ No You must manually create an index on the foreign key column to improve performance, especially for joins and deletes.
    Oracle ❌ No Oracle enforces the foreign key constraint but does not create an index. You should create it yourself for better performance.
    SQLite ❌ No SQLite supports foreign keys but does not automatically index them. Manual indexing is recommended.

    Q7. What are cascading actions in foreign keys?

    Cascading actions define how changes in the parent table affect the child table

    • ON DELETE CASCADE: Deletes child rows when the parent row is deleted.
    • ON UPDATE CASCADE: Updates child rows when the parent key changes.
    • SET NULL: Sets the child foreign key column to NULL.
    • RESTRICT / NO ACTION: Prevents the parent row from being updated or deleted if related child rows exist.

    Q8. Can a foreign key reference multiple columns (composite key)?

    Yes, A foreign key can reference composite keys, as long as the combination of columns in the parent table is a primary or unique key and the same number and type of columns are used in the child table.

    Q9. Can foreign keys be self-referencing?

    Yes, A table can have a self-referencing foreign key, where a column refers to another row in the same table. This is useful for hierarchies like employee-manager relationships.

    Example
    CREATE TABLE Employees (
        Id INT PRIMARY KEY,
        Name VARCHAR(100),
        ManagerId INT,
        FOREIGN KEY (ManagerId) REFERENCES Employees(Id)
    );

    Q10. What is the difference between a primary key and a foreign key?

    Feature Primary Key Foreign Key
    Purpose Uniquely identifies each record in the table Creates a link between two tables (child → parent)
    Allows NULLs ❌ No – cannot be NULL (every row must have a value) ✅ Yes – can be NULL (if no strict relationship is required)
    Must Be Unique ✅ Yes – no two rows can have the same value ❌ No – can have duplicate values
    References Other Table? ❌ No – stands on its own ✅ Yes – must reference a primary (or unique) key in another table
    Number per Table ✅ Only one per table ✅ Can have multiple foreign keys in one table

    Q11. Can a foreign key column have NULL values?

    Yes, A foreign key column can be NULL, meaning the relationship is optional. However, if the column is declared as NOT NULL, then a valid reference must exist in the parent table.

    Q12. What is a circular foreign key dependency?

    A circular foreign key dependency happens when two or more tables reference each other through foreign keys, either directly or indirectly.

    This creates a loop in the relationships, making it tricky to insert, update or delete records because the operations depend on each other.

    Example (Direct Circular Dependency)
    -- Table A references Table B
    CREATE TABLE A (
      id INT PRIMARY KEY,
      b_id INT,
      FOREIGN KEY (b_id) REFERENCES B(id)
    );
    
    -- Table B references Table A
    CREATE TABLE B (
      id INT PRIMARY KEY,
      a_id INT,
      FOREIGN KEY (a_id) REFERENCES A(id)
    );
    Why It’s a Problem
    • You can't insert a row into A without a valid row in B.
    • But you also can't insert into B without a valid row in A.
    • This creates a deadlock unless you use special handling.

    Q13. How to Handle Circular foreign key Dependencies

    Circular foreign key dependencies can make insertions, updates, and deletions difficult because the tables rely on each other. To handle them safely and efficiently, you can use one or more of the following strategies

    1. Use Deferred Constraints (If Supported)

    Postpone foreign key checks until the end of the transaction. This allows both rows to be inserted before enforcing the constraint.

    Supported in: PostgreSQL, Oracle

    -- PostgreSQL Example
    ALTER TABLE A
      ADD CONSTRAINT fk_b
      FOREIGN KEY (b_id)
      REFERENCES B(id)
      DEFERRABLE INITIALLY DEFERRED;

    2. Insert NULLs First, Then Update

    Insert records with NULL values for the foreign key columns first, then update them after both rows exist.

    -- Step 1: Insert A and B with NULL foreign keys
    INSERT INTO A (id, b_id) VALUES (1, NULL);
    INSERT INTO B (id, a_id) VALUES (10, 1);
    
    -- Step 2: Update A with B's ID
    UPDATE A SET b_id = 10 WHERE id = 1;

    3. Temporarily Disable Foreign Keys (With Caution)

    Disable constraints during data load/migration, then re-enable them afterward.

    ⚠️ Warning: Only safe if you're 100% sure your data is valid.

    -- Example in MySQL
    SET foreign_key_checks = 0;
    -- perform inserts
    SET foreign_key_checks = 1;

    4. Refactor the Schema (Recommended)

    Best long-term solution: Avoid circular dependencies by redesigning the database structure.

    Summary
    Method When to Use
    Deferred Constraints If the DB supports it and you need strong integrity
    Insert NULL, then Update Works in all databases; good for tight circular refs
    Temporarily Disable FKs Use during data migration with caution
    Schema Refactoring Best for long-term maintainable design

    Q14. What error do I get if a foreign key constraint is violated?

    When you try to insert, update or delete data that violates a foreign key constraint, your database will throw an error to prevent invalid relationships. Common error messages include

    MySQL
    Error Code: 1452. Cannot add or update a child row: a foreign key constraint fails
    PostgreSQL
    ERROR: insert or update on table "child_table" violates foreign key constraint "child_table_fk"
    DETAIL: Key (parent_id)=(999) is not present in table "parent_table".
    SQL Server
    The INSERT statement conflicted with the FOREIGN KEY constraint "FK_Child_Parent". 
    The conflict occurred in database "YourDB", table "dbo.Parent", column 'id'.

    Q15. Can I disable foreign key checks temporarily?

    Yes, in many (but not all) database systems you can temporarily disable foreign key enforcement , though the commands and support vary.

    MySQL
    SET FOREIGN_KEY_CHECKS = 0;  -- Disable
    -- Perform operations
    SET FOREIGN_KEY_CHECKS = 1;  -- Re-enable
    SQL Server
    ALTER TABLE TableName NOCHECK CONSTRAINT ALL;
    -- To re-enable:
    ALTER TABLE TableName WITH CHECK CHECK CONSTRAINT ALL;
    

    Q16. How can I find foreign key constraints on a table?

    You can easily retrieve foreign key information using built-in system views or commands in major databases. Here are effective methods for each:

    MySQL
    SELECT * FROM information_schema.KEY_COLUMN_USAGE 
    WHERE TABLE_NAME = 'your_table_name' AND REFERENCED_TABLE_NAME IS NOT NULL;

    Alternatively, simply run below query to view any defined foreign key constraints in the table creation statement.

    SHOW CREATE TABLE your_table_name;
    SQL Server
    EXEC sp_fkeys 'your_table_name';
    PostgreSQL
    SELECT conname, confrelid::regclass AS parent_table
    FROM pg_constraint
    WHERE conrelid = 'your_table_name'::regclass AND contype = 'f';
    

    Q17. Can I update a referenced key in the parent table?

    Yes, in some cases but it depends on how the foreign key constraint is defined.

    • You can update a parent key only if it's defined with ON UPDATE CASCADE or there are no referencing rows.
    • When ON UPDATE CASCADE is in effect, updating the parent table automatically updates matching foreign key values in child tables.
    • If ON UPDATE CASCADE is not specified and there are existing child rows referencing that key, the update will fail with a referential integrity violation.
    • Many databases (e.g., MySQL, SQL Server) by default use NO ACTION or RESTRICT for update rules, which block updates when dependent rows exist.

    Q18. How does a foreign key affect DELETE operations?

    By default, if a referenced row exists in the child table, deleting it in the parent table is blocked. You can control behavior using

    • ON DELETE CASCADE – Deletes child rows automatically.
    • ON DELETE SET NULL – Sets child foreign key column to NULL.
    • ON DELETE RESTRICT or NO ACTION – Prevents deletion if related rows exist.

    Q19. Can I create a foreign key on a computed or expression column?

    No, Foreign keys must reference real, persistent columns, not derived or computed ones.

    Q20. When should I avoid foreign keys?

    While foreign keys are important for data integrity, you may avoid them in following cases

    • High-throughput systems where constraint checks add overhead
    • Data warehousing (ETL) environments where constraints are handled by logic.
    • Applications where relationships are enforced at the application level rather than database level.

    1. High-Throughput OLTP or Microservices Environments

    • Every INSERT, UPDATE, DELETE with foreign keys incurs additional integrity checks. In high-concurrency systems with very frequent writes, this can introduce latency or lock contention.
    • It is checked by some developer that importing large data sets took minutes with FKs and only seconds when constraints were disabled.

    2. Bulk Loading or ETL Pipelines / Data Warehousing

    • In data warehouse workflows, constraints are often handled in SQL/ETL logic rather than enforced in the database.
    • Disabling or avoiding foreign keys is common to speed up batch loading. In some ETL approaches, relationships are documented but constraints aren't enforced at runtime.

    3. Application-Level Integrity Enforcement

    • Some teams handle relational integrity in application code instead of relying on database-level constraints. This avoids database overhead—but often results in increased coding complexity and potential for bugs.

    4. Simplified or Evolving Schema Needs

    • Scenarios involving frequent schema redesign, partitioning or ad-hoc migrations may suffer complexity when foreign keys are present.
    • Foreign keys can restrict schema changes and slow down migrations.