T-SQL verilənlər tipləri – 2-ci hissə. TARİX və ZAMAN.

Salam Dostlar.

Bugünkü dərsimizdə cədvəllərin yaradılması zamanı ən vacib işlərdən biri olan verilənlər tiplərinin təyin olunması qaydaları barədə bəhsimizi davam edəcəyik. Məqalənin 1-ci hissəsində T-SQL – də istifadə olunan tam ədədlər, dəqiqliyi və miqyası təyin olunmuş onluq kəsr ədədlər, pul (valyuta), təxmini ədədlər verilənlər tipləri barədə bəhs etdik. Bu gün tarix və zaman tipləriylə tanış olacağıq. Bu tiplər barədə bir qədər ətraflı danışmaq lazımdır, çünki ən çox anlaşılmazlıqlar və problemlər yaradan tiplərdir. Buna görə də bugünkü dərsimiz tamamilə tarix və zaman tiplərinə həsr olunub.

TARIX VƏ ZAMAN (DATE AND TIME) VERILƏNLƏR TIPLƏRI.

Bu kateqoriyaya 6 tip daxildir: DATE, DATETİME2, DATETİME, DATETİMEOFFSET, SMALLDATETİME və TİME.

Bu tiplərin xüsusiyyətləri aşağıdakı cədvəldə göstərilib:

Verilənlər tipləri Yazılış formatı Diapazonu Dəqiqliyi Yaddaşda tutduğu yer, bayt
TIME hh:mm:ss[.nnnnnnn]Uzunluğu minimum- 8 maksimum-16 simvol 00:00:00.0000000-dən 23:59:59.9999999-dək. İlkin təyinetmə (default) qiyməti: 00:00:00 100 nanosaniyə 3-dən 5-ə dək
DATE YYYY-MM-DD Uzunluğu-10 simvol 1 yanvar 0001-ci ildən 31 dekabr  9999-cu ilədək. İlkin təyinetmə (default) qiyməti: 1900-01-01 1 gün 3
SMALLDATETIME YYYY-MM-DD hh:mm:ssUzunluğu-19 simvol Tarix və zamanı birləşdirir. Tarix:  1 yanvar 1900-cu ildən 6 iyun  2079-cu ilədək. Zaman: 00:00:00-dan 23:59:59-dək. İlkin təyinetmə (default) qiyməti: 1900-01-01 00:00:00 1 dəqiqə 4
DATETIME YYYY-MM-DD hh:mm:ss[.nnn]Uzunluğu minimum- 19 maksimum-23 simvol Tarix və zamanı birləşdirir. Tarix: 1 yanvar 1753-cü ildən 31 dekabr  9999-cu ilədək. Zaman: 0:00:00-dən 23:59:59,997-dək İlkin təyinetmə (default) qiyməti: 1900-01-01 00:00:00 0.00333 saniyə 8
DATETIME2 YYYY-MM-DD hh:mm:ss[.nnnnnnn]Uzunluğu minimum- 19 maksimum-27 simvol Tarix və zamanı birləşdirir. 1 yanvar 0001-ci ildən 31 dekabr  9999-cu ilədək. Zaman: 00:00:00-dan 23:59:59.9999999-dək  İlkin təyinetmə (default) qiyməti: 1900-01-01 00:00:00 100 nanosaniyə 6-dan 8-ə dək
DATETIMEOFFSET YYYY-MM-DD hh:mm:ss[.nnnnnnn] [+|-]hh:mmUzunluğu minimum-26 maksimum-34 simvol Tarix və zamanı birləşdirir. 1 yanvar 0001-ci ildən 31 dekabr  9999-cu ilədək. Zaman: 00:00:00-dan 23:59:59.9999999-dəkSaat  qurşağının yerdəyişmə diapazonu: -14:00 dən +14:00-dək İlkin təyinetmə (default) qiyməti: 1900-01-01 00:00:00 00:00 100 nanosaniyə 8-dən 10-a dək

Microsoft SQL Server 2008-dək SQL Serverdə cəmi iki ədəd tarix və zaman verilənlər tipləri var idi: SMALLDATETİME DATETİME. Bu tiplərdə həm tarix, həm də zaman saxlanılır. SMALLDATETİME verilənlər tipi DATETİME verilənlər tipindən daha qısa diapazonlu tarix və zaman saxlanılması üçün istifadə olunur. Bu tiplər iki hissədən ibarətdir: tarix və zaman. Əgər yalnız tarix hissəsini təyin etsək, SQL Server zamanı 00:00:00.000 şəklində saxlayacaq. Əgər yalnız zaman hissəsini təyin etsək, SQL Server tarixi 01.01.1900 şəklində saxlayacaq.

Misal üçün: test bazasını yaradaq, həmin bazada DatetimeColumnSmalldatetimeColumn sütunlarını olan TestTable cədvəlini yaradaq, sütunlara tarix və zaman verilənlərini daxil edək və sonda həmin cədvələ sorğu verək:

