Konačna referenca na tipove podataka datum i vrijeme. Referentni vodič za MySQL

vrste podataka o datumu i vremenu: DATETIME, DATE, TIMESTAMP, TIME i YEAR. Svaki od njih ima interval prihvatljive vrijednosti, kao i vrijednost "null", koja se koristi kada korisnik unese stvarno nevažeću vrijednost. Imajte na umu da vam MySQL omogućuje pohranu nekih datumskih vrijednosti koje nisu posve pouzdane, na primjer 1999-11-31. Razlog je taj što je upravljanje validacijom datuma odgovornost specifična primjena, a ne SQL poslužitelji. Kako bi ubrzao provjeru valjanosti datuma, MySQL provjerava samo je li mjesec u rasponu 0-12, a dan u rasponu 0-31. Ovi intervali počinju od 0, ovo je učinjeno kako bi se MySQL-u omogućilo pohranjivanje datuma u kojima je dan ili mjesec u stupcima DATE ili DATETIME jednaka nuli. Ova značajka je posebno korisna za aplikacije koje zahtijevaju pohranjivanje datuma rođenja - ovdje dan ili mjesec rođenja nisu uvijek poznati. U takvim slučajevima, datum se jednostavno pohranjuje kao 1999-00-00 ili 1999-01-00 (ali ne biste trebali očekivati ​​da će funkcije DATE_SUB() ili DATE_ADD vratiti točne vrijednosti za takve datume).

MySQL dohvaća vrijednosti za ove vrste samo datumi ili vremena standardni format, ali u isto vrijeme pokušava protumačiti različite formate koji mogu doći od korisnika (na primjer, kada se navodi vrijednost kojoj bi se trebala dodijeliti vrsta datuma ili vremena ili usporediti s vrijednošću koja ima jednu od ovih vrsta). Međutim, podržani su samo formati opisani u sljedećim odjeljcima. Od korisnika se očekuje da unese valjane vrijednosti za količine jer korištenje količina u drugim formatima može proizvesti nepredvidive rezultate.

  • Iako MySQL pokušava interpretirati vrijednosti u više formata, u svim slučajevima očekuje se da će odjeljak datumske vrijednosti koji sadrži godinu biti krajnje lijevo. Datumi moraju biti navedeni redom godina-mjesec-dan (na primjer, "98-09-04"), a ne redom mjesec-dan-godina ili dan-mjesec-godina, tj. ne onako kako ih obično pišemo (na primjer, "09-04-98", "04-09-98").
  • MySQL će automatski pretvoriti vrijednost vrste datuma ili vremena u broj ako dana vrijednost koristi se u numeričkom kontekstu i obrnuto.
  • Vrijednost koja ima tip datuma ili vremena koji je izvan granica postavljeni interval ili je nevažeći za ovu vrstu podataka (pogledajte početak odjeljka), pretvara se u vrijednost "null" za ovu vrstu. (Izuzetak su vrijednosti tipa TIME koje izlaze izvan granica utvrđenog intervala, a koje su skraćene na odgovarajuću graničnu točku navedeni interval VRIJEME). U tablici 4.3. Ovo su formati za vrijednost "null" za svaku vrstu stupca:
  • Nulte vrijednosti su posebne. Da biste ih pohranili ili uputili na njih, možete eksplicitno koristiti vrijednosti predstavljene u tablici ili možete koristiti "0", što je lakše napisati.
Tipovi podataka DATETIME, DATE i TIMESTAMP

Tip podataka DATETIME koristi se za vrijednosti koje sadrže informacije o datumu i vremenu. MySQL dohvaća i prikazuje DATETIME vrijednosti u formatu "GGGG-MM-DD HH:MM:SS". Podržani raspon vrijednosti je od "1000-01-01 00:00:00" do "9999-12-31 23:59:59". ("podržano" znači da iako vrijednosti s ranijim vremenskim vrijednostima mogu i dalje raditi, nema jamstva da će biti pohranjene i ispravno prikazane).

Tip DATE koristi se za vrijednosti samo s informacijama o datumu, bez vremenskog dijela. MySQL dohvaća i prikazuje vrijednosti DATUMA u formatu "GGGG-MM-DD". Podržani raspon vrijednosti je od "1000-01-01" do "9999-12-31".

Vrsta stupca TIMESTAMP pruža vrstu reprezentacije podataka koja se može koristiti za automatsko snimanje trenutni datum i vrijeme prilikom izvođenja operacija INSERT ili UPDATE. Ako imate više stupaca TIMESTAMP, automatski se ažurira samo prvi.

Za preostale (osim prvog) stupce tipa TIMESTAMP također možete postaviti vrijednost na trenutni datum i vrijeme. Da biste to učinili, jednostavno trebate postaviti stupac na NULL ili NOW() .

Svaki stupac TIMESTAMP (čak i prvi stupac te vrste) može se postaviti na vrijednost koja nije trenutni datum i vrijeme. To se postiže eksplicitnim postavljanjem na željenu vrijednost. Ova nekretnina može se koristiti, na primjer, ako želite postaviti stupac TIMESTAMP na trenutni datum i vrijeme kada kreirate red, a kada naknadno ažurirate taj red, vrijednost stupca se ne bi trebala promijeniti.

Vrijednosti TIMESTAMP-a mogu se kretati od početka 1970. do neke vrijednosti u 2037. s rezolucijom od jedne sekunde. Ove se količine ispisuju kao numeričke vrijednosti.

Format podataka u kojem MySQL dohvaća i prikazuje vrijednosti TIMESTAMP ovisi o broju prikazanih znakova. To je ilustrirano u tablici 4.4. Puni format TIMESTAMP ima 14 decimalnih mjesta, ali možete stvoriti TIMESTAMP stupce s kraćim izlaznim nizom:

Tablica 4.4.
TIMESTAMP format podataka ovisno o broju ekstrahiranih znamenki Vrsta stupca
Izlazni format VREMENSKA OZNAKA (14)
GGGGMMDDHHMMSS VREMENSKA OZNAKA (12)
GGMMDDHHMMSS VREMENSKA OZNAKA (10)
GGMMDDHHMM VREMENSKA OZNAKA (8)
GGGGMMDD VREMENSKA OZNAKA (6)
GGMMDD VREMENSKA OZNAKA (4)
GGMM VREMENSKA OZNAKA(2)

