Hatékony kódolás pl
Arup Nanda, az Oracle ACE igazgatója
Váltja ki, hogy a tűz többször függően az esemény, a képesség, hogy kiváltja az egyik típusú műveleti sorrendjét, az új javaslat FOLYTATÁS - íme néhány az új funkciók, amelyek egyszerűsítik programozás PL / SQL.
A kezdetektől fogva a PL / SQL az Oracle Database programozásához választott nyelv volt. Egy idő után nyilvánvalóvá vált, hogy a növekvő funkcionalitás miatt, amely kevesebb kódolást igényel, a nyelv olyan mértékben fejlődött ki, hogy elegendő legyen teljesen kifejlesztésre. Az Oracle Database 11g a PL / SQL kódolást még hatékonyabbá teszi a programozók számára. Ebben a cikkben néhány példát fogunk megnézni, amelyek segítségével röviden megismerheti az új funkciókat.
Tekintse meg a szálloda adatbázist: a szállodai szobatáblákat a BOOKINGS tábla tárolja. A táblázathoz módosítani kell a változtatásokat is - ellenőrzéshez hasonlóan, de egy különlegességgel: tranzakciót kell végrehajtania. A triggerek a legjobbak ehhez.
Ehhez kicsi indítót kell kipróbálni a frissítés után egy olyan karakterláncra, amely a régi és az új értékeket írja a BOOKINGS_HIST táblába, valamint a változást végrehajtó személyre. Eddig olyan jó.
Van azonban egy kis probléma. Az utánkövetés utáni soros trigger mindegyik sorra aktiválódik, és egyes rekordok tömeges sorrendben változnak, tranzakciónként több száz sort változtatnak. Az egyes sorok utáni frissítéssor-trigger aktiválása és a bejegyzés beillesztésének végrehajtása a bookings_hist táblában a teljesítmény nem optimális.
Jobb, ha ezeket a lapokat a table bookings_hist könyvtárba illesztheted, és egy csomóponttal végrehajtod őket. Ezt egy komplex kiváltó sorozattal lehet végrehajtani. A lényeg az, hogy meg kell tenni az értékeket szánt bookings_hist táblázatban szerepelnek a gyűjteményben a ravaszt minden csatorna, majd töltse be az adatokat a gyűjtemény a táblázat bookings_hist segítségével utáni frissítés ravaszt hez, amely csak egyszer lép működésbe. Mivel a beillesztés csak egyszer megy végbe, a folyamat gyorsabban fut, mint az egyes sorok beillesztése.
De ezek két különbözõ kódjelûek. Csak egy módja annak, hogy adja át a változót a gyűjtemény egy flip-flop a másik -, hogy hozzon létre egy csomagot egy gyűjtemény változó, például tömb vagy PL / SQL-tábla a csomagban leírás, töltse meg a sorban ravaszt utáni frissítés és olvasni után a ravaszt ajánlat - és ez nem egyszerű feladat. Nem egyszerűbb lenne minden kiváltó egy kódot elhelyezni?
Az Oracle Database 11 g-ban összetett triggereket használhat. A vegyületindítók négyféle kiváltó tényezőt jelentenek. Például egy összetett UPDATE trigger egy mondat előtt, egy string előtt, egy mondat után és egy olyan karakterlánc után, amely egyszerre jelen van egy összetett triggerben. Itt van annak a kódnak a része, amely leírja, hogyan változtathatja át a változókat egy monolitikus PL / SQL kódon belül.
Tekintsünk egy példát. Sorszámokat adunk hozzá, hogy megkönnyítsük a magyarázatot.
A ravaszt működésének jobb megértéséhez tegyen bemutató frissítést, amely megváltoztatja a négy sort.
Vegye észre, hogy az összetett trigger végrehajtása. Négy részből áll:
A kijelentés előtt
. a javaslat előtt egyszer végrehajtásra kerül.
Sor előtt
. minden egyes sorban egyszer végrehajtásra kerül a művelet előtt.
Sor után
. a művelet után minden egyes sorban végrehajtódik.
Nyilatkozat után
. a javaslatot egyszer végrehajtják.
Amint látja, ez a kód egy, de minden egyes szakasz végrehajtása különböző időpontokban történik.
Az előző példában a dbms_output záradékokat különböző helyeken tettem fel, hogy megmutassam, hogyan hajtják végre az egyes szakaszokat ezeken a pontokon. Azt módosított booking_ids négysoros 100, 101, 102 és 103, és ez látható, amely kiváltja amelyekről előzőleg és után dolgozott az ajánlatot egyszer, és kiváltja vonal (előtt és után), ha soronként. (Az előző példában nincs szükség a mondatra és a húrra vonatkozó triggerekre, de a funkciók bemutatására írtam őket).
Ha megnézed a bookings_hist táblát, akkor láthatod, hogy most négy bejegyzés van benne - egy-egy foglalásidőt - de ez a négy bejegyzés a mondat végén egy halomba került, ahelyett, hogy minden sort megváltoztatna:
Az összetett triggerek egyik nagyon hasznos tulajdonsága, hogy a belső PL / SQL kódobjektumok, például változók, csomagok stb. akkor keletkeznek, amikor a trigger aktiválódik, és a kiváltó művelet végén az állapotuk törlődik. A fenti példában a gyűjtemény nem lett inicializálva, és a gyűjtemény tartalmát nem törölték. Mindez automatikusan beavatkozás nélkül történt meg.
A triggerek végrehajtásának sorrendje
Az Oracle8-mal kezdődően lehetőség nyílt arra, hogy egyazon táblázatban több azonos típusú aktiválót lehessen leírni - például két soros utólagos triggerelést, amikor egyetlen táblázatba illesztik őket. Az aktiválók típusa határozza meg a végrehajtás sorrendjét: a mondat előtt, a sor előtt, a mondat után és a sor után. Ha azonban két alacsonyabb rendű utólag aktiválódik, a T1 és a T2, akkor melyik lesz az első?
Az azonos típusú futó aktiválók önkényesen vagy legalábbis nem feltétlenül követik a mintát. Ez probléma? Nézzünk egy példát a KIFIZETÉSEK táblázatra:
A kockázati besorolást a fizetés típusától és az összegtől függően kell kiszámítani, és el kell menteni a RISK_RATING oszlopba. A következő egyszerű vonalszintű trigger a frissítés előtt egyszerűen kezeli ezt a feladatot:
Most valaki hozzáad egy másik követelményt: a RISK_RATING, PAY_MODE stb oszlopoktól függő értékeket egy FOLLOW_UP oszlop emelésével kell jelölni. Az indítót módosítani kell, de jobb, ha nem érinti a meglévő kódot, de hozzon létre egy új, ugyanolyan típusú (egy frissítés előtti sort) triggert, az alábbiak szerint. (A dbms_output-ot a kódba mutattam be, hogy megmutassam, hogyan fognak aktiválni az aktiválókat).
Most, ha frissíti a táblázatot:
Mi történt? A risk_rating oszlop HIGH, és a pay_mode oszlop értéke "C", ami azt jelenti, hogy a FOLLOW_UP oszlopnak "Y", nem "N" kell lennie. Miért? A kérdés megválaszolásához nézze meg, hogy a triggerek milyen sorrendben indultak: a tr_pay_follow_up a tr_pay_risk_rating előtt dolgozott. Ez utóbbi az oszlop értékét magas minősítésként állította be. Ezért, amikor az első dolgozott, null (vagy "N") találta a risk_rating oszlopban, és ezért érezte, hogy ez a feltétel teljesült.
Ebben az esetben a triggerek sorrendje nagyon fontos. Ha a tr_pay_risk_rating nem működik a második másodpercen belül, akkor a helyes értékek nem lesznek beállítva, és a telepített adatok a követelmények helytelen végrehajtását eredményezik. Az egyetlen egyszerű megoldás az lenne, ha az egész logikát egyetlen kódra cserélnék és végrehajtaná a megfelelő sorrendben.
Az Oracle Database 11 g-ban megadhat egy kifejezést a kiváltó parancsfájlban, amely meghatározza az indítógombok sorrendjét. Itt van a ravasz felső része, amely magában foglalja ezt a kifejezést:
Ez a kifejezés (FOLLOWS <название_триггера>) okozza a triggert a megadott trigger után. Ezt a korábban bemutatott frissítési parancsfájl futtatásával teszteljük.
A várakozásoknak megfelelően az oszlop kitöltése helyesen történt. Vegye figyelembe a triggerek helyes sorrendjét is, ami megerősíti, hogy a kifejezés működik.
Az aktiválók sorrendje lehetővé teszi, hogy kihasználja a modulkód használatát, lehetővé téve a megfelelő sorrendben történő végrehajtást is.
Ha nincs mit végrehajtani, folytatjuk a CONTINUE műveletet
Az eddigi összes képességével együtt a PL / SQL-ben a nyelvtan egyik fontos része kimaradt: hogyan kell bizonyítania, hogy nem kell semmit csinálnia, hanem a hurok végére kell mennie és folytatnia.
Az Oracle Database 11g-ban a PL / SQL egy új CONTINUE konstrukcióval rendelkezik, amelyet a hurokban használnak. Ez a mondat áthelyezi a logikát a hurok végére, majd a hurok elejére. Itt van egy kis példa, amely bemutatja, hogy a vezérlés átkerül a hurok végére, amikor a számláló nem több, mint 10.
A CONTINUE egy másik változata a ciklus nevének használata.
Az előre definiált konstrukció, például a mod (belső, 3) helyett egy olyan funkciót használhat, amely valamilyen számítást végez.
Mondanom sem kell, hogy ez a design csak egy hurokban használható, ha van értelme. Ha megpróbálja használni a hurokon kívül, fordítási hibát kap.
Ha korábban egy PL / SQL programot használtak, akkor SELECT-et kellett használnia <последовательность>.NEXTVAL INTO <название_переменной> A DUAL-tól a kiadásig.
Nincs többé szükség. A következő értéket közvetlenül rendelheti a változóhoz:
Ezt hívom egyszerűnek.
Az a mondat, "Mikor a MÁSODIK azt követően" bármit megtesz
Számos PL / SQL programozó vesz igénybe veszélyes gyakorlatot, így az OTHERS kivételeket figyelmen kívül hagyja az alábbiak szerint:
Ez a következőket mondja: "Ha hiba történik, ne csinálj semmit, csak hagyd figyelmen kívül, vagy úgy tedd, hogy ez soha nem fog megtörténni, és nem fog megtörténni". Ha csak a világ olyan egyszerű volt! Ez a gyakorlat potenciálisan hibás, instabil kódot eredményez.
Az Oracle Database 11g segítséget nyújt ebben az irányban. Ebben benne van egy új megjegyzés PLW-06009, amely egy ilyen problémáról értesíti a fordítási időt. Íme egy példa:
Az összeállítás során az eljárást megjegyzések nélkül állítják össze, 10 g-nál. Ennek engedélyezéséhez be kell állítania a munkamenet paraméterét.
Vegye figyelembe, hogy a PLW-06009 új megjegyzés fordítási időben jelenik meg. És ez csak egy megjegyzés; az egész összeállítás sikeres volt. Végezze el az eljárást, de tartsa szem előtt a megjegyzést!
Az Oracle Database 11g-ban ez a szkript már nem jelent problémát. Olyan triggeret hozhat létre, amelyet korábban letiltott, és amely lehetővé teszi az összes összeállítási hiba tesztelését. És később, szerkesztés közben engedélyezze. Így hozzon létre egyet:
Most ellenőrizheti állapotát:
SQL> kiválaszthatja az állapotot
2> a user_triggerektől
3> ahol trigger_name = 'TR_T'
4> /
Annak ellenére, hogy a trigger létre lett hozva, hibásnak kell lennie. Ezért ha hibaüzenetet próbál létrehozni (például az "M" tábla használatával, amely nem létezik):
Ez a funkció nagyon hasznos a változások szabályozásában. Ennek a funkciónak egy másik figyelemre méltó alkalmazása a triggerek egy adott pillanatban történő bevonása. Például az aktiválók használatával létrehozhat egy auditálási megoldást, és az audit_table nem törlődik a régi rekordokból. A triggerek létrehozhatók és később bekapcsolhatók, amikor az asztal kész.
Nevezett funkcióparaméterek
Tekintsünk egy egyszerű funkciót:
Ez a funkció nagyon egyszerű művelet, de jól szemlélteti a koncepciót. Mivel ebben a függvényben két paraméter van megadva, úgy hívhatjuk, ha a paramétereket pozícióértékekként adjuk át, nevezetesen:
Vagy nevezett paraméterekként:
Azonban a végén probléma merül fel, ha bizonyos mondatokban használja. Ha az Oracle Database 10g következő állítását futtatja:
Az Oracle Database 11 g-ben jogosult a jelölést használni:
amely megfelelően működik. Megadhat egy megnevezett jelölést a végén, és az első paramétereknek pozíciónak kell lenniük. Például a következő hívás, ahol a p_param1 értéke 1, helyes:
És ez nem (a pozícióparaméter a végén):
A dinamikus kurzor és a REF kurzor cserélhetősége
Tudod, hogy hasznos lehet a natív dinamikus kurzor, különösen akkor, ha nem tudod pontosan, hogy mit fogsz kérni a hívás előtt. A dinamikus PL / SQL a DBMS_SQL segítségével is használható. Mindkét módszer előnye. De mi történik akkor, ha elkezdte fejleszteni egy olyan programot, amely először egy módszert alkalmaz, és át kell váltania egy másikra?
Az Oracle Database 11 g esetében ez a folyamat szokatlanul egyszerű. A támogatott DBMS_SQL csomag új funkcióval rendelkezik, TO_REFCURSOR, amely a dinamikus kurzort DBMS_SQL átalakítja egy ref kurzorhoz. Íme egy példa egy ilyen átalakításra:
Tegyük fel, hogy olyan általános eljárást szeretne írni, amely nem ismeri a kijelölt kifejezés oszlopainak listáját fordítási időben. Ez az eset áll fenn, ha szükség van a natív dinamikus SQL-re. Leírhatja a ref kurzort. Most, hogy érdekesebbé tegyük, feltételezzük, hogy nem ismeri az összes kötelező változót, a dbms_sql a legalkalmasabb ebben az esetben. Hogyan teljesítheted ezt a komplex követelményt, ha egy minimális kódot írsz? Egyszerűen: indítsa el a dbms_sql-et a kötési változókhoz, majd konvertálja a ref kurzort.
Hasonlóképpen, ha a natív dinamikus SQL REF kurzorra konvertál, meg kell hívnia egy másik funkciót, TO_CURSOR_NUMBER:
A c_ref_cur változóban definiált ref kurzort meg kell nyitni a hívás előtt. E hívás után a ref cursor élete vége; Csak a dbms_sql-kurzort kezelheti.
Tegyük fel, hogy tudjuk a bind változókat a fordítási időben, de nem ismeri a kiválasztási listát; elindíthatja a natív dinamikus sql-et, a ref kurzornál, majd cserélje ki a dbms_sql segítségével az oszlopok kurzorbeviteli leírására és kivonására.
Mint láthatja, az Oracle Database 11g több olyan fejlesztést tartalmaz, amelyek hatékonyabban írják a kódot a PL / SQL-re.