Mehmet Karataş LogoMehmet Karataş
HomeServicesProjectsBlogAboutFunToolsCourses (TR)
Contact
Mehmet Karataş LogoMehmet Karataş

Contact

I build solutions with modern web and mobile technologies.

Contact
benmuhendisiniz@gmail.com

Diyarbakır, Türkiye — Remote services across Türkiye and abroad

Quick links

  • Home
  • Services
  • Projects
  • Blog
  • About
  • Contact
  • Fun
  • Tools
  • Courses (TR)
  • CV / Résumé (TR)

Services

  • Web Development
  • Mobile App Development
  • Custom Software Development
  • E-Commerce Websites
  • SEO and Online Visibility
  • Software and Project Consulting

© 2026 Mehmet Karataş. All rights reserved.

Privacy noticeCookie policy
HomeProjectsBlogServicesAboutFunToolsCourses (TR)
HomeBlogTutorialWhat Is PostgreSQL? A Guide to SQL Queries and Database Design in 2025
All articles
Tutorial
12 December 2025
63
5 min read

What Is PostgreSQL? A Guide to SQL Queries and Database Design in 2025

What is PostgreSQL, and why is this open-source database management system so popular in 2025? This comprehensive guide covers PostgreSQL fundamentals, SQL queries and relational database design. Written for beginners and experienced developers, it includes comparisons with MySQL and MongoDB, practical SELECT, INSERT, UPDATE and DELETE commands, JOINs, normalisation and performance tips. Learn to build modern web applications using PostgreSQL with Supabase. Practise with blog and e-commerce examples, and explore ACID compliance and security features such as Row Level Security (RLS).

Mehmet Karataş

Mehmet Karataş

Back to blog Work with me

Author

What Is PostgreSQL? A Guide to SQL Queries and Database Design in 2025

An Introduction to PostgreSQL: The Database Elephant 🐘

Time to Learn the Foundations of Data Management

Grab a coffee and let’s talk about PostgreSQL. It is a database that powers many modern web applications.

What Is PostgreSQL?

Every application needs somewhere to store its data: user details, blog posts, orders, comments and more.

PostgreSQL, or Postgres for short, is a powerful, reliable, open-source relational database management system that does exactly that.

What does relational mean?

It means data is stored in tables that can relate to one another. Think of spreadsheet tables, but with much more structure and capability.

Why PostgreSQL?

With alternatives such as MySQL, MongoDB and SQLite available, why choose Postgres?

1. Powerful and Stable

It has more than 30 years of development behind it. Software with that kind of history has stood the test of time.

2. Open Source and Free

There are no licence fees, and the community is strong. You can use and customise it to suit your needs.

3. ACID Compliant

  • Atomicity

  • Consistency

  • Isolation

  • Durability

These properties help keep database transactions complete, consistent, isolated and durable.

4. JSON Support

JSON is common in modern applications. Postgres can store both relational data and JSON, giving you the benefits of both.

5. Scalability

You can start with a small blog and grow into a platform with millions of users. Postgres can support that growth with appropriate architecture.

6. Used by Major Companies

Postgres is used in large technology organisations as well as smaller projects.

PostgreSQL vs MySQL vs MongoDB

A quick comparison:

PostgreSQL:

  • A relational database

  • ACID compliant

  • Well suited to complex queries

  • Supports JSON

  • Enforces a structured schema

MySQL:

  • A relational database

  • Straightforward setup

  • Widely used

  • Popular with platforms such as WordPress

MongoDB:

  • A NoSQL database

  • Flexible document structure

  • Does not require a fixed table schema

  • Useful for rapid prototyping

  • Complex relationships require different modelling approaches

My recommendation: Learn PostgreSQL if you want to build a well-structured database. It combines relational foundations with modern features.

Core Concepts

Database

The main container for your data. A project often uses one database.

Table

A structure that stores data in rows and columns.

Column

An individual field in a table, such as id, username or email.

Row

An individual record. For example, one row can contain all of Ahmet’s user details.

Primary Key

A field that uniquely identifies each row, usually called id.

Foreign Key

A field that links one table to another.

Getting Started: Designing a Simple Blog Database

Suppose you are building a blog. What do you need?

1. The Users Table

