Skip to main content

Database Table Naming and Primary Key (PK) Design

This document provides best practices for naming database tables and designing primary keys (PKs) in PostgreSQL.


Table Naming: Singular vs. Plural​

Recommendation: Plural Table Names​

It is generally recommended to use plural table names (e.g., users, projects, tasks, notifications). This approach is widely adopted and aligns with common database naming conventions.

Benefits of Using Plural Table Names​

  1. Descriptive and Intuitive:

    • Plural names clearly indicate that the table contains multiple records of the entity.
    • Example: users table contains multiple user records.
  2. Consistency:

    • Using plural names ensures uniformity across the schema.
    • Example: users, projects, tasks, and notifications maintain a consistent naming style.
  3. Avoids Ambiguity:

    • Singular table names like user can be confused with:
      • A single user record.
      • The concept of a "user" entity.
      • Reserved keywords in databases (e.g., user in PostgreSQL refers to the current database user).
  4. Future-Proof:

    • Even if a table starts with a single record (e.g., settings), using a plural name ensures the schema is ready for multiple records later.

Exceptions: When Singular Names Are Acceptable​

In rare cases, singular table names may be acceptable:

  • Metadata Tables: Tables that store a single row or a collection of fixed settings.
    • Examples: system_setting, application_config.
  • Highly Domain-Specific Conventions: If your team or organization prefers singular names.

Primary Key (PK) Design​

When designing primary keys, you can choose between:

  1. Using a generic id column for all tables.
  2. Using specific column names like user_id, project_id, etc.

1. Generic id Column​

  • Example:

    CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    username VARCHAR(50) NOT NULL
    );

    CREATE TABLE projects (
    id SERIAL PRIMARY KEY,
    name VARCHAR(100) NOT NULL
    );

Advantages​

  • Consistency: Every table has the same primary key name (id), making the schema consistent.

  • Simplicity: Many ORMs (e.g., SQLAlchemy, Django ORM) expect the primary key to be id.

  • Ease of Foreign Keys: Foreign keys can use descriptive names for better clarity:

    CREATE TABLE tasks (
    id SERIAL PRIMARY KEY,
    project_id INT REFERENCES projects(id)
    );

Disadvantages​

  • Ambiguity in Joins: When querying across multiple tables, you must qualify the id column with the table name to avoid conflicts:

    SELECT users.id, projects.id FROM users JOIN projects ON users.id = projects.id;

2. Specific Column Names (e.g., user_id, project_id)​

  • Example:

    CREATE TABLE users (
    user_id SERIAL PRIMARY KEY,
    username VARCHAR(50) NOT NULL
    );

    CREATE TABLE projects (
    project_id SERIAL PRIMARY KEY,
    name VARCHAR(100) NOT NULL
    );

Advantages​

  • Clarity: Descriptive column names like user_id and project_id make the schema more self-explanatory.

  • No Ambiguity in Joins:

    SELECT user_id, project_id FROM users JOIN projects ON users.user_id = projects.project_id;
  • Improved Readability: Makes the purpose of each column clear, especially in large schemas.

Disadvantages​

  • Redundancy: Repeating the table name in the column name adds verbosity.
  • Inconsistency with Some ORMs: Some tools assume the primary key is id by default, requiring additional configuration.

Hybrid Approach: Best of Both Worlds​

Use a generic id column for primary keys and descriptive names for foreign keys:

  • Example:

    CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    username VARCHAR(50) NOT NULL
    );

    CREATE TABLE projects (
    id SERIAL PRIMARY KEY,
    user_id INT REFERENCES users(id)
    );

Benefits​

  • Combines the simplicity of generic id columns with the clarity of descriptive foreign key names.
  • Works well with ORMs and reduces ambiguity in relationships.

Conclusion​

Table Naming​

  • Recommended: Use plural table names (e.g., users, projects, tasks) for clarity and consistency.
  • Exceptions: Consider singular names only for metadata tables or when domain-specific conventions require it.

Primary Key Design​

  • Use a generic id column for primary keys in each table for simplicity and ORM compatibility.
  • Use descriptive names (e.g., user_id, project_id) for foreign keys to improve clarity in relationships.
  • A hybrid approach provides the best balance between simplicity and readability.

By following these best practices, you can ensure a clean, consistent, and maintainable database design.