USE test
GO
IF EXISTS (SELECT 1 from sys.objects WHERE name = 'TestTable'and TYPE = 'u')
DROP TABLE TestTable
CREATE TABLE dbo.TestTable
(
 DatetimeColumn datetime
 ,SmalldatetimeColumn smalldatetime
);
GO
INSERT INTO dbo.TestTable (DatetimeColumn, SmalldatetimeColumn) 
VALUES ('20150906', '20150906')
INSERT INTO dbo.TestTable (DatetimeColumn, SmalldatetimeColumn) 
VALUES ('14:30:25', '14:30:25')
GO
SELECT * FROM dbo.TestTable;
GO

Burada birinci INSERT əmriylə tarix daxil edilir, ikinci əmriylə isə zaman daxil edilir.

Nəticədə alırıq:

DatetimeColumn                  SmalldatetimeColumn
-----------------------         ---------------------
2015-09-06 00:00:00.000         2015-09-06 00:00:00
1900-01-01 14:30:25.000         1900-01-01 14:30:00

Gördüyünüz kimi birinci əmrlə yalnız tarix hissəsini daxil etdik, SQL Server 00:00:00.000 zamanını əlavə etdi. İkinci əmrdə yalnız zaman hissəsini daxil etdik, SQL Server 01.01.1900 tarixini əlavə etdi.

Bəzi hallarda verilənlərin yalnız tarix və yalnız zaman tipində saxlanılması zərurəti yarandı. Bu səbəbdən Microsoft SQL Server 2008-də yalnız tarix və yalnız zaman tipləri əlavə olundu: TİME DATE. Həmçinin daha dəqiq zaman diapazonunda və saat qurşağına görə dəyişən verilənlərin saxlanılması üçün DATETİME2 DATETİMEOFFSET verilənlər tipləri yaradıldı.

TİME tipi yüksək dəqiqliyi olan zaman (saat) verilənlərin saxlanılması üçün istifadə olunur. Yazılış sintaksisi:

TİME [{<miqyas>}]

Burada “miqyas” 0-dan 7-yə qədər olan rəqəmdir. Saniyənin kəsr rəqəmlərinin (vergüldən sonrakı) sayını bildirir. Miqyas göstərilməyibsə, 7 qiyməti təyin olunur. Miqyasın xüsusiyyətləri aşağıdakı cədvəldə göstərilib:

Miqyas Saniyələrin kəsr hissəsi Yaddaşda tutduğu yer  (bayt)
time 7 5
time(0) 0-2 3
time(1) 0-2 3
time(2) 0-2 3
time(3) 3-4 4
time(4) 3-4 4
time(5) 5-7 5
time(6) 5-7 5
time(7) 5-7 5

Yenə də təkrar etmək lazımdır ki, tiplərdə hədlərin qoyulması verilənlərin yaddaşda tutduğu yerə görə və verilənlər bazasının həcminə daha səmərəli şəkildə nəzarət etmək üçün tətbiq edilib.

Misal: test bazasını yaradaq, həmin bazada TimeTable, TimeTable0, TimeTable1, TimeTable2, TimeTable3, TimeTable7 sütunları olan TestTable cədvəlini yaradaq, sütunlara zaman verilənlərini daxil edək və sonda həmin cədvələ sorğu verək:

USE test
GO
IF EXISTS (SELECT 1 from sys.objects WHERE name = 'TestTable'and TYPE = 'u')
DROP TABLE TestTable
CREATE TABLE dbo.TestTable
(
 TimeTable time 
,TimeTable0 time(0) 
,TimeTable1 time(1) 
,TimeTable2 time(2)
,TimeTable3 time(3)
,TimeTable7 time(7) 
);
GO
INSERT INTO dbo.TestTable 
VALUES
('14:30:25', '14:30:25', '14:30:25', '14:30:25', '14:30:25', '14:30:25')
GO
SELECT * FROM dbo.TestTable;
GO

Nəticədə alırıq:

TimeTable         TimeTable0     TimeTable1      TimeTable2      TimeTable3     TimeTable7
----------------  -----------    -----------     -------------   -------------  ----------------
14:30:25.0000000    14:30:25     14:30:25.0      14:30:25.00     14:30:25.000   14:30:25.0000000

Göründüyü kimi çox böyük dəqiqlik tələb olunmadıqda TİME(0) tipinin seçilməsi daha məqsədəuyğundur.

