Databáze > Ostatní DB
SQLite a dátumy v tvare DateTime (FireDAC)
miroB:
V prípade dátumov typu DATETIME v SQLite+FireDAC, nastane menší problém pri použití takéhoto typu vo výraze.
(Ako reakcia na príspevky Stano Hruška a Delfin. Odkazy viď dolu.)
Majme tabuľku:
--- Kód: MySQL ---DROP TABLE if exists [demo];CREATE TABLE if not exists [demo] ( Datum DateTime );INSERT INTO [demo] ( Datum ) VALUES ( GETDATE() );Stĺpec definovaný v tabuľke ako DATETIME je v rámci SELECT prezentovaný očakávane. Prejaví sa správne aj vo výpise v dbGrid.
Akonáhle sa ale jedná o výraz, stratí sa informácia o rozšírenom type DATETIME
Miesto toho je typ zmenený na REAL/FLOAT. Teda na jeden zo základných typov SQLite.
Nie je možné použiť ani Accessor AsDateTime. Treba použiť Accessor Value, alebo AsFloat. Takto získanú hodnotu je ale možné rovno priradiť do premennej typu DateTime. K tomuto tvrdeniu viď príklad.
--- Kód: MySQL ---SELECT Datum, Datum + 1 AS Zajtra FROM [demo]Napríklad MS Access pre výraz Datum + 1 vráti samozrejme rovno správny typ dátum..
Podobne, keď sa vyrobí užívateľská funkcia, ktorá má vrátiť výsledok typu DateTime, pre SQLite vráti iba typ REAL.
Funkcia v SQLite nie je schopná vrátiť iný typ, než základný typ.
Preto nemá význam ani:
--- Kód: MySQL ---CAST( Datum + 1 AS DATE )Pre prípadné ďalsie uživateľské funkcie, ktoré by boli závislé na vstupe typu DATETIME alebo REAL (overload), teda nie je šanca.
Vyššie uvedené fakty sa samozrejme premietnu aj do výpisu v dbgride, kde výrazy nad typom dátum už nie sú dátum, ale float.
Ale to všetko sa dá obísť. Napríklad takto:
--- Kód: MySQL ---Datum + 1 AS [xy::DATETIME]Negatívom tohoto riešenia je, že TypeCast sa síce vykoná správne, ale pole sa nevolá xy, ako by sa dalo čakať, ale takto: 'xy::DATETIME' !!!
Takže sme vlastne stratili možnosť použitia nejakého prijateľného aliasu pre stĺpec.
Ešte horšie je, že Delphi sa interne tvári, že názov stĺpca je xy, rovnako aj vo výpise v dbGrid. Lenže interne je stĺpec označený aj s dvojbodkou a typom. Takže prípadný ďalší SELECT musí obsahovať komplet názov.
Pozitívne je, že všetky operácie nad dátumom, či double sa samozrejme stále vykonávajú správne.
Pretože DATETIME je skutočne double. Len chýba tá rozšírená info, pre výpisy a prípadné funkcie.
Tie "drobné" úpravy zostávajú teda na užívateľovi.
Teoretickým východiskom pre výpis do dbGrid, je napríklad vytvorenie dočasnej tabuľky so štruktúrou, kde sa vhodne nahradí REAL za DATETIME. Keď sa do takejto tabuľky nasype výsledok výrazu s dátumom v rámci SELECT, tak potom pri SELECT-e z tejto tabuľky bude zobrazenie dátumov v poriadku.
Dátum v tvare DATETIME je kompatibilný s MS Access, Delphi a s Excelom, resp. aj s Variant typu varDate.
Tento príspevok je reakciou na :
--- Citace: Stanislav Hruška 12-12-2017, 20:54:23 ---.. SQLite som raz skúšal, ale veľmi rýchlo som pohorel na dátumoch. Nestojí mi to zato. ..
--- Konce citace ---
a na:
--- Citace: Delfin 12-12-2017, 21:55:57 ---
--- Citace: mibainfo 12-12-2017, 21:43:24 ---Stano, myslim, ze datumy v SQLite nie su az taky problem.
Staci prepnut v Connection na datum typu DateTime a si ako v Delphi.
--- Konce citace ---
O zadnem problemu s datumy nevim. Co nastavujes v connection definition parametru DateTimeFormat je jen zpusob jakym se budou data do databaze ukladat. Accessorem AsDate(Time) zapisujes do parametru a ctes z poli Delphi typ TDate(Time) a je jedno jak jsou data o vrstvu niz ulozena. Kdyztak ho zkuste popsat v samostatnem vlakne nebo poslete odkaz na existujici... ;)
--- Konce citace ---
Daniel_Andrascik:
toto vlakno si uz asi videl: http://forum.delphi.cz/index.php/topic,15289.0.html
ja som v sqlite s datumami pracoval vzdy vo formate unixoveho casu, cize cele cislo vyjadrujuce pocet sekund od tusim 1970 ci tak nejako. Jednoznacne roky som takto v sqvlite pracoval a vyuzival som potom tieto integrovane funkcie sqlitu: https://sqlite.org/lang_datefunc.html. Je to mierne prace navyse, ale mal som to ciste a rychle... Sqlite nie je moc na pracu s datumami to prave orechove a ako som cital tvoj prispevok tak aj aj kadejake kaskaderske kusky FireDACu ktore by mohli pomoct asi nikdy nebudu stopercentne... Isiel by som od toho, zamotas sa.
miroB:
Dík, chápem. Aj ja mám trochu obavu, ale verím, že to zvládnem.
Zatiaľ som nenarazil na zásadný problém. Vŕtam sa v tom už dlho.
Príspevky o SQLite na tomto fóre snáď poznám už naspamäť.
Link v tvojom odkaze poznám veľmi dobre.
--- Citace: Daniel_Andrascik 15-12-2017, 17:02:32 ---toto vlakno si uz asi videl: http://forum.delphi.cz/index.php/topic,15289.0.html
--- Konce citace ---
Zdá sa mi však, že ide mimo záujmov, ktoré sledujem, pretože každý tu doteraz riešil nejakú verziu dátumov, okrem tej, ktorá je pre mňa zásadná. To je tvar DATETIME, teda vlastne DOUBLE.
Predpokladám, že je známe, ako krásne funguje:
Celé číslo je počet dní od 1.1. 1900 a každý ďalší deň je teda + 1.
Na to ani nie je treba funkcie. Snáď jedna jediná je dôležitá DateSerial( rok, mesiac, deň). Pričom je treba, aby mesiace a dni nemali limity. Takže DateSerial(2017,0,1), je napríklad 1.12.2016
Tak to funguje aj v Excel/Access.
Samozrejme funkcie Today a Now. No a matematický TRUNC, aby sa dal čas (TIME) odtrhnúť od DATETIME.
Čas je tiež geniálny, napríklad 0.5 znamená 12:00:00. Keď sa dosiahne jedna celá, je to už vlastne nový deň a čas začína prvou sekundou nového dňa: =1/24/60/60
potom už len zostáva funkcia Format, ktorá má podobné vlastnosti, ako FormatFloat v Delphi.
* Tvar TDATETIME našťastie veľmi dobre poznám.
* Neočakávam problémy, pretože v zásade vôbec nevadí, že SQLite ich uchováva ako double
* Je to vlastne double a matematika s dátumom a časom je geniálne jednoduchá
* Počítam s vlastnými funkciami pre dátumy. Ale nie je ich treba veľa. Už 5 je tu veľké číslo
* Potrebujem kompatibilitu s Excelom a Accessom. Tá s OLE a Delphi, nie je na škodu
* Tiež potrebujem výraznú jednoduchosť.
* Požiadavka na jednoduchosť tu možno mnohých zarazí, lebo databázy používate na riešenie globálnych úloh
* Moje riešenia sú skôr pre začiatočníkov. Nejaké strftime s jej obrovským rozsahom, či zložité výpočty, by ich prizabili.Ak by si mal ešte niečo na mysli, čo mi evidentne uniká, prosím povedz mi to presnejšie.
Ďakujem,
Miro
Daniel_Andrascik:
No ono uznavam ze pouzit format identicky s TDateTime usetri robotu a je to najprijemnejsie. Pracuje sa s nim pohodlne a vela funkcii naozaj netreba.
Ale bol by som opatrny s vyjadreniami ze matematika s takymto datumom je genialne jednoducha. To sa naozaj k strojovej matematike s realnymi cislami moc tvrdit nema. Mnozstvo problemov s presnostou, zaokruhlovanim a porovnavanim realnych cisiel je velmi dobre zname. Cize cislo 0.5 je z tohto pohladu 12:00:00.000 a cislo 0.500000001 je z pohladu ludskeho vnimania casu stale na milisekundu presnych 12:00:00.000. Ale s pohladu mikro alebo nanosekund to uz rovnaky cas nie je. A ak pouzijes nevhodne porovnanvacie funkcie tak na teba vypluvnu ze tieto datumi nie su rovnake, napriek tomu ze sa javia byt uplne rovnake. Vykon prace s realnymi cislami je tiez niekde uplne inde. Cize vyhodou unixackeho celociselneho "sekundoveho" casu je rychlost a jednoznacnost. Ale nevyhodou je ze nie je mozne jednoduchym sposobom pracovat s presnestou vacsou ako na sekundy. Ale to vacsinou vobec nevadi a vdaka tomu komparacie a triedenie je ovela rychlejsie bez rizika anomalii z oboru realnych cisel. Nastastie datovy typ double je dostatocne presny na potreby prace s casom. Ale ja uz som na problemy so zoukruhovanim a pripocitavanim "neviditelnych" fragmentov casu narazil a zrazu mi lietali hore dole sekundy a ja som nechapal ze preco.
Ako druhy potencionaly problem vidim v samotnej benevolentnosti SQLitu k datovym typom. Darmo ze ty mas navoleny stlpec typu real. Moze sa stat ze na jednom pocitaci budes zapisovat realne cisla s ciarkou na druhom s bodkou a problem bude na svete. Pokial sqlite pozna ze je to realne cislo tak ho tak aj ulozi, akonahle ho nepozna ulozi ho ako TEXT. To zatial nebude velky problem pokial budes s tym stale pracovat na rovnakom pc s rovnakym nastavenim narodneho prostredia. SQLite tie konverzie urobi a bude to fungovat. Ale potom sa moze stat ze prejdes z anglickeho windowsu na slovensky alebo naopak a mohla by ti vyletiet chyba ze hodnota v danom stlpci nie je hodnota REAL ale TEXT ktory on nevie previest na double cislo. Da sa to osetrit aby sa to nestalo, ale treba na to mysliet.
Takze chcel si pocut ci mozu existovat nejake zadrhele ak v databazach pouzivas typ real na ukladanie casu. Tak ako vidis hlavne v pripade sqlitu mozu. Pretom som radsej pouzival unixacky celociselny cas. Myslim ze ani viacere velke databazy nepouzivaju realne cislo na uchovavanie datumu a casu. Ale nebudem sa hadat, nie som zrovna najsilnejsi v databazach.
miroB:
Mas pravdu, s realnymi cislami je potencialny problem a nie jeden.
V tomto prostredi budem musiet mozno spravit funkciu na porovnanie celociselnych datumov, bez time, aby bola istota. A nielen tu. Cisla s bodkou a ciarkou o tom viem.
Budem to musiet este cele preskumat.
Dufam, ze sa bude dat spolahnut na deklaraciu typov v tabulke, takze tie cisla, ak bude problem osetrim.
Dakujem za namety.
Navigace
[0] Seznam témat
[#] Další strana
Přejít na plnou verzi