YY Vrijednosti DATETIME, DATE i TIMESTAMP mogu se postaviti na bilo koje standardni set

  • formati:
  • Kao niz u formatu "GGGG-MM-DD HH:MM:SS" ili u formatu "GG-MM-DD HH:MM:SS". Dopuštena je "lagana" sintaksa - možete koristiti bilo koji interpunkcijski znak kao razdjelnik između dijelova odjeljaka datuma ili vremena. Na primjer, vrijednosti "98-12-31 11:30:45", "98.12.31 11+30+45", "98/12/31 11*30*45" i "98@12@31 11^30^ 45" su ekvivalentni.
  • Kao niz u formatu "GGGG-MM-DD" ili u formatu "GG-MM-DD". Ovdje je također prihvatljiva "lagana" sintaksa. Na primjer, vrijednosti "98-12-31", "98.12.31", "98/12/31" i "98@12@31" su ekvivalentne.
  • Kao niz bez graničnika u formatu "GGGGMMDDHHMMSS" ili u formatu "GGMMDDHHMMSS", pod uvjetom da se niz razumije kao datum. Na primjer, vrijednosti "19970523091528" i "970523091528" mogu se protumačiti kao "1997-05-23 09:15:28", ali vrijednost "971122129015" nije važeća (vrijednost minutnog odjeljka je apsurdna) i pretvara se na "0000-00-00 00 :00:00."
  • Kao niz bez graničnika u formatu "GGGGMMDD" ili u formatu "GGMMDD", pod uvjetom da se niz tumači kao datum. Na primjer, vrijednosti "19970523" i "970523" mogu se protumačiti kao "1997-05-23", ali vrijednost "971332" je nevažeća (vrijednosti odjeljka mjeseca i dana su besmislene) i pretvara se u " 0000-00-00".
  • Kao broj u formatu GGGGMMDDHHMMSS ili u formatu GGMMDDHHMMSS, pod uvjetom da se broj tumači kao datum. Na primjer, vrijednosti 19830905132800 i 830905132800 tumače se kao "1983-09-05 13:28:00".
  • Kao broj u formatu GGGGMMDD ili u formatu GGMMDD, pod uvjetom da se broj tumači kao datum. Na primjer, vrijednosti 19830905 i 830905 tumače se kao "1983-09-05".
