MySQL utf8mb4 CHARSET → PostgreSQL Encoding

Why PostgreSQL sets character encoding once per database instead of per table/column, and how MySQL's utf8mb4 maps onto it.

LOW

Quick answer

PostgreSQL sets character encoding once, at CREATE DATABASE time — there is no per-table or per-column CHARACTER SET clause. MySQL's utf8mb4 maps cleanly onto PostgreSQL's UTF8 encoding, since PostgreSQL's "UTF8" is already full 4-byte Unicode (unlike MySQL's legacy 3-byte "utf8", which utf8mb4 itself exists to fix).

Why it breaks

MySQL allows a different CHARACTER SET per table and even per column within the same table. PostgreSQL has one encoding for the entire database, chosen when the database is created — there is nothing to set at the table or column level, so every CHARACTER SET / CHARSET clause in the source schema needs to simply be dropped, with the encoding decision made once, upfront, at the database level.

Real examples

Dropping per-table CHARSET in favor of database-level encoding

MySQL
CREATE TABLE posts (
  title VARCHAR(255)
) DEFAULT CHARSET=utf8mb4;
PostgreSQL
-- CREATE DATABASE ... ENCODING 'UTF8' (once, for the whole database)
CREATE TABLE posts (
  title VARCHAR(255)
);
The encoding decision moves from every CREATE TABLE statement to a single CREATE DATABASE statement.

Dropping a column-level CHARACTER SET clause

MySQL
CREATE TABLE posts (
  title VARCHAR(255) CHARACTER SET utf8mb4
);
PostgreSQL
CREATE TABLE posts (
  title VARCHAR(255)
);
PostgreSQL has no column-level character-set clause either — the database-level encoding already covers every column.

Safe migration options

  • Create the target database with ENCODING 'UTF8' — this single setting covers everything utf8mb4 was doing per-table/per-column in MySQL.
  • If the source schema mixes multiple character sets across different tables (rare, but possible in older multi-tenant schemas), that mixing has no PostgreSQL equivalent — pick one encoding for the whole database and convert any non-matching data during migration.

PostgreSQL solution

CREATE DATABASE mydb WITH ENCODING 'UTF8' LC_COLLATE 'en_US.UTF-8' LC_CTYPE 'en_US.UTF-8' TEMPLATE template0;

Validation

Before cutover

After loading data, spot-check rows containing 4-byte Unicode characters (emoji, some CJK extension characters) specifically — these are exactly the characters MySQL's original 3-byte "utf8" (as opposed to utf8mb4) would have silently mangled, so they are the most likely place for encoding round-trip bugs to surface.

Scan your own schema

This page documents detector rule CHARACTER_SET_OPTION in the DevEquiv analyzer — paste or upload your real MySQL/MariaDB schema to find every occurrence of this (and 19 other documented issues) automatically, with a prioritized readiness report.

Analyze a schema free

References

  • MySQL Manual — The utf8mb4 Character Set (v8.0) — checked 2026-07-30
  • PostgreSQL Manual — Character Set Support (v17) — checked 2026-07-30

Last verified 2026-07-30.