Lesson 9 / الدرس 9
Designing a table / تصميم جدول
Choosing the columns, their types and their names. These decisions are cheap on the first day and expensive on every day after, because changing a column means changing every row and every query that mentions it.
اختيار الأعمدة وأنواعها وأسمائها. وهذه قرارات رخيصة في اليوم الأول وغالية في كل يوم بعده، لأن تغيير عمود يعني تغيير كل صف وكل استعلام يذكره.
One fact per column
CREATE TABLE guests (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(120) NOT NULL,
city VARCHAR(60),
email VARCHAR(160) NOT NULL UNIQUE,
phone VARCHAR(20)
);
The LIKE '%Cairo%' query works, and that is the trap. It also matches a guest whose street is Cairo Road and one whose email is me@cairo.com; it cannot count guests per city, cannot sort by city, cannot find the guests with no phone, and gets slower with every row because there is nothing to index. One column holding four facts is not a shortcut — it is four columns you will have to extract later, from data that has drifted into three different formats by then.
LIKE '%Cairo%' يعمل، وذلك هو الفخ. فهو يطابق أيضًا نزيلًا شارعه Cairo Road وآخر بريده me@cairo.com؛ ولا يستطيع عدّ النزلاء بحسب المدينة، ولا الفرز بها، ولا إيجاد من لا هاتف له، ويصير أبطأ مع كل صف لأن لا شيء يُفهرَس. والعمود الواحد الحامل لأربع حقائق ليس اختصارًا — بل أربعة أعمدة سيكون عليك استخراجها لاحقًا، من بيانات ستكون قد انجرفت إلى ثلاث صيغ مختلفة.Types, and the ones that bite
| For | Use | Not |
|---|---|---|
| A short name or email | VARCHAR(n) | TEXT — it cannot be indexed as easily |
| Money | DECIMAL(10,2) | FLOAT — 0.1 + 0.2 is not 0.3 |
| A count or an id | INT | VARCHAR — sorting gives 1, 10, 2 |
| A date | DATE or DATETIME | VARCHAR — no comparison, no arithmetic |
| Yes or no | TINYINT(1) / BOOLEAN | VARCHAR holding 'yes' and 'Y' and '1' |
| A fixed set of states | VARCHAR with a check, or ENUM | Free text nobody spells the same twice |
The money row is not pedantry. FLOAT stores a very close approximation, and invoices that are one piastre out on a thousandth of a row are a real support ticket. Store money as DECIMAL, or as an integer number of piastres, and never as a float.
FLOAT يخزّن تقريبًا قريبًا جدًا، والفواتير التي تخطئ بقرش في جزء من ألف من صف تذكرة دعم حقيقية. خزّن المال DECIMAL، أو عددًا صحيحًا من القروش، ولا تخزّنه عشريًا عائمًا أبدًا.INT وNULL في NOT NULL، لأنه محرّك استعلامات لتعلّم الاستعلامات لا خادم قاعدة بيانات. وMySQL الحقيقية ترفض كليهما. وذلك الفرق يهم في هذا الدرس بعينه، فصمّم جداولك هنا ثم أنشئها حقًا على جهازك — فالرفوض نصف ما تحاول تعلّمه، ولن تراها إلا هناك.
Four naming habits, worth adopting on day one because renaming later touches every query in the project. Table names plural and lower case: guests, not Guest or tbl_guest. The primary key called id in every table, so you never have to look it up. A foreign key named <table>_id — guest_id — so its meaning is visible without a diagram. And no prefixes repeating the table name: guests.name, never guests.guest_name, which reads as a stammer in every join you will ever write.
guests لا Guest ولا tbl_guest. والمفتاح الأساسي يسمّى id في كل جدول، فلا تحتاج البحث عنه أبدًا. والمفتاح الأجنبي يسمّى <الجدول>_id — guest_id — فيكون معناه ظاهرًا بلا مخطط. ولا بادئات تكرر اسم الجدول: guests.name لا guests.guest_name، التي تُقرأ تلعثمًا في كل وصل ستكتبه.NULL أن يعنيه قبل أن تسمح به. ففي هذه القاعدة phone يقبل العدم ويعني "ليس لدينا واحد"، وتلك حقيقة حقيقية تستحق التسجيل. وما يجب ألا يعنيه أبدًا هو "صفر" و"لا ينطبق" و"نسينا" معًا — فالعمود القابل للعدم الذي يعني ثلاثة أشياء لا يمكن الاستعلام عن أي منها. وإن كان للعمود قيمة دائمًا فقل NOT NULL ووفّر على نفسك الفحوص.Try it live / جرّب بنفسك
Check yourself / اختبر نفسك
1. Why is one column holding "name, city, email, phone" a bad idea?
And LIKE '%Cairo%' also matches Cairo Road and me@cairo.com.
LIKE '%Cairo%' يطابق أيضًا Cairo Road وme@cairo.com.2. Which type should hold money?
A float stores a very close approximation, and invoices out by one piastre are a real support ticket.
3. What does the practice engine NOT do that MySQL does?
Design here, then create the tables for real on your own machine: the refusals are half of what you are learning.
Score / النتيجة: 0 / 3
Your task / مهمتك
Design the tables for a small system of your choosing — not a hotel. Write the CREATE TABLE statements out in full, with a type for every column, NOT NULL where a value is always present, and a note beside each nullable column saying exactly what its NULL means. Then run them on your own MySQL, and deliberately break three rules — text into an integer, a duplicate in a unique column, a missing required value — and record the exact message each time. Bring the three messages back here with your schema.
صمّم جداول نظام صغير من اختيارك — لا فندقًا. واكتب جمل CREATE TABLE كاملة، بنوع لكل عمود، وNOT NULL حيث تكون القيمة موجودة دائمًا، وملاحظة بجانب كل عمود يقبل العدم تقول بالضبط ما يعنيه NULL فيه. ثم شغّلها على MySQL عندك، واكسر ثلاث قواعد عمدًا — نص في عدد صحيح، وتكرار في عمود فريد، وقيمة مطلوبة ناقصة — وسجّل الرسالة بنصها كل مرة. وأحضر الرسائل الثلاث معك هنا مع مخططك.
- Full CREATE TABLE statements with types جمل CREATE TABLE كاملة بالأنواع
- Every nullable column explained كل عمود يقبل العدم مشروح
- Three constraint violations attempted on real MySQL ثلاث مخالفات قيود على MySQL حقيقية
- The three exact error messages recorded رسائل الخطأ الثلاث بنصها مسجَّلة