Kako podesiti pametne telefone i računare. Informativni portal
  • Dom
  • OS
  • Oracle funkcije datuma. Kratki praktični vodič za programere informacionih sistema baziranih na Oracle bazi podataka

Oracle funkcije datuma. Kratki praktični vodič za programere informacionih sistema baziranih na Oracle bazi podataka

Kako izvući datum iz baze podataka pogodan format d.m.Y. (dan.mjesec.godina) Oracle. Funkcija to_char() će nam pomoći. Zahvaljujući njemu možete pretvoriti vrijeme u željeni format. Pogledajte primjer.

SELECT to_char(current_timestamp, "DD.MM.GGGG") kao date_create iz DUAL

Format vremena DD.MM.GGGG (dan.mjesec.godina). Možete koristiti bilo koje znakove kao graničnike: /, :, -.

Za prikaz trenutnog vremena u formatu dan.mjesec.godina sati:minute:sekunde, koristite parametre DD.MM.GGGG HH24:MI:SS.

SELECT to_char(current_timestamp, "DD.MM.GGGG HH24:MI:SS") kao date_create iz DUAL /* izlaz: 10/06/2017 16:50:52 */

Recimo da trebate prikazati početak godine? Tekuća godina će vam automatski biti zamijenjena. U ovom primjeru koristio sam konkatenaciju ||. Više detaljne informacije naći ćete stranicu TO_CHAR FUNCTION. Na toj stranici je velika lista opcije za pretvaranje datuma u niz.

ODABERITE "01.01." || to_char(current_timestamp, "YYYY") kao date_create iz DUAL

Pregledi: 1762, nivo: laki nivo, rejting: 0, datum: 26.10.2016 14:07:32

U ovom odeljku ćemo govoriti o funkcijama za rad sa datumom/vreme i funkcijama konverzije tipa za datume. Za pohranjivanje datuma i vremena, Oracle nudi poseban tip DATE. WITH fizička tačka pogledajte razlomak broj, cijeli dio koji pohranjuje broj dana od određenog osnovnog datuma, a razlomak pohranjuje vrijeme. Ovo vam omogućava da izvodite preko datuma aritmetičke operacije- sabiranje i oduzimanje.

SYSDATE funkcija

Ovo je jedna od najčešće korištenih funkcija; vraća trenutni datum i vrijeme prema satu servera. primjer:

SELECT SYSDATE
FROM dual

SYSDATE
26.12.2007 16:24:43

Funkcija ADD_MONTHS(d, x)

Vraća datum dobijen dodavanjem jednog ili više mjeseci do datuma d. Broj mjeseci je određen parametrima x, a x može biti negativan - u ovom slučaju se navedeni broj mjeseci oduzima od datog datuma.

ODABIR SYSDATE d,
ADD_MJESECI(SYSDATE, 3) d1, ADD_MONTHS(SYSDATE, -3) d2
FROM dual

26.12.2007 16:24:43

26.03.2008 16:24:43

26.09.2007 16:24:43

LAST_DAY(d) funkcija

Vraća zadnji dan u mjesecu naveden u datumu d. primjer:

ODABIR SYSDATE d,
LAST_DAY(SYSDATE) d1
FROM dual

26.12.2007 16:24:43

31.12.2008 16:24:43

Ova funkcija je vrlo zgodna za određivanje broja dana u datom mjesecu, na primjer:

ODABIR SYSDATE d,
TO_CHAR(LAST_DAY(SYSDATE), "DD") d1
FROM dual

26.12.2007 16:24:43

Funkcija MONTHS_BETWEEN(dl, d2)

Funkcija MONTH_BETWEEN vraća broj mjeseci između dva datuma dl i d2, uzimajući u obzir predznak kao dl-d2, vraćeni broj je razlomak.

SELECT MONTHS_BETWEEN("2.09.2006", "2.05.2006") d1,
M0NTHS_BETWEEN("12.09.2006", "2.05.2006") d2,
M0NTHS_BETWEEN("2.05.2006", "12.09.2006") d3
FROM dual

4,32258064516129

4,32258064516129

Funkcija TRUN C (d[,mask ])

Skraćuje navedeni datum prema maski. Ako maska ​​nije navedena, onda se skraćivanje vrši prije datuma (vrijeme se odbacuje).

SELECT SYSDATEd1,
TRUNC(SYSDATE) d2
FROM dual

26.09.2006 16:45:26

Pogledajmo tipične primjere - skraćivanje datuma na sate, dane, mjesec i godinu. Zadana maska ​​formata je "DD"

SELECT SYSDATEdl,
TRUNC(SYSDATE, "HH24") d2,
TRUNC(SYSDATE, "DD") d3,
TRUNC(SYSDATE, "MM") d4,
TRUNC(SYSDATE, "YYYY") d5
FROM dual

26.09.2006 16:49:21

26.09.2006 16:00:00

26.09.2006 01.09.2006 01.01.2006

Funkcija ROUND(d[,maska])

ROUND funkcija je slična TRUNC, ali umjesto skraćivanja, ona zaokružuje. Zadana maska ​​formata je "DD". primjer:

SELECTSYSDATEd1,
KRUG (SYSDATE)d2,
ROUND (SYSDATE," NN24") d3,
ROUND(SYSDATE, " DD") d4,
ROUND (SYSDATE,"MM") d5
FROM dual

26.09.2006 16:50:50

27.09.2006 26.09.2006 17:00:00

27.09.2006 01.10.2006

Dozvoljene maske formata za funkcije TRUNC i ROUND

Pogledajmo pobliže maske formata i značajke njihove upotrebe:

Svrha

Prvi dan veka

GODINA, ili GGGG,

Prvi dan u godini

ili YY ili Y

Prvi dan tromjesečja

MJESEC, ili PON,

Prvi dan u mjesecu

Isti dan u sedmici kao i dan tekuće godine

