NULL, indeksi, surogātvērtības un citi zvēri

Šis pagaidām būs pēdējais raksts no rakstu sērijas par NULL speciālo vērtību SQL valodā. Iepriekšējos divi ir redzami šeit:

Šī raksta pirmā lielā daļa ir pārspriedumi un mani komentāri par to vai vajadzētu/nevajadzētu null izmantot, kas principā attiecas uz jebkuru DBVS. Rakstā otrajā pusē ir piemēri no Oracles parādot, kas notiek, ja mākslīgi uzspiež NOT NULL ierobežojumus.

NULL surogātaizstājēji

Tā kā vairums cilvēku baidās no lietām, ko viņi īsti nepazīst, un Null tāda reizēm mēdz būt, tad viens no paņēmieniem, kā tikt no Null vaļā ir tādas vērtības nepieļaut. Ir dzirdēts par stāstiem, kur, piemēram, noteiktā projektā tiek uzspiests absolūts ierobežojums, ka neviena kolona datubāzē nedrīkst atļaut Null vērtības. Citos projektos līdz tādam absurdam gluži nenonāk, bet vienalga mēdz šad tad šur tur Null aizstāt ar kādu citu surogātvērtību. Tad nu lūk paskatīsimies, kādi no tā var būt ieguvumi un kādi zaudējumi.

Galvenie argumenti, kāpēc Null vispār būtu jāaizstāj ar kaut ko citu parasti ir šādi:

  • Null strādā dīvaini un speciāli, mēs īsti nezinam kā tas strādā, bet gribam, lai tā apstrāde būtu tāda pati kā visu pārējo vērtību apstrāde. Zināmā mērā loģiska vēlme, nevar noliegt. Ja bizness operē ar tādu jēdzienu, kā nezināms vai nedefinēts vai kaut ko tamlīdzīgu, tad šī vērtība, protams, ir tikpat laba, kā jebkura cita. Tādā gadījumā droši vien ir klasifikators, kur vērtība nezināms ir kopā ar visām citām vērtībām un zināmā mērā datu ievadītāju stimulē izvēlēties tieši vērtību Nezināms, pa ko tad viņš ir arī atbildīgs, nevis vienkārši cilvēks aizmirsa lauku ievadīt. No otras puses jebkurā klasifikatorā vērtība Nezināms ļauj lietotājam gala rezultātā ievadīt visus klasificētos laukus ar šo vērtību un tad rodas jautājums, kam šāds ieraksts vispār ir vajadzīgs?
  • Negribam SQL teikumos izmanot IS (NOT) NULL konstrukcijas. Zināmā mērā sasaucās ar iepriekšējo argumentu, taču šai gadījumā mēs zinam, ka mums būtu šādas konstrukcijas jālieto, vienkārši slinkums 🙂
  • Null vērtības netiek indeksētas. Null vērtības neparādās parastajos b-koku indeksos, tā vismaz tas ir Oracle, SQL Server un MySQL. Tātad atlasot datus no tabulas, kur kāda kolona ir Null Jūs tiešā veidā indeksu uz šīs kolonas izmantot nevarēsiet.
  • Esam dzirdējuši mītus, ka NOT NULL vienmēr strādā ātrāk, aizņem mazāk vietas vai vēl kaut ko no šīs sērijas. Es negribu teikt, ka visi šādi izteikumi visām DBVS ir kļūdaini, tā droši vien nav, bet noteikti par tiem vajadzētu pārliecināties, jo arī oficiālā dokumentācija, diemžēl reizēm mēdz uzturēt šādus mītus spēkā, piemēru, skat šeit. Tātad, ja Jums nākas saskarties ar šādiem izteikumiem, tad vairumā gadījumu ir ļoti vienkārši izveidot mazu testa skriptiņu, kas salīdzina divas vai vairāk izmantojamās metodes, un pārbauda izteikumu. Tam ir vairākas priekšrocības:
  1. Primārais mērķis – Jūs noskaidrosiet, vai izteikums ir patiess tieši jūsu videi, jūsu DBVS versijai, jūsu operētājsistēmai, jūsu datora atmiņas, disku un pārējai konfigurācijai;
  2. Jūs uztrenēsieties veidot testa skriptus;
  3. Pēc tam, kad pāris reizes izrādīsies, ka izteikumi nav patiesi, jums radīsies veselīga skepse attiecībā pret to, kas rakstīts internetā, kas patiesībā ilgtermiņā, manuprāt, ir vislielākais ieguvums.
  • Protams, testu izveidē jāatceras dažas pamatlietas:
  1. Salīdzinājumus izdarīt pie vienādas datora noslodzes un censties maksimāli izolēt citus potenciālos iespaidus;
  2. Salīdzināt ābolus ar āboliem, nevis zirgāboliem, pie tam atrodiet mērījumus, uz kuriem var paļauties;
  3. Mērījumus izdarīt vairākas reizes, lai izslēgtu statistiskās kļūdas, iekešotas vai tieši otrādi neiekešotas vērtības u.c. lietas, kas tika viena mērījuma gadījumā var iespaidot rezultātu pavisam nepareizā virzienā.