Kao rezultat izvršavanja funkcije koja vraća vrijednost prihvatljivu u kontekstu tipova podataka DATETIME, DATE ili TIMESTAMP (na primjer, funkcije NOW() ili CURRENT_DATE().

MySQL dohvaća i prikazuje VRIJEME u formatu "HH:MM:SS" (ili u formatu "HHH:MM:SS" za veće satne vrijednosti). Vrijednosti VRIJEME mogu varirati od "-838:59:59" do "838:59:59". Razlog zašto dio vrijednosti "sat" može biti tako velik je taj što se tip TIME može koristiti ne samo za predstavljanje doba dana (koje mora biti manje od 24 sata), već i za predstavljanje ukupnog proteklog vremena ili vremenski interval između dva događaja (koji može biti znatno dulji od 24 sata ili čak negativan).

Vrijednosti VRIJEME mogu se navesti u različitim formatima:

Kao niz u formatu "D HH:MM:SS.fractional part" (imajte na umu da MySQL još ne podržava pohranjivanje fractional dijela vrijednosti u stupcu dotične vrste). Također možete koristiti jedan od sljedećih "laganih" prikaza: HH:MM:SS.razlomački dio, HH:MM:SS , HH:MM , D HH:MM:SS , D HH:MM , D HH ili SS . Ovdje su D dani iz raspona vrijednosti 0-33.

  • Kao niz bez graničnika u formatu "HHMMSS", pod uvjetom da se niz tumači kao datum. Na primjer, vrijednost "101112" shvaćena je kao "10:11:12", ali vrijednost "109712" bila bi nevažeća (vrijednost odjeljka minuta je apsurdna) i pretvorila bi se u "00:00:00".
  • Kao broj u formatu HHMMSS, pod uvjetom da se niz tumači kao datum. Na primjer, vrijednost 101112 shvaća se kao "10:11:12". MySQL također razumije sljedeće alternativni formati: SS
  • Kao četveroznamenkasti broj u rasponu od 1901 do 2155.
  • Kao niz od dva znaka u rasponu vrijednosti od "00" do "99". Vrijednosti u intervalima od "00" do "69" i od "70" do "99" zatim se pretvaraju u vrijednosti GODINE u intervalima od 2000. do 2069. odnosno od 1970. do 1999. godine.
  • Kao dvoznamenkasti broj u rasponu od 1 do 99. Vrijednosti u rasponima od 1 do 69 i od 70 do 99 zatim se pretvaraju u vrijednosti GODINE u rasponima od 2001. do 2069. i od 1970. do 1999., odnosno. Imajte na umu da je razmak za dvoznamenkaste brojeve i dvoznamenkaste nizove malo drugačiji jer ne možete navesti "nulu" izravno kao broj i protumačiti ga kao 2000. Morate ga navesti kao niz "0" ili "00" ili to će se protumačiti kao 0000.
  • Kao rezultat izvršavanja funkcije koja vraća vrijednost prihvatljivu u kontekstu tipa podataka YEAR (kao što je NOW()).

Nevažeće vrijednosti YEAR pretvaraju se u 0000.

Vrste DATETIME, DATE i TIMESTAMP

Vrste DATETIME, DATE i TIMESTAMP povezane su jedna s drugom. Ovaj odjeljak opisuje njihove karakteristike, po čemu su slični i po čemu se razlikuju.
Tip DATETIME koristi se kada trebate imati vrijednosti koje uključuju i datum i vrijeme. MySQL dohvaća i prikazuje DATETIME vrijednosti u formatu TGGT-MM-DD HH:MM:SS". Podržani raspon vrijednosti za njih je od "1000-01-01 00:00:00" do "9999- 12-31 23:59 :59" (Podržano znači da ranije vrijednosti mogu funkcionirati, ali nisu zajamčene.)
Tip DATE se koristi kada trebate imati vrijednosti koje uključuju samo datum, bez vremena. MySQL dohvaća i prikazuje DATETIME vrijednosti u formatu "GGGG-MM-DD". Podržani raspon je od CH000-01-0G do "9999-12-31".
Vrsta stupca TIMESTAMP ima niz svojstava koja ovise o verziji MySQL-a i SQL načinu rada u kojem poslužitelj radi. Ova svojstva su opisana kasnije u ovom odjeljku.
Možete navesti vrijednosti tipova DATETIME, DATE i TIMESTAMP koristeći bilo koji od općeprihvaćenih skupova formata:

  1. Kao niz u formatu "GGGG-MM-DD HH:MM:SS" ili "GG-MM-DD HH:MM:SS". Dopuštena je opuštena sintaksa: bilo koji interpunkcijski znak može se koristiti kao graničnik između datuma i vremena. Na primjer, "98-12-31 11:30:45", "98.12.31 11+30+45", "98/12/31 11*30*45" i "98012031 11L30L45" su ekvivalentni.
  2. Kao niz u formatu "GGGG-MM-DD" ili "GGG-MM-DD". Dopuštena je i opuštena sintaksa. Na primjer, ekvivalent sljedeće vrijednosti: "98-12-31", "98.12.31", "98/12/31" i "98012031".
  3. Kao niz bez graničnika u formatu "GGGGMMDDHHMMSS" ili "GGMMDDDHHMMSS", pod pretpostavkom da niz ima smisla kao datum. Na primjer, "19970523091528" i "970523091528" tumače se kao "1997-0 5-23 09:15:28", ali "971122129015" je netočan (jer ima besmislenu vrijednost minuta) i postaje "0000-00-00 00:00": 00".
  4. Kao nerazgraničeni niz u formatu "GGGGMMMDD" ili TGMMDD", pod pretpostavkom da niz ima smisla kao datum. Na primjer, "19970523" i "980523" tumače se kao "1997-05-23", ali "971332" je netočno ( kriva vrijednost mjesec i dan) i postaje "0000-00-00".
  5. Kao broj u formatu GGGGMMDDDHHMMSS ili GGMMDDDHHMMSS, pod pretpostavkom da broj ima smisla kao datum. Na primjer, 19830905132800 i 830905132800 tumače se kao "1983-09-05 13:28:00".
  6. Kao broj u formatu GGGGMMDD ili GGMMDD, pod pretpostavkom da broj ima smisla kao datum. Na primjer, 19830905 i 830905 tumače se kao "1983-09-05".
  7. Kao rezultat funkcije koja vraća vrijednost prihvatljivu u kontekstu DATETIME, DATE ili TIMESTAMP, kao što je NOW() ili CURRENT_DATE.

Nevažeće vrijednosti DATETIME, DATE ili TIMESTAMP pretvaraju se u nulte vrijednosti odgovarajućeg tipa ("0000-00-00 00:00:00", "0000-00-00" ili 0000000000000000).
Za vrijednosti navedene kao niz koji uključuje razdjelnik datuma, nema potrebe za navođenjem dvije znamenke za mjesec ili dan koje su manje od 10. "1976-6-9" je isto što i "1976-06-09" . Isto tako, za vrijednosti navedene kao niz koji uključuje razdjelnik vremena, ne morate navesti dvije znamenke za sate, minute i sekunde koje su manje od 10. "1979-10-30 1:2:3" je isto kao ono "1979-10-30 01:02:03".


Vrijednosti navedene kao broj moraju imati 6, 8, 12 ili 14 znamenki. Ako broj ima 8 ili 14 znamenki, pretpostavlja se da predstavlja vrijednost u formatu GGGGMMDD ili GGGGMMDDDHHMMSS i da je godina navedena u četiri znamenke. Ako je broj duljine 6 ili 12, pretpostavlja se da se navodi vrijednost u formatu GGMMDD ili GGMMDDDHHMMSS, a godina je navedena u dvije znamenke. Brojevi čije se duljine razlikuju od 6, 8, 12 i 14 dopunjeni su vodećim nulama do najbližeg broja znamenki u navedenom nizu.

Vrijednosti navedene kao nerazgraničeni niz tumače se pomoću njihove duljine kao što je gore opisano. Ako niz ima 8 ili 14 znakova, pretpostavlja se da je godina u 4-znamenkastom formatu. Inače, pretpostavlja se da je godina dana s prve dvije znamenke. Niz se tumači s lijeva na desno kako bi se izdvojile vrijednosti godine, mjeseca, dana, sati, minuta i sekundi. To znači da ne biste trebali koristiti retke kraće od 6 znakova. Na primjer, ako navedete "9903" što znači ožujak 1999., vidjet ćete da će MySQL umetnuti nulti datum u tablicu. To se događa jer su vrijednosti godine i mjeseca 99 i 03, ali dio dana potpuno nedostaje, što znači da ova vrijednost ne postavlja točan datum. Međutim, od MySQL 3.23, možete eksplicitno odrediti nulta vrijednost mjesec ili dan. Na primjer, možete navesti "990300" da biste u tablicu umetnuli vrijednost "1999-03-00".
Unutar određenih ograničenja, možete dodijeliti vrijednosti jedne vrste objektima druge vrste. Međutim, moguća su određena izobličenja s gubitkom informacija:

  1. Ako dodijelite vrijednost tipa DATE objektu tipa DATETIME ili TIMESTAMP, pretpostavlja se da je vremenski dio vrijednosti "00:00:00" jer vrijednosti DATE ne sadrže podatke o vremenu.
  2. Ako objektu tipa DATE dodijelite vrijednost tipa DATETIME ili tiMesTAMP, gubi se vremenski dio vrijednosti jer ga DATE ne može uključiti.
  3. Zapamtite, iako se vrijednosti DATETIME, DATE i TIMESTAMP mogu specificirati pomoću istog skupa formata, njihovi važeći rasponi se razlikuju. Na primjer, vrijednosti TIMESTAMP-a ne mogu biti ranije od 1970. niti kasnije od 2037. godine. To znači da je datum poput "1968-01-10", koji je savršeno valjan kao vrijednost DATETIME ili DATE, netočan kao TIMESTAMP i bit će pretvoren u 0 kada se dodijeli takvom objektu.

Također biste trebali biti svjesni nekih zamki prilikom navođenja datumskih vrijednosti:

  1. Opušteni format vrijednosti danih kao nizovi može dovesti u zabludu. Na primjer, vrijednost poput "10:11:12" može izgledati kao vrijeme jer koristi razdjelnik ":", ali ako se koristi u kontekstu datuma, protumačit će se kao "2010-11-12". U isto vrijeme vrijednost "10:45:15"
    bit će pretvoren u "0000-00-00" jer "45" nije važeći mjesec.
  2. MySQL poslužitelj izvodi samo osnovnu provjeru valjanosti datuma: rasponi godina, mjeseca i dana su od 1000 do 9999, od 00 do 12, odnosno od 00 do 31. Svi datumi koji sadrže dijelove izvan ovih raspona podliježu konverziji u " 0000-00". -00". Imajte na umu da vam ovo omogućuje pohranjivanje nevažećih datuma poput "2002-04-31". Da biste bili sigurni da je datum točan, provjerite unutar aplikacije.
  • Datumi koji sadrže dvoznamenkastu godinu dvosmisleni su jer je stoljeće nepoznato. MySQL tumači dvoznamenkaste godine na sljedeći način: * Godina u rasponu 00-69 pretvara se u 2000-2069.
  • Godina u rasponu 70-99 pretvara se u 1970-1999.
TIMESTAMP svojstva u MySQL verzijama starijim od 4.1
TIMESTAMP je tip stupca koji se može koristiti za automatsko označavanje trenutnog datuma i vremena prilikom izvođenja operacije UPDATE ili INSERT. Ako u tablici postoji nekoliko stupaca TIMESTAMP, automatski se ažurira samo prvi.
Prvi stupac TIMESTAMP u tablici automatski se ažurira kada se dogodi jedan od sljedećih uvjeta:
  1. Kada mu se izričito dodijeli vrijednost NULL.
  2. Stupac nije eksplicitno naveden u INSERT ili LOAD DATA INFILE izrazu.
  3. Stupac nije eksplicitno naveden u naredbi UPDATE, ali je vrijednost nekog drugog stupca promijenjena. Izjava UPDATE koja postavlja stupac na istu vrijednost koju je prethodno imao ne ažurira stupac TIMESTAMP. Ako dodijelite staru vrijednost, MySQL je ignorira zbog učinkovitosti.

Stupci TIMESTAMP također se mogu ažurirati s trenutnim datumom i vremenom ako su eksplicitno postavljeni na željenu vrijednost. Ovo vrijedi čak i za prvi stupac TIMESTAMP. Ovo svojstvo možete koristiti, na primjer, ako želite postaviti vrijednost stupca na trenutni datum i vrijeme prilikom kreiranja retka, ali ga nemojte mijenjati pri sljedećim ažuriranjima retka:

  1. Neka MySQL postavi vrijednost stupca kada kreira red. Ovo ga inicijalizira s trenutnom vrijednošću datuma i vremena.
  2. Prilikom izvođenja naknadnih ažuriranja drugih stupaca retka, postavite stupac TIMESTAMP na njegovu trenutnu vrijednost:

AŽURIRATI naziv_tablice
POSTAVITE stupac_ imes tamp- stupac_Ytestmark, other_column1 = nova_vrijednost1, other_column2= novi_prigovor2, ...
Drugi način za održavanje stupca koji bilježi vrijeme stvaranja retka je korištenje stupca DATETIME koji se inicijalizira na NOW() kada se red kreira i nakon toga se ne mijenja.
Vrijednosti TIMESTAMP-a mogu se kretati od početka 1970. do dijela 2037. s rezolucijom od jedne sekunde. Vrijednosti se prikazuju kao brojevi.
Format u kojem MySQL dohvaća i prikazuje TIMESTAMP vrijednosti ovisi o širini prikaza, kao što je prikazano u tablici 1. 4.3. Puni format TIMESTAMP dugačak je 14 bita, ali se stupci TIMESTAMP-a mogu definirati u kraćem formatu prikaza.

Tablica Ovisnost formata prikaza o širini

Svi stupci TIMESTAMP imaju istu veličinu pohrane, bez obzira na format prikaza. Najčešće korišteni formati su 6, 8, 12 i 14 znakova. Možete pitati prilagođena veličina prikaz prilikom izrade tablice, ali vrijednosti 0 i veće od 14 pretvaraju se u 14. Neparne vrijednosti od 1 do 13 pretvaraju se u najbliži parni broj.
Stupci TIMESTAMP pohranjuju važeće vrijednosti koristeći punu preciznost s kojom su navedene, bez obzira na širinu prikaza. Međutim, postoje neka ograničenja povezana s ovim:

  1. Uvijek biste trebali navesti godinu, mjesec i dan, čak i ako je stupac deklariran kao TIMESTAMP(4) ili TIMESTAMP(2). U suprotnom, vrijednost se smatra netočnom i pohranjuje se na 0.
  2. Ako koristite ALTER tablica za proširenje stupca TIMESTAMP, informacije koje su prethodno bile skrivene bit će istaknute.
  3. Isto tako, kada suzite stupac TIMESTAMP, informacije se ne gube, osim u smislu da će biti manje informacija nego prije.
  4. Iako su stupci TIMESTAMP pohranjeni s punom preciznošću, jedina funkcija koja radi s punom količinom informacija pohranjenih u njima je UNIX_TIMESTAMP(). Sve ostale funkcije rade na formatiranoj ekstrahiranoj vrijednosti. To znači da ne možete koristiti funkciju poput HOUR() ili SECOND() osim ako odgovarajući dio nije uključen u formatiranu vrijednost stupca. Na primjer, HH dio stupca TIMESTAMP neće biti prikazan osim ako njegova širina prikaza nije najmanje 10, tako da će primjena HOURO na kraće vrijednosti TIMESTAMP proizvesti besmislen rezultat.
Svojstva TIMESTAMP u MySQL verziji 4.1 i novijim
Počevši od MySQL 4.1, svojstva TIMESTAMP razlikuju se od onih u prethodnim izdanjima: stupci TIMESTAMP prikazuju se u istom formatu kao i stupci DATETIME.
  • Širina prikaza više nije podržana kao što je prethodno opisano. Drugim riječima, više ne možete koristiti TIMESTAMP(4) ili TIMESTAMP(2). Osim toga, ako MySQL poslužitelj pokrenut u MAXDB modu, tip TIMESTAMP je identičan datumu i vremenu. To jest, ako poslužitelj radi u MAXDB načinu rada u vrijeme kada je tablica kreirana, svi stupci TIMESTAMP kreiraju se kao DATETIME. Kao rezultat toga, ovi stupci koriste format prikaza DATETIME, imaju isti raspon valjanih vrijednosti i nemaju automatsko ažuriranje ne događa se.
U MAXDB načinu rada, MySQL poslužitelj se može pokrenuti počevši od verzije 4.1.1. Kako biste omogućili ovaj način rada, navedite opciju -sql-mode=MAXDB prilikom pokretanja poslužitelja ili postavite vrijednost globalne varijable sqljnode tijekom izvođenja:
mysql SET GLOBAL sql_mode=MAXDB;
Klijent može prisiliti poslužitelj da radi u MAXDB modu za vlastitu sesiju pomoću naredbe:
mysql SET SESSION sql_mode=MAXDB;

U početku kratak opis svaka vrsta:

  • TIMESTAMP - vrsta podataka za pohranjivanje datuma i vremena. Podaci se pohranjuju kao broj sekundi koji su prošli od početka "Unix ere". Raspon vrijednosti: 1970-01-01 00:00:00 - 2038-12-31 00:00:00. Zauzima 4 bajta.
  • GODINA - tip podataka za pohranu godine. Raspon vrijednosti: 1901 - 2155. Zauzima 1 bajt.
  • DATE je vrsta podataka za pohranjivanje datuma. Raspon vrijednosti: 1000-01-01 - 9999-12-31. Zauzima 3 bajta.
  • TIME je vrsta podataka za pohranu vremena. Raspon vrijednosti: −828:59:59 - 828:59:59. Zauzima 3 bajta.
  • DATETIME je tip podataka za pohranjivanje datuma i vremena. Raspon vrijednosti: 1000-01-01 00:00:00 - 9999-12-31 00:00:00. Zauzima 8 bajtova.

Napomena domaćici. Zanimljivo je da većina programera vjeruje da je koncept "vremenske oznake" Unix vrijeme. Zapravo, vremenski žig je oznaka koja je niz znakova koji označavaju datum i/ili vrijeme kada se određeni događaj dogodio. A “Unix vrijeme” (Unix vrijeme) ili POSIX vrijeme je broj sekundi koji je prošao od ponoći 1. siječnja 1970. UTC. Koncept vremenske oznake je širi od Unix vremena.

Nakon analize opisa gore navedenih vrsta, možete izvući gotovo sve zaključke o prednostima i nedostacima određenih vrsta. Sve je vrlo jednostavno i očito.

Ali prije nego što govorim o upotrebi ovih tipova, želim napomenuti da se u praksi često koristi drugi tip za pohranu datuma i vremena: cjelobrojna vrijednost (za pohranjivanje datuma - INT (4 bajta), datum i vrijeme - BIGINT (8 bajtova)). Razlika u korištenju cjelobrojni tipovi od DATE i DATETIME samo zato što se podaci ne formatiraju tijekom ispisa, au izračunima s datumima i vremenima, cijeli brojevi moraju se pretvoriti u odgovarajući tip kalendara. Osim toga, ne postoji provjera valjanosti prikazane vrijednosti prije spremanja. Mogućnosti sortiranja su zadržane. Stoga ima smisla koristiti INT i BIGINT u istim slučajevima kao DATE i DATETIME, kako bi se maksimizirala prenosivost i neovisnost o DBMS-u. Ne vidim nikakve druge prednosti; ako ih ima, predlažem da ih navedete u komentarima.

Korištenje tipova podataka kalendara u MySQL-u

Počnimo s najjednostavnijim - tipom GODINA. Njegova jedina prednost je mala veličina - samo 1 bajt. Ali zbog toga postoji strogo ograničenje raspona valjanih vrijednosti (vrsta može pohraniti samo 255 različita značenja). Teško mi je zamisliti praktičnu situaciju u kojoj bi se željelo pohraniti godine striktno u rasponu od 1901. do 2155. Dodatno, tip SMALLINT (2 bajta) daje raspon koji je u većini situacija dovoljan za pohranu godine. A spremanje 1 bajta po retku u tablici baze podataka nema smisla u naše vrijeme.

Vrste DATUM I DATETIME mogu se spojiti u jednu grupu. Oni pohranjuju datum ili datum i vrijeme sa sasvim širok raspon prihvatljive vrijednosti, neovisno o vremenskoj zoni postavljenoj na poslužitelju. Njihova uporaba svakako ima praktičnog smisla. Ali ako želite pohraniti datume za povijesne događaje koji sežu nakon naše ere, morat ćete odabrati druge vrste podataka. Ove su vrste idealne za pohranjivanje datuma za određene događaje koji potencijalno izlaze iz raspona tipa TIMESTAMP (rođendani, datumi izdavanja proizvoda, predsjednički izbori, lansiranja svemirskih raketa itd.). Jedna stvar koju treba imati na umu kada koristite ove vrste je važna nijansa, ali o tome više u nastavku.

Tip VRIJEME može se koristiti za pohranjivanje vremenskog razdoblja kada nije potrebna točnost manja od 1 sekunde i vremenskih razdoblja kraćih od 829 sati. Ovdje se nema više što dodati.

Najzanimljivija vrsta ostaje - TIMESTAMP. Treba ga razmotriti u usporedbi s DATE i DATETIME: TIMESTAMP je također dizajniran za pohranjivanje datuma i/ili vremena pojave određenih događaja. Važna razlika između njih je u rasponima vrijednosti: očito, TIMESTAMP nije prikladan za pohranjivanje povijesnih događaja (čak ni poput rođendana), ali je izvrstan za pohranjivanje trenutnih (zapisivanje, datumi objavljivanja članaka, dodavanje proizvoda, narudžbe) i nadolazeći u doglednoj budućnosti budući događaji (izdanja novih verzija, kalendari i planeri, itd.).

Glavna pogodnost korištenja tipa TIMESTAMP je da za stupce ovog tipa u tablicama možete postaviti zadanu vrijednost u obliku zamjene trenutnog vremena, kao i postavljanje trenutnog vremena prilikom ažuriranja zapisa. Ako trebate ove značajke, postoji 99% šanse da je TIMESTAMP upravo ono što vam treba. (Pogledajte priručnik kako to učiniti.)

Nemojte se bojati da će vaš softver prestati raditi kako se približavamo 2038. Prvo, prije tog vremena, vaš softver će se najvjerojatnije jednostavno prestati koristiti (posebno verzije koje se sada pišu). Drugo, kako se ovaj datum približava, MySQL programeri će sigurno smisliti nešto za očuvanje funkcionalnosti vašeg softvera. Sve će se riješiti kao i problem Y2K.

Dakle, tip TIMESTAMP koristimo za pohranjivanje datuma i vremena događaja našeg vremena, a DATETIME i DATE za pohranjivanje datuma i vremena povijesnih događaja ili događaja duboke budućnosti.

Rasponi vrijednosti su važna razlika između tipova TIMESTAMP, DATETIME i DATE, ali ne i glavna stvar. Glavni taj TIMESTAMP pohranjuje vrijednost u UTC. Prilikom pohranjivanja vrijednosti, ona se prevodi iz trenutne vremenske zone u UTC, a prilikom čitanja, prevodi se iz trenutne vremenske zone iz UTC. DATETIME i DATE uvijek pohranjuju i prikazuju isto vrijeme, bez obzira na vremenske zone.

Postavljene su vremenske zone MySQL DBMS globalno ili za trenutni priključak.Potonje se može koristiti za osiguranje rada različite korisnike u različitim vremenskim zonama na razini DBMS-a. Sve vremenske vrijednosti će biti fizički pohranjene u UTC, a primljene od klijenta i dane klijentu - u vrijednostima njegove vremenske zone. Ali samo kada koristite tip podataka TIMESTAMP. DATE i DATETIME uvijek primaju, pohranjuju i vraćaju istu vrijednost.

Funkcija NOW() i njezini sinonimi vraćaju vrijednost vremena u trenutnoj vremenskoj zoni korisnika.

S obzirom na sve ove okolnosti, morate biti izuzetno oprezni kada mijenjate vremensku zonu unutar veze s poslužiteljem i koristite tipove DATE i DATETIME. Ako trebate pohraniti datum (na primjer, datum rođenja), tada neće biti problema. Datum rođenja je isti u bilo kojoj zoni. one. ako ste rođeni 1. siječnja u 0:00 UTC/GMT+0, onda ovo Ne znači da će ti u Americi slaviti rođendan 31. prosinca. Ali ako se odlučite za pohranu vrijeme događaja u stupcu DATETIME, tada jednostavno neće biti moguće raditi s korisničkim vremenskim zonama na razini DBMS-a. Dopustite mi da objasnim na primjeru:

Korisnik X radi u zoni UTC/GMT+2, Y - u zoni UTC/GMT+3. Za konekcije korisnika na MySQL postavlja se odgovarajuća (svaka ima svoju) vremenska zona. Korisnik objavi poruku na forumu, zanima nas datum kada je poruka napisana.

Opcija 1: DATETIME. Korisnik X piše poruku u 14:00 UTC/GMT+2. Vrijednost u polju "datum" poruke zamijenjena je rezultatom izvršavanja funkcije NOW() - 14:00. Korisnik Y čita vrijeme kada je poruka napisana i vidi isto 14:00. Ali njegove postavke su postavljene na UTC/GMT+3 i on misli da je poruka napisana ne sada, nego prije sat vremena.

Opcija 2: TIMESTAMP. Korisnik X piše poruku u 14:00 UTC/GMT+2. Polje "datum" sadrži rezultat izvršavanja funkcije NOW() - in u ovom slučaju- 12:00 UTC/GMT+0. KorisnikY čita vrijeme kada je poruka napisana i prima (UTC/GMT+3)(12:00 UTC/GMT+0) = 15:00 UTC/GMT+3. Sve ispadne upravo onako kako želimo. I što je najvažnije, izuzetno je praktičan za korištenje: da biste podržali prilagođene vremenske zone, ne morate pisati kod za pretvorbu vremena.

Mogućnosti zamjene trenutnog vremena i rada s vremenskim zonama u tipu TIMESTAMP su toliko moćne da ako trebate pohraniti datum bez vremena u određeni dnevnik, ipak biste trebali koristiti TIMESTAMP umjesto DATE, bez spremanja 1 bajta razlike između njih. U tom slučaju jednostavno zanemarite "00:00:00".

Ako ne možete koristiti TIMESTAMP zbog relativno malog raspona njegovih vrijednosti (obično 1-2 slučaja naspram 10-15 u bazi podataka stranice), morat ćete koristiti DATETIME i pažljivo prilagoditi njegove vrijednosti na pravim mjestima ( tj. kada upisujete u ovo polje, pretvorite datum u UTC, a kada čitate - u vrijeme u zoni korisnika za čitanje). Ako spremate samo datum, onda vjerojatno nije važno koju vremensku zonu imate: Nova godina Svi slave 1. siječnja po lokalnom vremenu, ovdje ne treba ništa prevoditi.

Svrha ovog članka je objasniti specifičnosti rada s tipovima DATETIME u SQL poslužitelj, uključujući uobičajene zablude i opće preporuke da ih prevlada. Zahvaljujući Franku Kalisu, ovaj je članak preveden na njemački.

Hvala:

Želio bih zahvaliti sljedećim ljudima na njihovim vrijednim prijedlozima i doprinosima ovom članku: Steve Kass, Aaron Bertrand, Jacco Schalkwijk, Klaus Oberdalhoff, Hugo Kornelis, Dan Guzman i Erland Sommarskog.

Verzije SQL Servera

Ovaj se članak odnosi na SQL Server 7.0, 2000, 2005 i 2008 osim ako nije drugačije navedeno.

Vrste datuma i vremena u SQL Serveru

Prije SQL Servera 2008, SQL Server je imao dvije vrste podataka za rukovanje datumom i vremenom. Budući da ćemo u ovom članku vrlo često spominjati ove vrste, uvest ćemo kraticu za svaku vrstu u dvije tablice u nastavku (stupac SC):

Ime

Min. značenje

Maks. značenje

Točnost

Iskorištena memorija

mali datumvrijeme sdt 1900-01-01 00:00:00 2079-06-06 23:59:00 minuta 4 bajta
datumvrijeme dt 1753-01-01 00:00:00.000 9999-12-31 23:59:59.997 3,33 ms 8 bajtova

Imajte na umu da ovdje ne postoji tip podataka koji sadrži samo datum ili samo vrijeme. Oba gornja tipa podataka sastoje se od dijelova/segmenata kao što su datum i vrijeme.

Ako navedete samo datumski dio, SQL Server će pohraniti vrijeme kao 00:00:00.000.
A ako postavite vrijednost samo na vrijeme, SQL Server će pohraniti datum kao 01.01.1900.
Ovo je vrlo važno. Pročitaj ponovno.

ODABERI CAST ('20041223' AS datumvrijeme )

———————–
2004-12-23 00:00:00.000

ODABERI CAST (’14:23:58′ AS datumvrijeme )

———————–
1900-01-01 14:23:58.000

S pojavom SQL Servera 2008, uvedeno je nekoliko novih tipova podataka povezanih s vrijednostima datuma i vremena:

Ime

Min. značenje

Maks. značenje

Točnost

Iskorištena memorija

datumvrijeme2 dt2 0001-01-01 00:00:00.0000000 9999-12-31 23:59:59.9999999 100 ns 6-8 bajtova
datum d 0001-01-01 9999-12-31 dan 3 bajta
vrijeme t 00:00:00.0000000 23:59:59.9999999 100 ns 3-5 bajtova
datetimeoffset dto 0001-01-01 00:00:00.0000000 9999-12-31 23:59:59.9999999 100 ns 8-10 bajtova
  • Kao što vidite, konačno smo dobili tipove podataka koji sadrže samo datum ( datum) i samo za vrijeme ( vrijeme).
  • Datumvrijeme2 ovo je "bolje DATETIME" iz više razloga i ne zauzima puno više memorije od datumvrijeme a potencijalno još manje!
  • Za novi tip koji uključuje vremensku vrijednost, možete navesti "preciznost frakcijskih sekundi" određivanjem redoslijeda znamenki u sekundama nakon decimalne točke koja će se koristiti. Dakle, time(3) može pohraniti vrijednosti poput 14:23:12.567, koje kada se unesu kao 14:23:12:5677 zaokružuju se na 14:23:12:568.
  • Novi tip datetimeoffset sadrži dio pomaka lokalne vremenske zone.

Formati datuma i vremena

Uobičajena zabluda je da SQL Server pohranjuje ove vrste podataka u nekom specifičnom čitljivom formatu. Ovo nije u redu. SQL Server pohranjuje takve vrijednosti u svom internom formatu (na primjer, dva cijela broja za datumvrijeme I mali datumvrijeme). Uz to, kada koristite T-SQL za postavljanje vrijednosti (na primjer u naredbi INSERT), izražavate je kao tekstualni niz. Postoje i pravila za tumačenje od strane SQL Servera raznih formata nizovi datuma. Ali imajte na umu da SQL Server ni u kojem slučaju neće zapamtiti ovaj format.

Formati unosa za datum i vrijeme

Ima ih mnogo dostupnih formata za pretvaranje vrijednosti u datum/vrijeme/datumvrijeme. Neki od njih su “bolji” od drugih, a kasnije ćete shvatiti zašto “bolji”. Važno je napomenuti da su svi ovi formati primjenjivi za sve vrste. Dakle, čak je i format "samo vrijeme" primjenjiv za tip "samo datum", itd. (Ovaj članak zanemaruje dio pomaka lokalne vremenske zone, koji se koristi samo u vrsti podataka datetimeoffset– više o čemu u Books Online.)

Ime

Format

SET DATEFORMAT ovisnost

SET LANGUAGE ovisnost

Jezična neutralnost

Nerazdvojeno u ‘19980223 14:23:05’ Ne Ne za svakoga
Odvojeni s '23.02.1998. 14:23:05' za svakoga za svakoga Ne
ANSI SQL ansisql ‘1998-12-23 14:23:05’ sdt , dt sdt , dt ne za sdt I dt
Abecedno a '23. veljače 1998. 14:23:05' Ne za sve (ime mjeseca) Ne
ODBC datum i vrijeme odt (ts ‘1998-02-23 14:23:05’) Ne Ne za svakoga
ODBC datum od (d '1998-02-23') Ne Ne za svakoga
ODBC vrijeme ot (t ’14:23:05′) Ne Ne za svakoga
ISO 8601 iso '1998-02-23T14:23:05' Ne Ne za svakoga
Vrijeme t '14:23:05'
'14:23:05'
Ne Ne za svakoga
  • Imajte na umu da ANSI SQL stvarno samo poseban slučaj razgraničeni format Odvojeni(tzv. "digitalni"), koristeći crticu (-), kosu crtu (/) i točku (.) kao razdjelnike. No, budući da je ovo jedini format definiran u ANSI SQL standardu, po mišljenju autora vrijedi ga spomenuti kao poseban slučaj.
  • Većina formata dopušta vam da uklonite dio s datumom i/ili vremenom, a u nekim slučajevima to može izgledati pomalo... čudno. Čini se nerazumnim navesti, na primjer, '2008-08-25' kao vrstu vremena ( vrijeme), ali krajnji rezultat je isti kao da ne postavite vrijednosti u nizu datumvrijeme. Razmotrite u nastavku:
    ODABERI CAST (KAO vrijeme )
    ODABERI CAST (‘2008-08-25’ AS vrijeme )

    Oba upita daju isti rezultat (vrijeme 00:00:00).
  • ODBC formati ( ODBC datum i vrijeme, ODBC datum, ODBC vrijeme) razlikuju se po tome što imaju token (literal_type, t, d ili ts) koji mora biti ispravno postavljen ovisno o tome dobivate li datum i vrijeme, samo datum ili samo vrijeme.
  • Za primjenu formata ISO 8601 potreban je segment datuma i vremena.
  • SET DATEFORMAT nasljeđuje svoje postavke od SET LANGUAGE (ali eksplicitni SET DATEFORMAT nadjačava kasniji SET LANGUAGE). Zadane postavke jezika postavljene su za svaki jezik koji se koristi prilikom unosa prijave. Zadani jezik za prijavu postavlja se pomoću sp_configure.
  • Pravila koja se odnose na oblikovanje dijela datuma i nove vrste mogu biti zbunjujuća. Microsoft je predan datira nove relevantne vrste podataka ( datum, datetime2 i datetimeoffset) bio je manje ovisan o postavkama i još više usklađen sa zahtjevima ANSI SQL. I kao rezultat toga, novi jezično neutralni tipovi za isticanje komponenti datuma i vremena sve dok je godina prva. SQL poslužitelj potrebno je odrediti da je ovaj dio godina, pa su stoga potrebna 4 mjesta koja čine godinu (gggg, ne gg). Ako je tako, tada će se niz prvo protumačiti kao godina, zatim mjesec i na kraju dan - bez obzira na FORMAT DATUMA ili jezične postavke. Ako je mjesec naveden prvi, zatim DATEFORMAT i jezične postavke bit će "promatrano":
    POSTAVITE JEZIK Britanski – koristi dmy
    IĆI
    ODABERI CAST (’02-23-1998 14:23:05′ KAO datum ) –Pogreška
    IĆI
    ODABERI CAST (‘2/23/1998 14:23:05’ KAO datum ) –Pogreška
    IĆI
    ODABERI CAST (‘1998-02-23 14:23:05’ KAO datum ) -U redu
    IĆI
    ODABERI CAST (‘1998.02.23 14:23:05’ KAO datum ) -U redu
    IĆI
    ODABERI CAST (‘1998/02/23 14:23:05’ KAO datum) -U redu
    IĆI
    Prvi
    dva upita su netočna jer godina nije na prvom mjestu (i nema 23 mjeseca u 1998). Nema pogrešaka u sljedeća tri upita jer su zahtjevi ispunjeni i godina je navedena prva (a mi koristimo jedan od novih stilova vrste datuma). Izuzetno transparentno, zar ne? 🙂

Opisi dostupnih formata dostupni su u Books Online, tako da nema smisla ulaziti u detalje za svaki format.

Developing Time-Based Database Applications in SQL Richard T. Snodgrass: sadrži mnogo informacija o predstavljanju vremenskih podataka u modelu podataka. I, naravno, moguće je koristiti ove dodatne (povijesne) podatke u svom SQL upiti. Ova knjiga je izašla iz tiska, ali na Richardovoj službenoj web stranici (www.cs.arizona.edu/people/rts), možete je besplatno preuzeti u PDF formatu.

Prijevod: Vinchik Evgeniy

Ne preporučam korištenje ni polje DATETIME, niti TIMESTAMP. Ako želite predstaviti određeni dan općenito (poput rođendana), upotrijebite vrstu DATUM, ali ako ste precizniji, vjerojatno ste zainteresirani za snimanje stvarnog trenutka, a ne jedinice vremena (dan, tjedan, mjesec, godina). Umjesto korištenja DATETIME ili TIMESTAMP, koristite BIGINT i samo pohranite broj milisekundi od epohe (System.currentTimeMillis() ako koristite Javu). Ovo ima brojne prednosti:

  1. Izbjegavate zaključavanje dobavljača. Gotovo svaka baza podataka podržava cijele brojeve na relativno sličan način. Recimo da želite prijeći u drugu bazu podataka. Želite li brinuti o razlikama između MySQL DATETIME vrijednosti i kako ih Oracle određuje? Čak i među različitim MySQL verzije, TIMESTAMPS imaju različite razine točnost. Nedavno je MySQL podržavao milisekunde u vremenskim oznakama.
  2. Nema problema s vremenskom zonom. Od tada je ovdje bilo nekih pronicljivih komentara o tome što se događa s vremenskim zonama različite vrste podaci. Ali je li ovo opće znanje, a vaši će kolege to stalno učiti? S druge strane, prilično je teško miješati BigINT u java.util.Date. Korištenje BIGINT-a dovodi do brojnih problema s vremenskom zonom koji prolaze usput.
  3. Ne brinite o dometima ili točnosti. Ne morate se brinuti da će vas budući rasponi datuma skratiti (TIMESTAMP je samo 2038).
  4. Integracija alata treće strane. Korištenje cijelog broja je trivijalno za alate treće strane (kao što je EclipseLink) za interakciju s bazom podataka. Neće svaki alat treće strane imati isto razumijevanje "datetime" kao MySQL. Želite li pokušati otkriti u Hibernateu trebate li koristiti objekt java.sql.TimeStamp ili java.util.Date ako koristite ove prilagođene vrste podataka? Korištenje osnovne vrste podaci koriste alate treće strane trivijalan.

Ovaj problem je usko povezan s načinom na koji biste trebali pohraniti novčanu vrijednost (tj. 1,99 USD) u bazi podataka. Trebate li koristiti Decimal ili novac u bazi podataka, ili što je najgore, Double? Sve ove 3 opcije su užasne, zbog mnogih gore navedenih razloga. Rješenje je pohraniti vrijednost novca u centima koristeći BIGINT, a zatim pretvoriti cente u dolare kada prikažete vrijednost korisniku. Posao baze podataka je pohranjivanje podataka, a NE prikupljanje podataka. Svi ti otmjeni tipovi podataka koje vidite u bazama podataka (osobito Oracle) dodaju malo i vode vas na put do zaključavanja dobavljača.

2018-12-04T00:00Z

TIMESTAMP je 4 bajta s 8 bajtova za DATETIME.

Ali kao što je skronid rekao, ima donju granicu od 1970. Ovo je sjajno za sve što bi se moglo dogoditi u budućnosti ;)