DATE tipində çox geniş diapazonda tarix verilənləri saxlanıla bilər: 1 yanvar 0001-ci ildən 31 dekabr  9999-cu ilədək. DATETİME tipində tarix diapazonu bir qədər azdır: 1 yanvar 1753-cü ildən 31 dekabr  9999-cu ilədək. Bu tarixin hədd kimi seçilməsi Sybase VBİS-lə əlaqədardır. 1 yanvar 1753-cü ildə Böyük Britaniyada və onun koloniyalarında Yulian təqvimindən Greqorian təqviminə keçid olmuşdur. Greqorian təqvimi Yulian təqvimindən 12 gün fərqlənir: yeni təqvimdə 3 sentyabr 1752-ci ildən 13 sentyabr 1752-ci ilədək olan 12 gün mövcud deyildir. 1753-cü ilədək olan tarix aralıqlarının tapılması və digər kalkulyasiyalarının aparılması zamanı çətinliklər yarandığı üçün Sydase SQL Server yaradıcıları 1753-cu ilədək verilənlərin daxil edilməsini qadağan edən həmin həddi tətbiq etdilər. Daha sonra Microsoft SQL Server tərəfindən inkişaf etdirilən T-SQL sorğu dilində həmin hədd DATETİME tipində qalmışdır. Lakin SQL Server 2008 versiyasında DATE, DATETİME2DATETİMEOFFSET tiplərində həmin hədd götürülərək eramızın 1-ci ilinin yanvar ayının 1-i təyin olunmuşdur.

DATETİME tipi tarix və zamanı birləşdirən verilənlər tipidir. Bu tipin miqyası təqribən 3-dür. Yazılışda miqyas görsədilmir.

SMALLDATETİME daha kompakt şəkildə tarix və zaman saxlanıla bilər: bu tipdə 1 yanvar 1900-cu ildən 6 iyun  2079-cu ilədək olan tarixi və 00:00:00-dan 23:59:59-dək olan zaman verilənlərini saxlamaq olar. Bu tipdə olan zaman hissəsindəki saniyələr dəqiqələrədək yuvarlaqlaşdırılır.

DATETİMESMALLDATETİME tiplərinin limitlərini nəzərə alaraq bunların əvəzinə yeni tiplərin: DATE, TİME, DATETİME2DATETİMEOFFSET istifadəsi tövsiyə olunur. Sütunda yalnız tarix saxlanacaqsa DATE tipi seçilir, yalnız zaman saxlanacaqsa TİME tipi seçilir. Tarix və zaman saxlanacaqsa DATETİME2 tipi seçilir, proqram təminatında saat qurşağı nəzərə alınacaqsa DATETİMEOFFSET tipi seçilir.

DATETİME2 tipi DATETİME tipinin genişləndilirlimş versiyasıdır. DATETİME2 tipi daha geniş diapazonlu tarix və yüksək dəqiqliyi olan zaman verilənlərin saxlanılması üçün istifadə olunur. Yazılış sintaksisi:

DATETİME2[{<miqyas>}]

Burada “miqyas” 0-dan 7-yə qədər olan rəqəmdir. Saniyənin kəsr rəqəmlərinin (vergüldən sonrakı) sayını bildirir. Miqyas göstərilməyibsə, 7 qiyməti təyin olunur.

 DATETİMEOFFSET tipi DATETİME2 tipinə oxşayır və saat qurşağının yerdəyişməsi saatını da nəzərə alır. Yazılış sintaksisi:

DATETİMEOFFSET[{<miqyas>}]

Burada “miqyas” 0-dan 7-yə qədər olan rəqəmdir. Saniyənin kəsr rəqəmlərinin (vergüldən sonrakı) sayını bildirir. Miqyas təyin olunmayıbsa ilkin təyinetməyə görə 7 həddi təyin olunur. Saat qurşağının yerdəyişməsi saatı -14:00-dan +14:00-dək təyin olunur.

Zaman tipi olan bütün verilənlər tipləri zamanı 24 saatlıq formatda yazılır: saat:dəqiqə:saniyə  (hh:mm:ss).

Misal: test bazasını yaradaq, həmin bazada DateColumn, DatetimeColumn, Datetime2Column, SmalldatetimeColum və DatetimeoffsetColumn sütunları olan TestTable cədvəlini yaradaq, sütunlara verilənlərini daxil edək və sonda həmin cədvələ sorğu verək:

USE test
GO
IF EXISTS (SELECT 1 from sys.objects WHERE name = 'TestTable'and TYPE = 'u')
DROP TABLE TestTable
CREATE TABLE dbo.TestTable
(
 DateColumn date
,DatetimeColumn datetime 
,Datetime2Column datetime2(0) 
,SmalldatetimeColum smalldatetime
,DatetimeoffsetColumn datetimeoffset(3)
);
GO
INSERT INTO dbo.TestTable 
VALUES
('20150906', '20150906 14:30:25', '14570906 23:52:56'
, '19020526 23:52:56', '20150906 14:30:25.6789 +04:00')
GO
SELECT * FROM dbo.TestTable;
GO

Nəticədə alırıq:

datetime2_resulte