Jau iepriekš gribu atgādināt, ka nākošie argumenti ne mazākā mērā neattiecas uz gadījumiem, kad tabula kolonai bizness pieprasa NOT NULL ierobežojumu, tieši otrādi es uzskatu, ka tas ir jānodrošina datu bāzē nevis, piemēram, tikai aplikācijas līdzekļiem. Tātad galvenie argumenti, kāpēc nevajag mākslīgi uzspiest NOT NULL ierobežojumus ir šādi:

  • Pastāv risks, ka kādreiz jūsu izvēlēto konstanti – Null aizstājēju patiesībā nāksies izmantot kādai reālai vērtībai. Septiņdesmitajos un astoņdesmitajos gados arī neviens nedomāja, ka reiz pienāks divtūkstošais gads un ar divciparu skaitļiem būs problēmas.
  • Jūs esat tikuši vaļā no IS (NOT) NULL rakstīšanas, bet tagad jums rodas citas problēmas. Ir jāuzmanās no minimālo, maksimālo vērtību atrašanas, jo visdrīzāk, ka kā NULL aizvietotāju Jūs būsiet izvēlējušies kādu ekstrēmu vērtību no viena vai otra gala, līdz ar to minimālā/maksimālā vērtība tieši vairs nederēs. Līdzīgi ir ar citām grupēšanas funkcijām – piemēram, SUM sāks skaitīt jūs konstantes, pieņemot, ka tās ir 0, avg vairs nerādīs tos datus, ko normāli rādītu (skat piemēru zemāk). Vislielākās šausmas un ārprāts man personīgi šai ziņā bija kādā projektā, kur arī visas ārējās atslēgas bija NOT NULL, pat tad, ja dabiski tām vērtība nevarēja būt, piemēram, personai neeksistē adrese. Tad, lai šādu situāciju apietu, tika izveidots falšs ieraksts ar identifikatoru -1, uz kuru rādīja visas tās ārējās atslēgas, kam patiesībā būtu bijis jābūt NULL. No uzturamības viedokļa tās bija šausmas un ārprāts, jo vienmēr lai ko arī darītu šīs rindas ar identifikatoru -1 nācās izkļaut, gan datu attēlošanā, gan atskaitēs, gan jebkur citur, Dabiski, ka cilvēki to aizmirsa un gala rezultātā problēmas radās nesalīdzināmi vairāk nekā tad, ja būtu šur tur jāpieraksta IS (NOT) NULL.
  • DBVS un visi citi cilvēki pazīst NULL, bet nepazīst jūsu surogātvērtības. Lai cik kādam nepatiktu Null, tā tomēr ir vērtība, kas visiem ir zināma. Tā ir zināma gan DBVS izstrādātājiem, gan programmētājiem, kas raksta SQL jebkurā DBVS. Tiklīdz kā Jūs ieviešat savu Null aizstājēju, tā Jūs radat jaunu nosacītu standartu, kas ir lietojams tikai un vienīgi Jūsu projektā un Jūsu konkrētajai datubāzei. Tā rezultātā šī Jūsu speciālā vērtība ir kā nepazīstams esperanto gan pašai DBVS, gan visiem pārējiem izstrādātājiem nākas pie tās pierast. Par to, kāpēc Jūsu izvēlētā Null vērtība var būt nepazīstams esperanto skat. konkrētu piemēru Oracle DBVS, par to kāpēc tā ir bīstama izstrādātājiem es jau rakstīju augstāk. Diemžēl arī šajā bloga rakstā autors nav bijis pazīstams ar Null vērtību specifiku, tagad to ir iepazinis un rezultātā spriežot pēc raksta ir kļuvis absolūts Null vērtību noliedzējs.