Isti dan u sedmici kao i dan u tekućem mjesecu

DAY ili DY ili D

Prvi dan u sedmici

NN, ili NN12, ili

Funkcija TO_DATE(str[,maska ​​[,nls_lang]])

Funkcija TO_DATE pretvara string str u datum. Konverzija se vrši pomoću maske maske, ako je navedena. Ako maska ​​nije navedena, uzima se zadana maska. Ako navedete masku, možete odrediti još jedan parametar - jezik koji se koristi pri formatiranju naziva mjeseci i dana. Ako postoji greška pri raščlanjivanju stringa str u skladu sa navedenim

nastaje maska izuzetna situacija. Najčešća greška je "ORA-01830: Šablon formata datuma se završava prije konverzije cijelog ulaznog niza." Osim toga, često se susreće i greška "ORA-01821: format datuma nije prepoznat" - javlja se kada je navedena nevažeća maska ​​formata. primjer:

SELECT T0_DATE("12.09.2006") d
FROM dual

Funkcija TO_CHAR(d[,maska])

Pretvara datum d u niz znakova prema navedenoj maski. Ako je navedena nevažeća maska, pojavljuje se izuzetak "ORA-01821: format datuma nije prepoznat". primjer:

ODABIR SISTEM D1,
TOLCHAR(SYSDATE, "DD.MM.GG HH24:MI") d2
FROM dual

Ovaj članak je posvećen formatima datuma u Oracleu i nekim značajkama njihove obrade. Članak daje pregled nekoliko standardnih maski za formatiranje datuma, eksplicitnu i implicitnu konverziju nizova u datume i Dodatne opcije, utičući na ovaj proces. Kao iu prvom dijelu članka, rasprava o materijalu temelji se na primjerima koji pokazuju nestandardne mogućnosti formatiranja. Oracle mehanizmi uključeni u proces su detaljno ispitani implicitna konverzija. Opisi većine karakteristika su popraćeni vezama do relevantnih dijelova dokumentacije.

U početku nisam planirao da pišem članak o datumima, već sam se fokusirao na razmatranje samo jednog pitanja na ovu temu. Međutim, tokom rada pojavila se potreba za osvjetljavanjem raznih dodatne funkcije Oracle, počeli su se pojavljivati ​​novi primjeri. Tako je razmatranje jednog pitanja preraslo u mali članak. Nadam se da nije ispalo dosadno, uprkos ne najzanimljivijoj temi.

Lociran je prvi dio članka, posvećen karakteristikama reda po operatoru, funkcioniranju not in i primjeru implicitne konverzije tipa.

funkcija to_date i formati datuma

Malo programera voli formatiranje tema. Na primjer, neki tečajevi se posebno fokusiraju na formatiranje datuma i formatiranje jezika. poslednjih sati poslednjeg dana treninga, jer slušaoci su dosadni. Razlog je u velikim količinama postojećim formatima uz njihovu relativno rijetku upotrebu u standardnim zadacima. Tri najčešće funkcije koje koriste maske su to_number, to_char i to_date. U sva tri slučaja, maska ​​je na drugom mjestu opcioni parametar. A ako još uvijek postoji manje-više razuman broj maski za formatiranje brojeva, onda postoji nepristojno veliki broj maski za formatiranje datuma, plus sufiksi i modifikatori.

Naravno, dostupnost velika količina maske je pozitivna stvar, pošto proširuje mogućnosti, npr. da li je 13. septembar 2011. dan programera možete provjeriti pomoću maske „DDD“ koja vraća broj dana u godini:
--Upit br. 1 odaberite to_char(to_date("09/13/2011"),"DDD") "Dan programera" iz dual;
Unatoč očiglednim prednostima formatiranja, nisam planirao uključiti pregled formata datuma i primjere korištenja egzotičnih maski u drugi dio članka. Prvo, malo je vjerojatno da će to nekoga zanimati, a drugo, autor također nije veliki obožavatelj složenog formatiranja, jer ga rijetko koristi u životu. Jedini razlog za pojavu ovaj odeljak– neka pitanja koja čitatelji imaju o korištenju RR formata.

Prije nego što prijeđemo direktno na glavnu temu ovog odjeljka, pogledajmo nekoliko nestandardni primjeri rad sa datumima.

Primjer br. 1. Korištenje skraćenih šablona
Počnimo sa standardno formatiranje. Neka današnji datum bude 16.09.2011., hoće li se sljedeći upiti izvršavati i šta će oni vratiti?
--Upit br. 2 odaberite to_char(sysdate, "YYYY") iz dual; --Upit br. 3 odaberite to_date("03", "DD") iz dual;
Upit #2 je tipičan primjer pretvaranja datuma u niz i pretvaranja u njega traženi format. Jedina razlika je u tome što smo umjesto poznatijih maski poput “DD.MM.GG” ili “DD-MON-GGGG” koristili masku koja specificira samo godinu. Upit #2 će biti uspješno izvršen i vratiće tekuću godinu u četverocifrenom formatu, tj. "2011".

Upit #3 je malo zanimljiviji, to je tipičan primjer eksplicitne konverzije stringa u datum sa maskom skraćenog formata, tako da je, sa sintaksne tačke gledišta, upit ispravan i uspješno će se izvršiti. Važnije pitanje je rezultat njegove implementacije, tj. koji datum će se vratiti ako se navede samo dan? Prije nego odgovorite ovo pitanje Prisjetimo se kako Oracle postavlja vrijeme ako nije eksplicitno postavljeno:
--Upit br. 4 odaberite to_char(to_date("02/03/2011","DD.MM.GGGG"),"DD.MM.GGGG HH24:MI:SS") iz dual; --Upit br. 5 odaberite to_char(to_date("02/03/2011 30", "DD.MM.GGGG MI"),"DD.MM.GGGG HH24:MI:SS") iz dual;
U zahtjevu br. 4 vrijeme nije navedeno, u zahtjevu br. 5 je naveden samo broj minuta, sati i sekunde su izostavljeni. U Oracle-u postoji pravilo prema kojem, ako nema vremenske komponente u datumu, vrijeme se automatski postavlja na 00:00:00 (tj. ponoć), ako je naveden samo dio vremenskih elemenata (kao u upitu br. 5), tada se elementi koji nedostaju postavljaju na 00. Stoga će upit br. 4 vratiti string “02/03/2011 00:00:00”, a upit br. 5 će vratiti “02/03/2011 00:30:00”.

