Диалекты SQL: SQLite, PostgreSQL, MySQL
Сезон снят на одном движке — SQLite. На настоящей работе чаще другой — PostgreSQL, иногда MySQL. Три отдела полиции, три свода правил: протокол, оформленный по правилам одного участка, во втором читается неправильно, а в третьем не читается вовсе.
Дата — первое расхождение. У SQLite своего типа даты нет вовсе, только текст. У PostgreSQL — полноценный тип с интервалами. У MySQL — свой формат и свои функции.
| Что | SQLite | PostgreSQL | MySQL |
|---|---|---|---|
| тип даты | нет (текст) | есть | есть |
| часть даты | strftime | EXTRACT | YEAR() |
| склейка строк | только || | || и CONCAT | CONCAT (|| = ИЛИ) |
«|| в одном участке значит „склеить два слова“. В другом — „или“. Один и тот же значок, разный протокол.»
Куда встанет пустая графа при сортировке?
Порядок NULL при сортировке — второе минное поле: в SQLite и MySQL призрак идёт первым при ASC, в PostgreSQL — последним. Один и тот же ORDER BY даёт разные первые строки на разных участках.
ORDER BY amount ASC
-- SQLite/MySQL: NULL первым
-- PostgreSQL: NULL последнимОконные функции и WITH RECURSIVE — приобретение всех трёх участков, но пришли они порознь: оконных функций нет на SQLite до 3.25 и на MySQL до 8.0, а WITH RECURSIVE появился раньше — в SQLite 3.8.3. На старом архиве те же строки — просто синтаксическая ошибка, а не медленный запрос.
«„Работало у меня“ — не оправдание. Это признание, что архив был другой.»
Что ещё не переедет вместе с запросом?
GROUP BY с «голыми» колонками — третье расхождение, и самое коварное: PostgreSQL и современный MySQL требуют строгости и падают с ошибкой, а SQLite молча берёт значение из произвольной строки группы — работает, но врёт, и об этом никто не предупредит.
Перед переносом запроса между участками — сверьтесь с протоколом того, куда идёте. Мост во второй сезон: то, что раскрывало дела здесь, на настоящей работе иногда придётся написать заново — не потому что вы ошиблись, а потому что участок другой.
Весь сезон снят на SQLite. Откройте дело и запомните, что именно вы сделали, — на работе этот же запрос придётся написать заново.