Gördüyünüz kimi, DATETİME tipində zamana millisaniyələr əlavə olunur, SMALLDATETİME tipində saniyyələr dəqiqələrədək tamamilə yuvarlaqlaşır, DATETİMEOFFSET(3) tipində isə miqyas 3 təyin olunduğu üçün əlavə etdiyimiz zamanda millisaniyələr üç rəqəmədək yuvarlaqlaşdı. Misaldan göründüyü kimi, eyni zamanda tarix və zaman saxlanılacaq verilənlər üçün ən ideal variant DATETİME2 tipidir.

Ümumi yayılmış yanlışlıq ondan ibarətdir ki, SQL Server tarix və zaman tipində olan verilənləri xüsusi bir oxunan formatda saxlayır. Bu belə deyil. SQL Server bu tipdə olan verilənləri öz daxili formatında saxlayır; məsələn: DATETİMESMALLDATETİME tipində olan verilənlər 2 tam ədədlə saxlayır: birinci tam ədəd tarixi üçün, ikinci tam ədəd isə zaman üçün . Bu tipdə olan verilənləri daxil etmək üçün onlar sətir (string) formatında yazılmalıdır. SQL Server həmin sətir formatları özü tarix və zaman formatına çevirir və tam ədədlər formatında saxlayır.

TARIX VƏ ZAMAN VERILƏNLƏRIN DAXIL EDILMƏSI

Tarix və zaman tiplərində olan verilənlər bir neçə üsulla daxil edilə bilər. Daxil edilən yazıya, məsələn: ‘19020526 23:52:56’ literal deyilir. Tarix verilənlərini daxil etmək üçün istifadə edilən literalda il, ay və gün bildirən rəqəmlər bir-birindən nöqtə (.), tire (-), və ya əyri xətt (/) istifadə olunmaqla ayrıla bilər. Tarixi ayrıcı işarələrin heç birini qoymadan bitişik formada da yazmaq olar. Ayrıcı işarələrdən asılı olaraq literalların özünəməxsus adları və formatları vardır. Aşağıdakı cədvəldə tarix və zaman tipində daxil edilən literlaların formatları göstərilib:

Formatın  adı Nümunə Formatdan asılılığı
SET DATEFORMAT
Dildən asılılığı
SET LANGUAGE
Un-separated
ISO 8601
‘20150525 23:30:35’ Yoxdur Yoxdur
Numeric və ya separated ’05/25/2015 23:30:35′
‘05.25.2015 23:30:35’
Var Var
(DATEFORMAT)
Alphabetical ’25 May 2015 23:30:35′ Yoxdur Var (ay və ya qısa ay)
ANSI SQL Standard ‘2015-05-25 23:30:35’
‘2015-05-25 23:30:35-04:00’
datetime, smalldatetime datetime, smalldatetime
ISO 8601 ‘2015-05-25T23:30:35’
‘2015-05-25T23:30:35 -04:00’
Yoxdur Yoxdur
ODBC date-time {ts ‘2015-05-25 23:30:35’} Yoxdur Yoxdur
ODBC date {d ‘2015-05-25’} Yoxdur Yoxdur
ODBC time {t ’23:30:35′} Yoxdur Yoxdur
ODBC time {t ’23:30:35′} Yoxdur Yoxdur
ISO 8601 Time ’23:30:35′
’10:00:00.123456′
Yoxdur Yoxdur

Göründüyü kimi, ən əsas çətinlik literalda yazılan rəqəmlərdən hansının il, ay və gün təyin olunmasıdır. Bəzi formatlarda bu ardıcıllıq SQL Serverin və ya sessiyanın dil ayarlarından asılıdır. Ardıcıllıq mdy, dmy, ymd, ydm, myd dym şəklində ola bilər. Burada y- il, m-ay, d isə günü bildirən rəqəmlərdir. Gün və ay iki rəqəm, il isə əsasən dörd rəqəmlə yazılır. Bəzi formatlarda ili iki rəqəmlə də yazmaq mümkündür, məsələn: ‘05-25-15’. Lakin Burada bir məqama diqqət yetirmək lazımdır: əgər il iki rəqəmlə yazılırsa, SQL Server ili bildirən 01-dən 49-a qədər olan rəqəmlərin qarşısına 20 əlavə edir, 50-dən 99-a qədər olan rəqəmlərin qarşısına isə 19 rəqəmini əlavə edir. Məsələn: ‘05-25-49’ yazılarsa tarix 2049-05-25 şəklində qəbul olunur, ‘05-25-50’ yazılarsa tarix 1950-05-25 şəklində qəbul olunur. Lakin digər əsrlərin illərini əlavə etmək üçün il mütləq dörd rəqəmlə yazılmalıdır, məsələn: ‘1815’. Bu səbəbdən də SQL Serverdə tarix daxil edilən zaman ilin 4 rəqəmlə yazılması tövsiyə olunur.