Vratimo se na zahtjev br. 3, da li je to tačno? ovo pravilo za datume, tj. Da li se elementi datuma koji nedostaju tokom konverzije zamjenjuju sa 00 ili 01? Da, zamjenjuju se, ali ne svi, tačnije, za elemente datuma koji nedostaju koriste se vrijednosti iz sysdate (prvi dan tekućeg mjeseca tekuće godine). Stoga će upit #3 koristiti 09 kao mjesec i 2011 kao godinu, tako da će rezultat upita biti 09.03.2011.

Primjer br. 2. Redoslijed opcija formatiranja
Hoće li sljedeći upit biti uspješan, i ako jeste, koji datum će vratiti?
--Upit br. 6 odaberite to_date("20092011", "YYYYDDMM") iz dual;
Na prvi pogled, odsustvo graničnika u nizu datuma može se činiti kritičnim faktorom koji nije kompatibilan sa izvršavanjem upita, ali maska ​​datuma je takođe navedena bez razgraničenja i niz koji se konvertuje odgovara navedenom uzorku. Stoga će zahtjev br. 6 biti uspješno izvršen i vratit će se 20.11.2009. (format rezultata može se neznatno razlikovati u zavisnosti od postavki sesije). U sljedećem primjeru detaljnije ćemo razmotriti pitanja vezana za graničnike.

Primjer br. 3. Implicitna konverzija

--Upit br. 7 odaberite months_between("1\September-9","01$Oct/08") iz dual;
IN ovaj zahtjev navedena su dva parametra niza koji se moraju konvertirati u datume korištenjem implicitne konverzije. Prema dokumentaciji, kada se koriste zadani formati, niz koji se implicitno pretvara u datum mora zadovoljiti obrazac: separator1 separator2. Većina separatora i separatora može se koristiti kao separator1 i separator2 specijalni znakovi, uključujući razmake, tabulatore i " i dvojnike jednostruki navodnik"". Štaviše, ako red sadrži najmanje dvije cifre za određivanje dana, mjeseci i godina, tada se separator može potpuno izostaviti. Na primjer:
--Upit br. 8 odaberite to_date("01September09") iz dual; --Upit br. 9 odaberite to_date("01Sep09") iz dual; --Zahtjev #10 za ovaj zahtjev zadani format datuma bi trebao biti DD.MM.RR select to_date("010909") iz dual;
Pošto se oba reda navedena u zahtjevu br. 7 poklapaju sa datim obrascem, zahtjev će se uspješno izvršiti i vratiti broj 11.

Primjer br. 4. Parametri funkcije to_date
Neka zadani format datuma bude DD.MON.RR, a jezik datuma ruski, radiće sljedeći upit:
--Upit br. 11 odaberite to_date(sysdate,"mm/dd/yyyy hh24:mi:ss") iz dual;
Sličan zahtjev pojavio se u jednoj od rasprava na stranici pitajte Toma. Zamka zahtjeva je u tome što pokušavamo pretvoriti datum (sysdate) u datum. Ako je zahtjev izgledao ovako:
--Upit br. 12 odaberite to_char(sysdate,"mm/dd/yyyy hh24:mi:ss") iz dual;
To izvršenje bi uspjelo i vratilo bi niz "09/15/2011 23:00:11". Međutim, funkcija to_date očekuje string kao svoj prvi parametar, tako da prvo implicitno konvertuje datum u string (što je ekvivalentno pozivu to_char(sysdate) sa zadanom maskom). Rezultat ove konverzije je niz "09/15/11", a zatim se poziva to_date. Dakle, upit #11 je ekvivalentan sljedećem upitu:
--Zahtjev br. 13 odaberite to_date("09/15/11","mm/dd/yyyy hh24:mi:ss") iz dual;
Kako nije teško provjeriti, zahtjev br. 13 se ne može izvršiti, jer se red “09.15.11” ne poklapa sa postavljenom maskom, shodno tome, zahtjev br. 11 takođe ne može biti izvršen.

Postavite zadani format datuma
Zadani format datuma specificiraju dva parametra: NLS_DATE_FORMAT (odgovoran za sam format) i NLS_DATE_LANGUAGE (odgovoran za jezik koji će se koristiti prilikom pisanja naziva dana, mjeseci itd.). Ako ovi parametri nisu eksplicitno postavljeni, njihove vrijednosti se postavljaju na osnovu parametra NLS_LANG.

Postoje tri nivoa na kojima možete postaviti format datuma:

  1. Nivo baze podataka: odaberite * iz nls_database_parameters gdje je parametar u ("NLS_DATE_FORMAT","NLS_DATE_LANGUAGE"); Parametri ovog nivoa se postavljaju prilikom kreiranja baze podataka i upisuju se u datoteku init.ora.
  2. Nivo instance: odaberite * iz nls_instance_parameters gdje je parametar u ("NLS_DATE_FORMAT","NLS_DATE_LANGUAGE"); Parametri na ovoj razini se postavljaju kada se instanca pokrene i mogu se promijeniti korištenjem naredbe ALTER SYSTEM.
  3. Nivo sesije: odaberite * iz nls_session_parameters gdje je parametar u ("NLS_DATE_FORMAT","NLS_DATE_LANGUAGE"); Parametri na ovoj razini mogu se mijenjati naredbom ALTER SESSION. Također možete provjeriti vrijednost ovih parametara pomoću upita: odaberite SYS_CONTEXT ("USERENV", "NLS_DATE_FORMAT"), SYS_CONTEXT ("USERENV", "NLS_DATE_LANGUAGE") iz dual;
