PostgreSQL CREATE TABLE

Learn how to create tables in PostgreSQL using the CREATE TABLE statement. Define columns, data types, constraints, and table options to structure...

PostgreSQL is a powerful open-source relational database management system (RDBMS) known for its robustness, extensibility, and adherence to SQL standards. One of the fundamental operations in database management is creating tables to store and organize data effectively. 

PostgreSQL CREATE TABLE

In this article, we'll delve into the CREATE TABLE statement in PostgreSQL, exploring its syntax, options, and best practices to empower you in designing efficient database schemas.

Understanding the PostgreSQL CREATE TABLE Statement

The CREATE TABLE statement is a foundational SQL command used to create a new table in a PostgreSQL database. This statement allows you to define the structure of the table by specifying its columns, data types, and any constraints or rules that should be applied to the data within the table. 

Let's break down its syntax:

CREATE TABLE table_name (
    column1 datatype [constraint],
    column2 datatype [constraint],
    ...
);

Here's a breakdown of each component:

  • CREATE TABLE: This keyword initiates the creation of a new table.
  • table_name: The name of the table being created.
  • (column1, column2, ...): The list of columns within the table.
  • datatype: Specifies the data type for each column.
  • [constraint]: Optional constraints such as PRIMARY KEY, FOREIGN KEY, UNIQUE, NOT NULL, CHECK, etc.

Column Definitions

Columns are the building blocks of a table, defining the structure and type of data it can hold. Each column has a name and a data type. Here are some common data types in PostgreSQL:

  • INTEGER: The INTEGER data type is used to store whole numbers (integers) without any fractional components. It represents a range of integer values, and its size depends on the platform, typically taking up 4 bytes of storage. The INTEGER data type is commonly used for storing values such as counts, indices, and other whole numbers.
  • VARCHAR(n): It is a variable-length character string data type, where n represents the maximum number of characters that can be stored in the column. The actual storage size of a VARCHAR column is the actual length of the data plus 4 bytes, which are used to store the length of the string
  • TIMESTAMP: It is used to store date and time values, representing a point in time with both date and time components. It includes information such as the year, month, day, hour, minute, second, and fractional seconds. The TIMESTAMP type is particularly useful for scenarios where precise timestamps are required, such as recording when events occurred or tracking the timing of database transactions.
  • BOOLEAN: Used to store binary truth values, representing either true or false. It is a simple and straightforward data type that is commonly used to store boolean or logical values in a database.

Constraints

Constraints are rules that enforce data integrity within the table. They define limitations or conditions for the values allowed in certain columns. Common constraints include:

  • PRIMARY KEY: It is used to uniquely identify each record in a table. It ensures that the values in one or more columns (referred to as the primary key columns) are unique for each row and that these columns do not contain NULL values. 
  • FOREIGN KEY: Establish a link between two tables by defining a relationship based on the values in one or more columns. It enforces referential integrity, ensuring that the values in the specified columns of the referencing table (the one with the FOREIGN KEY constraint) match the values in the corresponding columns of the referenced table (the one to which the FOREIGN KEY refers)
  • UNIQUE: Used to ensure that values in a specified column or a group of columns are unique across all rows in a table. This constraint helps maintain data integrity by preventing duplicate values in the specified columns, ensuring that each row is uniquely identifiable based on the defined uniqueness criteria.
  • NOT NULL: ensure that a particular column in a table cannot contain NULL values. It enforces that every record in the table must have a valid, non-null value in the specified column. This constraint is often applied to columns that are essential for record identification or columns where missing values are not acceptable.
  • CHECK: define a condition that must be satisfied for each row in a table. It allows you to specify a Boolean expression, and any attempt to insert or update a record that does not meet the specified condition will result in a constraint violation error.

Let's illustrate the usage of constraints with an example:

CREATE TABLE employees (
    employee_id SERIAL PRIMARY KEY,
    first_name VARCHAR(50) NOT NULL,
    last_name VARCHAR(50) NOT NULL,
    department_id INTEGER,
    CONSTRAINT fk_department FOREIGN KEY (department_id) REFERENCES departments(department_id)
);

In this example, we create a table named employees with columns for employee_id, first_name, last_name, and department_id. The employee_id column is defined as a SERIAL data type, which automatically generates a unique value for each new row. ThePRIMARY KEY constraint is applied to employee_id, making it the primary key for the table.

The first_name and last_name columns are defined as VARCHAR(50) data types and are marked as NOT NULL, ensuring that these fields cannot contain NULL values.

The department_id column is an INTEGER data type, and a FOREIGN KEY constraint is applied to it, referencing the department_id column in another table named departments. This establishes a relationship between the employees and departments tables, enforcing referential integrity.

Additional Table Options

In addition to column definitions and constraints, the CREATE TABLE statement in PostgreSQL supports various options to customize table behavior. Some common options include:

  • TABLESPACE: It is used to specify the tablespace where the table will be stored. Tablespaces in PostgreSQL allow you to control the physical storage location of database objects, such as tables and indexes, separately from the main data directory. 
  • WITH OIDS: Specify whether the table should have object identifiers (OIDs) or not. OIDs were unique identifiers assigned to each row in a table by default. However, OIDs have been deprecated starting from PostgreSQL version 12, and they have been completely removed in PostgreSQL version 13.
  • WITHOUT OIDS: Used to explicitly specify that the table should not have object identifiers (OIDs). OIDs were unique identifiers assigned to each row in a table by default, but they have been deprecated starting from PostgreSQL version 12 and have been completely removed in PostgreSQL version 13 and later.
  • PARTITION BY: It is used to define table partitioning. Partitioning allows you to split a large table into smaller, more manageable pieces called partitions, based on specified criteria. 

Here's an example demonstrating the usage of table options:

CREATE TABLE example_table (
    id SERIAL PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    age INTEGER,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
)
TABLESPACE pg_default
PARTITION BY RANGE (id)
WITH (
    OIDS = FALSE,
    fillfactor = 70
);

The table is assigned to the pg_default tablespace, and it is partitioned by the id column using the RANGE method. The WITH clause sets the options, specifying that OIDs are disabled OIDS = FALSE and setting the fill factor to 70 fillfactor = 70.

Let's create a simple "accounts" table step by step using the psql client tool. This example assumes you have PostgreSQL installed and running on your system.

1. Open your terminal or command prompt on your computer.

2.  Use the psql command to connect to your PostgreSQL database. Replace <username>, <database_name>, <host>, and <port> with your actual database credentials.

 psql -U <username> -d <database_name> -h <host> -p <port>

Example:

 psql -U myuser -d mydatabase -h localhost -p 5432

3. In the psql prompt, execute the CREATE TABLE statement for the "accounts" table:

CREATE TABLE orders (
    order_id SERIAL PRIMARY KEY,
    order_date TIMESTAMP NOT NULL,
    customer_id INTEGER NOT NULL,
    total_amount NUMERIC(10, 2) NOT NULL,
    );

This creates a table named "accounts" with columns account_id, account_number, account_holder, and balance.

4. You can use the \dt command to list all tables in the connected database:

\dt

It should display the "accounts" table among the existing tables.

5. To view the structure of the "accounts" table, you can use the \d command followed by the table name:

\d accounts

It will show you the details of the "accounts" table, including column names, data types, and constraints.

8. To exit the psql session, type \q and press Enter.

That's it! You've successfully created the "accounts" table in your PostgreSQL database using the psql client tool. 

Conclusion

In this comprehensive guide, we've explored the intricacies of the CREATE TABLE statement in PostgreSQL. By understanding its syntax, column definitions, constraints, and additional options, you can design efficient and robust database schemas tailored to your specific requirements. Whether you're a beginner or an experienced PostgreSQL user, mastering the CREATE TABLE statement is essential for effective database management and application development.