Beləliklə, tarixi bildirən literal 6 və ya 8 rəqəmlə yazıla bilər, məsələn: ‘05-25-15’, ’05.25.15’,  ’05/25/15’ və ya ‘05-25-2015’, ’05.25.2015’, ’05/25/2015’. Bu literalları ayricı qoymadan bitişik yazsaq: ‘052515’ və ya ‘05252015’ verilənlərin daxil olunmadığı barədə səhv mesajı çıxacaq. Səbəb isə ondan ibarətdir ki, ayrıcılarla yazılan literallar üçün öncədən təyin olunmuş gün, ay, il ardıcıllığı əsas götürülür, bitişik yazılan literallar üçün isə bu ardıcıllığın yalnız bir formatı mövcuddur: ilk 4 rəqəm il, onlardan sonrakı 2 rəqəm ay, və son 2 rəqəm isə günü bildirir. Bitişik formada da literal 6 və ya 8 rəqəmlə yazıla bilər.

Tarixin ardıcıllığı SET DATEFORMAT əmriylə idarə olunur. İngilis dilində quraşdırılmış SQL Serverin ilkin təyin olunmuş dili (default) us-english-dir. Bu zaman ardıcıllıq ilkin olaraq (default) mdy (yəni ay-gün-il) təyin olunur və buna uyğun olaraq literalda tarix bu şəkildə yazılmalıdır: ‘05-25-2015’, ’05.25.2015’ və ya ’05/25/2015’. Bu ardıcıllığı pozsaq məsələn: ‘25-05-2015’ yazsaq, verilənlərin daxil olunmadığı barədə səhv mesaji çıxacaq. Lakin ardıcıllıqda ilk olaraq 4 rəqəm yazılarsa, SQL Server həmin 4 rəqəmini il kimi qəbul edir. Ümumiyyətlə SQL server daxil edilən literalı skan edir və ardıcıl 4 rəqəm tapıldıqda onları il kimi qəbul edir. Məsələn: ‘2015-05-25’ yazılan zaman ilk 4 rəqəm il kimi qəbul olunur, onlardan sonra gələn birinci iki rəqəm ay, sonuncu iki rəqəm isə gün kimi qəbul olunur. Bu literalı ‘2015-25-05’ şəklində yazsaq verilənlərin daxil olunmadığı barədə səhv mesajı çıxacaq, çünki ayların sayı 12 olduğu halda ayı bildirən iki rəqəmdə ‘25’ yazılıb. Bu qayda ayrıcı kimi nöqtə (.) və əyri xətt (/) istifadə olunan və rəqəmlər bitişik yazılan literallara da şamildir. Lakin tarixi ‘2015-25-05’ şəklində daxil etmək mümkündür.  Bunu üçün sütunun verilənlər tipi datetime və ya smalldatetime seçilməli və tarix formatı ydm təyin olunmalıdır.

SQL Serverin ilkin təyin olunmuş tarixin formatını da dəyişmək olar. Məsələn: SQL Serverin ilkin təyin olunmuş dili (default) us-english-dir. Bu zaman ardıcıllıq ilkin olaraq (default) mdy təyin olunur. Biz istəyirik ki, dil ayarları qalsın, lakin tarix ardıcıllığı ay-gün-il deyil gün-ay-il olsun, yəni dmy. Bunu SET DATEFORMAT əmriylə etmək mümkündür:

SET DATEFORMAT dmy

Əmr icra olunduqdan sonra ardıcıllıq gün-ay-il təyin olunur və buna uyğun olaraq literallar yazılmalıdır. Məsələn: ‘25-05-2015’ literalı yazsaq verilənlər daxil olunacaq, lakin ‘05-25-2015’ şəklində yazsaq verilənlərin daxil olunmadığı barədə səhv mesaji çıxacaq. İndi isə ayrici işarələri yığışdıraq və bitişik yazaq ‘25052015’ və ‘05252015’ hər iki literalı yazsaq verilənlərin daxil olunmadığı barədə yenə də səhv mesaji çıxacaq. Deyə bilərsiniz ki, ardıcıllıq gün-ay-il təyin olunubsa ‘25052015’ keçməli idi. Lakin, yuxarıdakı cədvələ diqqət etsək görərik ki, bitişik, yəni “un-separated” formatı SET DATEFORMAT ayarlarından asılı deyil. Yəni bu format üçün fərqi yoxdur, biz ardıcıllığı neçə təyin etmişik: mdy, dmy və s. Literal bu formatda yazılarsa SQL server ardıcıllığa baxmır və 8 rəqəmli literalda ilk 4 rəqəmi həmişə il kimi qəbul edir, ondan sonrakı iki rəqəmi isə ay, sonuncu iki rəqəmi isə gün kimi qəbul edir. Məsələn: yazdığımız ‘25052015’ literalda ‘2505’ – il, ‘20’ – ay,  ‘15’ – gün kimi qəbul olunur. Ayların sayı 12 olduğu halda ayı bildirən iki rəqəmdə ‘20’ yazılıb, buna görə də bu şəkildə verilənləri daxil etmək mümkün olmur.