Parametri svakog sljedećeg nivoa “prepisuju” parametre prethodnog, tj. Ako imate postavljene parametre razine sesije, tada parametri drugih razina neće utjecati na vašu sesiju. Za postavljanje jedinstvenog formata datuma za sve sesije, Tom u svojoj koloni predlaže korištenje okidača ON-LOGON: kreirajte ili zamijenite okidač data_logon_trigger nakon što se logovanje NA BAZU DATAKA počne izvršiti odmah "izmijeni set sesije nls_date_format = ""dd/mm/yyyy""" ; kraj;
Primjer br. 5. Format DD.MM.RR vs DD-MON-RR
Bio sam inspiriran da obratim pažnju na zadano formatiranje datuma zbog neke neobičnosti u implicitnoj konverziji stringova u datume. hajde da razmotrimo sljedeći primjer:
--Zahtjev br. 14 --Postavite zadani format datuma alter set session NLS_DATE_FORMAT="DD.MM.RR"; --Postavite zadani jezik datuma alter session set NLS_DATE_LANGUAGE="AMERICAN"; --Provjerite vrijednost parametara sesije odaberite * iz nls_session_parameters gdje je parametar u ("NLS_DATE_FORMAT","NLS_DATE_LANGUAGE"); --Pretvori nizove u datum select to_date("11.09.11") iz dual; select to_date("11.SEP.11") iz dual;
Logično je pretpostaviti da će konverzija stringa “11.09.11” u datum biti uspješna, ali konverzija stringa “11.SEP.11” neće. Međutim, to nije slučaj; obje konverzije će uspjeti. U početku sam pretpostavio da ako je nemoguće konvertovati string koristeći masku sesije, Oracle pokušava da koristi maske drugih nivoa (moja maska ​​nivoa baze podataka je postavljena na “DD-MON-RR”). Čitanje dokumentacije pokazalo je da to nije slučaj, a Oracle se rukovodi principima opisanim u prethodnom paragrafu.

Pokušajmo s drugim primjerom:
--Zahtjev br. 15 --Postavite zadani format datuma alter set session NLS_DATE_FORMAT="DD.MON.RR"; --Postavite zadani jezik datuma alter session set NLS_DATE_LANGUAGE="AMERICAN"; --Provjerite vrijednost parametara sesije odaberite * iz nls_session_parameters gdje je parametar u ("NLS_DATE_FORMAT","NLS_DATE_LANGUAGE"); --Pretvori nizove u datum select to_date("11.09.11") iz dual; select to_date("11.SEP.11") iz dual;
Ako mislite da će rezultat biti identičan prethodnom zahtjevu, onda se varate. Jedna od konverzija neće uspjeti. IN u ovom slučaju niz "11.09.11" ne odgovara uzorku. Možda je ovo misticizam?

Nažalost nema. Čitanje dokumentacije pokazalo je da postoje pravila za automatsku zamjenu elemenata formatiranja datuma. Ispod je tabela zamjena.

Element originalnog formata Dodatni elementi formata koje možete isprobati umjesto originala
"MM" "MON" i "MONTH"
„PON "MJESEC"
"MJESEC" "PON"
"YY" "YYYY"
"RR" "RRRR"
Gledajući sadržaj ove tabele, postaje jasno da format "DD.MM.RR" implicitno sadrži format "DD.MON.RR" (kao i "DD.MONTH.RR" i drugi), ali format "DD .MON.RR" format "DD.MM.RR" nije prisutan, što objašnjava ponašanje zahtjeva br. 14 i br. 15.

Primjer br. 6. RR vs YY format
Većina korisnika je itekako svjesna razlika između RR i YY maski, ali ima i onih koji ove informacijeće biti od koristi. Pređimo direktno na primjer. Koje podatke će vratiti sljedeći upiti:
--Zahtjev br. 16 odaberite to_date("11","RR") "RR", to_date("11","YY") "YY" iz dual; --Zahtjev br. 17 odaberite to_date("99","RR") "RR", to_date("99","YY") "YY" iz dual;
Oba gornja upita će se uspješno izvršiti i vratiti datume prema pravilima opisanim u primjeru #1 za zahtjev #3. Dakle, vrijednost dana u svim preuzetim datumima će biti 01, a vrijednost mjeseca će biti 09 (ako pokrenete upit u septembru). Glavno pitanje, koja će biti vrijednost godine?

Kao što možete lako pretpostaviti, u zahtjevu broj 16, pod “11” sam mislio na 2011. godinu, a obje maske su mi to vratile, tj. rezultat upita br. 16 je 09.01.2011. i 01.09.2011.

U zahtjevu br. 17 pod “99” sam mislio na 1999. godinu, a ovdje su mišljenja maski bila podijeljena: RR maska ​​je vratila očekivanu 1999. godinu, a YY maska ​​2099. tj. rezultat upita br. 17 je 01.09.1999. i 01.09.2099.

