To start this process, obtaining the objects that need validating in the destination database needs to be the first step upon migration completion.
Table Definitions
For MySQL, the definitions are;
- ‘DESC table_name’ will be the console client run SQL statement in MySQL.
- For phpMyAdmin, the ‘Structure’ tab needs to be found in the left pane after highlighting the table.
Within PostgreSQL, the statement will be ‘d table_name’.
When each column has identical default value, type, and size, it is easy to say that the table definition for MySQL is converted property in the PostgreSQL that comes as a result. For each MySQL data type, we have the table of conversions that apply;
In truth, many date types are similar between MySQL and PostgreSQL but some are not equivalent. Therefore, it is vital to know the following tables when migrating from one to the next.
MySQL | PostgreSQL |
BIGINT | BIGINT |
BINARY(n) | BYTEA |
BIT | BOOLEAN |
CHAR(n), CHARACTER(n) | CHAR(n), CHARACTER(n) |
DATE | DATE |
DATETIME | TIMESTAMP [WITHOUT TIME ZONE] |
DECIMAL(p,s), DEC(p,s) | DECIMAL(p,s), DEC(p,s) |
DOUBLE | DOUBLE PRECISION |
FLOAT | REAL |
INT, INTEGER | INT, INTEGER |
MEDIUMINT | INTEGER |
NUMERIC(p,s) | NUMERIC(p,s) |
SMALLINT | SMALLINT |
TINYBLOB, BLOB, MEDIUMBLOB, LONGBLOB | TEXT |
TINYINT | SMALLINT |
TINYTEXT, TEXT, MEDIUMTEXT, LONGTEXT | TEXT |
TIME | TIME [WITHOUT TIME ZONE] |
TIMESTAMP | TIMESTAMP [WITHOUT TIME ZONE] |
VARBINARY(n), VARBINARY(max) | BYTEA |
VARCHAR(n) | VARCHAR(n) |
VARCHAR(max) | TEXT |
To increase the value of the field as soon as a new row is in place, MySQL has ‘auto_increment’ for integer-like columns. For the same purpose, PostgreSQL has SERIAL type and modifications.
MySQL | PostgreSQL |
BIGINT AUTO_INCREMENT | BIGSERIAL |
INTEGER AUTO_INCREMENT | SERIAL |
SMALLINT AUTO_INCREMENT | SMALLSERIAL |
TINYINT AUTO_INCREMENT | SMALLSERIAL |
In MySQL, smallint, bigint, and other integer types can have an UNSIGNED attribute but this isn’t possible on PostgreSQL. When the unsigned attribute is used, only positive numbers with larger upper range of acceptable values will be taken. For the process to be successful, all unsigned types in MySQL must be mapped into PostgreSQL.
MySQL | PostgreSQL |
BIGINT UNSIGNED | NUMERIC(20) |
INT UNSIGNED | BIGINT |
MEDIUMINT UNSIGNED | INTEGER |
SMALLINT UNSIGNED | INTEGER |
TINYINT UNSIGNED | INTEGER |
Finally, the fact that MySQL can store ‘0000-00-00’ in date columns is yet another challenge to face as PostgreSQL does not. When migrating, many experts say that one should change values to NULLs. However, you might need to use different mapping if the technique breaks the database logics.
Data
Using MySQL and Postgres tables, converted data can be validated by simple visual comparison of different fragments. For example, MySQL allows for the following;
- SELECT * FROM the_table LIMIT start_position, number_of_rows
is the run SQL statement in the MySQL console client
- For phpMyAdmin, the ‘Browse’ tab must be selected in the left pane after highlighting the table.
In order to extract fragments of data, PostgreSQL allows for a similar syntax of SELECT-query. Using SELECT * FROM the_table LIMIT number_of_rows OFFSET start_position;
this process can be achieved.
Furthermore, the tables for MySQL and PostgreSQL will need the same count of rows. The next query allows to get the number of rows in a table with both DBMS:
SELECT COUNT(*) FROM the_table;
Indexes
- Statement SHOW INDEXES FROM the_table; is getting indexes for the MySQL console client
- For phpMyAdmin, the ‘Structure’ tab must be selected after first highlighting the table. After doing this, all indexes will be shown.
By using the command ‘d table_name’, information can be attained regarding the indexes within PostgreSQL.
Foreign Keys
Statement SHOW CREATE TABLE `the table name` is getting information about foreign keys for the table in MySQL console client. Foreign keys go at the bottom of the table definition.
- For phpMyAdminm, the ‘Structure’ tab should show a ‘Relations View’ link after highlighting the table.
Using the following SQL statement:
SELECT
tabcon.constraint_name, tabcon.table_name, keycol.column_name,
concol.table_name AS foreign_table_name,
concol.column_name AS foreign_column_name
FROM
information_schema.table_constraints AS tabcon
JOIN information_schema.key_column_usage AS keycol
ON tabcon.constraint_name = keycol.constraint_name
JOIN information_schema.constraint_column_usage AS concol
ON concol.constraint_name = tabcon.constraint_name
WHERE constraint_type = ‘FOREIGN KEY’ AND tabcon.table_name=’the_table_name’;
information regarding foreign keys can be extracted from the ‘information_schema’ service table in PostgreSQL.
Views
Aside from comparing the SELECT-statement for each of the views in MySQL and PostgreSQL, there is no way to verify that every view has been converted successfully. Comprehensive knowledges of database programming are required for this task. The list of all views in source and destination databases can be attained through these queries:
MySQL – SHOW FULL TABLES IN `database name` WHERE TABLE_TYPE LIKE ‘VIEW’;
PostgreSQL – SELECT table_name FROM INFORMATION_SCHEMA.views;
In order to reduce efforts of controlling database migration results, the special reliable software may be used. One of such tools is MySQL to PostgreSQL converter developed by Intelligent Converters, a software company specializing in database conversion and synchronization since 2001.
Nelson Jenkins has been around the block, and it’s made him wise. He knows what he wants to write about, and how to do so effectively. He has an insatiable curiosity that drives him to explore new technologies in order to keep up with all of the latest developments in his field. He enjoys being on top of things, but also likes taking time off from work now and then just to relax or play games with friends – especially if there are good food involved!