This is a multi-part series starting with Part 1.
After perfecting the schema and data migration with pgloader rules and getting the application sessions and login code working, it was time to convert the non-working SQL statements to Postgres syntax.
Here’s the SQL syntax I had to change (note: I use placeholders (?) whenever possible):
MySQL | Postgresql 9.1 | Notes/PG 9.5 |
---|---|---|
unix_timestamp(?) | floor(extract(epoch from ?)) | |
from_unixtime(?) | to_timestamp(?) | |
date_add(?, interval ? unit) | ? + interval ‘$x unit’ | |
date_sub(?, interval ? unit) | ? – interval ‘$x unit’ | |
? = 0 or ‘0000-00-00 00:00:00’ | ? is null | |
rand() | random() | |
insert ignore | insert | in the case when the action is not important. PG 9.5: INSERT … ON DUPLICATE KEY IGNORE |
replace into | custom code | in the case when rows are immutable (never updated). PG 9.5: INSERT … ON DUPLICATE KEY UPDATE |
if() | case when … then … else .. end | |
limit ?, ? | limit ? offset ? | can use same syntax for both databases |
group by | group by | Postgresql is stricter about the columns list here |
order by null | MySQL optimization only | |
SQL_CALC_ … FOUND_ROWS | select count(*) | MySQL optimization only |
date(?) | to_char(?, ‘YYYY-MM-DD’),EXTRACT(HOUR FROM ?) | |
`user` | users | Postgresql has public.user, so treat user symbol as reserved table name |
update table1, table2 … | update table1 … where id in (select id from table2 where) | |
last insert id (various) | returning |
Don’t forget to:
- ensure string lengths don’t exceed your schema column widths, and that Postgresql char() space-padding isn’t an issue for your application code
- verify how Postgresql dates use timezones
- run EXPLAIN on each of your statements.
Perl CGI::Session Notes
pgloader migrates the MySQL CGI::Session table using a Postgresql text column. This works better:
alter table sessions alter a_session type bytea using a_session::bytea;