Cədvəldən göründüyü kimi, formatların əksəriyyəti DATEFORMAT ayarlarından asılı deyil, yəni bu formatlar üçün fərqi yoxdur, biz ardıcıllığı neçə təyin etmişik. Lakin başqa məsələ də ondan ibarətdir ki, bəzi formatlarda bu asılılıq olmasa da dil ayarlarından asılılığı vardır. Məsələn: “Alphabetical” formatında SET DATEFORMAT ayarlarından asılılıq olmasa da, dil ayarlarından asılılığı vardır. Dil ayarları SET LANGUAGE əmriylə dəyişmək olur. Məsələn: dil ayarları us-english olsa, ’25 May 2015′ literalı yazılan zaman verilənlər daxil ediləcək. Lakin literalı ’25 Мая 2015′ şəklində yazsaq, verilənlərin daxil olunmadığı barədə səhv mesaji çıxacaq. Bu formada tarixi daxil etmək üçün dil ayarları dəyişməlidir, məsələn: SET LANGUAGE russian əmriylə ilkin dili Rus dilinə dəyişərək ’25 Мая 2015′ tarixini daxil edə bilərik. Dil ayarları verilənlər bazasına qoşulan istifadəçinin (sql login) ayarlarına uyğun təyin olunur. Yəni istifadəçi üçün russian təyin olunubsa bu zaman verilənlər bazasında dil ayarları russiandmy tarix formatı təyin olunur.

Yuxarıda izah edilən məsələlər verilənlər bazası qurulan zaman ən mühüm məsələlərdən biridir. Düzgün dil və düzgün tarix formatlarının seçilməsi olduqca vacibdir. Aşağıda bir nümunədə bunun nə qədər vacib olduğu izah olunur:

Fərz edək ki, test bazamız var. Həmin bazada TestTable cədvəli var, cədvəldə date tipində olan DateColumn sütunumuz var və həmin sütuna ‘2013-05-25’, ‘2014-06-15’, ‘2012-04-20’ tarixləri daxil edilib. Proqram təminatının koduna iki tarixin aralığında olan bütün tarixlərin tapılması SQL sorğusu yazılıb:

SELECT * 
FROM dbo.TestTable 
WHERE DateColumn > '04-20-2012'AND 
      DateColumn < '06-15-2014'

Bildiyiniz kimi, dil ayarları us-english olsa bu sorğu işləyəcək və istədiyimiz nəticə çıxacaq. Lakin SQL Serverin dil ayarları (hər hansı bir səbəbdən) dəyişdirilsə, məsələn: russian təyin olunsa, bu zaman həmin sorğu nəticə verməyəcək və səhv mesajı çıxacaq. Lakin sorğunu aşağıda göstərilən formatlarda yazsaq dil ayarlarından asılı olmayaraq sorğu işləyəcək:

SELECT * 
FROM dbo.TestTable 
WHERE DateColumn > '20120412'AND 
      DateColumn < '20140612'

Və ya:

SELECT * 
FROM dbo.TestTable 
WHERE DateColumn > '2012-04-20'AND 
 DateColumn < '2014-06-15'

Diqqət etdinizsə sorğular eynidir, biz yalnız tarixi bildirən literalların formatını dəyişdik.

Təcrübəyə əsasən tarix və zaman literllarının un-separated: ‘20150525 23:30:35’ və ya İSO 8601: ‘2015-05-25T23:30:35’ formatlarında  yazılması tövsiyə olunur. İSO 8601 formatı ümumi standart olduğuna görə digər VBİS-lərdə də keçərlidir.

TARİX VƏ ZAMANIN ƏKS OLUNMASI (NƏTICƏDƏ GÖSTƏRILMƏSI)

SQL serverdə zaman və tarix ilkin təyin etməyə görə yyyy-mm-dd formatında əks olunur. Burada yyyy-il, mm-ay, dd isə gündür. Misal üçün aşağıdakı sorğunun nəticəsinə baxaq:

USE test
GO
IF EXISTS (SELECT 1 from sys.objects WHERE name = 'TestTable'and TYPE = 'u')
DROP TABLE TestTable
CREATE TABLE dbo.TestTable
(
 DateColumn date
);
GO
INSERT INTO dbo.TestTable VALUES ('05/25/2015')
GO
SELECT * 
FROM dbo.TestTable

Nəticə:

DateColumn
-----------
2015-05-25

Göründüyü kimi biz tarixi ’05/25/2015′ formatında daxil etdik, lakin SQL Server nəticəni 2015-05-25 formatında əks etdirdi. Saat həmişə hh:mm:ss formatında əks olunur. Burada hh-saat, mm-dəqiqə, ss isə saniyədir. Məsələn: 23:30:15.