Pogledajmo kako ovi elementi oblikovanja funkcioniraju detaljnije:
--Zahtjev br. 18 odaberite to_date("00","RR") "00", to_date("49","RR") "49", to_date("50","RR") "50", do_date ( "99","RR") "99" iz dual union-a sve odaberite to_date("00","YY") "00", to_date("49","YY") "49", to_date("50" , "YY") "50", to_date("99","YY") "99" iz dual;
Kao što se vidi iz zahtjeva broj 18, razlike u radu maski počinju 50-ih godina, tj. YY format uvijek vraća godinu u tekućem stoljeću, a RR uvijek vraća godinu<50 воспринимает как год текущего столетия, а год >50 je kao godina prošlog veka. Zapravo, vrijednosti to_date("99","RR") = 1999 i to_date("00","RR") = 2000 su tačne samo ako je trenutni datum manji od 2051, nakon čega to_date("99 ","RR" ) = 2099 i to_date("00","RR") = 2100. Ako želite eksperimentirati, možete promijeniti vrijeme servera na 2051 i vidjeti kako se mijenja rezultat upita br. 18, samo donirajte. nemojte to raditi na pokrenutim sistemima! Ako se promijeni vrijeme servera, promijenit će se sistemski datum i bolje je ne razmišljati o tome kakvu ćete glavobolju imati u svim izvještajima, log tablicama itd. Opća pravila pretvaranje dvocifrene godine u četverocifrenu godinu koristeći RR format izgleda ovako:
Ako je navedena dvocifrena godina od 00 do 49, onda

  • Ako su posljednje dvije cifre tekuće godine od 00 do 49, onda je vraćena godina ima iste prve dvije cifre kao i tekuća godina.
  • Ako su posljednje dvije znamenke tekuće godine 50 do 99, tada su prve 2 cifre vraćene godine za 1 veće od prve 2 znamenke tekuće godine.
Ako je navedena dvocifrena godina 50 do 99, onda
  • Ako su posljednje dvije cifre tekuće godine od 00 do 49, tada su prve 2 cifre vraćene godine za 1 manje od prve 2 znamenke tekuće godine.
  • Ako su posljednje dvije znamenke tekuće godine 50 do 99, tada vraćena godina ima iste prve dvije znamenke kao i tekuća godina.
Imajte na umu da govorim samo o slučaju navođenja godine pomoću dvije znamenke; ako navedete godinu sa četiri znamenke, YY maska ​​će biti automatski zamijenjena maskom YYYY, a RR maska ​​će biti automatski zamijenjena RRRR.
--Upit br. 19 odaberite to_date("1950","RR") "50RR", to_date("1950","YY") "50YY" iz dual;
Stoga će upit #19 vratiti 1950 u oba slučaja.

Primjer br. 7. Neki drugi primjeri
Da zaključimo recenziju, pogledajmo malo egzotike. Hoće li doći do greške kao rezultat pokretanja sljedećeg upita:
--Upit br. 20 izaberite DATUM "1928-12-25" iz dual;
Ako ste odlučili da je ovo besmislen unos, onda ste u zabludi - ovo je potpuno ispravna dodjela datuma u skladu sa ANSI standardom, upit br. 20 će se uspješno izvršiti i vratiti 25.12.1928.

Koji od zahtjeva neće biti ispunjen?
--Upit br. 21 select to_date("1998-JAN-25 17:30","YYYY-MON-DD HH24:MI","NLS_DATE_LANGUAGE=AMERICAN") iz dual; --Zahtjev br. 21 odaberite to_date("1998-JAN-25 17:30","YYYY-MON-DD HH24:MI","NLS_DATE_LANGUAGE=RUSSIAN") iz dual;
Ovaj primjer ima za cilj da pokaže prisustvo trećeg parametra u funkciji to_date. Ovaj parametar omogućava vam da postavite vrijednost jednog od parametara NLS (podrška nacionalnom jeziku) samo za ovaj poziv funkcije to_date. Pogledali smo postavljanje NLS parametara za sesiju u primjeru br. 5. Ključna razlika između zahtjeva br. 20 i br. 21 nije u nazivu mjeseca (maska ​​MON se automatski zamjenjuje maskom MJESEC, kao što je opisano u primjeru br. 5), već u indikaciji različitim jezicima datumi. Zahtjev br. 21 očekuje naziv mjeseca na engleskom jeziku i, shodno tome, neće biti izvršen, zahtjev br. 22 očekuje naziv mjeseca na ruskom jeziku i biće uspješno izvršen.

Kada bi sljedeća deklaracija tablice uzrokovala greške prilikom umetanja podataka?
--Upit br. 23 kreiranje tabele za_test (broj, b datum podrazumevano do_date("09/11/2011"));
Svaki put kada će sesija sa zadanim formatom datuma "DD.MON.RR" izvršiti umetanje specificirajući samo vrijednost prvog umetanja stupca u for_test(a) vrijednosti(1); doći će do greške.

Karakteristike prikaza datuma u raznim aplikacijama

Šta utiče na prikaz datuma
Ovaj odjeljak je dodan nakon što je članak objavljen zahvaljujući preporukama datim u komentarima. Sljedeće vrijedi i za prikaz datuma i za prikaz brojeva. Moguće je da ste, kada ste pokrenuli neke od gore navedenih primjera u članku, primili datume u formatu različitom od onog navedenog u rezultatima. Ako se vaše postavke sesije poklapaju sa onima navedenim u primjerima, onda se ovo čini u najmanju ruku čudno.

Istina je da prilikom izvršavanja zahtjeva
--Zahtjev br. 24 odaberite sysdate iz dual; dobijete datum, ali da bi se rezultat prikazao na ekranu, određeni uslužni program kojim pristupate bazi podataka mora konvertovati datum u niz. Dakle, za prikaz datuma (i brojeva) implicitno poziva to_char, tj. imamo klasičan slučaj implicitne konverzije (ova konverzija je samo za prikaz, njeni rezultati ne učestvuju ni u kakvim proračunima i ne utiču ni na šta osim na prikaz podataka). Ako postoji implicitna konverzija, onda postoji maska ​​pomoću koje se ona izvodi. U klasičnom slučaju to je mora biti set maski za sesiju, tj. maska ​​specificirana u parametru NLS_DATE_FORMAT tabele nls_session_parameters, s kojom smo aktivno radili kroz cijeli članak.

