Oracle SQL Developer Migration Workbench
2008. augusztus 6., szerda by Zoltan Tanczos
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)
AS
begin
select @dummy = 5
end
PL/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)
AS
begin
set @dummy = 5
end
má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
)
AS
BEGIN
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 foo
AS
begin
insert into sometable (foobar)
exec sp_something
end
erre fordítja át:
CREATE OR REPLACE PROCEDURE foo
AS
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.
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)
AS
begin
select @dummy = 5
end
PL/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)
AS
begin
set @dummy = 5
end
má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
)
AS
BEGIN
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 foo
AS
begin
insert into sometable (foobar)
exec sp_something
end
erre fordítja át:
CREATE OR REPLACE PROCEDURE foo
AS
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.