Best practices to name tables and columns in PostgreSQL

Updated: January 6, 2024 By: Guest Contributor Post a comment

Introduction

Ensuring clear and consistent naming for tables and columns in PostgreSQL is crucial for database maintainability, scalability, and team collaboration. This guide outlines best practices for naming your database schema elements effectively.

Understanding PostgreSQL Naming Conventions

In PostgreSQL, as in any database system, using intuitive and consistent naming conventions is fundamental. By following established standards, developers can make databases more navigable and self-documenting, easing team onboarding and future maintenance. The general consensus is to use lowercase letters separated by underscores for readability and avoid reserved words to prevent confusion or errors.

CREATE TABLE public.invoice_details (
  invoice_id SERIAL PRIMARY KEY,
  customer_id INTEGER REFERENCES customers(customer_id),
  payment_total DECIMAL(10, 2),
  payment_date DATE
);

Table Naming Best Practices

Tables represent entities within your domain, so their names should be clear and descriptive. Use singular or plural names consistently across the database. Here we will choose plural:

CREATE TABLE public.users (
  user_id SERIAL PRIMARY KEY,
  username VARCHAR(50) UNIQUE NOT NULL,
  email VARCHAR(255) UNIQUE NOT NULL
);

Avoid using SQL keywords as names.Never prefix table names with ‘tbl’ as it adds unnecessary clutter.Align the naming convention with the application domain language.

/* Do not do this */
CREATE TABLE public.tblUserAccount {...};

/* Do this */
CREATE TABLE public.account {...};

Column Naming Best Practices

Columns should have descriptive names that make their contents obvious at a glance. Using concise names improves legibility. Prefix column names with table names if it clarifies relationships but avoid redundancy where possible. Foreign keys should directly reference their origination by name and purpose.

-- Consider clarity and avoid redundancy
CREATE TABLE public.books (
  book_id SERIAL PRIMARY KEY, -- Redundant: 'books_book_id'
  title VARCHAR(255) NOT NULL,
  author_id INTEGER REFERENCES authors(author_id)
);

Choosing Appropriate Data Types

The correct data type selection can significantly impact the clarity of the naming. A column with text data should not have a name suggesting numeric data, and likewise.


CREATE TABLE public.measurements (
  measurement_id SERIAL PRIMARY KEY,
  temperature DECIMAL(5, 2),
 height DECIMAL(5, 2)
);

Handling Abbreviations and Acronyms

Use commonly understood abbreviations consistently to retain meaning while avoiding excessively long names. Acronyms should also be standardized to avoid confusion.

CREATE TABLE public.http_requests (
  req_id SERIAL PRIMARY KEY,
  url TEXT NOT NULL,
  ip_address INET NOT NULL,
  http_status_code SMALLINT NOT NULL
);

Naming for Join Tables

Explicitly name join tables by combining the names of the tables being joined, which facilitates immediate recognition of their purpose.

CREATE TABLE public.user_roles (
  user_id INTEGER REFERENCES users(user_id),
  role_id INTEGER REFERENCES roles(role_id),
  PRIMARY KEY (user_id, role_id)
);

Schema Naming Considerations

Splits database objects into logical groups called schemas. Naming them well is as important as naming tables and should generally reflect the application’s major functional areas or domain boundaries.

-- Good practice for a multi-tenancy application
CREATE SCHEMA tenanta;
CREATE SCHEMA tenantb;

Advanced Naming Patterns

For more complex databases, incorporating version numbers, entity-relationship indicators, or language tags in table or column names may provide additional clarity, especially when dealing with APIs, internationalization, or extensive temporal records.


CREATE TABLE public.users_v2 (
  user_id SERIAL PRIMARY KEY,
  username VARCHAR(50) NOT NULL,
  email VARCHAR(255) NOT NULL,
  created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

/* Assuming multilingual support */
CREATE TABLE public.product_descriptions (
  product_id INTEGER REFERENCES product(product_id),
  language_code VARCHAR(2),
  description TEXT,
  PRIMARY KEY (product_id, language_code)
);

Conclusion

Consistent and clear naming in PostgreSQL is a fundamental aspect of database design that can greatly alleviate complexity and enhance collaboration. By adhering to best practices, your database schema will be more robust, scalable, and manageable in the long term.