Sling Academy
Home/PostgreSQL/Best practices to name tables and columns in PostgreSQL

Best practices to name tables and columns in PostgreSQL

Last updated: January 06, 2024

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.

Next Article: PostgreSQL: How to select distinct on multiple columns

Previous Article: PostgreSQL Crosstab Query: Display data vertically

Series: PostgreSQL Tutorials: From Basic to Advanced

PostgreSQL

You May Also Like

  • PostgreSQL with TimescaleDB: Querying Time-Series Data with SQL
  • PostgreSQL Full-Text Search with Boolean Operators
  • Filtering Stop Words in PostgreSQL Full-Text Search
  • PostgreSQL command-line cheat sheet
  • How to Perform Efficient Rolling Aggregations with TimescaleDB
  • PostgreSQL with TimescaleDB: Migrating from Traditional Relational Models
  • Best Practices for Maintaining PostgreSQL and TimescaleDB Databases
  • PostgreSQL with TimescaleDB: Building a High-Performance Analytics Engine
  • Integrating PostgreSQL and TimescaleDB with Machine Learning Models
  • PostgreSQL with TimescaleDB: Implementing Temporal Data Analysis
  • Combining PostgreSQL, TimescaleDB, and Airflow for Data Workflows
  • PostgreSQL with TimescaleDB: Visualizing Real-Time Data with Superset
  • Using PostgreSQL with TimescaleDB for Energy Consumption Analysis
  • PostgreSQL with TimescaleDB: How to Query Massive Datasets Efficiently
  • Best Practices for Writing Time-Series Queries in PostgreSQL with TimescaleDB
  • PostgreSQL with TimescaleDB: Implementing Batch Data Processing
  • Using PostgreSQL with TimescaleDB for Network Traffic Analysis
  • PostgreSQL with TimescaleDB: Troubleshooting Common Performance Issues
  • Building an IoT Data Pipeline with PostgreSQL and TimescaleDB