понеділок, 2 листопада 2009 р.

Перенесення SQL між MySQL і PostgreSQL у «Корпорація 2»

Під час переходу «Корпорація 2» на PostgreSQL ми прагнули зберегти роботу також із MySQL та Firebird. Це вимагало перевірки SQL окремо для кожної СУБД.

Початковий запит із нотатки:

select MK.KARTA_ID, MK.P_BALANS, MK.P_VLASN, MK.P_ZALOG, MK.P_UGON,

MK.MARKA_ID MARKA_ID,MK.VID_ID, MK.ZAV_NOMER ZAV_NOMER, MK.DVIG_NOMER DVIG_NOMER, MK.NSHAS, MK.YEAR_PROD, MK.SER_SVID SER_SVID, MK.DATA_SVID, MK.SER_ZNAK, MK.DATE_NUM, MK.KOD_F, MK.KOD_USER, MK.OLD_ID, MK.DATA_EDIT, MK.DATE_INSERT, MK.DATE_DELETE, MK.IS_DELETED, MK.DATE_COMPILE, MK.DATE_UPDATE, MK.ID_REGION_KOD ID_REGION_KOD, MK.ID_RAJON ID_RAJON, MK.ID_VID, MK.ID_KOD_F, MK.NAME_ORG NAME_ORG, MK.NAME_VID NAME_VID, MK.UPPER_ZAV_NOMER, MK.UPPER_DVIG_NOMER, MK.UPPER_NSHAS, MK.UPPER_SER_SVID, MK.UPPER_SER_ZNAK, MK.DATA_SPISAN, MK.ADDR_ORG, MK.P_REG, MK.DATA_FIRST_REG, MK.D_OLDSVID, MK.N_OLDSVID, MK.YEAR_SVID, MK.YEAR_NUM, MK.YEAR_SPISAN, MK.YEAR_FIRST_REG,MK.YEAR_

OLDSVID, MK.DATA_BALANS, MK.REGION_BALANS, MK.RAJON_BALANS, R.REGION_NAME, MO.KOD_EDRPO, MO.N_PASSP from MTP_KARTA MK



left join TBLREGIONS R

on MK.ID_REGION_KOD=R.ID_REGION_KOD

left join MTP_ORG MO

on (MK.ID_KOD_F=MO.ID_KOD_F)

and (MK.ID_REGION_KOD=MO.ID_REGION_KOD)

where (MK.MARKA_ID<>') and (MK.DATA_SPISAN is null)

and(MK.NAME_ORG like '%трактор%')

order by MARKA_ID





limit 0, 50



Данный запрос прекрасно работает в MySQL, но совершенно не работает в PostgreSQL.

Запропонований тоді варіант:

select MK.KARTA_ID, MK.P_BALANS, MK.P_VLASN, MK.P_ZALOG, MK.P_UGON,

MK.MARKA_ID as MARKA_ID,

MK.VID_ID,

MK.ZAV_NOMER as ZAV_NOMER,

MK.DVIG_NOMER as DVIG_NOMER, MK.NSHAS, MK.YEAR_PROD,

MK.SER_SVID as SER_SVID, MK.DATA_SVID, MK.SER_ZNAK, MK.DATE_NUM, MK.KOD_F, MK.KOD_USER, MK.OLD_ID, MK.DATA_EDIT, MK.DATE_INSERT, MK.DATE_DELETE, MK.IS_DELETED, MK.DATE_COMPILE,

MK.DATE_UPDATE, MK.ID_REGION_KOD as ID_REGION_KOD,

MK.ID_RAJON as ID_RAJON, MK.ID_VID, MK.ID_KOD_F,

MK.NAME_ORG as NAME_ORG,

MK.NAME_VID as NAME_VID, MK.UPPER_ZAV_NOMER,

MK.UPPER_DVIG_NOMER, MK.UPPER_NSHAS, MK.UPPER_SER_SVID, MK.UPPER_SER_ZNAK, MK.DATA_SPISAN, MK.ADDR_ORG, MK.P_REG, MK.DATA_FIRST_REG, MK.D_OLDSVID, MK.N_OLDSVID, MK.YEAR_SVID, MK.YEAR_NUM, MK.YEAR_SPISAN, MK.YEAR_FIRST_REG,MK.YEAR_OLDSVID, MK.DATA_BALANS, MK.REGION_BALANS, MK.RAJON_BALANS, R.REGION_NAME, MO.KOD_EDRPO, MO.N_PASSP



from MTP_KARTA MK



left join TBLREGIONS R

on MK.ID_REGION_KOD=R.ID_REGION_KOD

left join MTP_ORG MO

on (MK.ID_KOD_F=MO.ID_KOD_F)

and (MK.ID_REGION_KOD=MO.ID_REGION_KOD)

where (MK.MARKA_ID<>') and (MK.DATA_SPISAN is null)

and(MK.NAME_ORG like '%трактор%')

order by MARKA_ID



limit 50 offset 10

Обидва фрагменти збережено для аналізу, але в них є незавершений рядковий літерал у MK.MARKA_ID<>'. У першому також розірвано ім’я YEAR_OLDSVID. У такому вигляді це не перевірені робочі запити.

AS робить псевдонім явним, але для звичайного псевдоніма стовпця не завжди обов’язковий у PostgreSQL. Істотна відмінність прикладів — синтаксис пагінації: MySQL підтримує LIMIT offset, count і LIMIT count OFFSET offset, тоді як PostgreSQL використовує другий варіант. При цьому LIMIT 0, 50 та LIMIT 50 OFFSET 10 вибирають різні сторінки, а не однаковий результат.

Не слід автоматично вважати LIMIT універсальним синтаксисом для всіх SQL-серверів, зокрема Firebird. Для перенесення також перевіряють типи, регістр, порівняння тексту та стабільність ORDER BY.

Документація: PostgreSQL SELECT, MySQL SELECT. Конкретну схему таблиць і тестові дані в нотатці не наведено.

Немає коментарів:

Калькулятор K2: від запитання про ціну до готової комерційної пропозиції

«А скільки коштуватиме інша комплектація?» — природне запитання покупця. Якщо для відповіді менеджер щоразу відкриває таблицю, шукає коефіці...