Tarixin digər formatda əks olunması üçün verilənlər tiplərinin dəyişdirilməsi funksiyasından istifadə olunur. Həmin funksiyalar CAST və CONVERT funksiyalarıdır. Funksıyaların yazılış sintaksisi:

CONVERT sintaksisi:
CONVERT ( verilənlər_tipi [ ( uzunluq ) ] , dəyişdirilən ifadə [ , stil ] )
CAST sintaksisi:
CAST ( dəyişdirilən ifadə AS verilənlər_tipi [ ( uzunluq ) ] )

Bu funksiyalar barədə növbəti məqalələrdə ətraflı məlumat verməyə calışacağam.

CONVERT funksiyasının 3-cü parametri stili bildirən rəqəmdir. Tarix və zamanın əks olunması üçün bir neçə stil mövcuddur. Məsələn: aşağıdakı sorğunun nəticəsində cari tarixi aldıq:

SELECT GETDATE()

Nəticə:

2015-06-18 17:04:48.307

Lakin biz istəyirik ki, tarix həmin formatda deyil, Rusiyada qəbul olunmuş stildə nəticədə əks olunsun. Bunun üçün sorğunu aşağıdakı şəkildə verə bilərik:

SELECT convert(varchar, GETDATE(), 104)

Nəticə:

18.06.2015

Bu sorğuda stil olaraq 104 təyinj olunub. 104 isə tarixin Almaniya (German) standartına uyğunluğunu göstərir. Bu ölkədə və əksər Avropa ölkələrində (Rusiyada həmçinin) tarix gün.ay.il formatinda (dd.mm.yyyy) yazılır. Stillərin tam siyahısı ilə aşağıdakı qaynaqdan tanış ola bilərsiniz:

Tarix və zaman stilləri

TARİX VƏ ZAMAN FUNKSIYALARI

Tarix və zamanla işləmək üçün SQL Serverdə bir neçə funksiya vardır. Ən əhəmiyyətli funksiyalardan biri cari tarixi qaytaran funksiyadır. Bu funksiya sorğularda tez-tez istifadə olunur. Bu kateqoriyaya GETDATE, CURRENT_TIMESTAMP, GETUTCDATE, SYSDATETIME, SYSUTCDATETIME və SYSDATETIMEOFFSET funksiyaları aiddir.

GETDATE funksiyası – qoşulduğunuz SQL Server nüsxəsində cari tarixi və vaxtı qaytaran T-SQL dilinin funksiyasıdır. GETDATE  əmriylə tarix və zaman DATETIME tipində əks olunur. CURRENT_TIMESTAMP funksiyası eyni işi görür, lakin bu funksiya standarta uyğun olduğuna görə istifadə edilməsi tövsiyə edilir. SYSDATETIME və SYSDATETIMEOFFSET funksiyaları tarix və zamanı daha dəqiq məlumat tipləriylə əks etdirirlər, müvafiq olaraq DATETIME2 və DATETIMEOFFSET tiplərində. Qeyd etmək lazımdır ki, yalnız cari tarixi və ya yalnız cari zamanı əks etdirən inteqrasiya edilmiş funksiyalar mövcud deyil. Belə məlumatları almaq üçün SYSDATETIME funksiyasının tipini DATE və ya TIME tiplərinə dəyişdirmək lazımdır. Məsələn yalnız cari tarixi almaq üçün aşağıdakı sorğudan istifadə etmək olar:

SELECT CAST (SYSDATETIME() AS DATE)

GETUTCDATE funksiyası UTC terminlərində cari tarix və zamanı DATETIME tipində qaytarır; SYSUTCDATETIME funksiyası eyni işi görür, lakin tarix və zamanı DATETIME2 tipində qaytarılır.

TARİX VƏ ZAMAN HİSSƏLƏRİ

Bəzi vaxtlar tarix və zamanın hissələrinin qaytarılması və ya ayrı-ayrı hissələrdən tarix və zamanın düzəldilməsi zərurəti yaranır. Bu əməliyyatları etmək üçün T-SQL-də müəyyən funksiyalar mövcuddur. DATEPART funksiyası vasitəsilə giriş tarix və zamanın hissələrini, məsələn: il, gün, saniyə və s. tam ədədlərlə almaq olar. Misal üçün: SELECT DATEPART (month, ‘20150525’) əmri nəticəsində “5” alırıq, bu isə verilmiş tarixin ayını göstərir. T-SQL-da ayrıca hissələrdən ibarət funksiyalar mövcuddur: YEAR, MONTH, DAY. Bu zaman DATEPART əmrini yazmaq lazım olmur, məsələn: SELECT month (‘20150525’).  Bu əmr yuxarıdakı əmrin qısaldılmış formasıdır. DATENAME funksiyası DATEPART funksiyasından fərqli olaraq nəticəni tam ədədlərlə deyil simvol sətir formatında verir və göstərilmiş hissənin adını qaytarır. Məsələn SELECT DATENAME (month, ‘20150525’) əmri nəticəsində “May” alırıq. Bu isə verilmiş tarixdəki ayın adını bildirir. Bu funksiya dil ayarlarından asılıdır. Məsələn: sessiyanın dili us_english-dirsə funksiya “May” nəticəsini verir, sessiyanın dili russian-dirsə funksiya “Mай” nəticəsini verir.

