NULL ဆိုတာ

အတွေ့အကြုံရှိတဲ့ Developer တော်တော်များများဟာ NULL ကို နားလည်တယ်လို့ ထင်တတ်ကြပါတယ်။ IS NULL check တွေ ရေးဖူးမယ်၊ NOT NULL constraint တွေ သတ်မှတ်ဖူးမယ်၊ Empty row တွေကို Filter ထုတ်ဖူးပါလိမ့်မယ်။ ဒါပေမဲ့ SQLite က NULL နဲ့ ပတ်သက်ရင် လုံးဝသတိမထားမိနိုင်တဲ့ တစ်ခုခုကို လုပ်ဆောင်လေ့ရှိပါတယ်။ အဲဒါကို သေချာနားမလည်မချင်း NULL ရဲ့ သဘောသဘာဝဟာ ရှုပ်ထွေးနေဦးမှာပါ။
NULL ဆိုတာ ထင်ထားသလို မဟုတ်ဘူး
ဒါဟာ Developer တော်တော်များများ အနည်းဆုံး တစ်ကြိမ်တော့ ကြုံဖူးကြမယ့် အမှားမျိုးပါ။ အောက်ပါ Query ကို ကြည့်ရအောင်-
SELECT * FROM users WHERE age != 25;
ရိုးရှင်းပါတယ်။ အသက် ၂၅ နှစ် မဟုတ်တဲ့ User တိုင်းကို ရချင်တာပါ။ ဒါပေမဲ့ User အချို့မှာ အသက် (age) မသိမ်းထားဘဲ NULL ဖြစ်နေတယ်ဆိုပါစို့။ ဒါဆိုရင် သူတို့တွေ Result ထဲမှာ ပါလာလိမ့်မယ်လို့ မျှော်လင့်ရပါတယ်။
ဒါပေမဲ့ မပါလာပါဘူး။
age column မှာ NULL ရှိတဲ့ Row တွေဟာ တိတ်တဆိတ် ပျောက်ကွယ်သွားပါတယ်။ Error လည်း မပြသလို၊ Warning လည်း မပေးပါဘူး။ ဒါဟာ Bug မဟုတ်ပါဘူး။ ဒါဟာ NULL ကို ဒီဇိုင်းဆွဲထားတဲ့အတိုင်း အတိအကျ အလုပ်လုပ်နေတာပါ။ ဘာကြောင့်လဲဆိုတာကို နားလည်သွားရင် ကျန်တဲ့ SQL အယူအဆတွေပါ ရှင်းလင်းသွားပါလိမ့်မယ်။
Three-Valued Logic ရဲ့ ပြဿနာ
Programming language အတော်များများက Logic ကို Binary (True သို့မဟုတ် False) အနေနဲ့ပဲ ကိုင်တွယ်ကြပါတယ်။ SQL ကတော့ ဒီလို မဟုတ်ပါဘူး။ SQL မှာ Truth Value (၃) မျိုး ရှိပါတယ်။ ဒါတွေကတော့ TRUE, FALSE နဲ့ UNKNOWN တို့ပဲ ဖြစ်ပါတယ်။
NULL ဆိုတာ Zero မဟုတ်သလို၊ Empty string လည်း မဟုတ်ပါဘူး။ NULL ရဲ့ အဓိပ္ပာယ်က “တန်ဖိုးကို မသိရသေးခြင်း” (Unknown Value) လို့ ဆိုလိုတာပါ။ မသိရသေးတဲ့ တန်ဖိုးတစ်ခုကို ဘာနဲ့ပဲ နှိုင်းယှဉ်နှိုင်းယှဉ် (NULL ချင်း နှိုင်းယှဉ်ရင်တောင်) ရလဒ်ဟာ UNKNOWN ပဲ ဖြစ်ပါတယ်။
ဒါကြောင့်မို့လို့ age != 25 ဆိုတဲ့ Comparison ဟာ NULL row တွေအတွက် FALSE လည်း မဟုတ်သလို TRUE လည်း မဟုတ်ဘဲ UNKNOWN ဖြစ်သွားပါတယ်။ SQL ရဲ့ WHERE clause ဟာ Condition က TRUE ဖြစ်တဲ့ Row တွေကိုပဲ ရွေးထုတ်ပေးတာကြောင့် UNKNOWN ဖြစ်နေတဲ့ Row တွေဟာ ပျောက်ဆုံးသွားရခြင်း ဖြစ်ပါတယ်။
ဒါကို ပိုမြင်သာအောင် ကြည့်မယ်ဆိုရင်-
SELECT NULL = NULL;
-- Result: NULL
SELECT NULL != NULL;
-- Result: NULL
SELECT NULL = 0;
-- Result: NULL
SELECT NULL IS NULL;
-- Result: 1 (TRUE)
မသိတဲ့ တန်ဖိုးတစ်ခုကို ဘာနဲ့ပဲ နှိုင်းယှဉ်နှိုင်းယှဉ် (နောက်ထပ် မသိတဲ့ တန်ဖိုးတစ်ခုနဲ့ ဖြစ်စေ၊ သုညနဲ့ ဖြစ်စေ) ရလဒ်ဟာ အမြဲတမ်း UNKNOWN ပဲ ဖြစ်နေမှာပါ။ ဒါဟာ SQL Query တွေ ရေးသားတဲ့အခါမှာ အထူးသတိထားရမယ့် အချက်ဖြစ်ပါတယ်။
ဒီပြဿနာကို ဖြေရှင်းဖို့အတွက် SQL မှာ သီးသန့် Operator (၂) မျိုးကို တည်ဆောက်ထားပါတယ်-
IS NULLIS NOT NULL
ဒါဟာ NULL ဟုတ်မဟုတ်ကို တိုက်ရိုက် စစ်ဆေးပေးနိုင်တဲ့ တစ်ခုတည်းသော နည်းလမ်း ဖြစ်ပါတယ်။ ဥပမာ- SELECT * FROM users WHERE age IS NULL; လို့ ရေးသားမှသာလျှင် အသက်စာရင်း မရှိတဲ့ Row တွေကို မှန်ကန်စွာ ရရှိမှာ ဖြစ်ပါတယ်။
NULL ဟာ Query တွေထဲမှာ ဘယ်လို ပျံ့နှံ့သွားသလဲ
Three-valued logic ဟာ WHERE clause တစ်ခုတည်းမှာတင် ပြဿနာပေးတာ မဟုတ်ပါဘူး။ ရေးသားသမျှ SQL statement တော်တော်များများကို တိတ်တဆိတ် သက်ရောက်မှု ရှိနေတာပါ။ Logic operator တွေဖြစ်တဲ့ AND, OR, NOT တွေနဲ့ NULL (Unknown) တွဲမိတဲ့အခါ ရလဒ်တွေက အခုလို ဖြစ်လာပါတယ်။
AND:
| A | B | A AND B |
|---|---|---|
| TRUE | TRUE | TRUE |
| TRUE | FALSE | FALSE |
| TRUE | UNKNOWN | UNKNOWN |
| FALSE | UNKNOWN | FALSE |
| UNKNOWN | UNKNOWN | UNKNOWN |
ဒီနေရာမှာ နောက်ဆုံး case တစ်ခုကို သတိထားမိမှာပါ။ FALSE AND UNKNOWN ရဲ့ ရလဒ်ဟာ UNKNOWN မဟုတ်ဘဲ FALSE ဖြစ်နေပါတယ်။ ဘာကြောင့်လဲဆိုတော့ Unknown တန်ဖိုးက ဘာပဲဖြစ်နေပါစေ FALSE AND ဆိုတာနဲ့ ရလဒ်ဟာ အမြဲတမ်း FALSE ပဲ ထွက်မှာမို့လို့ပါ။ SQL ဟာ ဒီနေရာမှာ Logic အရ အရမ်းကို ကိုက်ညီမှုရှိပါတယ်။
OR:
| A | B | A OR B |
|---|---|---|
| TRUE | UNKNOWN | TRUE |
| FALSE | UNKNOWN | UNKNOWN |
| UNKNOWN | UNKNOWN | UNKNOWN |
TRUE OR UNKNOWN ဟာ TRUE ဖြစ်ပါတယ်။ အကြောင်းရင်းကတော့ Unknown တန်ဖိုးက ဘာပဲဖြစ်ဖြစ် TRUE OR ဆိုတာနဲ့ ရလဒ်ဟာ True ဖြစ်ဖို့ သေချာနေလို့ပဲ ဖြစ်ပါတယ်။
NOT:
NOT TRUE = FALSE
NOT FALSE = TRUE
NOT NULL = NULL
Unknown ရဲ့ Negation ဟာ ဆက်လက်ပြီး Unknown ပဲ ဖြစ်နေပါလိမ့်မယ်။ ဒါဟာ ရှုပ်ထွေးတဲ့ WHERE clause တွေ ရေးသားတဲ့အခါမှာ မမျှော်လင့်ဘဲ ကြုံတွေ့ရတတ်တဲ့ အန္တရာယ်အရှိဆုံး ထောင်ချောက်တစ်ခုပါပဲ။
Aggregate Function များတွင် NULL ပျောက်ဆုံးသွားခြင်း
SQLite ရဲ့ Aggregate function တွေဟာ NULL နဲ့ ပတ်သက်ရင် အလွန် တိကျတဲ့ မူဝါဒတစ်ခု ရှိပါတယ်။ အဲဒါကတော့ ၎င်းတို့ဟာ NULL တန်ဖိုးတွေကို လုံးဝ Ignore လုပ်ထားခြင်းပါပဲ။
SELECT AVG(score) FROM results;
ဥပမာအားဖြင့် score column မှာ NULL ရှိတဲ့ Row တွေ ပါဝင်နေမယ်ဆိုရင် SQLite ဟာ အဆိုပါ Row တွေကို တွက်ချက်မှုထဲမှာ ထည့်မတွက်ဘဲ ချန်လှပ်ထားမှာ ဖြစ်ပါတယ်။ SUM ထဲမှာလည်း မပါဝင်သလို၊ ပျမ်းမျှရှာဖို့အတွက် စားရမယ့် အရေအတွက် (Denominator) ကိုလည်း တိုးမပေးပါဘူး။ ဒါဟာ အများအားဖြင့် ကျွန်တော်တို့ လိုလားတဲ့အတိုင်းပါပဲ။ “မသိရသေးတဲ့ တန်ဖိုး” ကို သုညလို့ မသတ်မှတ်ဘဲ တကယ်သိရှိပြီးသား Score တွေကိုပဲ ပျမ်းမျှတွက်ချက်ပေးတာ ဖြစ်ပါတယ်။
ဒါပေမဲ့ ဒီနေရာမှာ အလွန် အန္တရာယ်များတဲ့ ထောင်ချောက်တစ်ခု ရှိနေပါတယ်။ အဲဒါကတော့ COUNT ရဲ့ အပြုအမူပဲ ဖြစ်ပါတယ်-
SELECT COUNT(*) FROM results; -- Row အားလုံး ရေတွက်တယ်
SELECT COUNT(score) FROM results; -- NULL မဟုတ်တဲ့ row တွေပဲ ရေတွက်တယ်
ဒီဂဏန်းနှစ်ခုရဲ့ ကွာဟချက်ဟာ Data ပေါ်မူတည်ပြီး အလွန်များနိုင်ပါတယ်။ မမျှော်လင့်ဘဲ ကြုံတွေ့ရတဲ့အခါ ဒါဟာ ရှာဖွေရခက်ခဲတဲ့ Logical Bug တစ်ခု ဖြစ်လာနိုင်ပါတယ်။
ထို့အပြင် Column တစ်ခုလုံးမှာရှိတဲ့ Value တွေဟာ NULL တွေချည်းပဲ ဖြစ်နေမယ်ဆိုရင် SUM ရဲ့ ရလဒ်ဟာ သုညမဟုတ်ဘဲ NULL ပဲ ပြန်လာမှာ ဖြစ်ပါတယ်။ အလားတူပဲ MIN နဲ့ MAX ကလည်း NULL ကိုပဲ ပြန်ပေးမှာပါ။ ဒီ Behavior တွေဟာ “မသိတဲ့တန်ဖိုး (Unknown)” ဆိုတဲ့ Philosophy နဲ့ အပြည့်အဝ ကိုက်ညီနေပါတယ်။ သိရှိတဲ့တန်ဖိုး တစ်ခုမှ မရှိတဲ့အတွက်ကြောင့် Aggregate ရလဒ်ဟာလည်း “မသိတဲ့အတိုင်း” ပဲ ဆက်လက်တည်ရှိနေခြင်း ဖြစ်ပါတယ်။
NULL နှင့် Index များ
ဒီနေရာမှာ Storage Level ကနေ စိတ်ဝင်စားစရာကောင်းတဲ့ အချက်အလက်တစ်ခု ထွက်ပေါ်လာပါတယ်။ အဲဒါကတော့ NULL ဟာ Query Performance အပေါ်ကို တိုက်ရိုက် သက်ရောက်မှု ရှိနေခြင်းပါပဲ။
SQLite ဟာ NULL တန်ဖိုးတွေကို Standard B-tree Index တွေထဲမှာ အခြားတန်ဖိုးတွေနည်းတူ ထည့်သွင်းသိမ်းဆည်းပါတယ်။ ဒါကြောင့် IS NULL ကို Query လုပ်တဲ့အချိန်မှာ SQLite ဟာ Full Table Scan လုပ်စရာမလိုဘဲ Index ကို အသုံးပြုပြီး NULL Row တွေကို ထိရောက်စွာ ရှာဖွေနိုင်ပါတယ်။ ဒါဟာ အခြား Database တချို့နဲ့ ကွာခြားတဲ့အချက်ပါ။ ဥပမာ PostgreSQL မှာဆိုရင် Index ထဲမှာ NULL ကို ကိုင်တွယ်ပုံက ပိုမိုရှုပ်ထွေးပါတယ်။ SQLite ရဲ့ ချဉ်းကပ်ပုံကတော့ ရိုးရှင်းပြီး ကိုက်ညီမှု ရှိပါတယ်။ NULL ဆိုတာ Index ထဲမှာ Sort Order အနိမ့်ဆုံး Position မှာ ထိုင်နေတဲ့ တန်ဖိုးတစ်ခုသာ ဖြစ်ပါတယ်။
ဒါဟာ Sort Order ကိုပါ သက်ရောက်မှု ရှိစေပါတယ်။ SQLite မှာ NULL ဟာ အရာအားလုံးရဲ့ အရှေ့မှာ Sort ဖြစ်ပါတယ်။ ဘယ် Number၊ ဘယ် String ဒါမှမဟုတ် ဘယ် Blob ထက်မဆို ပိုပြီး “နိမ့်” တယ်လို့ သတ်မှတ်ထားတာကြောင့် ORDER BY column ASC လို့ ရေးသားတဲ့အခါ NULL Row တွေက အရင်ဆုံး ပေါ်လာမှာ ဖြစ်ပါတယ်။ ဆန့်ကျင်ဘက်အနေနဲ့ ORDER BY column DESC ကတော့ NULL တွေကို နောက်ဆုံး ရောက်သွားစေပါတယ်။
SELECT name, score FROM results ORDER BY score ASC;
-- NULL row တွေ အရင်ဆုံး ပေါ်တယ်
တကယ်လို့ ဒါကို မလိုလားဘဲ NULL တွေကို နောက်ဆုံး ရောက်သွားစေချင်ရင်တော့ အခုလို Trick လေးကို အသုံးပြုနိုင်ပါတယ်-
SELECT name, score FROM results ORDER BY score IS NULL ASC, score ASC;
-- NULL တွေ နောက်ဆုံး ရောက်တယ်
ဒီ Command ဟာ ရှည်လျားတယ်လို့ ထင်ရပေမဲ့ လက်တွေ့မှာ အလွန် အလုပ်ဖြစ်သလို ရလဒ်ဟာလည်း မှန်ကန်မှု ရှိပါတယ်။
NULL နှင့် Constraint များ နဲ့ UNIQUE ၏ခြွင်းချက်
SQLite မှာ Constraint behavior နဲ့ ပတ်သက်ရင် ပထမဆုံးအကြိမ် ကြုံတွေ့ရသူတိုင်းကို အံ့အားသင့်သွားစေမယ့် အချက်တစ်ခု ရှိပါတယ်။ ပုံမှန်အားဖြင့် UNIQUE constraint ဆိုတာ Column တစ်ခုထဲကို Duplicate value တွေ ထပ်မံဝင်ရောက်မလာအောင် တားဆီးပေးတာ ဖြစ်ပါတယ်။ ဒါဟာ အလွန်ရှင်းလင်းတဲ့ သဘောတရားပါ။ ဒါပေမဲ့ NULL တန်ဖိုးတစ်ခုထက်ပိုပြီး ထည့်သွင်းမိရင် ဘာဖြစ်မလဲဆိုတာကို ကြည့်ရအောင်-
CREATE TABLE tokens (
id INTEGER PRIMARY KEY,
code TEXT UNIQUE
);
INSERT INTO tokens (code) VALUES (NULL);
INSERT INTO tokens (code) VALUES (NULL);
INSERT INTO tokens (code) VALUES (NULL);
ဒီနေရာမှာ ထူးခြားတာက INSERT သုံးကြောင်းလုံးဟာ အောင်မြင်သွားပါတယ်။ UNIQUE constraint ရှိနေပေမဲ့ Constraint Violation Error လုံးဝ မတက်လာပါဘူး။
ဘာကြောင့် ဒီလိုဖြစ်ရတာလဲဆိုတော့ UNIQUE constraint ဟာ တန်ဖိုးတွေကို အချင်းချင်း နှိုင်းယှဉ်ပြီးမှ တူမတူ ဆုံးဖြတ်တာ ဖြစ်ပါတယ်။ အထက်မှာ ဖော်ပြခဲ့တဲ့ Three-valued logic အရ NULL ဟာ နောက်ထပ် NULL တစ်ခုနဲ့ မညီမျှပါဘူး။ မသိရသေးတဲ့ တန်ဖိုးနှစ်ခုဟာ “(Same value)” လို့ သတ်မှတ်လို့မရတဲ့အတွက် Uniqueness ကို ချိုးဖောက်တယ်လို့ ယူဆလို့မရခြင်း ဖြစ်ပါတယ်။ ဒါကြောင့် SQLite ဟာ UNIQUE column တစ်ခုမှာ NULL တန်ဖိုး ဘယ်နှစ်ခုကိုမဆို ခွင့်ပြုပေးထားတာ ဖြစ်ပါတယ်။
ဒါဟာ SQL Standard အရ မှန်ကန်တဲ့ အပြုအမူဖြစ်သလို Database အများစုကလည်း ဒီနည်းလမ်းအတိုင်းပဲ ကျင့်သုံးကြပါတယ်။ ဒါပေမဲ့ “ဒီ Column မှာ တူညီတဲ့တန်ဖိုးကို နှစ်ကြိမ် ထည့်လို့မရဘူး” ဆိုတဲ့ ကျွန်တော်တို့ရဲ့ ပုံမှန် Mental Model ကိုတော့ ဒီနေရာမှာ ခဏဘေးဖယ်ထားဖို့ လိုအပ်ပါလိမ့်မယ်။ NULL အတွက်တော့ ဒီစည်းမျဉ်းက အကျုံးမဝင်ပါဘူး။
လက်တွေ့ Checklist နှင့် ရှောင်ကြဉ်ရမည့်အချက်များ
NULL နဲ့ ပတ်သက်တဲ့ Bug တွေဟာ အလွန်တိတ်ဆိတ်လွန်းပါတယ်။ Error လုံးဝမပြဘဲ ရလဒ်တွေ မှားယွင်းနေတာ၊ Count တွေ လွဲနေတာမျိုးတွေကို တိတ်တဆိတ် ပြန်ပေးလေ့ရှိပါတယ်။ ဒါကြောင့် လုပ်ငန်းခွင်မှာ အောက်ပါအချက်တွေကို အထူးသတိပြုသင့်ပါတယ်။
ပထမဆုံးအနေနဲ့ NOT IN ကို အသုံးပြုတဲ့အခါမှာ အလွန်ဂရုစိုက်ဖို့ လိုအပ်ပါတယ်။ တကယ်လို့ Subquery ထဲမှာ NULL Value တစ်ခုတည်း ပါဝင်နေရင်တောင် NOT IN Expression တစ်ခုလုံးဟာ Row တိုင်းအတွက် UNKNOWN ဖြစ်သွားတဲ့အတွက် Query က ဘာရလဒ်မှ ပြန်ပေးတော့မှာ မဟုတ်ပါဘူး။ ဒါဟာ အန္တရာယ်ရှိတဲ့ အခြေအနေတစ်ခုဖြစ်ပြီး ပိုမိုလုံခြုံစေဖို့အတွက် Subquery ထဲမှာ WHERE id IS NOT NULL လို့ ထည့်သွင်းစစ်ဆေးပြီးမှသာ အသုံးပြုသင့်ပါတယ်။
-- Subquery ထဲမှာ NULL ပါနိုင်ရင် အန္တရာယ်ရှိ
SELECT * FROM orders WHERE customer_id NOT IN (SELECT id FROM blacklist);
-- ပိုလုံခြုံတဲ့ နည်း
SELECT * FROM orders WHERE customer_id NOT IN (
SELECT id FROM blacklist WHERE id IS NOT NULL
);
ဒုတိယအချက်အနေနဲ့ COALESCE Function ကို အကျွမ်းတဝင်ရှိအောင် လေ့ကျင့်ထားဖို့ ဖြစ်ပါတယ်။ သူဟာ ပေးထားတဲ့ List ထဲမှာ NULL မဟုတ်တဲ့ ပထမဆုံးတန်ဖိုးကို ရှာဖွေပေးပါတယ်။ NULL ဖြစ်လာနိုင်တဲ့ နေရာမျိုးမှာ Default တန်ဖိုးတစ်ခုခု (ဥပမာ- 0 သို့မဟုတ် အခြားစာသားတစ်ခုခု) အစားထိုးဖို့အတွက် အသန့်ရှင်းဆုံးနဲ့ အထိရောက်ဆုံး နည်းလမ်းပဲ ဖြစ်ပါတယ်။
SELECT COALESCE(score, 0) FROM results;
နောက်ဆုံးအချက်ကတော့ NOT NULL Constraint ရဲ့ အရေးပါမှုပါ။ Column တစ်ခုမှာ တန်ဖိုးတစ်ခု အမြဲတမ်း ရှိနေသင့်တယ်ဆိုရင် Schema ရေးသားစဉ်ကတည်းက NOT NULL သတ်မှတ်ထားဖို့ ဝန်မလေးသင့်ပါဘူး။ ဒါဟာ နောက်ပိုင်းမှ NULL တွေကို လိုက်လံရှာဖွေပြီး Audit လုပ်ရတာထက် အများကြီး ပိုမိုလွယ်ကူသလို၊ Bug တစ်မျိုးလုံးကို Application Level အထိ မရောက်ခင် Database Level မှာတင် ကြိုတင်တားဆီးပေးနိုင်တဲ့ ခိုင်မာတဲ့ Guardrail တစ်ခု ဖြစ်လာမှာပါ။
NULL ကို ဘာကြောင့် သီးသန့် Part တစ်ခုအနေနဲ့ လေ့လာရသလဲ
NULL ဆိုတာ တစ်ကြိမ်သင်ပြီးတာနဲ့ ဆက်မတွေးဘဲ ထားခဲ့လို့ရတဲ့ Feature တစ်ခုမဟုတ်ပါဘူး။ သူဟာ Filtering, Counting, Aggregating, Joining, Sorting နဲ့ Constraint Behavior အားလုံးကို တစ်ပြိုင်နက် တိတ်တဆိတ် သက်ရောက်နေတဲ့ Philosophy ဖြစ်လို့နေပါတယ်။
တကယ်တော့ NULL ကြောင့် အမှားအယွင်းဖြစ်ရတဲ့ Developer တွေဟာ အခြေခံလေ့လာသူတွေ မဟုတ်ကြပါဘူး။ ရှုပ်ထွေးတဲ့ Query တွေ ရေးသားနိုင်လောက်တဲ့ အတွေ့အကြုံရှိသူတွေပဲ ဖြစ်ပါတယ်။ ဒါပေမဲ့ သူတို့ဟာ Query ရဲ့ အဆင့်တိုင်းမှာ “ဒီ Column သာ NULL ဖြစ်ခဲ့ရင် ဘာဆက်ဖြစ်မလဲ” လို့ ကိုယ့်ကိုယ်ကိုယ် မေးလေ့မရှိသေးတာကြောင့် ဖြစ်ပါတယ်။
ဒီအလေ့အကျင့် ရလာတဲ့အချိန်၊ တစ်နည်းအားဖြင့် Three-valued logic ဟာ မိမိတို့အတွက် ဒုတိယသဘာဝလို ဖြစ်သွားတဲ့အချိန်မှာတော့ NULL နဲ့ ပတ်သက်တဲ့ Bug တွေကို ဖြစ်လာပြီးမှ မဟုတ်ဘဲ မဖြစ်ခင်ကတည်းက ကြိုတင်မြင်လာနိုင်ပါလိမ့်မယ်။ အဲဒီအခါ “ဒီ Query က ဘာကြောင့် Result မှားနေတာလဲ” ဆိုတဲ့ မေးခွန်းတွေဟာ ကိုယ်တိုင်အဖြေရှာစရာမလိုဘဲ ရှင်းလင်းသွားမှာ ဖြစ်ပါတယ်။
For the Part-4 (The Engine Machinery)
Part-4 မှာတော့ ကျွန်တော်တို့ SQLite Engine ရဲ့ အတွင်းပိုင်းထဲအထိ ဆက်လက်ဆင်းကြမှာပါ။ SELECT တစ်ခုကို ရိုက်ထည့်လိုက်တာကနေ Result ပြန်ရတဲ့အချိန်အထိ နောက်ကွယ်မှာ တကယ်ဘာတွေ ဖြစ်သွားသလဲဆိုတာကို အသေးစိတ် လိုက်ကြည့်ကြပါမယ်။
- Tokenizer & Parser: SQL စာသားတွေကို နားလည်အောင် ဘယ်လို ခွဲခြမ်းစိတ်ဖြာသလဲ။
- Code Generator: Query တစ်ခုကို အလုပ်လုပ်မယ့် Plan အဖြစ် ဘယ်လို ပြောင်းလဲသလဲ။
- VDBE Bytecode: SQLite ရဲ့ ကိုယ်ပိုင် Virtual Machine က Bytecode တွေကို ဘယ်လို Execute လုပ်သလဲ။
ဒီ Machinery တစ်ခုလုံးကို နားလည်သွားတဲ့အခါ မိမိတို့ရဲ့ SQL ရေးသားပုံတွေဟာ အရင်နဲ့မတူဘဲ ပိုမိုကောင်းမွန်တဲ့ဘက်ကို ပြောင်းလဲသွားတာကို သတိထားမိလာပါလိမ့်မယ်။