CREATE TABLE users (
  id SERIAL PRIMARY KEY,
  username VARCHAR(50) UNIQUE NOT NULL,
  email VARCHAR(100) UNIQUE NOT NULL,
  password_hash VARCHAR(255) NOT NULL,
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

Explanation:

  • SERIAL = an automatically increasing number (1, 2, 3…)

  • PRIMARY KEY = a unique identifier

  • VARCHAR(50) = a maximum of 50 characters

  • UNIQUE = duplicate values are not allowed

  • NOT NULL = a value must be provided

  • TIMESTAMP = a date and time

2. The Posts Table

CREATE TABLE posts (
  id SERIAL PRIMARY KEY,
  title VARCHAR(200) NOT NULL,
  slug VARCHAR(200) UNIQUE NOT NULL,
  content TEXT NOT NULL,
  author_id INTEGER REFERENCES users(id),
  published BOOLEAN DEFAULT false,
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

Explanation:

  • TEXT = text without a declared length limit

  • REFERENCES users(id) = a link to the users table through a foreign key

  • BOOLEAN = true/false

3. The Comments Table

CREATE TABLE comments (
  id SERIAL PRIMARY KEY,
  post_id INTEGER REFERENCES posts(id) ON DELETE CASCADE,
  user_id INTEGER REFERENCES users(id),
  content TEXT NOT NULL,
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

Explanation:

  • ON DELETE CASCADE = deleting a post also deletes its comments

Basic SQL Commands

Adding Data (INSERT)

-- Kullanıcı ekle
INSERT INTO users (username, email, password_hash)
VALUES ('mehmet', 'mehmet@email.com', 'hashed_password_123');

-- Blog yazısı ekle
INSERT INTO posts (title, slug, content, author_id, published)
VALUES (
  'PostgreSQL Öğreniyorum',
  'postgresql-ogreniyorum',
  'Bu benim ilk blog yazım!',
  1,
  true
);

Retrieving Data (SELECT)

-- Tüm kullanıcıları getir
SELECT * FROM users;

-- Sadece username ve email getir
SELECT username, email FROM users;

-- Yayınlanmış yazıları getir
SELECT * FROM posts WHERE published = true;

-- En yeni 10 yazıyı getir
SELECT * FROM posts ORDER BY created_at DESC LIMIT 10;

Updating Data (UPDATE)

-- Kullanıcının email'ini güncelle
UPDATE users 
SET email = 'yeni@email.com' 
WHERE id = 1;

-- Yazıyı yayınla
UPDATE posts 
SET published = true, updated_at = CURRENT_TIMESTAMP 
WHERE id = 1;

Deleting Data (DELETE)

-- Bir yorumu sil
DELETE FROM comments WHERE id = 1;

-- Yayınlanmamış yazıları sil
DELETE FROM posts WHERE published = false;

Relationships and JOINs

This is where tables become especially useful: combine them to retrieve meaningful information.

INNER JOIN

-- Yazıları yazarlarıyla birlikte getir
SELECT 
  posts.title, 
  posts.content, 
  users.username as author
FROM posts
INNER JOIN users ON posts.author_id = users.id;

LEFT JOIN

-- Tüm kullanıcıları, yazı yazmamış olanları da getir
SELECT 
  users.username,
  COUNT(posts.id) as post_count
FROM users
LEFT JOIN posts ON users.id = posts.author_id
GROUP BY users.username;

Complex Queries

-- Her yazının yorum sayısını getir
SELECT 
  posts.title,
  users.username as author,
  COUNT(comments.id) as comment_count
FROM posts
INNER JOIN users ON posts.author_id = users.id
LEFT JOIN comments ON posts.id = comments.post_id
WHERE posts.published = true
GROUP BY posts.id, posts.title, users.username
ORDER BY comment_count DESC;

Database Design Principles

1. Normalisation

Organising data to avoid unnecessary duplication.

Poor Design ❌

Problem: Ahmet’s email address is repeated in every row. If it changes, you have to update all of them.


Better Design ✅

Solution: Store the email address once in the users table. Then you only need to update it in one place.

2. Indexing

Indexes help speed up queries.

-- Email'e göre sık arama yapıyorsan
CREATE INDEX idx_users_email ON users(email);

-- Slug'a göre sık arama yapıyorsan
CREATE INDEX idx_posts_slug ON posts(slug);

Without a useful index, the database may need to scan every row. An appropriate index can help it find matching records more directly.

3. Choosing Data Types

Use the right type for each value:

  • Numbers: INTEGER, BIGINT, DECIMAL

  • Text: VARCHAR, TEXT

  • Dates: DATE, TIMESTAMP

  • Boolean: BOOLEAN

  • JSON: JSON, JSONB

4. Constraints

Use constraints to protect data integrity:

CREATE TABLE products (
  id SERIAL PRIMARY KEY,
  name VARCHAR(100) NOT NULL,
  price DECIMAL(10, 2) CHECK (price > 0),
  stock INTEGER CHECK (stock >= 0),
  category_id INTEGER REFERENCES categories(id)
);

PostgreSQL with Supabase

If you use Supabase, you already use PostgreSQL. Supabase is a platform built on top of it.

Creating a Table in Supabase

  1. From the dashboard:

    • Open the Table Editor

    • Click “New Table”

    • Add your columns

    • Save

  2. From the SQL Editor:

-- Supabase SQL Editor'de çalıştır
CREATE TABLE todos (
  id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
  user_id UUID REFERENCES auth.users(id),
  task TEXT NOT NULL,
  completed BOOLEAN DEFAULT false,
  created_at TIMESTAMP DEFAULT NOW()
);

Row Level Security (RLS)

An important Supabase capability: access rules enforced at the database level.

-- Kullanıcılar sadece kendi todo'larını görsün
CREATE POLICY "Users can view own todos"
ON todos FOR SELECT
USING (auth.uid() = user_id);

-- Kullanıcılar sadece kendi todo'larını ekleyebilsin
CREATE POLICY "Users can insert own todos"
ON todos FOR INSERT
WITH CHECK (auth.uid() = user_id);

Practical Examples

Example 1: A Blog

Requirements:

  • Users

  • Blog posts

  • Categories

  • Comments

  • Tags

Table structure:

-- Kullanıcılar
CREATE TABLE users (
  id SERIAL PRIMARY KEY,
  username VARCHAR(50) UNIQUE NOT NULL,
  email VARCHAR(100) UNIQUE NOT NULL,
  bio TEXT,
  avatar_url TEXT,
  created_at TIMESTAMP DEFAULT NOW()
);

-- Kategoriler
CREATE TABLE categories (
  id SERIAL PRIMARY KEY,
  name VARCHAR(50) UNIQUE NOT NULL,
  slug VARCHAR(50) UNIQUE NOT NULL
);

-- Yazılar
CREATE TABLE posts (
  id SERIAL PRIMARY KEY,
  title VARCHAR(200) NOT NULL,
  slug VARCHAR(200) UNIQUE NOT NULL,
  content TEXT NOT NULL,
  excerpt TEXT,
  cover_image TEXT,
  author_id INTEGER REFERENCES users(id),
  category_id INTEGER REFERENCES categories(id),
  published BOOLEAN DEFAULT false,
  view_count INTEGER DEFAULT 0,
  created_at TIMESTAMP DEFAULT NOW(),
  updated_at TIMESTAMP DEFAULT NOW()
);

-- Etiketler
CREATE TABLE tags (
  id SERIAL PRIMARY KEY,
  name VARCHAR(50) UNIQUE NOT NULL
);

-- Yazı-Etiket ilişkisi (Many-to-Many)
CREATE TABLE post_tags (
  post_id INTEGER REFERENCES posts(id) ON DELETE CASCADE,
  tag_id INTEGER REFERENCES tags(id) ON DELETE CASCADE,
  PRIMARY KEY (post_id, tag_id)
);

-- Yorumlar
CREATE TABLE comments (
  id SERIAL PRIMARY KEY,
  post_id INTEGER REFERENCES posts(id) ON DELETE CASCADE,
  user_id INTEGER REFERENCES users(id),
  parent_id INTEGER REFERENCES comments(id),
  content TEXT NOT NULL,
  created_at TIMESTAMP DEFAULT NOW()
);

Example 2: An Online Shop

Requirements:

  • Products

  • Categories

  • Orders

  • Shopping carts

  • Reviews

-- Ürünler
CREATE TABLE products (
  id SERIAL PRIMARY KEY,
  name VARCHAR(200) NOT NULL,
  slug VARCHAR(200) UNIQUE NOT NULL,
  description TEXT,
  price DECIMAL(10, 2) NOT NULL CHECK (price >= 0),
  stock INTEGER NOT NULL DEFAULT 0 CHECK (stock >= 0),
  category_id INTEGER REFERENCES categories(id),
  image_url TEXT,
  created_at TIMESTAMP DEFAULT NOW()
);

-- Siparişler
CREATE TABLE orders (
  id SERIAL PRIMARY KEY,
  user_id INTEGER REFERENCES users(id),
  total_amount DECIMAL(10, 2) NOT NULL,
  status VARCHAR(20) DEFAULT 'pending',
  shipping_address TEXT NOT NULL,
  created_at TIMESTAMP DEFAULT NOW()
);

-- Sipariş detayları
CREATE TABLE order_items (
  id SERIAL PRIMARY KEY,
  order_id INTEGER REFERENCES orders(id) ON DELETE CASCADE,
  product_id INTEGER REFERENCES products(id),
  quantity INTEGER NOT NULL CHECK (quantity > 0),
  price DECIMAL(10, 2) NOT NULL,
  subtotal DECIMAL(10, 2) NOT NULL
);

-- İncelemeler
CREATE TABLE reviews (
  id SERIAL PRIMARY KEY,
  product_id INTEGER REFERENCES products(id) ON DELETE CASCADE,
  user_id INTEGER REFERENCES users(id),
  rating INTEGER CHECK (rating >= 1 AND rating <= 5),
  comment TEXT,
  created_at TIMESTAMP DEFAULT NOW()
);

Performance Tips

1. Use EXPLAIN

See how a query runs:

EXPLAIN ANALYZE
SELECT * FROM posts WHERE author_id = 1;

2. Add Indexes

Index columns used frequently in queries:

CREATE INDEX idx_posts_author ON posts(author_id);
CREATE INDEX idx_posts_slug ON posts(slug);
CREATE INDEX idx_posts_published ON posts(published);

3. Use LIMIT

Avoid retrieving unnecessary data:

-- Kötü
SELECT * FROM posts;

-- İyi
SELECT * FROM posts LIMIT 20;

4. Avoid SELECT *

Retrieve only the columns you need:

-- Kötü
SELECT * FROM users;

-- İyi
SELECT id, username, email FROM users;

Common Mistakes and Solutions

1. The N+1 Problem

-- Kötü: Her yazı için ayrı sorgu
SELECT * FROM posts;
-- Sonra her post için:
SELECT * FROM users WHERE id = post.author_id;

-- İyi: Tek sorguda al
SELECT 
  posts.*, 
  users.username 
FROM posts 
JOIN users ON posts.author_id = users.id;

2. Forgetting Cascading Deletes

-- İlişkili verileri otomatik sil
FOREIGN KEY (post_id) REFERENCES posts(id) ON DELETE CASCADE

3. Missing Indexes

Consider indexes on columns used in WHERE, JOIN and ORDER BY clauses.

4. Incorrect Data Types

-- Yanlış
age VARCHAR(10)  -- Yaş string mi?

-- Doğru
age INTEGER

Conclusion: Why PostgreSQL Matters

Modern applications need reliable data storage. PostgreSQL has become an established choice for this job.

Why learn it?

  1. A core skill: Database knowledge is essential for full-stack development

  2. Powerful: Suitable for projects ranging from small apps to large platforms

  3. Popular: A skill sought in many developer roles

  4. Free: Open-source software without licence fees

  5. Modern: Combines the capabilities of SQL and JSON

Where should you start?

  1. Practise using Supabase’s free plan

  2. Build a simple to-do app

  3. Create a blog project

  4. Design an online shop

  5. Think about the data model in every project

Learning PostgreSQL takes time, but it is worthwhile. Once you understand it, many other database concepts become easier to grasp.

Get started, practise, make mistakes and learn. Take control of your data.

Let’s write some code!

Comments (0)

No comments yet. Be the first!

Leave a comment

Write a comment
Mehmet Karataş

Mehmet Karataş

Computer Engineer

About me
Related articles
  • What Are Frontend and Backend? Their Differences and Roles in a Software Project

    What are frontend and backend, how do they differ and what do they do in a software project? This guide explains the visible and hidden parts of software, from user screens to servers that store data. If you are planning a website, mobile app, dashboard or custom application, learn how interfaces, APIs, databases, accounts, payments and security affect development. We also explore what determines frontend and backend costs, when both are needed and what to define before starting.

  • What Is Node.js? Its Role in Backend Development

    Node.js is an open-source runtime that runs JavaScript outside the browser, including on servers. It can power APIs for websites, mobile apps, dashboards and real-time systems. This guide explains its execution model, event loop, database connections, authentication, messaging and API development, along with suitable use cases, limitations and planning considerations.

  • What Is Next.js? Why It Matters for Modern, SEO-Friendly Websites

    Next.js is a comprehensive React framework for building fast, modern, secure and SEO-friendly websites. Server rendering and pre-rendering can make content easier for search engines to access. It provides organised ways to manage titles, descriptions, social images, sitemaps, robots.txt, structured data and image optimisation. Using Next.js alone does not guarantee high search rankings. Good results also require useful content, appropriate keywords, mobile usability, security, performance and a strong user experience.

Explore projects