DATEFROMPARTS funksiyası ilə tarix və zamanı ayrı-ayrı hissələrdən yığmaq olar. Məsələn: SELECT DATEFROMPARTS (2015, 05, 25) nəticəsində 2015-05-25 tarixini alırıq. Həmin funksiya bütün tarix və zaman tipləri üçün mövcuddur. Sadəcə olaraq tipin sonuna FROMPARTS əlavə olunur, məsələn TİMEFROMPARTS, SMALLDATETİMEFROMPARTS və s.

Və sonuncu funksiya EOMONTH funksiyasıdır. Bu funksiya vasitəsilə verilmiş tarixdəki ayın sonunu tapmaq olur. Məsələn: bu gün 22 iyun 2015-si il tarixidir. SELECT EOMONTH (GETDATE ()) əmri nəticəsində 2015-06-30 tarixini alırıq, və bu onu bildirir ki, iyun ayının sonuncu günü 30 iyundur.

TARIX VƏ ZAMANIN ƏLAVƏ OLUNMASI VƏ ÇIXILMASI FUNKSIYALARI

T-SQL-də tarix və zamanı cəmləmək və çıxmaq üçün DATEADD və DATEDİFF adlı funksiyalar mövcuddur.

DATEADD funksiyası çox geniş istifadə olunur. Həmin funksiya vasitəsilə verilmiş tarixlərə il, ay, gün əlavə olunur. Məsələn: verilmiş tarix 25 may 2015-ci ildir. Həmin tarixə 1 il əlavə etmək istəyirik. Bunu aşağıdakı əmrlə edə bilərik:

SELECT DATEADD (year, 1, '20150525')

DATEDİFF funksiyası da çox geniş istifadə olunur. Həmin funksiya vasitəsilə verilmiş tarixlərin fərqini almaq olur. Məsələn: iki tarix verilib: 25 may 2015-ci il və 25 may 2016-cı il. Sual qoyulur: tarixlər arasında neçə il fərq var. Bunu aşağıdakı əmrlə ala bilərik:

SELECT DATEDIFF (year, '20150525', '20160525')

Nəticədə “1” alırıq. Bu funksiyanın nəticələri tam ədədlə verilir.

Digər funksiyalar saat qurşağının istənilən qiymətdə qaytarılması və əlavə olunması funksiyalarıdır:

SWITCHOFFSET  və  TODATETIMEOFFSET.

STANDARTA UYĞUNLUĞU VƏ PL/SQL-DƏ OLAN ANALOQU

Qeyd etmək lazımdır ki, DATETİME və SMALLDATETİME tipləri ANSİ və İSO 8601 standartlarına uyğun deyildir. DATE və TİME tipləri ANSİ və İSO 8601 standartlarına uyğundur. DATETİME2 və DATETİMEOFFSET tipləri yalnız DATE və TİME hissələrində ANSİ və İSO 8601 standartlarına uyğundur.

T-SQL sorğu dilində olan tarix və zaman tiplərinin PL/SQL dilində olan analoqları aşağıdakı cədvəldə göstərilib. Gördüyünüz kimi, T-SQL sorğu dilində istifadə edilən tarix və zaman tiplərindən yalnız DATE tipi  PL/SQL dilinə uyğundur, bütün digər tiplər PL/SQL-də mövcud deyildir və TİMESTAMP verilənlər tipi ilə əvəz olunur. TİMESTAMP tipi isə T-SQL-də tamamilə başqa məqsədlər üçün istifadə olunur:

MS SQL Server Oracle Database
DATE DATE
DATETIME TIMESTAMP(3) və ya DATE
DATETIME2 TIMESTAMP
DATETIMEOFFSET TIMESTAMP WITH TIMEZONE
SMALLDATETIME TIMESTAMP(3) və ya DATE
TIME TIMESTAMP
VARCHAR(37) TIMESTAMP WITH TIMEZONE
Dəstəkləmir INTERVAL YEAR TO MONTH
Dəstəkləmir INTERVAL DAY TO SECOND

Dərsimizin ikinci hissəsinin sonuna gəlib çatdıq. Bu hissədə T-SQL-də istifadə olunan tarix və zaman verilənlər tipləri barədə bəhs etdik.

Ümid edirəm yararlı olacaq.

Diqqətinizə görə təşəkkür edirəm.

Səs: +30. Bəyənilsin Zəifdir

Müəllif: Rauf Khalafov

Şərh yazın