Manage Data in Different Time Zones
MÜXTƏLIF BÖLGƏLƏRDƏKI VAXTLARIN FUNKSIYALARLA IDARƏ OLUNMASI
Salam, bloguma xoş gəlmisiniz! Oracle SQL yazılarımın bugünkü mövzusuyla artıq tanış olmuşsunuzdur, elə isə başlayaq 🙂
ORACLE SQL lokal və uzaq(remote) vaxt zonalarının idarə edilməsi üçün bir çox xüsusiyətlərə malikdir. Məsələn helpdesk-ə edilən müraciətlər fərqli ölkələrdən, zonalardan ola bilər və bu müraciətləri vaxtları ilə daha dəqiq şəkildə bazada saxlamaq lazımdır, Bunun üçün oracle sql-in bir neçə yararlı funksiyalarından və verilən tiplərindən istifadə edəcəyik.
ORACLE SQL – dəki bütün tranzaksiyalar 3 vaxt zonası ilə əlaqədardır.
- UTC vaxtı – hansı ki Qrinviç meridianının orta Günəş vaxtıdır və digər vaxt zonaları bu vaxta görə hesablanır.
- Verilənlər bazası vaxt zonası – Verilənlər bazasının yükləndiyi bölgənin vaxt zonasıdır(DBTIMEZONE funksiyası ilə baxa bilərsiniz)
- Sessiya vaxt zonası – Verilənlər bazasına qoşulan istifadəçilərin sahib olduğu vaxt zonasıdır(SESSIONTIMEZONE funksiyası ilə baxa bilərsiniz)
Bu vaxt zonalarını DATE və TIMESTAMP tarix tipləri dəstəkləmir. Vaxt zonaları üçün istifadə edəcəyimiz verilən tipləri TIMESTAMP WITH TIME ZONE və TIMESTAMP WITH LOCAL TIME ZONE olacaq. Bu verilən tiplərinin fərqlərinə bu şəkildən baxa bilərsiniz.
BAZA vaxtı vs SESSIYA vaxtı (Database Time vs. Session Time)
- Baza vaxt zonası DBTIMEZONE funksiyası ilə təyin edilir.
- Sessiya vaxt zonası SESSIONTIMEZONE funksiyası ilə təyin edilir.
SELECT DBTIMEZONE, SESSIONTIMEZONE FROM DUAL;
DBTIMEZONE SESSIONTIMEZONE
———- ————————————
+00:00 America/New_York
Nəticəyə baxdığımız zaman DBTIMEZONE-un UTC+0, SESSIONTIMEZONE-un isə America/New_York olduğunu görürük.
DBTIMEZONE-u dəyişmək üçün: ALTER DATABASE SET TIME_ZONE = ‘Europe/Zurich’;
SESSIONTIMEZONE-u dəyişmək üçün: ALTER SESSION SET TIME_ZONE = ‘America/Los_Angeles’;
Əgər baza vaxt zonasını dəyişdirdiyiniz zaman xəta ilə qarşılaşırsınızsa bu sizin bazada TIMESTAMP WITH LOCAL TIME ZONE verilən tipində cədvəllərinizin olduğu deməkdir. Bu sorğu ilə xətaya səbəb olan cədvəllərinizi tapa bilərsiniz.
SELECT OWNER, TABLE_NAME, COLUMN_NAME, DATA_TYPE
FROM DBA_TAB_COLUMNS
WHERE DATA_TYPE LIKE ‘%LOCAL TIME_ZONE%’
ORDER BY OWNER, TABLE_NAME, COLUMN_NAME;
UTC nədir?
Coordinated Universal Time və ya qısaca UTC, Greenwich Mean Time(GMT)-in “yeni” adıdır. Koordinasiya edilmiş ümumdünya vaxtıdır və beynəlxalq olaraq vaxtın ölçülmə standartıdır. UTC və GMT arasında fərqlər mövcuddur ancaq bu fərqlər bizim bazadakı işlərimizə təsir etmir. Digər dünya ərazilərindəki vaxtlar yerləşim yerinə görə UTC+offset şəklində bir dəyər alır. Məsələn bu dəyər Bakı üçün UTC/GMT + 04:00-dür.
SQL dünyasında önəmlilik dərəcəsinə görə birinci UTC-ə daha sonra database server(DBTIMEZONE) vaxtına sonra isə client system(SESSİONTIMEZONE)-a önəm verilir.
Vaxt Zonası Region Adları
UTC sistemində mövcud olan müxtəlif region adlarıdır.Hər birinin mətn formasında adı və qısaltması vardır.
- Central Daylight Time (UTC-5)
- Central Standard Time (UTC-6)
- Eastern Standard Time (UTC-5)
- Local Mean Time (UTC-6)
Bu şəkildə bir neçə region adları və qısaltmaları verilib.
Bundan əlavə əgər bazanızda olan bütün vaxt zonaları adlarına baxmaq istəyirsinizsə bu sorğudan istifadə edə bilərsiniz.
SELECT TZABBREV, TZNAME FROM V$TIMEZONE_NAMES ORDER BY TZABBREV, TZNAME;
VAXT ZONASI VERİLƏN TİPLƏRİ
ORACLE SQL-də 2 verilən tipi vardır ki, müxtəlif vaxt zonalarında olan vaxtları idarə etmək üçün istifadə olunur.
- TIMESTAMP WITH TIME ZONE
- TIMESTAMP WITH LOCAL TIME ZONE
TIMESTAMP WITH TIME ZONE
TIMESTAMP WITH TIME ZONE verilən tipi ORACLE SQL-in TIMESTAMP tipində oxşardır. TIMESTAMP tipinə əlavə olaraq TIMEZONE_HOUR, TIMEZONE_MINUTE, TIMEZONE_REGION, TIMEZONE_ABBR dəyərlərini əlavə edir.
Saxladığı məlumatı 2 cür saxlaya bilir.
- Vaxt zonası region adı ilə
- Vaxt zonası offset(UTC və lokal vaxt arasındakı interval)-i ilə
Oracle tövsiyə edirki vaxt zonaları ilə əlaqədar məlumatlarınızı vaxt zonası region adı ilə saxlamağa üstünlük verin.
TIMESTAMP WITH LOCAL TIME ZONE
TIMESTAMP WITH LOCAL TIME ZONE verilən tipi ORACLE SQL-in TIMESTAMP tipinə oxşardır. TIMESTAMP WITH TIME ZONE-dan fərqli olaraq vaxt zonasını saxlamır(doesnt store) və hər zaman qaytardığı məlumat istifadəçinin yerləşdiyi vaxt zonasının dəyəri olur.
VAXT ZONASI FUNKSİYALARI
CURRENT_DATE, CURRENT_TIMESTAMP
Cari gün və cari gün+saatı+vaxt sonasını qaytarır.
SELECT CURRENT_DATE, CURRENT_TIMESTAMP FROM DUAL;
CURRENT_DATE CURRENT_TIMESTAMP
————————- ———————————-
20-NOV-15 20-NOV-15 11.12.50.843000 +04:00
LOCALTIMESTAMP
LOCALTIMESTAMP istifadəçinin lokal sessiya vaxtını TIMESTAMP şəklində qaytarır.
SELECT LOCALTIMESTAMP(4) FROM DUAL;
LOCALTIMESTAMP(4)
—————————————
18-NOV-15 11.15.20.031300 AM
SYSTIMESTAMP
SYSTIMESTAMP bazanın əməliyyat sisteminin vaxtını TIMESTAMP WITH TIME ZONE şəklində qaytarır.
SELECT SYSTIMESTAMP FROM DUAL;
SYSTIMESTAMP
————————————
18-NOV-15 12.21.27.437000000 AM -04:00
NEW_TIME
NEW_TIME(d,t1,t2)
d – DATE tipindədir.
t1, t2 – vaxt zonası göstəriciləridirlər. Bu şəkildə ətraflı göstərilib.
Verilmiş DATE tipindəki d-dəyərini t1 və t2 dəyərlərinə əsasən yeni tarixə çevirir, t1 verilmiş d-dəyərinin aid olduğu vaxt zonasıdır.NEW_TIME funksiyası d-dəyərini t2 vaxt zonasına çevirəcək.
SELECT TO_CHAR(NEW_TIME(TO_DATE('2015-NOV-20 12:55:56','RRRR-MON-DD HH24:MI:SS'),'AST','HST'),'DD-MON-RR HH:MI:SS') NEW_DATE FROM DUAL;
NEW_DATE
————————-
20-NOV-15 06:55:56
FROM_TZ
FROM_TZ(ts, tz)
ts – TIMESTAMP tipindədir.
tz – vaxt zonasının UTC qarşılığıdır.
Verilmiş TIMESTAMP dəyərini(ts) vaxt zonası ilə birlikdə TIMESTAMP WITH TIME ZONE tipində qaytarır.
SELECT FROM_TZ( TIMESTAMP '2015-11-20 09:08:30', '+07:30') FROM DUAL;
FROM_TZ(TIMESTAMP’2015-11-2009:08:30′,’+07:30′)
——————————————————————–
20-OCT-15 09.08.30.000000000 AM +07:30
TO_TIMESTAMP_TZ
TO_TIMESTAMP_TZ(c, format_model)
c – char tipindədir
format_model – verilmiş c-dəyərinə uyğun format modelidir.
Verilmis char tipdə olan məlumatı TIMESTAMP WITH TIME ZONE tipinə çevirir.
SELECT TO_TIMESTAMP_TZ('20-11-2015 09:25:30','DD-MM-RRRR HH24:MI:SS') "Time" FROM DUAL;
Time
———————————————————
20-NOV-15 09.25.30.000000000 AM +04:00
CAST
CAST(e AS d)
d – verilən tipi
e – d verilən tipinə çevirmək istədiyimiz ifadə
Verilmis e ifadəsini d verilən tipinə çevrir.
SELECT CAST('20-NOV-15 10:07:30' AS TIMESTAMP WITH LOCAL TIME ZONE) "Converted " FROM DUAL;
Converted
————————————
20-NOV-15 10.07.30.000000000 AM
SELECT CAST(TO_TIMESTAMP('20-NOV-15 10:12:30','DD-MON-RR HH24:MI:SS') AS TIMESTAMP WITH LOCAL TIME ZONE) "Converted " FROM DUAL;
Converted
——————————
20-NOV-15 10.12.30.000000000 PM
EXTRACT
EXTRACT( fm FROM e)
fm – format model-dir. Bu şəkildə “keyword” adı altında olan modellərdən biridir. Məs: year, month, day, hour, minute, second, timezone_hour, timezone_minute, timezone_region, timezone_abbr
e – tarix tiplərindən biridir.
SELECT EXTRACT(MINUTE FROM TO_TIMESTAMP('2015-11-20 10:19:14','RRRR-MM-DD HH24:MI:SS')) "Minute" FROM DUAL;
Minute
———–
19
SYS_EXTRACT_UTC
SYS_EXTRACT_UTC(dtz)
dtz – özündə vaxt zonasını saxlayan hər hansı tarix tipi.
Verilmis tarix tipindən UTC dəyərini xaric edi TIMESTAMP tipində dəyər qaytarır.
SELECT SYS_EXTRACT_UTC(TIMESTAMP '2015-11-20 10:38:00 +04:00') "HQ" FROM DUAL;
HQ
——————————————
20-NOV-11 06.38.00.000000000 AM
AT TIME ZONE, AT LOCAL
Bu ifadələri bir misal üzərində anlatmaq istəyirəm. Birinci bazamızın və sessiyamızın hansı vaxt zonalarında olduğunu öyrənək.
SELECT DBTIMEZONE, SESSIONTIMEZONE FROM DUAL;
DBTIMEZONE SESSIONTIMEZONE
—————– —————————
-05:00 America/ Los_Angeles
İndi isə istifadəçi olaraq sessiya vaxtımızı baza vaxtına görə necə dəyişdiyinə baxaq.
SELECT TO_TIMESTAMP('2015-NOV-20 10:58:00','RRRR-MON-DD HH24:MI:SS') AT TIME ZONE DBTIMEZONE "DB Time" FROM DUAL;
DB Time
——————————————————–
20-NOV-15 01.58.00.000000000 PM -05:00
Normalda Los Angeles və Bakı arasında 12 saatlıq bir fərq var ancaq biz bu nəticədə 3 saatlıq bir fərq gördük çünki Los Angeles UTC-08:00 , Bakı isə UTC-05:00 vaxt zonalarına məxsusdur və ORACLE UTC -ə öncəlik verdiyini qeyd etmişdik yəni bu 3 saatlıq fərq məhz UTC-lər arasındakı fərqdir.
AT LOCAL
Başqa vaxt zonalarında olan tarix və saatların bizim yerləşdiyimiz vaxt zonasına çevirmək üçün istifadə edirik.
Aşağıdakı sorğuda daha ətraflı başa düşəcəksiniz.
SELECT FROM_TZ( CAST( TO_DATE(2015-11-20 11:40:00', 'RRRR-MM-DD HH:MI:SS') AS TIMESTAMP ), 'America/Los_Angeles') AT LOCAL "Local Time" FROM DUAL;
Local Time
—————————————–
20-NOV-15 02.00.00.000000000 PM AMERICA/NEW_YORK
Beləliklə single-row funksiyalar mövzusunu bitirmiş olduq, ümid edirəm sizlərə faydalı olar 🙂