A naptár végrehajtása az alárendelt orákulum segítségével

köszönöm

Most nagyon divatos, hogy különböző webes alkalmazásokat készítsenek, így valami hasonlót fejlesztettem ki a naptárhoz kapcsolódóan. Megnyitja a felhasználói oldalt. ahol ilyen kis havi naptár és minden nap referencia formájában van. Ha rákattintasz a hónap kívánt napjára, és ott vannak hírek a mai napig, vagy a különféle, megjelenített események listája.







Az alkalmazás végrehajtásának adatbázisaként természetesen az Oracle-ot választották, és fejlesztési eszközökként - ez azonban nem fontos, mert Rögtön gondoltam, hogy egy egyszerű SQL megoldásnak kell lennie, ennek megfelelően, nem a fejlesztőeszközöktől függően.

Természetesen ez a feladat sok szempontból megoldható, de mégis úgy tűnik számomra, hogy egy tiszta SQL megoldás legyen a legelőnyösebb, mivel minden olyan fejlesztési környezetben használható, ahol a SELECT parancs támogatott (megmutatja, hol nem támogatott).

Ennek során a döntést meg kellett foglalkozni a különböző érdekes helyzeteket, amelyek ténylegesen és kéri, hogy ezt a cikket írni, és remélem, lesz az érdeke, nemcsak nekem, hanem mindazoknak is, az olvasók, különösen szoftverfejlesztők.

Filozófiai kérdés. Nagyon fontos, hogy egyszerre válasszuk ki a megfelelő utat, különben mindent újra kell kezdeni.

A havi naptár nyomtatásához általában asztalra van szükség, amely garantálja a 31 bejegyzést. És nem számít, hogy mi van ebben a táblában. Mindenre szükségünk van a ROWNUM pszeudooszlop és a dátum funkciók.

LAST_DAY függvény utolsó napja hónapban egy adott napon a TO_CHAR egy méret maszk „DD” párosítva TO_NUMBER így az utolsó napon, mint egy számot, és még fontosabb, hogy a rekordok száma, amit szeretne kiválasztani, és amely soha nem haladhatja meg a 31 (Munchhausen nem számít!).
Nos, Thomas Kait kedvence közül választhatunk: ALL_OBJECTS:

A kezdet szükséges!
Van egy kérésünk, amely az aktuális hónap minden napját visszaadja.
Csak ne mondd el, hogy nem helyes támaszkodni arra a tényre, hogy mindig lesz 31 bejegyzés az ALL_OBJECTS nézetben. Igen, erre támaszkodom, és szerintem ez a feltevés teljesen indokolt!

Szeretném felhívni a figyelmet arra a tényre, hogy a lekérdezés csak az aktuális hónap napjait jeleníti meg (a SYSDATE funkció vezetékes), bár helyénvaló lenne valahogy elképzelni a különböző hónapok napi kimenetelét. Ezzel a feladatot részekre osztom. Először is, az eredmény eléréséhez az aktuális hónapban, és csak akkor kell paraméterezéssel foglalkozni. És ez a helyes út! Nem kell megpróbálnod magadat felfogni, külön kell elkülöníteni és eldönteni (és azt akarsz mondani, hogy "uralkodj", de ez valaki "szerzői jog" :-)).