Tehniskas problēmas, kas var rasties mākslīgi uzspiežot NOT NULL ierobežojumus.

NULL un indeksi, surogātvērtības un indeksi

Kā jau tika teikts Null vērtības indeksā netiek rakstītas. Līdz ar to mēs varam izveidot unikālu ierobežojumu un Null vērtības tiek ignorētas. Šoreiz lietosim šādu tabulu:

Piemērs 1. Izmantojamā tabula.
SQL> CREATE TABLE personas (
  2    prs_id INTEGER NOT NULL,
  3    prs_vards VARCHAR2(40),
  4    prs_uzvards VARCHAR2(40),
  5    prs_personas_kods VARCHAR2(11),
  6    prs_alga NUMBER(10, 2)
  7  );

Izveidojam ierobežojumu, ka personas kodam ir jābūt unikālam:

SQL> ALTER TABLE personas ADD CONSTRAINT prs_pkd_uk
  2  UNIQUE (prs_personas_kods);
Table altered.

Rakstam iekšā jaunas personas ar nezināmiem personas kodiem:

Piemērs 2. Vairākas Null vērtības var rakstīt unikālajā indeksā.
SQL> INSERT INTO personas VALUES (
  2    1, 'JĀNIS', 'BĒRZIŅŠ', NULL, NULL);
1 row created.
SQL> INSERT INTO personas VALUES (
  2    2, 'ŽANIS', 'APSĪTIS', NULL, 250);
1 row created.

Kā redzams mums bez problēmām izdevās izveidot vairākus ierakstus ar personas kodiem, kuru vērtība ir Null. Tagad mēģinam, kas notiks, ja personas kodu vērtības būs definētas:

Piemērs 3. Vairākas definētas (NeNull) vērtības unikālajā indeksā rakstīt nevar.
SQL> INSERT INTO personas VALUES (
  2    3, 'ANNA', 'BĀRBALE', '12345678901', 180);
1 row created.
SQL> INSERT INTO personas VALUES (
  2    4, 'LIENE', 'ŠMAUKŠĀNE', '12345678901', NULL);
