Küsimus
Vastus (22.11.2024 15:23):
Deterministlik funktsioon tagastab samade argumentidega (sisendandmetega) alati samasuguse väärtuse. Mittedeterministlik funktsioon võib tagastada samade argumentidega erinevatel ajahetkedel erineva tulemuse. Mittedeterministlikud funktsioonid on näiteks CURRENT_DATE (tagastab hetke kuupäeva), CURRENT_TIMESTAMP (tagastab hetke kuupäeva ja kellaaja koos ajavööndiga) ja LOCALTIMESTAMP (tagastab hetke kuupäeva ja kellaaja ilma ajavööndita).
CHECK kitsendus on kujul CHECK(loogikaavaldis). Iga tabelisse lisatava rea korral peab selle loogikaavaldise väärtuse arvutamise tulemus olema TRUE või UNKNOWN (kui reas mõnes väljas väärtus puudub e on NULL).
Järgnevas tabeli loomise lauses:
- kitsendus chk_pakkumine_alguse_aeg on retrospektiivselt deterministlik
- Kui lisada tabelisse rida, mis lisamise hetkel vastas sellele kitsendusele, siis see rida vastab sellele kitsendusele ka tulevikus.
- kitsendus chk_pakkumine_lopu_aeg ei ole retrospektiivselt deterministlik
- Kui lisada tabelisse rida, mis lisamise hetkel vastas sellele kitsendusele, siis mingil hetkel tulevikus see rida enam sellele kitsendusele ei vasta. Nii tekib kahetsusväärne olukord, kus tabelis on andmed, mis ei ole kooskõlas tabelile defineeritud kitsendusega.
CREATE TABLE Pakkumine (pakkumine_id INTEGER NOT NULL,alguse_aeg DATE NOT NULL,lopu_aeg DATE NOT NULL,CONSTRAINT pk_pakkumine PRIMARY KEY (pakkumine_id),CONSTRAINT chk_pakkumine_alguse_aeg CHECK (alguse_aeg<=CURRENT_DATE),CONSTRAINT chk_pakkumine_lopu_aeg CHECK (lopu_aeg>=CURRENT_DATE));Eelnevalt viidatud SQL standardi lõik ütleb, et kitsendusi, mis pole retrospektiivselt deterministlikud, ei tohiks saada defineerida. Kui andmebaasisüsteem ei toeta omadust F672, “Retrospective check constraints”, siis ei peaks CHECK kitsendustes saama üldse CURRENT_DATE, CURRENT_TIMESTAMP ja LOCALTIMESTAMP kitsendusi kasutada.
Milline on tegelik olukord andmebaasisüsteemides? Kasutasin katsetamiseks keskkondi DB Fiddle, SQL Fiddle ja db<>fiddle.
Andmebaasisüsteemid jagunesid kaheks:
- CHECK kitsendustes ei saa üldse CURRENT_DATE, CURRENT_TIMESTAMP ja LOCALTIMESTAMP funktsioone kasutada (sulgudes veateade eelneva CREATE TABLE lause käivitamisel).
- MySQL 9 (Query Error: An expression of a check constraint 'chk_pakkumine_alguse_aeg' contains disallowed function: curdate.)
- MariaDB 10.7 (ERROR 1901 (HY000) at line 1: Function or expression 'curdate()' cannot be used in the CHECK clause of `chk_pakkumine_alguse_aeg`)
- Oracle 23ai (ORA-02436: date or system variable wrongly specified in CHECK constraint)
- IBM DB2 Developer-C 11.1 (SQL0546N The check constraint "CHK_PAKKUMINE_ALGUSE_AEG" is invalid.)
- CHECK kitsendustes saab kasutada CURRENT_DATE, CURRENT_TIMESTAMP ja LOCALTIMESTAMP funktsioone piiranguteta, st saab luua ka kitsendusi, mis ei ole retrospektiivselt deterministlikud.
- PostgreSQL 17
- SQLite 3.46
- MS SQL Server 2022 (CURRENT_DATE tuli asendada GETDATE())
- MS Access 2019 (CURRENT_DATE tuli asendada DATE())
- Firebird 4
- HSQLDB 1.8 (LibreOffice Base)
Süsteemides, mis lubavad kitsendusi, mis pole retrospektiivselt deterministlikud, tuleb olla kitsenduste defineerimisel ise tähelepanelik!