Provjerimo neke aplikacije. Provjerit ćemo pomoću sljedeće skripte:
--Upit br. 25 --Provjera zadanih parametara sesije odaberite * iz nls_session_parameters gdje je parametar u ("NLS_DATE_FORMAT","NLS_DATE_LANGUAGE"); --Izlaz sysdate za odabir datuma iz dual; --Promijenite zadane parametre sesije mijenjajte set sesije NLS_DATE_FORMAT="DD.MON.RR hh24:mi:ss"; --Izlaz sysdate za odabir datuma iz dual;
Provjerimo koje parametre sqlplus koristi za prikaz datuma.

Rice. 1. Rezultat izvršavanja upita br. 25 u sqlplus-u.

Kao što se može vidjeti sa slike 1, format prikaza datuma se mijenja u zavisnosti od postavki sesije, tj. sqlplus koristi postavke sesije. Ovo olakšava razumijevanje procesa pretvaranja datuma u nizove i obrnuto, budući da se iste maske koriste i za konverziju i za prikaz.

Neki napredni razvojni alati koriste sopstvene NLS postavke koje nisu povezane sa postavkama Oraclea. Kao primjer, provjerimo koje parametre PL/SQL Developer koristi za prikaz datuma. Da bismo to uradili, izvršimo u njemu upit br. 25.


Rice. 2. Rezultat izvršavanja upita br. 25 u PL/SQL Developeru.

Kao što se može videti na slici 2, format prikaza datuma se ne menja kada se promene podešavanja sesije. Štaviše, ako pažljivo pogledate, možete vidjeti da i prvi i drugi rezultat prikaza datuma na ekranu ne odgovaraju parametrima sesije (u prvom slučaju prikazani datum je imao godinu u četverocifrenom formatu, a maska ​​je označavala godinu u dvocifrenom formatu). To znači da uslužni program koristi vlastite NLS postavke; u slučaju PL/SQL Developer-a, njihova lokacija je prikazana na Sl. 3.


Rice. 3. Postavljanje NLS parametara za prikaz datuma u PL/SQL Developeru.

Kako postavke NLS uslužnog programa mogu biti štetne
Prikazivanje datuma u formatu različitom od formata sesije je štetno iz jednog razloga - obmanjuje korisnika i može dovesti do grešaka. Pokrenimo sljedeći upit u sqlplus i PL/SQL Developer:
--Zahtjev br. 26 --Promjena zadanih parametara sesije mijenja set sesije NLS_DATE_FORMAT="DD.MON.RR hh24:mi:ss"; --Izlaz sysdate za odabir datuma iz dual; --Pokušavamo da konvertujemo podatke primljene iz prethodnog zahteva u datum izabran do_datum(HHHHHHHH) iz dual; U posljednji red zahtjeva, umjesto XXXXXXXXX, ubacit ćemo one dobijene od prethodni red podaci.

Rezultati upita prikazani su na slikama ispod.


Rice. 4. Rezultat izvršavanja upita br. 26 u sqlplusu.


Rice. 5. Rezultat izvršavanja upita br. 26 u PL/SQL Developeru.

Zašto su podaci prikazani na ekranu u sqlplus-u uspešno konvertovani u datum, ali podaci koje je na ekranu prikazao PL/SQL Developer nisu mogli da se konvertuju? Zato što za konverziju, Oracle koristi format podataka naveden u sesiji, a izlazni podaci od strane PL/SQL Developer-a su konvertovani za prikaz u sopstveni format, različit od formata sesije.

Zaključak

Kao zaključak, podsjetio bih da u gotovo svakom svom postu posvećenom radu sa datumima, Tom Kite govori o potrebi korištenja eksplicitnih konverzija i obaveznoj specifikaciji maske. “Kada konvertujete string u datum, nikada se ne oslanjajte na podrazumevani format datuma, uvek eksplicitno postavite masku” – ovo je rekao. Dodatni primjeri i moguće greške kada radite sa konverzijom datuma, možete je pronaći koristeći stranicu pitajte Tom.

Budući da je rad s datumima zauzeo cijeli članak, mnogi su ostali “pretjerani”. zanimljiva pitanja, što bih želeo da razmotrim. Najvjerovatnije će se treći dio članka pojaviti čim budem imao slobodnog vremena.

U prethodnom članku pogledali smo ugrađene funkcije za rad sa stringovima. U ovom članku razgovaraćemo o funkcijama za rad s datumom/vrijeme i funkcijama konverzije tipa za datume. Za pohranjivanje datuma i vremena, Oracle nudi poseban tip DATE. Sa fizičke tačke gledišta, ovo je razlomak broj, čiji cijeli broj pohranjuje broj dana od nekog osnovnog datuma, a razlomački dio pohranjuje vrijeme. Ovo vam omogućava da izvodite aritmetičke operacije nad datumima - sabiranje i oduzimanje.

SYSDATE funkcija

Ovo je jedna od najčešće korištenih funkcija, vraća se trenutni datum i vrijeme prema satu servera.

Funkcija LAST_DAY(d)

Vraća zadnji dan u mjesecu naveden u datumu d.

ODABIR SYSDATE d,

LAST_DAY(SYSDATE) d1

Funkcija MONTHS_BETWEEN(d1, d2)

Funkcija MONTH_BETWEEN vraća broj mjeseci između dva datuma d1 i d2, uzimajući u obzir predznak kao d1-d2, vraćeni broj je razlomak.

SELECT MONTHS_BETWEEN("2.09.2006", "2.05.2006") d1,

MJESECI_IZMEĐU("12.09.2006", "2.05.2006") d2,

MJESECI_IZMEĐU("2.05.2006", "12.09.2006") d3

Hajde da razmotrimo tipični primjeri- skraćivanje datuma na sate, dane, mjesec i godinu. Zadana maska ​​formata je "DD"

ODABIR SISTEM D1,

TRUNC(SYSDATE, "HH24") d2,

TRUNC(SYSDATE, "DD") d3,