2018-12-11T00:00Z

Glavna razlika je u tome što je DATETIME konstantan, dok TIMESTAMP ovisi o postavci time_zone.

Dakle, ovo je važno samo ako imate - ili biste u budućnosti mogli imati - sinkronizirane klastere u vremenskim zonama.

U više jednostavnim riječima: Ako imam bazu podataka u Australiji i napravim ispis te baze podataka kako bih sinkronizirao/popunio bazu podataka u Americi, tada će se TIMESTAMP ažurirati kako bi odražavao stvarnom vremenu događaja u novoj vremenskoj zoni, dok DATETIME i dalje odražava vrijeme događaja u vremenskoj zoni.

Izvrstan primjer DATETIME koji se koristi tamo gdje se trebao koristiti TIMESTAMP je Facebook, gdje njihovi poslužitelji nikada ne mogu biti sigurni što se dogodilo tijekom vremenskih zona. Jednom sam imao razgovor u kojem mi je vrijeme govorilo da odgovaram na poruke prije nego što je poruka zapravo poslana. (Ovo, naravno, također može biti uzrokovano netočnim prijevodom u vremenskoj zoni u softver za slanje poruka ako je vrijeme poslano i nije sinkronizirano).

2018-12-18T00:00Z

Uvijek koristim polja DATETIME za sve osim metapodataka retka (datum stvaranja ili izmjene).