Egyik előző bejegyzésben már írtam, hogy a migrációhoz igen nagy segítséget jelent az SQL Developer Migration Workbench része (dokumentáció
itt). Van egy ún. Translation Scratch Editor része, ami két panelből áll, egyikbe beírja az ember a Transact-SQL kódot, és egy gombnyomásra megjelenik a másik oldalon a PL/SQL változata. Meglepő, de a generált kód igen nagy százalékban működik, és helyes! :)
Eddig két tipikus esetet találtunk, amikor valami bug miatt mégsem jó kódot generál. Az egyik paraméterkezeléssel kapcsolatos, a másik a T-SQL-ben létező
INSERT INTO ... EXEC szerkezet átalakításával.
Az SQL Server megengedi, hogy a bemenő paramétereket mezei változóként használjunk, azaz a lenti kód helyes:
CREATE PROCEDURE foo (@dummy int = null)ASbegin select @dummy = 5endPL/SQL-ben viszont bemenő paraméter nem szerepelhet értékadás bal oldalán. A konvertáló ezt a kódot helyesen az alábbira alakítja át:
CREATE OR REPLACE PROCEDURE foo(iv_dummy IN NUMBER DEFAULT NULL)AS v_dummy NUMBER(10,0) := iv_dummy;BEGIN v_dummy := 5;END;Azaz létrehoz egy változót is, aminek kezdeti értékül a paraméter értékét adja. Ez teljesen jó.
Viszont abban az esetben, ha az értékadást nem SELECT, hanem a SET operátorral végezzük:
CREATE PROCEDURE foo (@dummy int = null)ASbegin set @dummy = 5endmár nem veszi észre, hogy valójában egy paraméterről van szó, és egy az egyben átfordítja:
CREATE OR REPLACE PROCEDURE foo( v_dummy IN NUMBER DEFAULT NULL)ASBEGIN v_dummy := 5;END;Ez a kód természetesen nem fordul le.
A másik hiba akkor fordul elő, ha T-SQL-ben meglévő INSERT INTO...EXEC struktúrát próbálja átalakítani. T-SQL-ben lehetőség van arra, hogy egy táblába szúrjuk bele egy tárolt eljárás által visszaadott eredményhalmazt (ugyanis T-SQL tárolt eljárás képes eredményhalmazokkal is visszatérni, nem úgy, mint a PL/SQL eljárások). Az alábbi T-SQL kódot:
CREATE PROCEDURE fooASbegin insert into sometable (foobar) exec sp_somethingenderre fordítja át:
CREATE OR REPLACE PROCEDURE fooAS v_temp SOMETABLE%ROWTYPE;BEGIN sp_something(); LOOP FETCH cv_1 INTO v_temp; EXIT WHEN cv_1%NOTFOUND; INSERT INTO sometable VALUES v_temp; END LOOP; CLOSE cv_1;END;Maga a logika teljesen jó lenne: a tárolt eljárás egy kurzorváltozóval tér vissza, amin végigmenve egyesével beszúrjuk a sorokat a táblába. A bökkenő csak az, hogy nem deklarálja a cv_1 kurzorváltozót, így a fenti kód szintén nem fordul.
UPDATE: visszaigazolt bug No: 7335256 FORUMS: INSERT INTO .. EXEC PROCEDURE HAS UNDECLARED VARIABLES.
Ezek a hibák természetesen nem vészesek akkor, ha valaki csak pár eljárást szeretne átkonvertálni. Viszont akkor, ha több ezerről lenne szó, akkor már bosszantóak, ugyanis így nehézkes automatizálni.