Migráció I.

Lassan egy hónapja tart a migráció előkészítése, gyűjtjük a megoldásra váró problémákat, próbálunk egy átfogó képet szerezni az előttünk álló folyamatról. Ebben a bejegyzésben megpróbálom összefoglalni, hogy mire jutottunk eddig.

Jelenleg van egy .NET-es, C#-ban írt alkalmazás (kliens), ami Microsoft SQL Server-t használ adatbázisként. A kliens oldalon szinte kizárólag tárolt eljárás hívások szerepelnek. A cél az, hogy ugyanaz a kliens szoftver képes legyen SQL Server-t is és Oracle Database-t is használni adatbázisként, azaz egy klienshez lenne két külön adatbázis-oldali rész. Ezért a migrációnak csak minimális mértékben kéne visszahatnia a kliens oldali részre. Sajnos ez közel sem olyan egyszerű. Lássuk a problémás területeket!

Adattípusok

Habár az Oracle és az SQL Server által támogatott adattípusok különböznek egymástól, szerencsére az esetek igen nagy százalékában megfeleltethetőek egymásnak. Egy Oracle white paper szerint is: "Microsoft SQL Server and Oracle9i Database data types differ. However these differences are usually small enough to have little or no impact on your applications."

Az SQL Developerbe integrált Migration Workbench (OMWB) a konvertáláskor automatikusan leképezi az SQL Server adattípusokat Oracle adattípusokra. Számunkra lényeges eltérés a (N)VARCHAR típus maximális hosszában van: míg SQL Server alatt maximum 8000 karaktert képes tartalmazni, addig Oracle alatt ez a szám 4000. De szerencsére az OMWB a 4000-nél hosszabb (N)VARCHAR típusokat automatikusan (N)CLOB-okká konvertálja.

Különböznek még a dátum típusok pontosságai: míg SQL Server alatt a DATETIME 3.33 mikroszekundum pontosságú, addig Oracle alatt másodperc pontosságú a DATETIME-nak megfelelő DATE típus. Ahol ez nem elég, ott érdemes a TIMESTAMP típust használni, ami viszont már 1 mikroszekundum pontosságú. Persze kérdés az, hogy az adatbázisunkban kismillió helyen használt DATETIME-ok közül hol elég a másodperces felbontás, és hol nem. Ebből még lehetnek bonyodalmak..

Az adattípusok konvertálásáról bővebben lehet még olvasni az SQL Developer dokumentációjában és a Migrating Applications from Microsoft SQL Server to Oracle9i Database című white paper-ben.

Implicit/explicit konverzió

Az adattípusokhoz erősen kapcsolódó téma a típusok közötti implicit vagy explicit konverziók kérdése.

SQL Server alatt az explicit típuskonverziót a CAST és CONVERT függvények valósítják meg:

CAST ( expression AS data_type [ (length ) ])
CONVERT ( data_type [ ( length ) ] , expression [ , style ] )

Forrás: http://msdn.microsoft.com/en-us/library/ms187928.aspx

A CONVERT függvény SQL Server specifikus, és nagyobb rugalmasságot biztosít dátumok és tört számok konvertálásakor. A CAST pedig inkább ANSI-szerű, ezért többé-kevésbé ugyanolyan szintaxissal lehet használni a különböző adatbázis szerverek alatt.

Implicit konverzió például akkor történik, amikor két különböző típusú adatot hasonlítunk össze, vagy ha egy tábla adott oszlopába szúrunk be egy attól különböző típusú értéket. Az implicit konverzió a felhasználó elől rejtve marad.

SQL Server alatt a lehetséges implicit és explicit típuskonverziók mátrixát az alábbi kép tartalmazza:



Ugyanez az ábra Oracle alatt picit máshogy néz ki, implicit konverziók:



explicit konverziók:



Habár implicit típuskonverzió alkalmazása több okból is helytelen (a kód nehezebben értelmezhető, nem feltétlen optimális az utasítások végrehajtása performancia szempontból, a különböző verziók során változhatnak a konverziós szabályok, stb.) mi mégis több helyen alkalmazzuk, egész egyszerűen azért, mert kényelmes. Például SQL Server a képen látható módon többféle dátumformátumot is képes kezelni:


Kavarodás itt is történhet (ÉV-HÓNAP-NAP, NAP-HÓNAP-ÉV, stb.), de ha az ember ragaszkodik valami megszokott formátumhoz, nem érheti baj. Kivéve, ha a kódot más adatbázis szerver alatt is szeretné használni :)

Oracle alatt az alapértelmezett formátumot az NLS_DATE_FORMAT paraméter tartalmazza, ami az én szerveremen:

SELECT Value FROM v$nls_parameters WHERE parameter = 'NLS_DATE_FORMAT'

VALUE
-----
RR-MON-DD

Azaz a '2008-01-01' például csak explicit módon konvertálható át DATE típusúvá. Ilyen esetekben célszerűbb a TO_DATE függvény használata. A mi esetünkben tehát minden ilyen esetben kézzel át kell írni minden implicit konverziót tartalmazó kódot explicit konverzióvá.

Ideiglenes táblák, táblaváltozók

Ideiglenes táblák SQL Server és Oracle alatt is léteznek, a különbség annyi, hogy míg SQL Server alatt a táblában tárolt adatok és maga a struktúra is ideiglenes, addig Oracle alatt a struktúra (séma) állandó.

A Migration Workbench kiszedi a tárolt eljárások kódjából az ideiglenes táblákat létrehozó DDL utasításokat, és külön hozza létre őket:

/* Translation Extracted DDL For Required Objects */
CREATE GLOBAL TEMPORARY TABLE tt_foo
(
...
);

Az ideiglenes táblákat törlő DROP utasításokból pedig ez lesz:

EXECUTE IMMEDIATE ' TRUNCATE TABLE tt_foo ';

Azaz csak a tartalmát törli a táblának, magát a táblát nem.

Egyelőre úgy tűnik, hogy számunkra ez tökéletesen megfelelő. Egyedül az zavaró, hogy (hanyagságból) rengeteg #temp nevű táblát használunk SQL Server oldalon, és mivel Oracle alatt a séma nem ideiglenes, ezért ahány helyen #temp táblát használunk, annyi darab TT_TEMP_n jön létre Oracle oldalon. Az n jelenleg olyan 30 körüli (TT_TEMP_1, TT_TEMP_2, ... TT_TEMP_30, ..).

Táblaváltozók viszont nincsenek Oracle alatt, ezek kiváltására vagy ideiglenes táblákat, vagy PL/SQL collection-öket kell majd használnunk. Azaz itt is marad a kézi átírás.

1 megjegyzés:

    On 2010. január 22. 9:03 Névtelen írta...

    mit kerestem, koszonom