Data Types and Keys (ဒေတာ အမျိုးအစားများနဲ့ key များ)
A3.2.3: Outline the different data types used in relational databases. A3.2.4: Construct tables for relational databases (primary, foreign, composite, concatenated keys).
မြန်မာလို: A3.2.3: relational database (table တွေ ချိတ်ဆက်ထားတဲ့ database) တွေမှာ သုံးတဲ့ data type (ဒေတာ အမျိုးအစား) အမျိုးမျိုးကို အကျဉ်းချုပ် ဖော်ပြနိုင်ရပါမယ်။ A3.2.4: relational database တွေအတွက် table တွေကို key အမျိုးအစားတွေ (primary key၊ foreign key၊ composite key၊ concatenated key) ပါဝင်အောင် ကိုယ်တိုင် တည်ဆောက်နိုင်ရပါမယ်။
အဓိက အယူအဆများ
Data Type တွေ ဘာကြောင့် အရေးကြီးသလဲ
Data type (ဒေတာ အမျိုးအစား) က column (ဒေါင်လိုက် ကော်လံ) တစ်ခုမှာ ဘယ်လို တန်ဖိုးမျိုး သိမ်းခွင့် ရှိလဲ ဆိုတာကို ကြေညာပေးပါတယ်: ကိန်းပြည့်တွေပဲ၊ သတ်မှတ်ထားတဲ့ အရှည်အထိ စာသား၊ true/false၊ ပြက္ခဒိန် ရက်စွဲ စသဖြင့်ပါ။ MySQL ဒါမှမဟုတ် PostgreSQL လို DBMS (database ကို စီမံတဲ့ software) က ကြေညာထားတဲ့ type ကို လိုက်နာအောင် စစ်ပေးပါတယ်: DATE column က "next Tuesday" (လာမယ့် အင်္ဂါနေ့) ဆိုတဲ့ တန်ဖိုးကို သိမ်းဖို့ ငြင်းပါတယ်၊ INT column က "hello" ကို ငြင်းပါတယ်၊ PostgreSQL မှာ BOOLEAN column က 42 ကို ငြင်းပါတယ်။ (SQLite ကတော့ ပိုလွတ်လပ်ပါတယ်: STRICT လို့ ကြေညာထားတဲ့ table မှာ ဒါမှမဟုတ် CHECK rule (တန်ဖိုးကို စစ်ပေးတဲ့ စည်းမျဉ်း) နဲ့မှသာ တန်ဖိုးတွေကို type နဲ့ ကိုက်မကိုက် စစ်ပါတယ်။)
Type မှန်မှန် ရွေးတာက နောက်ဆက်တွဲ အကျိုးသက်ရောက်မှု သုံးခု ရှိတဲ့ design ဆုံးဖြတ်ချက် တစ်ခုပါ:
- Validity (မှန်ကန်မှု)။ ဒေတာ မှားတွေကို database ထဲ ဝင်တဲ့ နေရာမှာတင် ငြင်းပယ်လိုက်လို့ နောက်ပိုင်း တွက်ချက်မှုတွေကို ပျက်စီးစေဖို့ အခွင့်အရေး မရပါဘူး။
- Operations (လုပ်ဆောင်ချက်များ)။ တန်ဖိုးနဲ့ ဘာတွေ လုပ်လို့ ရလဲ ဆိုတာကို type က သတ်မှတ်ပါတယ်။ Numeric type (ဂဏန်း type) တွေက ဂဏန်း တွက်ချက်မှုနဲ့ တန်ဖိုး အပိုင်းအခြား နှိုင်းယှဉ်မှုကို လုပ်ပေးနိုင်ပါတယ်၊ date type တွေက ရက်စွဲ အစဉ်အတိုင်း sort (အစဉ်တကျ စီခြင်း) လုပ်တာနဲ့ ရက်စွဲ တွက်ချက်မှုကို လုပ်ပေးနိုင်ပါတယ်၊ string (စာသား) တွေက
LIKEနဲ့ pattern matching (သတ်မှတ်ထားတဲ့ ပုံစံနဲ့ ကိုက်တဲ့ စာသားကို ရှာခြင်း) ကို လုပ်ပေးနိုင်ပါတယ်။ - Storage (သိမ်းဆည်းမှု)။ 4-byte integer (ကိန်းပြည့်) တစ်ခုက အဲဒီ ဂဏန်းကိုပဲ စာလုံး 20 လုံး ပါတဲ့ string အဖြစ် သိမ်းတာထက် နေရာ နည်းပါတယ်၊ ပြီးတော့ အရွယ်အစား သေးပြီး ပုံသေ ဖြစ်တဲ့ type တွေပေါ်က index (ရှာတာ မြန်အောင် database က သီးခြား ထားတဲ့ ညွှန်းစာရင်း) တွေက ပိုမြန်ပါတယ်။
မှတ်ထားရမယ့် စံ type စာရင်း တစ်ခုတည်း မရှိပါဘူး (DBMS အမျိုးမျိုးက type အနည်းငယ် မတူတာတွေ ပေးကြလို့ပါ)၊ ဒါပေမယ့် အောက်က အမျိုးအစား တွေကို မှတ်မိပြီး attribute (entity ရဲ့ အချက်အလက် တစ်ခု၊ table မှာ column ဖြစ်လာတယ်) တစ်ခုအတွက် သင့်တော်တဲ့ type ကို ရွေးနိုင်ရပါမယ်။
အဓိက Data Type အမျိုးအစားများ
| အမျိုးအစား | MySQL/PostgreSQL မှာ ဥပမာ | ဘာအတွက် သုံးလဲ |
|---|---|---|
| Whole numbers / integer (ကိန်းပြည့်) | INT, BIGINT, SMALLINT, TINYINT | အရေအတွက်၊ ID၊ အဆင့်၊ နှစ်ပြည့် အသက်၊ 10 မှတ်ပြည့် ရမှတ် |
| Decimal numbers (ဒသမ ကိန်း) | DECIMAL(p, s), NUMERIC | ငွေ၊ တိကျမှု အရေးကြီးတဲ့ အတိအကျ တိုင်းတာချက်များ |
| Floating-point numbers (ဒသမကိန်းကို ခန့်မှန်း တန်ဖိုးနဲ့ သိမ်းတဲ့ ကိန်း) | FLOAT, REAL, DOUBLE PRECISION | သိပ္ပံ တန်ဖိုးများ၊ အချိုးများ၊ ခန့်မှန်း တိုင်းတာချက်များ |
| Fixed-length text (အရှည် ပုံသေ စာသား) | CHAR(n) | အမြဲ စာလုံး n လုံး အတိအကျ ရှိတဲ့ code တွေ (ဥပမာ နိုင်ငံ code "GB"၊ "NZ") |
| Variable-length text (အရှည် ပြောင်းလဲနိုင်တဲ့ စာသား) | VARCHAR(n), TEXT | နာမည်၊ လိပ်စာ၊ ဖော်ပြချက်၊ စာလုံး ပါတဲ့ ID |
| Boolean (true ဒါမှမဟုတ် false တန်ဖိုးပဲ ယူတဲ့) | BOOLEAN (MySQL က TINYINT(1) အဖြစ် သိမ်းပါတယ်၊ SQL Server က BIT ကို သုံးပါတယ်) | True/false အမှတ်အသားများ (is_active၊ is_completed) |
| Date / time (ရက်စွဲ / အချိန်) | DATE, TIME, DATETIME, TIMESTAMP | မွေးနေ့၊ booking လုပ်တဲ့ ရက်စွဲနဲ့ အချိန်၊ server log (server က ဖြစ်ခဲ့တာတွေကို အစဉ်လိုက် မှတ်ထားတဲ့ မှတ်တမ်း) entry များ |
| Binary / blob (ပုံ၊ file လို byte ဒေတာ အစုအဝေး) | BLOB, BYTEA | ပုံ၊ PDF၊ byte ဒေတာ အကြမ်း (နည်းနည်းပဲ သုံးပါ၊ object storage (file တွေကို သီးခြား သိမ်းပေးတဲ့ storage ဝန်ဆောင်မှု) ကို အစားထိုး သုံးဖို့ စဉ်းစားပါ) |
CHAR(n) က သိမ်းဆည်းရာ နေရာကို အမြဲ စာလုံး n လုံးစာ သုံးပါတယ်၊ VARCHAR(n) ကတော့ လိုတဲ့ နေရာနဲ့ အပို နေရာ အနည်းငယ်ကိုပဲ သုံးပြီး n က အများဆုံး အရှည်ပါ။ DECIMAL(p, s) က စုစုပေါင်း ဂဏန်း p လုံး ရှိပြီး အဲဒီထဲက s လုံးက ဒသမ အမှတ်ရဲ့ နောက်မှာ ရှိတဲ့ ကိန်းကို သိမ်းပါတယ်၊ DECIMAL(7, 2) က 99999.99 အထိ တန်ဖိုးတွေကို rounding (အနီးစပ်ဆုံး တန်ဖိုးကို ယူခြင်း) မလုပ်ဘဲ လက်ခံပါတယ်။
မှန်ကန်တဲ့ Type ကို ရွေးခြင်း: မကြာခဏ ကျတတ်တဲ့ ထောင်ချောက် သုံးခု
ထောင်ချောက် 1: numeric type မှာ ရှေ့ဆုံးက သုည (leading zero) ပျောက်သွားခြင်း။
UK ဖုန်းနံပါတ်တွေက 0 နဲ့ စပါတယ်။ 02079460958 လို London ဖုန်းနံပါတ်ကို INT column ထဲ သိမ်းရင် 2079460958 ဖြစ်သွားပါတယ်: ရှေ့ဆုံးက သုည ပျောက်သွားပြီး နံပါတ်က မှားသွားပါတယ်။ 07700900123 လို mobile နံပါတ်ကတော့ INT အတွက် လုံးဝ ကြီးလွန်းလို့ MySQL နဲ့ PostgreSQL က လက်မခံပါဘူး။ ဖြေရှင်းနည်းက ဖုန်းနံပါတ်တွေကို ဂဏန်းအဖြစ် မဟုတ်ဘဲ string (VARCHAR) အဖြစ် သိမ်းတာပါ၊ ဘာလို့လဲဆိုတော့ ဖုန်းနံပါတ်တွေက ဂဏန်း တွက်ချက်မှု ဘယ်တော့မှ မလုပ်တဲ့ identifier (တစ်ခုချင်းကို ခွဲခြား သိရအောင် ပေးထားတဲ့ အမှတ်အသား) တွေ ဖြစ်လို့ပါ။
ဒီ ထောင်ချောက်ထဲကို စာလုံးနဲ့ စတဲ့ student ID (S1023)၊ postcode (စာပို့ လိပ်စာ သင်္ကေတ) (SW1A 1AA) နဲ့ product code အများစုလည်း ကျတတ်ပါတယ်။ ဂဏန်းလို ပုံပေါက်ပေမယ့် တကယ်တော့ identifier ဖြစ်တဲ့ ဘယ်အရာမဆို string ဖြစ်သင့်ပါတယ်။
ထောင်ချောက် 2: integer type မှာ ဒသမ တိကျမှု ပျောက်သွားခြင်း။
မိုးရေချိန် 12.7၊ 0.4 နဲ့ 3.85 မီလီမီတာ သိမ်းတဲ့ column က INT ဖြစ်လို့ မရပါဘူး: ဒသမ အပိုင်း ပျောက်သွားလို့ 12.7 က 13 အဖြစ်၊ 0.4 က 0 အဖြစ် သိမ်းမိပါတယ်။ DECIMAL (တိကျ) ဒါမှမဟုတ် FLOAT/REAL (ခန့်မှန်း၊ ပိုမြန်) ကို သုံးပါ။ ငွေအတွက်ဆိုရင် rounding error (အနီးစပ်ဆုံး တန်ဖိုး ယူရာက ဖြစ်တဲ့ အမှား အသေးလေးတွေ) တွေ စုမလာအောင် DECIMAL ကို ဦးစားပေး သုံးပါ။
ထောင်ချောက် 3: ရက်စွဲတွေကို string အဖြစ် အစဉ်မှားနဲ့ သိမ်းခြင်း။
"03/01/2026" ဆိုတဲ့ string အဖြစ် သိမ်းထားတဲ့ ရက်စွဲကို ရက်စွဲ အစဉ်အတိုင်း sort လုပ်လို့ မရပါဘူး: DBMS က string တွေကို စာလုံး တစ်လုံးချင်း နှိုင်းယှဉ်ပြီး sort လုပ်လို့ "03/01/2026" က "14/12/2025" ရဲ့ ရှေ့ ရောက်သွားပါတယ်၊ တကယ်တော့ 2026 ခုနှစ် ဇန်နဝါရီ 3 ရက်က နောက်ကျတဲ့ ရက်စွဲ ဖြစ်ပေမယ့်ပါ။ အောက်ပါ နှစ်ခုထဲက တစ်ခုကို လုပ်ပါ:
- တကယ့်
DATEcolumn ကို သုံးပါ (ဦးစားပေး နည်းပါ၊ ရက်စွဲ တွက်ချက်မှုနဲ့ validation (တန်ဖိုး မှန်မမှန် စစ်ခြင်း) ကို လုပ်ပေးပါတယ်)၊ ဒါမှမဟုတ် - ရက်စွဲတွေကို ISO 8601 format (ရက်စွဲကို နှစ်-လ-ရက် အစဉ်နဲ့ ရေးတဲ့ နိုင်ငံတကာ စံ) နဲ့ string အဖြစ် သိမ်းပါ (
"2026-06-15")၊ နှစ်က ရှေ့ဆုံးမှာ ရှိလို့ ရက်စွဲ အစဉ်အတိုင်း sort ဖြစ်သွားပါတယ်။
Data Type တစ်သမတ်တည်း ဖြစ်ဖို့ အရေးကြီးပုံ
Table မတူတဲ့ column နှစ်ခုက တန်ဖိုး အမျိုးအစား တူတူကို သိမ်းတဲ့အခါ (ဥပမာ MEMBER ထဲက MemberID နဲ့ BOOKING ထဲက MemberID) သူတို့မှာ ကြေညာထားတဲ့ type တူတူ ရှိရပါမယ်။ တစ်ခုက INT ဖြစ်ပြီး နောက်တစ်ခုက VARCHAR(8) ဖြစ်နေရင် database က foreign key (တခြား table ရဲ့ primary key ကို ညွှန်းတဲ့ column) ကို သေသေချာချာ လိုက်စစ်ပေးလို့ မရဘဲ join (table တွေကို ချိတ်ပြီး ဒေတာ တွဲယူခြင်း) တွေက နှေးသွားတာ ဒါမှမဟုတ် လုံးဝ မဖြစ်နိုင်တော့တာ ဖြစ်ပါတယ်။
Table တစ်ခုတည်းရဲ့ row (အလျားလိုက် အတန်း) တွေကြားမှာလည်း တစ်သမတ်တည်း ဖြစ်ဖို့ အရေးကြီးပါတယ်: Price column က DECIMAL(7, 2) ဖြစ်ရင် row တိုင်းက ဈေးနှုန်းကို တိကျမှု တူတူနဲ့ သိမ်းပါတယ်။ တိကျမှု ရောနေတဲ့ column (တချို့ row တွေက 12.5၊ တချို့က 12.500 သိမ်းထားတာ) က type ကို သေသေချာချာ မရွေးခဲ့ဘူး ဆိုတဲ့ လက္ခဏာပါ။
ရေးဖြေမှာ Type ရွေးချယ်မှုကို အကြောင်းပြခြင်း
Column ရဲ့ တကယ့် တန်ဖိုးတွေကနေ စပြီး type ဆီကို ချဉ်းကပ်ပါ။ ပထမ၊ column ထဲမှာ ဘယ်တန်ဖိုးတွေ တကယ် ပေါ်လာနိုင်လဲ၊ ဘယ်တန်ဖိုးတွေကို ငြင်းပယ်သင့်လဲ မေးကြည့်ပါ။ ပြီးရင် အဖွဲ့အစည်းက အဲဒီ တန်ဖိုးတွေနဲ့ database ကို ဘာလုပ်ခိုင်းဖို့ လိုမလဲ မေးပါ။ ကောင်းတဲ့ type က တကယ့် တန်ဖိုး အားလုံးကို လက်ခံပြီး မဖြစ်နိုင်တဲ့ တန်ဖိုးတွေကို ငြင်းပယ်ကာ အဲဒီ လုပ်ဆောင်ချက်တွေကို လုပ်ပေးနိုင်ပါတယ်။
ဥပမာ အများပြည်သူ စကိတ်စီးချိန် (public skating session) တစ်ခုစီ စတဲ့ ရက်စွဲနဲ့ အချိန် ဖြစ်တဲ့ SessionStart (ဥပမာ 2026-12-19 18:30) ကို မှတ်တမ်းတင်တဲ့ ရေခဲပြင် စကိတ်ကွင်း (ice rink) တစ်ခုကို ကြည့်ပါ။ DATE column က ရက်ကို သိမ်းပြီး အချိန်ကို ဖယ်ထုတ်လိုက်လို့ ရက်တူတဲ့ session တိုင်းမှာ တန်ဖိုး တူတူ ဖြစ်သွားပါလိမ့်မယ်။ DATETIME (ဒါမှမဟုတ် TIMESTAMP) column က နှစ်ခုလုံးကို သိမ်းပြီး MySQL ဒါမှမဟုတ် PostgreSQL လို DBMS က 2026-12-19 25:30 လို တန်ဖိုးကို ငြင်းပါတယ်၊ ဘာလို့လဲဆိုတော့ ဘယ်နေ့မှာမှ နာရီ 25 မရှိလို့ပါ။ ကွင်းက လိုအပ်တာတွေကိုလည်း လုပ်ပေးနိုင်ပါတယ်: session တွေကို အချိန် အစဉ်အတိုင်း စာရင်းလုပ်တာ၊ 18:00 နဲ့ 21:00 ကြား စတဲ့ ညနေ session တွေကို ရှာတာ၊ session တစ်ခုနဲ့ နောက်တစ်ခုကြား ကွာဟချိန်ကို တွက်တာပါ။ စာသားအဖြစ် သိမ်းရင် "9:30" လို့ ရေးထားတဲ့ အချိန်က "18:30" ရဲ့ နောက်မှာ sort ဖြစ်သွားမှာ ဖြစ်ပြီး column က "half six" (ခြောက်နာရီခွဲကို စကားလုံးနဲ့ ရေးထားတာ) လို စာရိုက်မှားတာကိုလည်း လက်ခံသွားပါလိမ့်မယ်။
Type ညံ့ညံ့ ရွေးမိရင် ဘာကြောင့် ပြဿနာ ဖြစ်လဲ ရှင်းပြဖို့လည်း အဲဒီ မေးခွန်းတွေကိုပဲ သုံးပါ: type က မှန်မှန်ကန်ကန် မသိမ်းနိုင်တဲ့ တကယ့် တန်ဖိုး တစ်ခု၊ type က ဝင်ခွင့်ပေးလိုက်တဲ့ မဖြစ်နိုင်တဲ့ တန်ဖိုး တစ်ခု၊ ဒါမှမဟုတ် အလုပ် မလုပ်တော့တဲ့ လုပ်ဆောင်ချက် တစ်ခုပါ။ Table သေးသေးလေး တစ်ခုအတွက်ဆိုရင် type တစ်ခု ယူတဲ့ နေရာ ပမာဏက ရွေးချယ်မှုကို ဆုံးဖြတ်တာ ရှားပါတယ်၊ column တစ်ခုကို အကြိမ် သန်းနဲ့ချီ သိမ်းတဲ့အခါမှာ ပိုအရေးကြီးလာပါတယ်။
Key များ: Table တွေကို ချိတ်ပေးတဲ့ Identifier များ
Relational database ထဲက key ဆိုတာ row တွေကို တစ်ခုချင်း မထပ်အောင် ခွဲခြား သိရဖို့ ဒါမှမဟုတ် table တွေကို အတူ ချိတ်ဆက်ဖို့ သုံးတဲ့ column တစ်ခု (ဒါမှမဟုတ် column အုပ်စု သေးသေးလေး) ပါ။ A3.2.4 (IB Computer Science သင်ရိုးထဲက table တည်ဆောက်ခြင်း အပိုင်း) အတွက် သိထားရမယ့် အမျိုးအစား လေးခုက:
| Key အမျိုးအစား | ရည်ရွယ်ချက် |
|---|---|
| Primary key (PK) (row တစ်ခုချင်းကို ခွဲခြားပေးတဲ့ key) | ကိုယ်ပိုင် table ထဲက row တစ်ခုစီကို မထပ်အောင် ခွဲခြား သိစေပါတယ်။ |
| Foreign key (FK) (တခြား table ရဲ့ primary key ကို ညွှန်းတဲ့ column) | တခြား table က row တစ်ခုရဲ့ primary-key တန်ဖိုးကို သိမ်းထားပြီး table နှစ်ခုကြား ချိတ်ဆက်မှု ဖန်တီးပေးပါတယ်။ |
| Composite key (column အများ ပေါင်းထားတဲ့ primary key) | Column နှစ်ခု ဒါမှမဟုတ် ပိုများတာကို ပေါင်းပြီး ဖွဲ့ထားတဲ့ primary key ပါ။ Column တစ်ခုတည်းက သူ့ဘာသာ unique (တန်ဖိုး မထပ်) မဖြစ်တဲ့အခါ သုံးပါတယ်။ |
| Concatenated key (တန်ဖိုး အများကို ဆက်ပြီး ဖွဲ့ထားတဲ့ key) | အချက်အလက် အပိုင်း အများကို string တစ်ခုတည်း အဖြစ် ဆက်ပြီး တန်ဖိုး ဖွဲ့ထားတဲ့ primary key ပါ။ Composite key နဲ့ နီးနီးကပ်ကပ် ဆက်စပ်ပါတယ်၊ အောက်မှာ ကြည့်ပါ။ |
Primary Keys (row တစ်ခုချင်းကို ခွဲခြားပေးတဲ့ key)
Primary key ဆိုတာ “ဒါက row X ပါ၊ တခြား row မဟုတ်ပါဘူး” လို့ DBMS ကို တန်ဖိုးနဲ့ ပြောပြတဲ့ column ပါ။ သူ့မှာ တင်းကျပ်တဲ့ စည်းမျဉ်း နှစ်ခု ရှိပါတယ်:
- Unique (တန်ဖိုး မထပ်ရ): row နှစ်ခုမှာ primary-key တန်ဖိုး တူတူ မရှိရပါဘူး။
- Not null (တန်ဖိုး ဗလာ မဖြစ်ရ): row တိုင်းမှာ တန်ဖိုး ရှိရပါမယ်၊ ပျောက်နေတာ ဒါမှမဟုတ် မသိတာကို ခွင့်မပြုပါဘူး။
Table တစ်ခုမှာ စည်းမျဉ်း နှစ်ခုလုံးနဲ့ ကိုက်ညီတဲ့ column ဒါမှမဟုတ် column အစု တစ်ခုထက် ပိုရှိနိုင်ပါတယ်။ အဲဒီ တစ်ခုစီကို candidate key (primary key ဖြစ်နိုင်တဲ့ column ဒါမှမဟုတ် column အစု) လို့ ခေါ်ပြီး designer က အဲဒီထဲက တစ်ခုကို primary key အဖြစ် ရွေးပါတယ်။ Column အစု တစ်ခုထဲက column တိုင်းက မဖြစ်မနေ လိုအပ်မှသာ အဲဒီ အစုကို candidate key လို့ သတ်မှတ်ပါတယ်: unique ဖြစ်ပြီးသား key တစ်ခုထဲကို column အပို ထည့်လိုက်တာက candidate key အသစ် မဖြစ်စေပါဘူး။
ဥပမာများ: MEMBER table ထဲက MemberID၊ BOOK table ထဲက ISBN (စာအုပ် တစ်အုပ်ချင်းစီကို ပေးထားတဲ့ နိုင်ငံတကာ နံပါတ်)၊ ORDER table ထဲက OrderID။
Primary key တွေက အမျိုးအစား နှစ်မျိုး ရှိပါတယ်:
| အမျိုးအစား | ဘာလဲ | အားသာချက်နဲ့ အားနည်းချက် |
|---|---|---|
| Natural key (လက်တွေ့ ကမ္ဘာက အဓိပ္ပာယ်ရှိတဲ့ identifier ကို သုံးတဲ့ key) | လူတွေအတွက် အဓိပ္ပာယ် ရှိတဲ့ လက်တွေ့ ကမ္ဘာက identifier (ISBN၊ Email၊ Passport_Number) | ရင်းနှီးပြီး လူ ဖတ်လို့ နားလည်ပါတယ်၊ ဒါပေမယ့် အချိန်နဲ့အမျှ ပြောင်းလဲနိုင်ပါတယ် (လူတွေက email လိပ်စာ ပြောင်းကြပါတယ်၊ ISBN တွေက 2007 မှာ ဂဏန်း 10 လုံးကနေ 13 လုံးကို ပြောင်းခဲ့ပါတယ်)၊ unique မဖြစ်တာလည်း ဖြစ်နိုင်ပါတယ် (မိသားစုဝင် နှစ်ယောက်က email လိပ်စာ တစ်ခုတည်းကို မျှသုံးတာ ဖြစ်နိုင်ပါတယ်) |
| Surrogate key (database က ထုတ်ပေးတဲ့ အဓိပ္ပာယ်မဲ့ ID key) | Database က ထုတ်ပေးတဲ့ အတု identifier (auto-increment (row အသစ်တိုင်း database က အလိုလို တစ်တိုးပေးတဲ့) integer ဖြစ်တဲ့ MemberID) | Unique ဖြစ်ပြီး တည်ငြိမ်ပါတယ်၊ join လုပ်ရာမှာ မြန်ပါတယ်၊ သူ ခွဲခြားပေးတဲ့ row အကြောင်း ဘာမှ ထုတ်ဖော် မပြပါဘူး၊ ဒါပေမယ့် ဒေတာကို ဖတ်တဲ့ လူတွေအတွက် အဓိပ္ပာယ် မရှိပါဘူး |
ခေတ်မီ ဒီဇိုင်း အများစုက primary key တွေအတွက် surrogate key တွေကို သုံးပြီး (သေးတယ်၊ တည်ငြိမ်တယ်၊ join လုပ်ရ လွယ်တယ်) email လို natural identifier တွေပေါ်မှာတော့ unique constraint (တန်ဖိုး မထပ်ရ ဆိုတဲ့ database စည်းမျဉ်း) တွေကို သီးခြား ထည့်ပါတယ်။
Foreign Keys (တခြား table ရဲ့ primary key ကို ညွှန်းတဲ့ column)
Foreign key ဆိုတာ တန်ဖိုးတွေက တခြား table ထဲက primary-key တန်ဖိုး တစ်ခုနဲ့ ကိုက်ညီရမယ့် column ပါ။ Table တစ်ခုက နောက် table တစ်ခုကို ညွှန်းတဲ့ နည်းလမ်းပါ။
Harbour Run schema (database ဖွဲ့စည်းပုံ ဖော်ပြချက်) မှာ:
BOOKING.MemberIDကMEMBER.MemberIDကို ညွှန်းတဲ့ foreign key ပါ။BOOKING.ClassIDကCLASS.ClassIDကို ညွှန်းတဲ့ foreign key ပါ။
Foreign key တွေက referential integrity (foreign key တွေ မှန်ကန်စွာ ချိတ်ထားရမယ့် စည်းမျဉ်း) ကို လိုက်နာအောင် စစ်ပေးပါတယ်: MemberID က MEMBER ထဲမှာ မရှိတဲ့ booking တစ်ခုကို ထည့်ဖို့ ကြိုးစားရင် DBMS က ငြင်းပါတယ်။ ဒါက relational model (ဒေတာကို ချိတ်ဆက်ထားတဲ့ table တွေနဲ့ ဖော်ပြတဲ့ ပုံစံ) ရဲ့ အဓိက အကျိုးကျေးဇူးတွေထဲက တစ်ခုပါ၊ ဘယ်ကိုမှ မညွှန်းတဲ့ orphan row (ညွှန်းထားတဲ့ row မရှိတော့တဲ့ row) တွေကို မတော်တဆ ဖန်တီးမိလို့ မရပါဘူး။
Referential integrity က ညွှန်းခံထားရတဲ့ row တစ်ခုကို update ဒါမှမဟုတ် delete လုပ်တဲ့အခါ ဘာဖြစ်မလဲ ဆိုတာကိုလည်း လွှမ်းခြုံပါတယ်။ အသုံးများတဲ့ ရွေးချယ်စရာတွေက:
- CASCADE: ပြောင်းလဲမှုကို မှီခိုနေတဲ့ row (dependent row) တွေဆီ ဆက်ပြီး သက်ရောက်စေပါတယ်။ Member တစ်ယောက်ကို delete လုပ်ရင် သူ့ booking တွေကိုလည်း ဖျက်ပစ်ပါတယ်။
- SET NULL: မှီခိုနေတဲ့ row တွေထဲက foreign-key column ကို
NULL(တန်ဖိုး မရှိကြောင်း ပြတဲ့ အမှတ်အသား) လို့ ပြောင်းပါတယ်။ Booking တွေ ကျန်နေပေမယ့် ဘယ်သူနဲ့မှ မသက်ဆိုင်တော့ပါဘူး။ - RESTRICT / NO ACTION: မှီခိုနေတဲ့ row တွေ ရှိနေရင် delete ဒါမှမဟုတ် update ကို တားပါတယ်။ မှီခိုနေတဲ့ row တွေကို အရင် ကိုင်တွယ်ပြီးမှသာ DBMS က အဲဒီ လုပ်ဆောင်ချက်ကို ခွင့်ပြုပါတယ်။
DBA (database ကို စီမံ ထိန်းသိမ်းသူ) က relationship (entity တွေကြားက ဆက်နွယ်မှု) ရဲ့ လုပ်ငန်း အဓိပ္ပာယ်ကို ကြည့်ပြီး foreign-key constraint တစ်ခုစီအတွက် ဒီထဲက တစ်ခုကို ရွေးပါတယ်။ Booking တွေကတော့ member နဲ့အတူ cascade-delete ဖြစ်သင့်ပါလိမ့်မယ်၊ order တွေကိုတော့ customer နဲ့အတူ delete မလုပ်သင့် ပါဘူး၊ ဘာလို့လဲဆိုတော့ ဖျက်လိုက်တဲ့ customer ရဲ့ order မှတ်တမ်းက စာရင်းကိုင် (accounting) အတွက် အရေးကြီးနေဆဲ ဖြစ်လို့ပါ။
Composite Keys (column အများ ပေါင်းထားတဲ့ primary key)
Composite key ဆိုတာ column တစ်ခုတည်းက သူ့ဘာသာ unique မဖြစ်တဲ့အခါ column နှစ်ခု ဒါမှမဟုတ် ပိုများတာကို ပေါင်းပြီး ဖွဲ့ထားတဲ့ primary key ပါ။ ပေါင်းထားတဲ့ အတွဲက unique ဖြစ်ရပါမယ်၊ column တစ်ခုချင်းကတော့ ထပ်နိုင်ပါတယ်။
ဥပမာ: junction table (entity နှစ်ခုကြားမှာ ထားပြီး ချိတ်ပေးတဲ့ table) BOOKING_ROOM က booking တစ်ခုစီက ဘယ်အခန်းတွေကို သုံးလဲ မှတ်တမ်း တင်ပါတယ်။ Booking တစ်ခုက အခန်း အများကြီး သုံးနိုင်ပြီး အခန်း တစ်ခန်းကိုလည်း booking အများကြီးက သုံးလို့ column တစ်ခုမှ သူ့ဘာသာ unique မဖြစ်ပါဘူး။ သဘာဝကျတဲ့ primary key က (BookingID, RoomID) နှစ်ခုကို ပေါင်းထားတာပါ။
Composite key ထဲမှာ ဘယ် column တွေ ပါရမလဲ ဆိုတာကို ဒီနေ့ table ထဲမှာ ရှိနေတဲ့ row တွေက မဆုံးဖြတ်ပါဘူး၊ အဖွဲ့အစည်းရဲ့ စည်းမျဉ်းတွေက ဆုံးဖြတ်ပါတယ်။ Column တစ်ခုစီအတွက် row နှစ်ခုက အဲဒီ column ရဲ့ တန်ဖိုး တူတူ ရှိခွင့်ကို စည်းမျဉ်းတွေက ခွင့်ပြုလား မေးကြည့်ပါ၊ ခွင့်ပြုရင် အဲဒီ column က သူ့ဘာသာ key မဖြစ်နိုင်ပါဘူး။ ပြီးရင် အတူတူ ထပ်ခွင့်ကို စည်းမျဉ်းက မပေးတဲ့ အသေးဆုံး column အစုကို ရှာပါ။ နမူနာ row အနည်းငယ်က လမ်းလွဲစေနိုင်ပါတယ်: column တစ်ခုက အခုထိ row တိုင်းမှာ မတူတာ ဖြစ်နေနိုင်ပေမယ့် နောင်မှာ row နှစ်ခုက တန်ဖိုး တူတူ ရှိလာတာကို စည်းမျဉ်းထဲမှာ ဘာမှ မတားထားတာ ဖြစ်နိုင်ပါတယ်။ အောက်က ဥပမာ 2 မှာ table တစ်ခုကို ဒီနည်းနဲ့ အဆင့်ဆင့် စစ်ပြထားပါတယ်။
Concatenated Keys (တန်ဖိုး အများကို ဆက်ပြီး ဖွဲ့ထားတဲ့ key)
Concatenated key က composite key နဲ့ နီးနီးကပ်ကပ် ဆက်စပ်ပါတယ်။ စာအုပ်စာတမ်းတွေမှာ အဓိပ္ပာယ်ကောက်ပုံ နှစ်မျိုး တွေ့ရပြီး နှစ်မျိုးလုံးကို အများက လက်ခံကြပါတယ်:
- Concatenated = composite။ ရင်းမြစ် အများအပြားက ဒီ term နှစ်ခုကို အရာ တစ်ခုတည်းအတွက် သုံးကြပါတယ်: column နှစ်ခု ဒါမှမဟုတ် ပိုများတာကနေ ဖွဲ့ထားတဲ့ primary key ပါ။
- Concatenated = column တစ်ခုတည်းထဲ ပေါင်းထည့်ထားတာ။ တချို့ အစဉ်အလာတွေက column အများကနေ တန်ဖိုးတွေကို ယူပြီး string တစ်ခုတည်းအဖြစ် ဆက် လိုက်တဲ့ အခြေအနေအတွက်ပဲ “concatenated key” ကို သုံးပါတယ် (ဥပမာ
"D07-fr"၊ dish code (ဟင်းပွဲ code) နဲ့ language code (ဘာသာစကား code) ကို ဆက်ထားတာ)၊ အဲဒီ string က သူ့ဘာသာ primary key ဖြစ်လာပါတယ်။
Composite နဲ့ concatenated ကို အယူအဆ တစ်ခုတည်းအဖြစ် သဘောထားပါ: unique ဖြစ်တာ သေချာအောင် အချက်အလက် အပိုင်း အများကို ပေါင်းထားတဲ့ key ပါ။ Term နှစ်ခုလုံးကို အများက သုံးကြပြီး ရင်းမြစ် အများစုက သူတို့ကြားမှာ ခွဲခြားချက် ခိုင်ခိုင်မာမာ မထားကြပါဘူး။
အားလုံးကို ပေါင်းကြည့်ခြင်း: Table တည်ဆောက်ပုံ
Primary key၊ foreign key နဲ့ composite key တွေကို ပြထားတဲ့ schema သေးသေးလေး တစ်ခုကို တည်ဆောက်ပြထားတာပါ:
erDiagram
STUDENT ||--o{ ENROLMENT : "enrols in"
CLASS ||--o{ ENROLMENT : "is taken by"
STUDENT {
int StudentID PK
string FirstName
string Surname
date DOB
}
CLASS {
string ClassID PK
string Title
string Coach
}
ENROLMENT {
int StudentID PK "FK to STUDENT"
string ClassID PK "FK to CLASS"
date EnrolledOn
}
ပုံထဲက enrols in က “(ကျောင်းသားက) စာရင်းသွင်း တက်ရောက်တယ်”၊ is taken by က “(class ကို) … က တက်တယ်” လို့ ဆိုလိုပြီး FK to STUDENT က “STUDENT ကို ညွှန်းတဲ့ foreign key” လို့ ဆိုလိုပါတယ်။ PK က primary key ဖြစ်ပြီး int၊ string၊ date တွေက column တစ်ခုစီရဲ့ data type တွေပါ။
STUDENT.StudentIDနဲ့CLASS.ClassIDက ရိုးရိုး primary key တွေပါ (column တစ်ခုစီ)။ENROLMENTမှာ(StudentID, ClassID)ဆိုတဲ့ composite primary key ရှိပါတယ်၊ ဘာလို့လဲဆိုတော့ အဲဒီ column နှစ်ခု ပေါင်းထားတာက enrolment (စာရင်းသွင်းမှု) record (အချက်အလက် အများကြီး စုထားတဲ့ ဒေတာ တစ်ခု) တစ်ခုစီကို unique ဖြစ်အောင် ခွဲခြားပေးလို့ပါ။- အဲဒီ column နှစ်ခုစီက foreign key တွေလည်း ဖြစ်ပါတယ်၊
StudentIDကSTUDENTကို ညွှန်းပြီးClassIDကCLASSကို ညွှန်းပါတယ်။ Column တစ်ခုတည်းက အခန်းကဏ္ဍ နှစ်ခုကို တစ်ပြိုင်နက် ထမ်းဆောင်နိုင်ပါတယ်။ EnrolledOnက enrolment ကိုယ်တိုင်ရဲ့ ရိုးရိုး attribute တစ်ခုပါ။
ဒါက junction table တစ်ခုအတွက် အသုံးများတဲ့ ပုံစံပါ: သူ ချိတ်ပေးတဲ့ entity (database ထဲမှာ ဒေတာ သိမ်းမယ့် အရာ တစ်ခု) နှစ်ခုဆီ ညွှန်းတဲ့ foreign key တွေကနေ သူ့ composite primary key ကို ဖွဲ့ပါတယ်။ ပေါင်းထားတဲ့ အတွဲ တစ်ခုစီက unique ဖြစ်ရလို့ ကျောင်းသား တစ်ယောက်တည်းကို class တစ်ခုတည်းမှာ နှစ်ခါ စာရင်းသွင်းလို့ မရပါဘူး။
အဆင့်ဆင့် ရှင်းပြထားတဲ့ ဥပမာများ
ဥပမာ 1: စာအုပ်ဆိုင် Schema အတွက် Type ရွေးခြင်း
စာအုပ်ဆိုင် သေးသေးလေး တစ်ဆိုင်က သူ့ ကုန်ပစ္စည်း စာရင်းကို ဒီ column တွေ ပါတဲ့ BOOK table ထဲမှာ မှတ်တမ်း ထိန်းပါတယ်:
| Column | ISBN | Title | Author | Price | Stock |
|---|---|---|---|---|---|
| နမူနာ တန်ဖိုး | ? | ? | ? | ? | ? |
Column တစ်ခုစီအတွက် data type ကို အကြောင်းပြချက်နဲ့ ရွေးပါ:
| Column | Type | အကြောင်းပြချက် |
|---|---|---|
ISBN | CHAR(13) (ဒါမှမဟုတ် hyphen တွေကို ထားချင်ရင် VARCHAR(17)) | ဂဏန်း တွက်ချက်မှု မလုပ်တဲ့ identifier ပါ: ဂဏန်း 13 လုံးက INT အတွက် များလွန်းပါတယ် (BIGINT လိုပါလိမ့်မယ်)၊ ဂဏန်း 10 လုံးပါတဲ့ ISBN အဟောင်းက X နဲ့ ဆုံးနိုင်ပါတယ်၊ ပြီးတော့ hyphen ပါတဲ့ ပုံစံ 978-0-306-40615-7 က စာသားပါ။ |
Title | VARCHAR(200) | အရှည် ပြောင်းလဲနိုင်တဲ့ စာသားပါ၊ ပျမ်းမျှ အားဖြင့် အများဆုံး အရှည်ထက် အများကြီး တိုပါတယ်။ Numeric type ကို သုံးလို့ မရပါဘူး။ |
Author | VARCHAR(120) | အကြောင်းပြချက် အတူတူပါပဲ။ (Normalise လုပ်ထားတဲ့ ဒီဇိုင်းမှာ Author က AUTHOR table ကို ညွှန်းတဲ့ foreign key ဖြစ်ပါလိမ့်မယ်၊ ဒါပေမယ့် မေးခွန်းက normalisation (ဒေတာ ထပ်မနေအောင် table တွေကို စီစဉ်ခြင်း) အကြောင်း မဟုတ်ဘဲ type တွေ အကြောင်းပါ။) |
Price | DECIMAL(6, 2) | ငွေမှာ တိကျမှု အတိအကျ လိုပါတယ်၊ FLOAT က rounding ကြောင့် penny (ပြား) တွေ လွဲသွားနိုင်ပါတယ်။ DECIMAL(6, 2) က 9999.99 အထိ တန်ဖိုးတွေကို လက်ခံပြီး စာအုပ် တစ်အုပ်အတွက် လုံလောက်တာထက် ပိုပါတယ်။ |
Stock | INT | ကိန်းပြည့် တစ်ခုပါ၊ stock-take (လက်ကျန် ပစ္စည်း ရေတွက်ခြင်း) နဲ့ ပြန်မှာဖို့ report တွေအတွက် ဂဏန်း တွက်ချက်မှုကို လုပ်ပေးနိုင်ပါတယ်။ |
ဥပမာ 2: Composite Primary Key
ကဖေး တစ်ဆိုင်က သူ့ menu ကို ဘာသာစကား အမျိုးမျိုးနဲ့ ရိုက်နှိပ်ပြီး ဟင်းပွဲ တစ်ပွဲစီရဲ့ နာမည်ကို ဘာသာစကား တစ်ခုစီနဲ့ သိမ်းထားပါတယ်:
DISH_NAME
| DishID | LanguageCode | DishName | CheckedBy |
|---|---|---|---|
| D07 | en | Lamb stew | Amira |
| D07 | fr | Ragoût d’agneau | Luc |
| D07 | de | Lammeintopf | Jonas |
| D12 | en | Lemon tart | Amira |
ကဖေးရဲ့ စည်းမျဉ်းတွေ: menu ပေါ်က ဘာသာစကား တစ်ခုစီမှာ ဟင်းပွဲ တိုင်းအတွက် နာမည် တစ်ခုတည်း အတိအကျ ရှိပြီး လူ တစ်ယောက်က နာမည် အများကြီးကို စစ်ဆေးနိုင်ပါတယ်။
မေးခွန်း: ဘယ် column တွေက primary key ကို ဖွဲ့သင့်သလဲ။
Column တွေကို တစ်ခုချင်း စစ်ကြည့်ခြင်း:
DishIDက ထပ်ပါတယ် (D07 မှာ နာမည် သုံးခု ရှိပါတယ်)၊ ဒါကြောင့် သူ့ဘာသာ key မဖြစ်နိုင်ပါဘူး။LanguageCodeလည်း ထပ်ပါတယ် (enက D07 အတွက်ရော D12 အတွက်ပါ ပေါ်ပါတယ်)။CheckedByထပ်ပါတယ် (Amira က နာမည် နှစ်ခုကို စစ်ခဲ့ပါတယ်)၊ ပြီးတော့ အဲဒါက ဘယ် row လဲ ဆိုတာကို မဟုတ်ဘဲ row ကို ဘယ်သူ စစ်ခဲ့လဲ ဆိုတာကို မှတ်တမ်း တင်တာပါ။DishNameက ပြထားတဲ့ row တိုင်းမှာ မတူပါဘူး၊ ဒါပေမယ့် စည်းမျဉ်းတွေက သူ့ကို unique ဖြစ်အောင် မသတ်မှတ်ထားပါဘူး: ဟင်းပွဲ တစ်ပွဲမှာ ဘာသာစကား နှစ်ခုမှာ နာမည် တူတူ ရှိနိုင်လို့ (tiramisu ကို English မှာရော Italian မှာပါ “Tiramisu” လို့ ခေါ်ပါတယ်) သူက key မဖြစ်နိုင်ပါဘူး။- “ဘာသာစကား တစ်ခုစီမှာ ဟင်းပွဲ တစ်ပွဲစီအတွက် နာမည် တစ်ခု” ဆိုတဲ့ စည်းမျဉ်းအရ
(DishID, LanguageCode)အတွဲက မထပ်ပါဘူး။ အဲဒီ အတွဲက composite primary key ပါ။
Key ထဲက column တစ်ခုစီက foreign key လည်း ဖြစ်ပါတယ် (DishID -> DISH၊ LanguageCode -> LANGUAGE)၊ ဒါကြောင့် ဒီ table က junction table တစ်ခုလိုပဲ ဟင်းပွဲတွေနဲ့ ဘာသာစကားတွေကို ချိတ်ပေးပါတယ်။
ဥပမာ 3: Type မှားရွေးမိရင် ဖြစ်လာမယ့် အကျိုးဆက်များ
ပြန်လည် အသုံးချ ပစ္စည်း လက်ခံရေး စင်တာ (recycling centre) တစ်ခုက လုပ်ငန်း တစ်ခုခုက ယူလာတဲ့ load (တစ်ခါ သယ်လာတဲ့ ပစ္စည်း အစု) တစ်ခုစီကို ချိန်ပါတယ်။ Developer က Weight column ကို VARCHAR(20) လုပ်ထားပါတယ်၊ ဒါမှ ဝန်ထမ်းတွေက အလေးချိန် တစ်ခုစီကို weighbridge ticket (ကားချိန်ခွင် လက်မှတ်) ပေါ်မှာ ပေါ်တဲ့အတိုင်း ရိုက်ထည့်လို့ ရမှာမို့ပါ။ တစ်လ ကြာတော့ column ထဲမှာ "350 kg"၊ "1,200kg"၊ "0.4 t" နဲ့ "95 KG" လို တန်ဖိုးတွေ ရှိနေပါတယ်။
ဘာတွေ မှားသွားလဲ:
- ယူနစ် ရောနေခြင်း။
"0.4 t"(တန်) နဲ့"400 kg"က အလေးချိန် တူတူကို နည်း နှစ်မျိုးနဲ့ ရေးထားတာမို့ report တိုင်းအတွက် တန်ဖိုးတွေကို မနှိုင်းယှဉ်ခင် ကိုယ်တိုင် ပြောင်းပေးရပါတယ်။ - စုစုပေါင်းကို ယုံကြည်လို့ မရခြင်း။ တန်ဖိုး တစ်ခုစီမှာ စာလုံးတွေ ပါပြီး တချို့မှာ comma ပါလို့ လစဉ် စုစုပေါင်းကို ရိုးရိုး ပေါင်းလို့ မရပါဘူး။ MySQL နဲ့ SQLite က စာသားကို ပေါင်းတဲ့အခါ တန်ဖိုး တစ်ခုစီရဲ့ အစက ဂဏန်းကိုပဲ သုံးလို့
"1,200kg"ကို 1 လို့၊"0.4 t"ကို 0.4 လို့ ရေတွက်ပြီး အပေါ်က တန်ဖိုး လေးခုကို 2,045 မဟုတ်ဘဲ 446.4 လို့ ပေါင်းပါတယ်။ PostgreSQL ကတော့ စာသားကို လုံးဝ ပေါင်းပေးဖို့ ငြင်းပါတယ်။ - အစဉ် မှားခြင်း။ စာသားအဖြစ် sort လုပ်ရင်
"1"ကို"3"နဲ့ နှိုင်းယှဉ်လို့"1,200kg"က"350 kg"ရဲ့ ရှေ့ ရောက်သွားပါတယ်၊ ဒါကြောင့် အလေးဆုံး load စာရင်းက မှားနေပါတယ်။ - စစ်ဆေးမှု မရှိခြင်း။ Column က
"heavy"(လေးတယ်)၊"35O kg"(ဂဏန်း 0 အစား စာလုံး O နဲ့ ရိုက်ထားတာ) ဒါမှမဟုတ် တန်ဖိုး ဗလာကို လက်ခံပြီး ဝန်ထမ်းတွေကို ဘာမှ သတိမပေးပါဘူး။
ဖြေရှင်းနည်းက ယူနစ် ရှင်းလင်းအောင် နာမည်ပေးထားတဲ့၊ ပုံသေ ယူနစ် တစ်ခုတည်း သုံးတဲ့ ဂဏန်း column ပါ: WeightKg DECIMAL(7, 1)။ ဒါဆိုရင် PostgreSQL နဲ့ MySQL (သူ့ရဲ့ default strict mode (တန်ဖိုးတွေကို တင်းတင်းကျပ်ကျပ် စစ်တဲ့ mode) မှာ) က စာသားကို ငြင်းပြီး တန်ဖိုး တိုင်းက kilogram နဲ့ ဖြစ်ကာ စုစုပေါင်း၊ ပျမ်းမျှနဲ့ sort လုပ်တာတွေ အလုပ်လုပ်ပါတယ်။ ရိုးရိုး SQLite table က column ရဲ့ type ကို မစစ်ပါဘူး၊ ဒါကြောင့် SQLite မှာ CHECK (typeof(WeightKg) IN ('integer', 'real')) လို CHECK rule တစ်ခု၊ ဒါမှမဟုတ် ဒေတာ ထည့်တဲ့ program က အဲဒီ စစ်ဆေးမှုကို လုပ်ရပါတယ်။ ဒါက identifier တစ်ခုကို ဂဏန်းအဖြစ် မှားသိမ်းခဲ့တဲ့ ထောင်ချောက် 1 ရဲ့ ပြောင်းပြန်ပါ၊ ဒီမှာတော့ တိုင်းတာချက် တစ်ခုကို စာသားအဖြစ် မှားသိမ်းထားပါတယ်။
Quick Check (အမြန် စစ်ဆေးမေးခွန်း)
Q1. Column တစ်ခုပဲ သုံးသုံး၊ အများကြီး သုံးသုံး၊ ကိုယ်ပိုင် table ထဲက row တစ်ခုစီကို unique ဖြစ်အောင် ခွဲခြားဖို့ ရွေးထားတဲ့ key ကို ယေဘုယျအားဖြင့် ဘယ်လို ခေါ်သလဲ။
Q2. 0207 946 0958 လို့ သိမ်းထားတဲ့ UK ဖုန်းနံပါတ် အတွက် အသင့်တော်ဆုံး data type က ဘာလဲ။
Q3. 19.99 နဲ့ 120.50 လို တန်ဖိုးတွေ သိမ်းတဲ့ ဈေးနှုန်း column အတွက် အသင့်တော်ဆုံး data type က ဘာလဲ။
Q4. ENROLMENT table မှာ StudentID၊ ClassID နဲ့ EnrolledOn column တွေ ရှိပါတယ်။ ကျောင်းသား-class အတွဲ တစ်ခုစီက အများဆုံး တစ်ကြိမ်ပဲ ပေါ်ပါတယ်။ Primary key ကို အကောင်းဆုံး ဖော်ပြထားတာက ဘယ်ဟာလဲ။
Q5. Foreign-key တန်ဖိုး တိုင်းက ညွှန်းထားတဲ့ table ထဲက ရှိပြီးသား primary-key တန်ဖိုး တစ်ခုနဲ့ ကိုက်ညီအောင် သေချာစေတဲ့ feature က ဘာလဲ။
Q6. Column တစ်ခုက ရက်စွဲတွေကို '15/06/2026' နဲ့ '20/12/2025' ဆိုတဲ့ string တွေအဖြစ် သိမ်းထားပါတယ်။ ဒါက ဘာကြောင့် ဒီဇိုင်း ညံ့တဲ့ ရွေးချယ်မှု ဖြစ်သလဲ။
သင့်တော်တဲ့ Data Type ကို ရွေးပါ
Column တစ်ခုစီအတွက် အသင့်တော်ဆုံး data-type အမျိုးအစားကို ရိုက်ထည့်ပါ၊ INT၊ DECIMAL၊ VARCHAR၊ DATE ဒါမှမဟုတ် BOOLEAN ထဲက တစ်ခုပါ။ အဖြေကို English စာလုံးနဲ့ ရိုက်ပါ။
| Column | အကောင်းဆုံး type |
|---|---|
MemberID၊ 1001 ကနေ စတဲ့ auto-increment ကိန်းပြည့် | |
PostCode၊ SW1A 1AA၊ EH3 6BX လို တန်ဖိုးများ | |
UnitPrice၊ 9.99၊ 120.50 လို တန်ဖိုးများ | |
DateOfBirth၊ ပြက္ခဒိန် ရက်စွဲ တစ်ခု | |
IsActive၊ membership က လက်ရှိ အသက်ဝင်နေရင် true | |
DailyVisitors၊ ရပ်ရွာ အလုပ်ရုံ (community workshop) တစ်ခုကို တစ်ရက်မှာ လာရောက်ခဲ့တဲ့ လူ အရေအတွက်၊ ဥပမာ 37 |
Fill in the Blanks (ကွက်လပ် ဖြည့်ခြင်း)
Relational key တွေအကြောင်း ဖော်ပြချက်ကို ပြည့်စုံအောင် ဖြည့်ပါ။ စာကြောင်းတွေက English လို ဖြစ်လို့ ကွက်လပ်တွေကို English စကားလုံးနဲ့ ရိုက်ထည့်ပါ။
KEYS IN A RELATIONAL DATABASE
=============================
A uniquely identifies each row within its table.
It cannot be null and cannot be duplicated.
A is a column whose values must match a primary key
in another table, creating a link between the two.
A is a primary key made of two or more columns
together, used when no single column is unique on its own.
The rule that every foreign-key value must match an existing
primary-key value is called .
A is an artificial identifier generated by the
database (e.g. an auto-increment integer), as opposed to a
real-world identifier like an email address.
စာကြောင်းတွေရဲ့ အဓိပ္ပာယ် (____ က ကွက်လပ်ပါ):
____ က သူ့ table ထဲက row တစ်ခုစီကို unique ဖြစ်အောင် ခွဲခြားပေးပါတယ်။ Null မဖြစ်ရသလို ထပ်လို့လည်း မရပါဘူး။
____ ဆိုတာ တန်ဖိုးတွေက တခြား table ထဲက primary key နဲ့ ကိုက်ညီရမယ့် column ဖြစ်ပြီး table နှစ်ခုကြား ချိတ်ဆက်မှု ဖန်တီးပေးပါတယ်။
____ ဆိုတာ column နှစ်ခု ဒါမှမဟုတ် ပိုများတာကို ပေါင်းပြီး ဖွဲ့ထားတဲ့ primary key ဖြစ်ပြီး column တစ်ခုတည်းက သူ့ဘာသာ unique မဖြစ်တဲ့အခါ သုံးပါတယ်။
Foreign-key တန်ဖိုး တိုင်းက ရှိပြီးသား primary-key တန်ဖိုး တစ်ခုနဲ့ ကိုက်ညီရမယ် ဆိုတဲ့ စည်းမျဉ်းကို ____ လို့ ခေါ်ပါတယ်။
____ ဆိုတာ email လိပ်စာလို လက်တွေ့ ကမ္ဘာက identifier နဲ့ မတူဘဲ database က ထုတ်ပေးတဲ့ အတု identifier (ဥပမာ auto-increment integer) ပါ။
Spot the Error (အမှား ရှာခြင်း)
Junior developer (အတွေ့အကြုံ နည်းသေးတဲ့ developer) တစ်ယောက်က contact (ဆက်သွယ်ရမယ့်သူ) စာရင်း တစ်ခုအတွက် CREATE TABLE statement (table အသစ် ဖန်တီးတဲ့ SQL ညွှန်ကြားချက်) တစ်ခု ရေးခဲ့ပါတယ်။ Line တစ်ကြောင်းမှာ data type မှားနေပါတယ်။ အမှားပါတဲ့ line ကို ရွေးပါ၊ ပြီးရင် မှန်ကန်တဲ့ ပြင်နည်းကို ရွေးပါ။
Line 2 အတွက် မှန်ကန်တဲ့ ပြင်နည်းကို ရွေးပါ:
Key အမျိုးအစားကို ရှာဖော်ပါ
"BOOKING.MemberID က တန်ဖိုးတွေဟာ MEMBER table ထဲက ရှိပြီးသား MemberID တန်ဖိုး တစ်ခုနဲ့ အမြဲ ကိုက်ညီရမယ့် column ပါ။ BOOKING table က MEMBER နဲ့ ချိတ်ဆက်တဲ့ နည်းလမ်းပါ။"
BOOKING.MemberID က ဘယ်လို key မျိုးလဲ။ (အဖြေကို English လို ရိုက်ပါ၊ ဥပမာ primary key။)
"REVIEW table က (UserID, GameID) ကို ပေါင်းပြီး သူ့ primary key အဖြစ် သုံးပါတယ်။ User တစ်ယောက်စီက board game (ဘုတ်ပေါ်မှာ ကစားတဲ့ ဂိမ်း) အများကြီးကို review (သုံးသပ်ချက်) ရေးနိုင်ပြီး ဂိမ်း တစ်ခုစီမှာ review အများကြီး ရှိလို့ column တစ်ခုမှ သူ့ဘာသာ unique မဖြစ်ပါဘူး၊ ဒါပေမယ့် user တစ်ယောက်စီက ဂိမ်း တစ်ခုစီကို အများဆုံး တစ်ကြိမ်ပဲ review ရေးပါတယ်။"
ဒါက ဘယ်လို key မျိုးလဲ။ (အဖြေကို English လို ရိုက်ပါ။)
Practice Exercises (လေ့ကျင့်ခန်းများ)
လေ့ကျင့်ခန်း တစ်ခုစီရဲ့ ရှေ့မှာ အဆင့် ([Core] စသဖြင့်)၊ ခေါင်းစဉ် link နဲ့ [4 marks] လို mark allocation (မေးခွန်း တစ်ခုစီအတွက် ပေးတဲ့ အမှတ်) ပါပါတယ်။ အမှတ်တွေက IB Computer Science (နိုင်ငံတကာ ကျောင်းတွေမှာ သင်တဲ့ ကွန်ပျူတာသိပ္ပံ သင်ရိုး) စာမေးပွဲ ပုံစံအတိုင်းပါ: IB သင်တန်း မတက်တဲ့သူတွေကတော့ အဖြေကို ဘယ်လောက် အသေးစိတ် ရေးရမလဲ ပြတဲ့ လမ်းညွှန်အဖြစ် သုံးနိုင်ပါတယ်။ အပိုင်းခွဲ တစ်ခုစီရဲ့ နောက်က [2] လို ဂဏန်းက အဲဒီ အပိုင်းရဲ့ အမှတ်ပါ။
Core (အခြေခံ အဆင့်)
[Core]Data types[4 marks]Column တစ်ခုစီအတွက် အသင့်တော်ဆုံး data type ကို state (ဖော်ပြပါ) လုပ်ပြီး သင့်ရွေးချယ်မှုကို စာကြောင်း တိုတို တစ်ကြောင်းနဲ့ justify (ဘာကြောင့် ရွေးတာလဲ အကြောင်းပြချက်နဲ့ ပြပါ) လုပ်ပါ။- (a)
StudentID၊S1023၊S1024လို တန်ဖိုးများ - (b)
Height_cm၊ လူ တစ်ယောက်ရဲ့ အရပ်ကို ဒသမ တစ်နေရာအထိ - (c)
IsActive၊ ကျောင်းသားက လက်ရှိ စာရင်းသွင်း တက်ရောက်နေရင် true - (d)
DateOfBirth၊ ပြက္ခဒိန် ရက်စွဲ တစ်ခု
- (a)
-
[Core]Data types[2 marks]အသံသွင်း စတူဒီယို တစ်ခုက booking တစ်ခုစီအတွက် ငွေချေပြီးပြီလား ဆိုတာကိုBOOLEANtype ရှိတဲ့Paidcolumn မှာ သိမ်းထားပါတယ်။ အခု စတူဒီယိုက booking လုပ်တဲ့အခါ စရံငွေ (deposit) တောင်းလာလို့ booking တစ်ခုက ငွေမချေရသေးတာ၊ တစ်စိတ်တစ်ပိုင်း ချေထားတာ (စရံငွေပဲ) ဒါမှမဟုတ် အပြည့် ချေပြီးတာ ဖြစ်နိုင်ပါတယ်။BOOLEANက ဒီ column နဲ့ ဘာကြောင့် မသင့်တော်တော့လဲ ဆိုတာကို Outline (အကျဉ်းချုပ် ဖော်ပြပါ) လုပ်ပြီး သင့်တော်တဲ့ data type တစ်ခုကို suggest (ဖြစ်နိုင်တဲ့ အဖြေ ဒါမှမဟုတ် ဖြေရှင်းနည်း တစ်ခုကို အကြံပြုပါ) လုပ်ပါ။ -
[Core]Keys[4 marks]လှေဆိပ် (marina) တစ်ခုက berth (လှေ ကပ်ထားဖို့ နေရာ) တွေကို လှေပိုင်ရှင်တွေဆီ ငှားပြီး အောက်ပါ table ထဲမှာ သိမ်းထားပါတယ်:BERTH(BerthID, Pontoon, BerthNumber, BerthCode, MaxLengthM)BerthIDက database က berth တစ်ခုစီကို ပေးတဲ့ နံပါတ်ပါ။ Pontoon (ရေပေါ်မှာ ပေါ်နေတဲ့ လမ်းလျှောက် တံတား) တွေကို A ကနေ F အထိ စာလုံးနဲ့ အမှတ်အသား ပေးထားပြီး pontoon တစ်ခုစီမှာ berth နံပါတ်တွေက 1 ကနေ ပြန်စပါတယ်။BerthCodeက နှစ်ခုကို တန်ဖိုး တစ်ခုတည်း (ဥပမာC14) အဖြစ် ဆက်ထားပြီး အဲဒါကို berth ပေါ်မှာ ဆေးနဲ့ ရေးထားပါတယ်။- (a)
BerthIDမဟုတ်တဲ့BERTHရဲ့ candidate key နှစ်ခုကို Identify (ဖြစ်နိုင်တဲ့ အဖြေတွေထဲက ရွေးပြီး ဖော်ပြပါ) လုပ်ပါ။ [2] - (b) Marina က
BerthIDကို primary key အဖြစ် ရွေးပါတယ်။BerthCodeအစား အဲဒါကို ရွေးရတဲ့ အကြောင်းပြချက် တစ်ခုကို Outline လုပ်ပါ။ [2]
- (a)
Extension (တိုးချဲ့ အဆင့်)
[Extension]Data types[3 marks]Fitness app တစ်ခုက user တစ်ယောက်စီရဲ့ နေ့စဉ် ခြေလှမ်း အရေအတွက်ကို -32,768 ကနေ 32,767 အထိ တန်ဖိုးတွေ သိမ်းနိုင်တဲ့ ကိန်းပြည့် type ဖြစ်တဲ့SMALLINTcolumn တစ်ခုမှာ သိမ်းပါတယ်။ လပေါင်းများစွာ နေ့တိုင်းကို ပြဿနာ မရှိဘဲ သိမ်းနိုင်ခဲ့ပါတယ်။ ပြီးတော့ တောင်ပေါ် လမ်းလျှောက်ခရီး ရှည်ရှည် တစ်ခု ပြီးနောက် user တစ်ယောက်ရဲ့ နာရီက ခြေလှမ်း 41,206 လှမ်းလို့ ပြလာပြီး app က error ပြပါတယ်: အဲဒီနေ့ရဲ့ ခြေလှမ်းတွေကို မသိမ်းနိုင်ခဲ့ပါဘူး။- (a) Database က ခြေလှမ်း အရေအတွက်ကို ဘာကြောင့် ငြင်းခဲ့လဲ Explain (ရှင်းပြပါ)။ [2]
- (b) Column အတွက် ပိုသင့်တော်တဲ့ data type တစ်ခုကို အကြောင်းပြချက်နဲ့ Suggest လုပ်ပါ။ [1]
-
[Extension]Keys[3 marks]လူငယ် သံပြိုင်အဖွဲ့ (youth choir) တစ်ခုက သီချင်း (piece) တစ်ပုဒ်စီမှာ အဆိုတော် (singer) တစ်ယောက်စီ ဘယ် voice part (အသံ အပိုင်း) ကို ဆိုလဲ ဆိုတာကိုSINGS(SingerID, PieceID, VoicePart)table ထဲမှာ မှတ်တမ်း တင်ပါတယ်။ သံပြိုင်အဖွဲ့ရဲ့ စည်းမျဉ်းက သီချင်း တစ်ပုဒ်စီမှာ အဆိုတော် တစ်ယောက်က part တစ်ခုတည်း (soprano၊ alto၊ tenor ဒါမှမဟုတ် bass) ကို အတိအကျ ဆိုရပြီး သီချင်း မတူရင်တော့ part မတူတာ ဆိုနိုင်ပါတယ်။ Designer A က(SingerID, PieceID)ကို primary key အဖြစ် အဆိုပြုပါတယ်၊ Designer B က(SingerID, PieceID, VoicePart)ကို အဆိုပြုပါတယ်။ သံပြိုင်အဖွဲ့က ဘယ် key ကို သုံးသင့်လဲ Explain လုပ်ပါ။ [Extension]Data types[3 marks]Booking စနစ် တစ်ခုကBookingDateကို"dd/mm/yyyy"string အဖြစ် သိမ်းပါတယ်။ ဒါကြောင့် ဖြစ်လာတဲ့ ပြဿနာ နှစ်ခု ကို Outline လုပ်ပြီး ပိုကောင်းတဲ့ နည်းလမ်း တစ်ခုကို suggest လုပ်ပါ။
Challenge (စိန်ခေါ်မှု အဆင့်)
-
[Challenge]Keys[6 marks]ကျောင်း စာကြည့်တိုက် တစ်ခုက spreadsheet ကနေ relational database ကို ပြောင်းနေပါတယ်။ စာကြည့်တိုက်ကMEMBER၊BOOKနဲ့LOAN(စာအုပ် ငှားမှု) ကို မှတ်တမ်း ထိန်းဖို့ လိုပါတယ်။ Table တစ်ခုစီရဲ့ primary key၊ foreign key အားလုံးနဲ့ composite key တွေ ရှိရင် အဲဒါတွေကို ပြထားတဲ့ table သုံးခုအတွက် schema တစ်ခုကို Construct (ကိုယ်တိုင် တည်ဆောက်ပါ) လုပ်ပါ။ Column တိုင်းအတွက် သင် သုံးမယ့် data type ကို ဖော်ပြပြီး ထင်ရှားမနေတဲ့ ရွေးချယ်မှု တစ်ခုစီကို အတိုချုပ် justify လုပ်ပါ။ -
[Challenge]Keys[6 marks]USERtable အတွက် surrogate primary key (ဥပမာ auto-increment integer) ကို natural primary key (ဥပမာ email လိပ်စာ) နဲ့ နှိုင်းယှဉ်ပြီး သုံးတဲ့ အားသာချက်နဲ့ အားနည်းချက်တွေကို Discuss (အမြင် အမျိုးမျိုးကို ချိန်ဆပြီး ဆွေးနွေးပါ)။ Unique ဖြစ်မှု၊ အချိန်ကြာလာရင် တည်ငြိမ်မှု၊ join performance (join လုပ်တဲ့ မြန်နှုန်း) နဲ့ လူ ဖတ်လို့ နားလည်လွယ်မှု တို့ကို ထည့်ပြောပါ။
မှတ်ချက်: A3.2.4 ရဲ့ recall question (မှတ်မိထားတာကို ပြန်ဖြေရတဲ့ မေးခွန်း) တွေ (
State the primary key၊Identify the foreign key) ကို schema ထဲမှာ မျဉ်းသားထားတဲ့ ဒါမှမဟုတ် label တပ်ထားတဲ့ column ကို ရှာပြီး သူ့နာမည်ကို ရေးရုံနဲ့ ဖြေရပါတယ်။ Composite key ကို ဘယ် column တွေ ဖွဲ့လဲ ဆုံးဖြတ်ဖို့ကတော့ နမူနာ row တွေကိုပဲ မကြည့်ဘဲ ဘယ်တန်ဖိုးတွေ ထပ်နိုင်လဲ ဆိုတဲ့ အဖွဲ့အစည်းရဲ့ စည်းမျဉ်းတွေကနေ စဉ်းစားပါ။
ဆက်စပ် ခေါင်းစဉ်များ
- အရင် လေ့လာထားရမယ့် ခေါင်းစဉ်: Entity-Relationship Diagrams (entity တွေနဲ့ ဆက်နွယ်မှုတွေကို ပြတဲ့ ပုံများ): ဘယ် entity က ဘယ် entity နဲ့ ချိတ်လဲ ဆိုတာကို ERD က ပြပါတယ်၊ အဲဒီ ချိတ်ဆက်မှုကို တကယ် ဘယ်လို သိမ်းလဲ ဆိုတာက key တွေပါ။
- ဆက်စပ် ခေါင်းစဉ်: Relational Database Fundamentals (relational database ရဲ့ အခြေခံများ): table၊ row နဲ့ key တွေရဲ့ အလုံးစုံ ဝေါဟာရပါ။
- နောက်ထပ် လေ့လာမယ့် ခေါင်းစဉ်: Normalisation (ဒေတာ ထပ်မနေအောင် table တွေကို စီစဉ်ခြင်း): အချက်အလက် တစ်ခုစီက နေရာ တစ်ခုတည်းမှာ ရှိအောင် column တွေကို table တွေထဲ စီစဉ်ပြီး ပြန်ချိတ်ဖို့ မှန်ကန်တဲ့ key တွေ ထားတဲ့ လုပ်ငန်းစဉ်ပါ။
- နောက်ပိုင်းမှာ: SQL Queries (SQL query များ):
JOINclause (table တွေကို ချိတ်ပြီး ဒေတာ တွဲယူတဲ့ SQL အပိုင်း) တွေက ဒီမှာ သတ်မှတ်ထားတဲ့ foreign-key ချိတ်ဆက်မှုတွေအတိုင်း လိုက်သွားပါတယ်။ - နောက်ပိုင်းမှာ (HL): Transactions and Views (transaction နဲ့ view များ): update အများ တစ်ချိန်တည်းမှာ ဖြစ်နေတဲ့အခါ transaction (အကုန်ဖြစ် ဒါမှမဟုတ် ဘာမှမဖြစ်တဲ့ database လုပ်ဆောင်ချက် အစု) တွေက ဒေတာကို ကိုက်ညီ မှန်ကန်နေအောင် ထိန်းပေးပါတယ်။ HL (Higher Level) ဆိုတာ IB သင်တန်းမှာ ပိုနက်နက်ရှိုင်းရှိုင်း လေ့လာရတဲ့ အဆင့်ပါ။