Switching from MySQL to PostgreSQL

Words
216
Reading
1 min
Listen
Play
1y

postgres Background Removed.png

I've never used PostgreSQL from scratch in production before, it's a great system but even so if you're familiar with MySQL and starting a project with PostgreSQL, the transition can feel a bit unfamiliar at first.

Why would you use it then? Well, in my case it was specified before I joined the project, but actually even though MySQL is plenty sufficient most of the time, Postgres does have a lot of powerful features missing from MySQL, so it is worth at least being familiar with it.

PostgreSQL vs MySQL: Key Differences

FeaturePostgreSQLMySQL
PhilosophyStandards-compliant, extensible, correctness-focusedSpeed-focused, simpler setup
ACID ComplianceFully ACID-compliant by defaultACID only with InnoDB engine
Data TypesRich: arrays, JSONB, custom types, strict typingBasic: looser typing, simpler types
JSON SupportAdvanced querying with JSONB and indexesBasic JSON support (since 5.7)
Index TypesB-tree, GIN, GiST, BRIN, partial indexes, expression indexesMostly B-tree, limited functional index support
Stored ProceduresPL/pgSQL, Python, Perl, and moreSimpler stored procedures
ExtensionsExtensible (e.g. PostGIS, uuid-ossp)Less flexible
Concurrency (MVCC)Excellent MVCC, avoids table-level locksMVCC via InnoDB, but still locking under load
CTEs / Window FunctionsFully supportedAvailable from MySQL 8.0+
Toolingpsql, pgAdmin, DBeaver, Posticomysql, Workbench, phpMyAdmin
LicensingOpen source, permissive PostgreSQL licenseGPL, owned by Oracle
ReplicationStreaming + logical replication supported out of the boxMature binlog-based replication

PostgreSQL vs MySQL SQL Syntax

Here are some differences you'll run into when writing SQL for PostgreSQL after using MySQL.

Auto-Increment / Identity



-- MySQL
CREATE TABLE users (
  id INT AUTO_INCREMENT PRIMARY KEY
);

-- PostgreSQL
CREATE TABLE users (
  id SERIAL PRIMARY KEY
);

-- or (preferred for standards)
CREATE TABLE users (
  id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY
);

'UPSERT':

MySQL: ON DUPLICATE KEY UPDATE
PostgreSQL: ON CONFLICT (...) DO UPDATE

Booleans:

MySQL: TINYINT(1)
PostgreSQL: BOOLEAN (TRUE/FALSE)

Case sensitivity:

MySQL: often case-insensitive
PostgreSQL: case-sensitive, use ILIKE for insensitive search

Example:
SELECT * FROM users WHERE name ILIKE 'chris';

IF/CASE

-- MySQL
SELECT IF(score > 50, 'Pass', 'Fail') FROM exams;

-- PostgreSQL
SELECT CASE WHEN score > 50 THEN 'Pass' ELSE 'Fail' END FROM exams;

Dates

-- Current timestamp
SELECT NOW(); -- same in both

-- Extract year
-- MySQL
SELECT YEAR(created_at) FROM orders;

-- PostgreSQL
SELECT EXTRACT(YEAR FROM created_at) FROM orders;

Strings

TypeMySQLPostgreSQL
String literals'text''text'
Identifiers`name`"name" (strict)

String Concatenation:

MySQL: CONCAT(a, b)
PostgreSQL: a || b

Switching from MySQL to PostgreSQL | Ecency