TRUNC(SYSDATE, "MM") d4,

TRUNC(SYSDATE, "YYYY") d5

Dozvoljene maske formata za funkcije TRUNC i ROUND

Pogledajmo pobliže maske formata i značajke njihove upotrebe.

Maska

Svrha

Prvi dan veka

GODINA, ili GGGG, ili GG, ili Y

Prvi dan u godini

Prvi dan tromjesečja

MJESEC, ili PON, ili MM

Prvi dan u mjesecu

Isti dan u sedmici kao i prvi dan tekuće godine

Isti dan u sedmici kao i prvi dan tekućeg mjeseca

DAY ili DY ili D

Prvi dan u sedmici

HH, ili HH12, ili HH24

Funkcija TO_DATE(str[,maska ​​[,nls_lang]])

Funkcija TO_DATE pretvara string str u datum. Konverzija se vrši pomoću maske maske, ako je navedena. Ako maska ​​nije navedena, uzima se zadana maska. Ako navedete masku, možete odrediti još jedan parametar - jezik koji se koristi pri formatiranju naziva mjeseci i dana. Ako postoji greška pri raščlanjivanju stringa str prema navedenoj maski, dolazi do izuzetka. Najčešća greška je "ORA-01830: Šablon formata datuma se završava prije konverzije cijelog ulaznog niza." Osim toga, često se susreće i greška "ORA-01821: format datuma nije prepoznat" - javlja se kada je navedena nevažeća maska ​​formata.

SELECT TO_DATE("12.09.2006") d

Dozvoljene maske formata za funkcije TO_CHAR prilikom formatiranja datuma

Stoljeća, sa znakom minus ispred datuma pne.

ODABIR SISTEM D1,

TO_CHAR(SYSDATE-1000000, "SCC") d2

26.09.2006 17:14:21

ODABIR SISTEM D1,

TO_CHAR(SYSDATE, "GGGG") d2

Godina, napisana riječima koristeći trenutni nacionalni jezik.

ODABIR SISTEM D1,

TO_CHAR(SYSDATE, "YEAR") d2

ODABIR SISTEM D1,

TO_CHAR(SYSDATE, "MM") d2

Naziv mjeseca riječima.

ODABIR SISTEM D1,

TO_CHAR(SYSDATE, "MONTH") d2

Sedmica u godini.

ODABIR SISTEM D1,

TO_CHAR(SYSDATE, "WW") d2

Dan u godini.

ODABIR SISTEM D1,

TO_CHAR(SYSDATE, "DDD") d2

Dan u nedelji se ispisuje rečima, ako je potrebno, dopunjen sa do devet znakova sa razmacima.

ODABIR SISTEM D1,

TO_CHAR(SYSDATE, "DAN") d2

Datum u julijanskom kalendaru. Da li je broj dana od 01.01.4712 pne.

ODABIR SISTEM D1,

TO_CHAR(SYSDATE, "J") d2

Sat dana na 12-satnoj skali (1-12).

ODABIR SISTEM D1,

TO_CHAR(SYSDATE, "HH") d2

Minute (0-59).

ODABIR SISTEM D1,

TO_CHAR(SYSDATE, "MI") d2

Ova maska ​​formata je korisna za mjerenje vremenskih intervala u sekundama.

Znakovi interpunkcije. Oni se izlaze na odgovarajuća mjesta u formatiranom datumu.

ODABIR SISTEM D1,

TO_CHAR(SYSDATE, "DD.MM.GGGG HH24.MI") d2,

TO_CHAR(SYSDATE, "DD/MM/GGGG HH12.MI PM") d3

Elementi maske formata namijenjeni za izlaz tekstualne informacije, razlikuje velika i mala slova - velika i mala slova kontroliraju velika i mala slova formatiranog teksta. Pogledajmo upravljanje registrom koristeći masku formata DAY kao primjer:

ODABIR SISTEM D1,

TO_CHAR(SYSDATE, "DAY") d2,

TO_CHAR(SYSDATE, "Dan") d3,

TO_CHAR(SYSDATE, "dan") d4

26.09.2006 17:47:45

Lako je vidjeti da ako je maska ​​napisana velikim slovima, onda je formatirana tekstualna vrijednost vraća se velikim slovima. Ako je u donjem, formatirana vrijednost će također biti u donjoj. I na kraju, snimanje maske sa veliko slovo uzrokuje da se generirani tekst formatira tako da počinje velikim slovom.

Zaključak

U ovom članku pogledali smo sve glavne ugrađene Oracle funkcije dizajnirane za rad s datumima i izvođenje operacija konverzije tipa s tipom „datum“. U sljedećem članku ćemo pogledati funkcije konverzije brojeva i formatiranja i prijeći na praktične upite koristeći funkcije o kojima smo ranije govorili.

Oracle implementira skup funkcija za rad sa vrijednostima tipa datuma/vremena. Nećemo ulaziti u detalje o svim funkcijama, već sažetak u tabeli. 1 će vas upoznati dostupne mogućnosti. Ako vas zanimaju neke karakteristike, kontaktirajte nas. Detaljan opis u imenik Oracle SQL Referenca.

Izbjegavajte korištenje tradicionalnih Oracle funkcije koji rukuju vrijednostima DATE kada rade s novim tipovima podataka TIMESTAMP. Umjesto toga treba koristiti nove funkcije za tipove INTERVAL ako je moguće. A DATE funkcije se trebaju koristiti samo za obradu vrijednosti tipa DATE.

Mnogi od onih datih u tabeli. 1 funkcije (uključujući ADD_MONTHS) primaju vrijednosti tipa DATE. Problemi mogu nastati kada koristite takve funkcije s novim tipovima podataka TIMESTAMP. Iako se bilo kojoj od ovih funkcija može proslijediti vrijednost tipa TIMESTAMP, Oracle će je implicitno pretvoriti u tip DATE prije nego što funkcija završi svoj zadatak, na primjer:

DECLARE ts TIMESTAMP SA VREMENSKOM ZONOM; BEGIN ts:= SYSTIMESTAMP; --Imajte na umu: vrijednost ts varijable specificira --razlomci sekundi I vremensku zonu. DBMS_OUTPUT.PUT_LINE(ts); --Promjena ts vrijednosti jedne od ugrađenih funkcija. ts:= LAST_DAY(ts); --Delić sekundi su IZGUBLJENE i vremenska zona je zamenjena --vremenskom zonom sesije. DBMS_OUTPUT.PUT_LINE(ts); END;

rezultat:

Ime Opis
ADD_MONTHS Vraća vrijednost DATE koja je rezultat inkrementiranja postavljena vrijednost DATE za navedeni broj mjeseci. Pogledajte zbrajanje i oduzimanje intervala
CAST Pretvara između tipova podataka - na primjer, između DATE i različita značenja TIMESTAMP. Pogledajte "CAST and EXTRACT"
TRENUTNI DATUM Vraća trenutni datum i vrijeme u vremenskoj zoni sesije kao vrijednost DATE
CURRENT_TIMESTAMP Vraća trenutni datum i vrijeme u vremenskoj zoni sesije kao vrijednost tipa TIMESTAMP WITH TIME ZONE
DBTIMEZONE Vraća pomak vremenske zone baze podataka u odnosu na UTC u obliku niza znakova (na primjer, "-05:00"). Vremenska zona baze podataka se koristi samo kada se radi sa vrijednostima tipa TIMESTAMP SA LOKALNOM VREMENSKOM ZONOM
EKSTRAKT Vraća vrijednost NUMBER ili VARCHAR2 koja sadrži određeni element datuma/vremena - sat, godina ili skraćenicu vremenske zone. Pogledajte "CAST and EXTRACT"
FROM_TZ Pretvara TIMESTAMP i podatke vremenske zone u vrijednost tipa TIMESTAMP WITH TIME ZONE
ZADNJI DAN Vraća zadnji dan u mjesecu za datu vrijednost DATE
LOCALTIMESTAMP Vraća trenutni datum i vrijeme kao vrijednost TIMESTAMP u lokalnoj vremenskoj zoni
MONTHS_BETWEEN Vraća vrijednost NUMBER koja sadrži broj mjeseci između dva datuma. Pogledajte "Izračunavanje intervala između dvije vrijednosti DATE"
NEW_TIME Pretvara vrijednost DATE iz jedne vremenske zone u sličnu vrijednost iz druge vremenske zone. Ova funkcija postoji radi održavanja kompatibilnosti sa starijim kodom; nove aplikacije bi trebale koristiti TIMESTAMP SA VREMENSKOM ZONOM ili TIMESTAMP SA LOKALNOM VREMENSKOM ZONOM
SLJEDEĆI DAN Vraća datum prvog dana u sedmici nakon navedenog datuma
NUMTODSINTERVAL Pretvara određeni broj dana, sati, minuta ili sekundi (po vašem izboru) u vrijednost tipa INTERVAL DAN DO SEKUND
NUMTOYMINTERVAL Pretvara određeni broj godina i mjeseci (po vašem izboru) u vrijednost tipa INTERVAL GODINA DO MJESEC
ROUND Vraća vrijednost DATE zaokruženu na navedene jedinice
SESSIONTIMEZONE Vraća pomak vremenske zone sesije (u odnosu na UTC) u obliku niza znakova
SYS_EXTRACT_UTC Pretvara vrijednost tipa TIMESTAMP WITH TIME ZONE u TIMESTAMP vrijednost s istim datumom i vremenom, normalizirano UTC vremenom
SYSDATE Vraća trenutni datum i vrijeme Oracle servera kao vrijednost DATE
SYSTIMESTAMP Vraća trenutni datum i vrijeme Oracle servera kao vrijednost tipa TIMESTAMP WITH TIME ZONE
TO_CHAR Pretvara vrijednost datuma/vremena u niz znakova. Pogledajte "Konverzija datuma i vremena"
IZLAZITI S Pretvara niz znakova u vrijednost DATE. Pogledajte "Konverzija datuma i vremena"
TO_DSINTERVAL Pretvara niz znakova u vrijednost tipa INTERVAL DAY TO SECOND . Pogledajte Intervalne transformacije
TO_TIMESTAMP Pretvara niz znakova u vrijednost TIMESTAMP. Pogledajte "Konverzija datuma i vremena"
TO_TIMESTAMP_TZ Pretvara niz znakova u vrijednost tipa TIMESTAMP WITH TIME ZONE . Pogledajte "Konverzija datuma i vremena"
TO_YMINTERVAL Pretvara niz znakova u vrijednost tipa INTERVAL YEAR TO MONTH. Pogledajte Intervalne transformacije
TRUNC Vraća DATE vrijednost skraćenu na navedene jedinice
TZ_OFFSET Vraća UTC pomak vremenske zone određene imenom ili skraćenicom, u VARCHAR2 obliku (na primjer, "-05:00")

U ovom primjeru, varijabla ts sadrži vrijednost tipa TIMESTAMP WITH TIME ZONE. Ova vrijednost se implicitno pretvara u DATE kada se prođe LAST_DAY. Budući da tip DATE ne pohranjuje djeliće sekundi ili pomake vremenske zone, ovi dijelovi vrijednosti ts jednostavno se odbacuju. Rezultat LAST_DAY je ponovo dodijeljen ts, što uzrokuje da se izvrši druga implicitna konverzija - ovaj put DATE se pretvara u TIMESTAMP WITH TIME ZONE . Druga konverzija dobija vremensku zonu sesije, tako da vidimo ?05:00 u rezultirajućem pomaku vremenske zone.

Najbolji članci na ovu temu