Nos, itt az ideje, hogy továbblépjünk a hét napjaira. Ezen a témán szeretnék részletesebben foglalkozni. kénytelen elismerni, hogy hosszú ideig, nem volt tudatában, hogy hogyan algoritmikusan meghatározzák a nap a hét egy adott időpontra :-(. Sokáig nem kell, de egy pár évvel ezelőtt, és szembefordult a megfelelő megoldás nem található hamarosan. Nem szeretnénk, hogy valaki más idejét töltötte.

Egyrészt úgy tűnik, hogy minden egyszerű, a funkciót választjuk, és megkapjuk a hét napjának rövid (hárombetűs) vagy teljes nevét. Igen, ez egy rossz szerencse, kiderül, hogy a hét napja vissza fog térni a felhasználói munkamenet NLS paraméterei által meghatározott nyelven. Ie ha a felhasználó angolul, MON (HÉTOR), ha az orosz, akkor a MON (Hétvégi) hétfőn lesz kiadva.

Biztos benne, hogy minden felhasználó ugyanazokat az NLS-beállításokat alkalmazza az alkalmazásához? Személy szerint én szinte biztosan tudom az ellenkezőjét, és ez a módszer nem felel meg nekem.

Megpróbálhatja a TO_CHAR használatát egy másik formátummaszkkal. amely a név helyett a hét számának napját adja vissza. Nos, a szám nem függ a nyelvtől! A nyelv valójában nem függ a nyelvtől, hanem a területet meghatározó NLS-paramétertől függ :-( Ha Oroszországban hétfő a hét első napja, akkor az USA-ban ez a második nap.

Mi a teendő ebben a helyzetben? Ismételten ellenőrizze a MON és HDPE funkciókat? Nem komolyan.
Ellenőrizze a felhasználói beállításokat a munkamenet elején és betöltse a nyelvi állandókat minden egyes munkamenethez? Ez nehézkes.
Olyan függvényt írjon, amely visszatér a hét napjára, függetlenül a nyelvi beállításoktól, az algoritmus előnye nem nehéz? Valószínűleg így lett volna, de normális megoldásnak kell lennie!

Valószínűleg minden fejlesztő élete során vannak olyan pillanatok, amikor több évnyi állandó használat után valami olyasmit kapsz, amit hirtelen valami újdonságot találsz, amit mindig hiányoltál, és hogy a leginkább sértő volt szinte a felszínen. Láttam (olvasd el) Stephen Furstein reakcióját a @@ parancsra sqlplus-ban, és ezt követően a PL / Vision kezdeti verzióját írta. Az én esetemben az érzelmek viharát a TO_CHAR funkció képessége okozta.

A megoldás kulcsa olyan egyszerű volt, hogy kezdetben ez a probléma megoldhatatlannak tűnt. Kiderül, hogy a TO_CHAR funkciónak van egy harmadik paramétere, amely lehetővé teszi, hogy beállítsa azt a nyelvet, amelyikben a dátum visszatér. Mindig visszatér a MON hétfőre, függetlenül az NLS felhasználói beállításaitól.

Egyébként tudod, hogy a logikai kifejezésnek vissza kell térnie: feltéve, hogy a my_date hétfő?

Ez így van, FALSE!
Miért? Mivel a TO_CHAR funkció ebben az esetben visszatér a faroklapokkal a hét leghosszabb (írásbeli) napján WEDNESDAY. Ennek megfelelően, ha az NLS_DATE_LANGUAGE nyelvet RUSZIAN-ban teszed, akkor a hét teljes napjait 11 karakterre állítjuk (hétfőig).
A hét teljes napjának helyes használatához hozzá kell adni az Fm módosítót a DAY formátumú maszkhoz:

A hét napjairól szóló beszéd végén azt akarom mondani, hogy sok alkalmazás létezik, bár Oroszországban fejlesztették (vagy Oroszországra alkalmazkodtak), de angolul használják a dátum megjelenítésének nyelvét. Valószínű, hogy a hét napjai helytelen meghatározása az egyik oka.

Gyakran különböző telekonferenciákon hallhatod a kérdést, hogyan lehet egy mátrixjelentést készíteni. És lehetőleg egy parancs SELECT.

Ezt a problémát vegye figyelembe a kedvenc (legalábbis nekem) EMP táblán. Annak érdekében, hogy a fizetések teljes összegét a beosztásokkal összefüggésben könnyűvé tegyük:







De mi van, ha ezt az információt a szervezeti egységekkel kapcsolatban is szeretnénk látni? Kiderül, hogy a SUM_SAL oszlopra van szükség:
  • több oszlopra oszlik (az osztályok száma szerint)
  • osztozik ezek között az adatok között
A második megoldást a DECODE funkció segítségével lehet megoldani. Például, ha egy számmal rendelkező (deptno) 10 osztályhoz tartozó fizetési összeget kapsz, akkor az alábbiakat használhatod: Az elsőnél kicsit bonyolultabb. A legegyszerűbb formában, ha tudjuk, hogy minden rendelkezésre álló osztály előre, akkor egyszerűen felsorolni: Így kiderül, hogy a helyzet, amikor tudjuk előre, hogy hány oszlopot kellett volna, hogy nem olyan ritka. És ez a módszer elég ahhoz, hogy egy úgynevezett ál-mátrix jelentést készítsen. Ez különösen fontos a pénzügyi beszámolókban, ahol a negyedévekben, hónapokban kell adatokat kapnia. Előre tudjuk, hogy vannak negyedek - 4, hónap - 12. Még a nevüket is tudjuk :-) Tehát a mi esetünkben, visszatérve a naptárhoz, előzetesen tudjuk, hogy meg kell szüntetni az egyetlen oszlopot 7-tel, a hét napjainak számával. Hogyan határozzuk meg a hét napját, azt is megtudtuk az előző részben. Így már semmi sem akadályozza, hogy a következő lépés e cél felé: A eredményeként a lekérdezés, akkor látni a következő rész, de most szeretném felhívni a figyelmet arra a tényre, hogy tettem a lekérést csatolt (át azt a mondat - inline nézet). Ennek több oka is van:
  • A lekérdezés jobb olvashatósága.
    A hosszú TO_CHAR funkció a helyesírásban egy álnevet (day_of_week) tartalmaz, amely egyértelműen leírja a visszatérési értéket. Alias ​​nélkül nem mindenki fogja azonnal meghatározni, hogy ez a funkció visszatér. Ez egy példa az úgynevezett öndokumentáló kódra.
    Ezenkívül a hosszú TO_CHAR helyett a hétfő hét napját duplázhatjuk meg a fő lekérdezésben. Próbálj TO_CHAR-t átvinni a felkérésről a csúcsra a DECODE-ban, és próbáld meg kitalálni a keletkezett hashot.
  • Jobb teljesítmény.
    A TO_CHAR funkció csak egyszer kerül végrehajtásra a hónap minden egyes visszatért napján. Ha egy lekérdezést használtunk, akkor minden héten hétszer végrehajtunk. Igen, talán ebben a példában a teljesítményváltozás egyáltalán nem lesz észrevehető, de ha a TO_CHAR helyett egy felhasználó által definiált függvény lenne, és a visszaadott rekordok jóval meghaladnák a 30-at, a hatás erős lenne.

Jól vagyok a mátrixjelentésekkel "lövés"! Egyszer a bokrok.
És mit tegyek, ha valódi mátrixjelentést szeretnék kapni, ha az oszlopok száma nem ismert előre?

Csak azt akarjuk, hogy csalódást okozzunk azoknak, akik ezt az igényt szeretnék megkapni. Nem tudok ilyen módszert. Ha valaki tudja - tudassa velem. Az általam javasolt megoldás az a tény, hogy mivel a lekérdezéshez szükséges oszlopok száma nem ismert előre, ez azt jelenti, hogy először meg kell határozni, majd dinamikusan létre kell hozni és végre kell hajtani a szükséges SELECT parancsot.

Egy adott megvalósítás függ a jelentés futási idejétől. Megmutatom kétféleképpen, mivel az SQL * Plus-ban történik, mert kivéve, hogy az Oracle Reports (amely támogatja a mátrixjelentések felépítését) a jelentéskészítés egyéb módjaival nem ismerősek.

Így hát vissza a naptárba. Itt van az előző lekérdezés kimenete.

Az első benyomás kettős. Egyrészt valóban kiderült, hogy hét oszlop van, és a hét napja naponta megfelelően oszlik meg, másrészt nem ez az, amire szükségünk van. Minden héten egy hétre van szükségünk, és itt van.

És amit akartam, mert több oszlop hozzáadása a lekérdezéshez nem érinti a visszaadott rekordok számát. 30 éves korában még mindig marad. Van valami megoldásunk, amely 30 rekord helyett 5 kívánatos marad.

Az első dolog, ami eszembe jut, az, hogy hozzáadja a csoportosítást (GROUP BY) a lekérdezéshez. De hozzáadásához meg kell határoznia:
  • A csoportosítás kifejezés (amely a GROUP BY csoportban van írva)
  • Hogyan konvertálunk több rekordot egybe (amely aggregálja a funkció használatát)

Nyilvánvaló, hogy hetente csoportosulnia kell. De hogyan lehet olyan kifejezést alkotni, amely visszatér ezen a héten? Itt ismét a TO_CHAR segít nekünk. Ez a funkciónak még egy IW formátummaszkja van, amely visszaadja a hét rendszáma egy év alatt. Pontosan erre van szükségünk!

Mi az összesített függvény?
Ha megnézzük a rekordokat fog vonatkozni csoportosulás, akkor könnyen belátható, hogy az egyes csoportokban rekordok (hét) minden oszlop (nap) tele lesz csak egy bejegyzés (szám), és a többi üres lesz (NULL). Szükségünk van a csoportfüggvényre, hogy visszaadjuk ezt az egyértéket. Ehhez különböző funkciókat használhat, MAXt választottam.

A strukturált programozás elvei szükségessé teszik a kód újrafelhasználásának elkerülését. Ezért sürgősen létre kell hoznia egy nézetet (VIEW) a lekérdezés szövegével, míg a fejlesztőknek nem volt ideje arra, hogy "programozzák" a programjukba. Igen, de hogyan kaphat más napi naptárakat? Míg egy külön lekérdezést használnak, egyszerűen kicserélheti a SYSDATE más dátumot. És hogyan kell ezt csinálni a prezentációval?

Itt térünk vissza a témára, amely a kezdet kezdetén érintette a feladat megosztását. Már előre láttam, hogy a végső lekérdezést fel kell venni a nézetbe. Most itt az ideje eldönteni, hogyan lehet ezt a nézetet paraméterezni.

Mivel a nézet szövegét (a SELECT parancs szövegével ellentétben) nem lehet (vagy nem) megváltoztatni a lekérdezésből a lekérdezéshez, kiderül, hogy ezt közvetetten kell végrehajtanunk.
A szabványos módszer a szövegben egyéni funkciók ábrázolása. Ez a függvény egy olyan értéket ad vissza, amelyet más eljárás hívásával megadhatunk. Egy ilyen paraméterezett nézetben dolgozunk a következőképpen. Megadta a kívánt értéket az eljárással, majd végrehajtotta a lekérdezést a nézethez. Más értéket állítottak be, végrehajtották a lekérdezést, és ugyanaz a nézet visszaad egyéb adatokat.

A lényeg az, hogy az eljárás által meghatározott érték megmarad a felhasználói munkamenet során. Ennek megvalósításához a PL / SQL csomag ideális. A csomag testében olyan köteg változót hozunk létre, amely megőrzi értékét a felhasználó teljes munkamenetében. A specifikációban olyan függvényt definiálunk, amely visszaadja a batch változó értékét és az általa meghatározott eljárást.

Most meg lehet jeleníteni naptárak adott hónapban, és ha még mindig nem adja, az alapértelmezett használata az aktuális hónap, amely úgy tűnik, elég logikus: Mint postkriptuma ebben a szakaszban, azt akarom mondani, hogy ha dolgozik az Oracle Portal, akkor nem Használjon batch változókat az értékek tárolásához az egész munkamenet során. Az Oracle Portal a munkameneteket használja, és nem kapcsolódik ahhoz, amit a felhasználói munkamenet megértéséhez használunk. Alternatív megoldásként a WWSTO_API_SESSION objektumtípus által kínált API-t kell használni, amely a Portál tulajdonosa sémájában található. A specifikációban részletesen tájékozódhat az ilyen típusú munkákról.

Tetszik a programok tesztelése?
Mosolygó? Vagy csavart? Én is nem szeretem, és soha nem láttam azokat, akik szeretik. Néhány fejlesztő, mint ürügy, azt mondja, hogy a fejlesztő maga nem tudja megfelelően tesztelni a programját, hogy mások mit kellene tennie.

Itt mindent el kell helyezni a helyén. Teszt - a teszt más. Van egy úgynevezett teszt egy külön modul (egység teszt), amely a fejlesztő maga kell tennie. Ez az egyéni eljárások, jelentések, képernyőformák tesztje. És van egy rendszer teszt, amelyben szükséges az interakció tesztelése az egyes modulok rendszerében. Itt a rendszer tesztet valóban nem a fejlesztők, hanem az idegenek (ideális kizsákmányolási csoport) hozhatják meg.

A 8.1.6 verzióban bemutatott CASE nyilatkozat nagyon alkalmas az ilyen feltételek leírására:

Nos, most mindennek tűnik. Ez működött!

Nincs minden. Mindez - azok számára, akiknek az Oracle 8.1.6-os és újabb verziója van, de ha nem?
Természetesen egyéni funkciót is írhat, de ne dobja ki a DECODE-t. Ez a régi jó funkció ebben az esetben is szolgálhat.

Különösen a szurkolók DECODE, és a kevesebb, mint az Oracle verzió 8.1.6, megmutatom, hogyan kell nézni WEEK_NUM oszlopon a dekódolás: nézd terjedelmes, úgy gondolom, hogy CASE ezen a helyen úgy néz ki, még előnyösebb. Ez azonban nem jelenti azt, hogy a DECODE-t egyetemesen el kell utasítani a CASE javára. Ebben a nézetben van egy másik funkció DECODE: amely véleményem szerint nagyon lakonikus és érthető.
Ez a funkció DECODE a CASE -ra, úgy tűnik számomra, hogy csak elveszítjük.

Ezenkívül a végső megoldás tartalmazza a DECODE opciót (az Oracle verzióinak nagyobb kiterjedése érdekében). Tehát, ha jobban szeretne CASE-t használni, akkor az előző rész V_CALENDAR nézetének szövegét használja.

Mielőtt az alábbi megoldást használom, azt javasoljuk, hogy olvassa el újra a cikket. nagyon fontos és hasznos megjegyzéseket, valamint két alternatív megoldást tartalmaznak.




Kapcsolódó cikkek