INSERT INTO personas VALUES (
*
ERROR at line 1:
ORA-00001: unique constraint (GINTS.PRS_PKD_UK)
violated

Kā redzams, Lienei, kura gribēja šmaukties, nekas nesanāca. Taču kas tagad būs, ja mēs mākslīgi uzspiedīsim NOT NULL ierobežojumu personas kodam?

SQL> ALTER TABLE personas MODIFY prs_personas_kods NOT NULL;
ALTER TABLE personas MODIFY prs_personas_kods NOT NULL
*
ERROR at line 1:
ORA-02296: cannot enable (GINTS.) - null values found

Nu, protams, nekas nesanāca, jo mums tur ir Null vērtības. Tas nozīmē, ka mums ir jāizvēlas kāda noklusētā personas koda vērtība un jāaizpilda esošie dati ar to. Pieņemsim, ka personas kods, kas satur tikai nulles, nevienam nevar būt un mēģinam aizpildīt lauku ar to:

SQL> UPDATE personas SET prs_personas_kods = '00000000000'
  2  WHERE prs_personas_kods IS NULL;
UPDATE personas SET prs_personas_kods = '00000000000'
*
ERROR at line 1:
ORA-00001: unique constraint (GINTS.PRS_PKD_UK)
violated

Ko mēs redzam – to, ka nekas nesanāca. Un mums tagad ir jāizvēlas vai mākslīgi uzspiest NOT NULL ierobežojumu, vai atļaut potenciāli dublējošās personas koda vērtības, kas normāli ir biznesa likumu pārkāpums, jo ar unikālu ierobežojumu to pārbaudīt nevar.

Patiesībā jau Oraclē Jūs varat izveidot funkciju bāzēto indeksu šādas vēlmes nodrošināšanai. Tātad vispirms tiekam vaļā no mūsu normālā ierobežojuma.

SQL> ALTER TABLE personas DROP CONSTRAINT prs_pkd_uk;
Table altered.

Tad izveidojam unikālo indeksu, kas mūsu feiko vērtību ‘00000000000’ pārveido atpakaļ uz NULL un redzam, ka feikās vērtības var ievadīt daudz, bet Lienei, kas gribēja šmaukties nekas tāpat nesanāks:

Piemērs 4. Funkciju bāzētā indeksa izveide un pārbaudes unikālo Null surogātvērtību maskēšanai.
SQL> CREATE UNIQUE INDEX prs_pkd_uk_faked ON personas (
  2    CASE WHEN prs_personas_kods = '00000000000'
  3         THEN NULL
  4         ELSE prs_personas_kods
  5    END);
Index created.
SQL>  UPDATE personas SET prs_personas_kods = '00000000000'
  2   WHERE prs_personas_kods IS NULL;
2 rows updated.
SQL> INSERT INTO personas VALUES (
  2    4, 'LIENE', 'ŠMAUKŠĀNE', '12345678901', NULL);
INSERT INTO personas VALUES (
*
ERROR at line 1:
ORA-00001: unique constraint (GINTS.PRS_PKD_UK_FAKED)
violated

Vienīgais, ka citās DBVS arī šāda šmaukšanās varētu nederēt, jo tur šādus indeksus izveidot nevar.

Agregātfunkcijas

Agregātfunkcijas ignorē Null vērtības. Turpinam skatīties iepriekšējo piemēru. Tātad kāda mums ir personu algu summa un vidējā alga?

Piemērs 5. Agregātfunkcijas ignorē null vērtības.
SQL> SELECT sum(prs_alga) summa, avg(prs_alga) vidējā
  2  FROM personas;

     SUMMA     VIDĒJĀ
---------- ----------
       430        215

Tā kā mums NULL vērtības nepatīk, tad nosakam, ka algai jābūt NE NULL vērtībai.

SQL> ALTER TABLE personas MODIFY prs_alga NOT NULL;
ALTER TABLE personas MODIFY prs_alga NOT NULL
*
ERROR at line 1:
ORA-02296: cannot enable (GINTS.) - null values found

Diemžēl, nekas nesanāca, jo tabulā ir personas, kam alga tādu vai citādu iemeslu dēļ ir 0. Nu ko iespējams, ka kādam vēl varētu būt alga 0, bet alga -1 taču nekad nebūs, vai ne? Koriģējam datus uzstādam atkal ierobežojumu:

Piemērs 6. Agregātfunkcijas NEignorē Null surogātvērtības.
SQL> UPDATE personas SET prs_alga = -1
  2  WHERE prs_alga IS NULL;
1 row updated.
SQL> ALTER TABLE personas MODIFY prs_alga NOT NULL;
Table altered.

Huhhh, nu šeit vismaz viss ir kārtībā. Diemžēl gan tikai līdz brīdim, kad laižam atskaiti par algām:

SQL> SELECT sum(prs_alga) summa, avg(prs_alga) vidējā
  2  FROM personas;

     SUMMA     VIDĒJĀ
---------- ----------
       429        143

Viss ir galīgi greizi saskaitījies ko? Diemžēl esam atpakaļ pie situācijas, kad mums ir speciāli jāapstrādā NULL vērtības, šoreiz diemžēl pilnīgi negaidītā vietā. Protams, apstrādājot mūsu specifisko Null vērtību nonākam pie pareizā rezultāta:

SQL> SELECT sum(prs_alga) summa, avg(prs_alga) vidējā
  2  FROM personas
  3  WHERE prs_alga <> -1;

     SUMMA     VIDĒJĀ
---------- ----------
       430        215

NOTE: Dont create indexes on beigu datums fields alone – they are making oracle go crazy and actually DEGRADE performance.

Šis bija reāls komentārs, ko uzrakstīja viens no izstrādātājiem datuma kolonai pirms vairākiem gadiem. Datuma kolona bija mākslīgi uzstādīta NOT NULL ar feiko vērtību 4000 gada 1 janvāris. Tiklīdz kā tika izveidots indekss uz šo kolonu un WHERE klauzā bija kritērijs uz datumu, tad momentāli Oracle lietoja šo indeksu. Kāpēc? Tāpēc ka Oracle saprot Null vērtības, bet neko nav dzirdējusi par mākslīgu 4000 gadu, kas simulē Null. Skatamies piemēru. Izveidojam tabulu, kurā ieliekam 1000 rindas ar vērtībām no šodienas datuma līdz 1000 dienām atpakaļ, kā arī vienu rindu, kurai beigu datums ir NULL. Izveidojam indeksu uz datuma lauka un izrēķinam statistikas:

Piemērs 7. Tabulas piemērs datumiem, kas atļauj Null `vertības.
SQL> CREATE TABLE datumi (
  2    dat_id INTEGER NOT NULL,
  3    spams VARCHAR2(1000),
  4    beigu_datums DATE);
Table created.
SQL> INSERT INTO datumi
  2  SELECT rownum, text, sysdate - rownum
  3  FROM all_source WHERE rownum <=1000;
1000 rows created.
SQL> INSERT INTO datumi VALUES (1001, NULL, NULL);
1 row created.
SQL> commit;
Commit complete.
SQL> CREATE INDEX beigu_dat_idx ON datumi(beigu_datums);
Index created.
SQL> exec dbms_stats.gather_table_stats(user, 'datumi',-
> cascade=>true)
PL/SQL procedure successfully completed.

Tagad atlasam datus no šīs tabulas un uzliekam ierobežojumu, ka datu jāatlasa intervālā no 2005 gada 1. janvāra līdz 2008 gada 25 aprīlim. Izmantojot autotrace uzstādam iespēju skatīties potenciālo izpildes plānu kopā ar statistiku, cik tad ierakstus atlasīja:

Piemērs 8. Oracle pazīst Null vērtības un spēj korekti izrēķināt sagaidāmo atlasāmo ierakstu skaitu un iegūt labāko vaicājuma izpildes plānu.
SQL> SET AUTOTRACE TRACEONLY
SQL> SELECT * FROM datumi
  2  WHERE beigu_datums BETWEEN
  3  to_date('2005-01-01', 'YYYY-MM-DD')
  4    AND to_date('2008-04-25', 'YYYY-MM-DD')
  5  /
1000 rows selected.
Execution Plan
----------------------------------------------------------
   0      SELECT STATEMENT Optimizer=ALL_ROWS (Cost=3
          Card=1000 Bytes=57000)
   1    0   TABLE ACCESS (FULL) OF 'DATUMI' (Cost=3
          Card=1000 Bytes=57000)
Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
         26  consistent gets
          0  physical reads
          0  redo size
      60817  bytes sent via SQL*Net to client
        610  bytes received via SQL*Net from client
         11  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
       1000  rows processed

Tātad redzam, ka Oracle ir domājusi, ka tiks atlasīti 1000 (Card=1000, No Cardinality (kardinalitāte)) ieraksti, un tos ir izdevīgi atlasīt izmantojot FULL SCAN. Redzam, ka rezultātā ir atlasīti 1000 (1000 rows processed) ieraksti, tātad tieši tikpat un no atmiņas ir nolasīti 26 datu bloki (26 consistent gets).
Kas notiek tagad, kad mēs NULL laukam uzstādam feiko vērtību 4000 gadu?

SQL> UPDATE datumi
  2  SET beigu_datums = to_date('4000-01-01', 'YYYY-MM-DD')
  3  WHERE beigu_datums IS NULL;
1 row updated.
SQL> COMMIT;
Commit complete.
SQL> exec dbms_stats.gather_table_stats(user, 'datumi',-
> cascade=>true)
PL/SQL procedure successfully completed.

Piemērs 9. Oracle NEpazīst Null surogātvērtības un NEspēj korekti izrēķināt sagaidāmo atlasāmo ierakstu skaitu un NEspēj iegūt labāko vaicājuma izpildes plānu.
SQL> SELECT * FROM datumi
  2  WHERE beigu_datums BETWEEN
  3  to_date('2005-01-01', 'YYYY-MM-DD')
  4    AND to_date('2008-04-25', 'YYYY-MM-DD');
1000 rows selected.
Execution Plan
----------------------------------------------------------
   0      SELECT STATEMENT Optimizer=ALL_ROWS (Cost=3 Card=2
          Bytes=114)
   1    0   TABLE ACCESS (BY INDEX ROWID) OF 'DATUMI' (Cost=3
          Card=2 Bytes=114)
   2    1     INDEX (RANGE SCAN) OF 'BEIGU_DAT_IDX' (NON-UNIQUE)
         (Cost=2 Card=2)
Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
         33  consistent gets
          0  physical reads
          0  redo size
      60819  bytes sent via SQL*Net to client
        610  bytes received via SQL*Net from client
         11  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
       1000  rows processed

Redzam, ka izpildes plāns tagad izmanto indeksu, ir galīgi nepareizs paredzamo atlasīto ierakstu skaits (Card=2), bet gala rezultātā protams atlasīto ierakstu skaits nav mainījies. Un redzam, ka arī šis izpildes plāns ir neefektīvāks, jo atlasa 33 datu blokus no atmiņas (33 consistent gets) tā vietā lai pietiktu ar 26. Jo lielāka būs tabula, jo vairāk arī jūs šo atšķirību jutīsiet. Tātad lai nolasītu 1000 rindas no 1001 Oracle izdomāja izmantot indeksu un domāja, ka nolasīsim tikai 2 ierakstus? Kāpēc, kāpēc tā DBVS ir tik dumja? Tāpēc, ka esam izmantojuši mūsu jauko feiko 4000 gadu. Oracle domā, ka dati visā tabulā ir izvietoti vienmērīgi, viņa nevar zināt, ka vērtība 4000 gads priekš mums ir ļoti speciāla vērtība un tāpēc gala rezultātā arī šāds izpildes plāns. Protams, varētu to mēģināt izlabot izmantojot histogrammas (speciālas konstrukcijas tabulu kolonām, kuru vērtības ir ļoti nevienmērīgi izmētātas), taču tās prasa papildus uzturēšanu un rada citas potenciālas problēmas.

Null surogātvērtības ārējo atslēgu laukos

Jau augstāk tika minēts, par to, ka šīs šausmas rada pamatīgas galvassāpes potenciāli jebkuram SQL teikumam, jo vienmēr ir jāfiltrē ārā ierakstus, kas ir radīti tikai tāpēc, lai uz šo tabulu varētu vienmēr norādīt ārējā atslēga. Taču bez tā ir arī vēl viena tehniska un ātrdarbību tieši ierobežojoša lieta – datubāze vienmēr visiem ārējo atslēgu laukiem ir spiesta pārbaudīt to eksistenci vecāku tabulā. Tā kā es jau tā esmu izvērsies ar piemēriem, tad atstāju lasītāju ziņā pārbaudīt, piemēram, izmantojot to pašu autotrace, cik tas iespaido konkrētu insert/update teikumu un ko tas nozīmē, aplikācijā, kurā tādi teikumi dienā potenciāli var būt miljoniem.

No NULL nekur neizbēgsi

No NULL diemžēl pavisam nekur aizbēgt nevar pat tad, ja ar milzīgu piepūli un pārkompleksām metodēm esam novērsuši iepriekšējās problēmas. Ir vairākas lietas, kas vienalga paliek NULL gribi vai nē.

Ārējie savienojumi

Tiklīdz kā mēs izmantojam tādu SQL konstrukciju kā ārējos savienojumus, tā mums ir iespēja abūt Null vērtības, kuras tik un tā būs jāapstrādā. Piemērus var redzēt augšminētajā saitē.

Null var būt funkciju rezultāts

Pietiekami daudzu funkciju rezultāts var dot NULL, piemēram, Oracle specifiski:

Piemērs 10. Funkciju izpildes rezultātā arī var iegūt Null vērtību.
SQL> SELECT LENGTH(SUBSTR('aaa', 4, 1)), LENGTH(NULL)
  2  FROM dual;
LENGTH(SUBSTR('AAA',4,1)) LENGTH(NULL)
------------------------- ------------

SQL Server gan ir mazliet savādāk:

SELECT len(substring('aaa', 4, 1)), len(null)
0	NULL

Bet, piemēram, CASE vienmēr dod NULL, ja gadījums nav apstrādāts. Oracle rezultāts:

SQL> SELECT CASE WHEN 'aaa' = 'bbb' THEN 1 END
  2  FROM dual;

CASEWHEN'AAA'='BBB'THEN1END
---------------------------

SQL Server rezultāts:

SELECT CASE WHEN 'aaa' = 'bbb' THEN 1 END
NULL

Nobeiguma vietā.

Aizstājot Null ar jūsu izdomātu Null vērtību vairumā gadījumu vienkārši problēmu nevis atrisina, bet nobīda kaut kur citur. Pie tam no vienas problēmas – tikt galā ar NULL, var rasties visai plaša problēma – tikt galā ar NULL aizstāšanas sekām, kas kā redzams var izpausties ļoti dažādos veidos. Ļoti iespējams, ka kādā konkrētā gadījumā ieguvums aizstājot NULL ar kādu definētu vērtību ir lielāks nekā potenciālie zaudējumi, bet akli veikt šādu mākslīgu aizstāšanu visur var radīt lielas un pamatīgas uzturamības un ātrdarbības problēmas.

4 Responses to NULL, indeksi, surogātvērtības un citi zvēri

  1. Pilnībā pievienojos viedoklim.

    Piemēros tikai pāris laikam vajag nevienādību izteikt savādāk nekā ar lielāks+mazāks, jo tas tiek uztverts kā html tags un gala tekstā neparādas (eg. alga -1 piemērā)

  2. Gints Plivna saka:

    O, jā wordpress redaktors bija norijis nevienādību, paldies!

  3. Pirmais normālais blogs latviešu valodā, ko atradu.

    Paldies, Gint!

  4. Gints Plivna saka:

    Khmmm paldies par komplimentu, protams :), bet nu es teiktu, ka neapšaubāmi ir krietns bariņš citu, kurus ir vērts palasīt un nosaukt par normāliem. Varbūt esi par maz meklējis 😉

Komentēt