SQL: أنواع البيانات
مثل صناديق التخزين بأحجام مختلفة — صناديق صغيرة للأقراط، متوسطة للساعات، كبيرة للوشاحات — كل عمود في قاعدة البيانات يحتاج أيضًا "الصندوق" المناسب لتخزين البيانات. اختر النوع الصحيح، وبياناتك تكون آمنة وموفرة للمساحة؛ اختر خطأً، إما أن تُخزن المساحة أو تفقد الدقة.
1. المفاهيم الأساسية
| المفهوم | الوصف |
|---|---|
| الأنواع الرقمية | تخزين الأعداد الصحيحة وال العشرية، بما في ذلك INT و BIGINT و DECIMAL و FLOAT، إلخ. |
| أنواع النصوص | تخزين بيانات النصوص، بما في ذلك CHAR و VARCHAR و TEXT |
| أنواع التواريخ | تخزين التواريخ والأوقات، بما في ذلك DATE و DATETIME و TIMESTAMP |
| الأنواع المنطقية | تخزين قيم صحيح/خطأ؛ SQLite يستخدم INTEGER (0/1) |
| NULL | يمثل "مجهول" أو "مفقود" — ليس نصًا فارغًا، ليس صفرًا |
| مبدأ اختيار النوع | اختر الأنسب بناءً على نطاق البيانات ومتطلبات الدقة وكفاءة التخزين |
2. بناء الجملة الأساسي
(1) الأنواع الرقمية
| النوع | الوصف | النطاق/الدقة | الأفضل لـ |
|---|---|---|---|
INTEGER / INT |
عدد صحيح | ±2.1 مليار | المعرّفات، الكميات، الأعمار |
BIGINT |
عدد صحيح كبير | ±9.2×10¹⁸ | معرّفات البيانات الضخمة، أحجام الملفات |
DECIMAL(p,s) / NUMERIC(p,s) |
عدد عشري دقيق | p = إجمالي الأرقام، s = الأرقام العشرية | المال، الأسعار (بدون فقدان الدقة) |
FLOAT / REAL |
نقطة عائمة | ~7 أرقام משמעותية | الحسابات العلمية، التقريبات |
DOUBLE |
نقطة عائمة مضاعفة الدقة | ~15 رقمًا משמעותיًا | الحسابات التقريبية عالية الدقة |
SQL
-- DECIMAL للتخزين النقدي الدقيق
CREATE TABLE accounts (
id INTEGER PRIMARY KEY,
balance DECIMAL(12, 2) -- حتى 12 رقمًا، رقمان عشريان
);
-- FLOAT للتخزين التقريبي
CREATE TABLE measurements (
id INTEGER PRIMARY KEY,
temperature REAL -- قيمة تقريبية، قد تكون بها أخطاء طفيفة
);
💡 نصيحة: استخدم دائمًا DECIMAL للمال، ولا تستخدم أبدًا FLOAT! يخزن FLOAT قيمًا تقريبية —
0.1 + 0.2 قد يساوي 0.30000000000000004، وهذا كارثة في السيناريوهات المالية.
(2) أنواع النصوص
| النوع | الوصف | الحد الأقصى للطول | الأفضل لـ |
|---|---|---|---|
CHAR(n) |
نص ثابت الطول | 255 بايت | بيانات ثابتة الطول (مثل: الجنس M/F، رموز الحالة) |
VARCHAR(n) |
نص متغير الطول | 65535 بايت | الأسماء، البريد الإلكتروني، العناوين |
TEXT |
نص طويل | غير محدود | محتوى المقالات، الملاحظات، الأوصاف |
SQL
CREATE TABLE articles (
id INTEGER PRIMARY KEY,
title VARCHAR(200), -- العنوان، أقصى 200 حرف
status CHAR(1), -- الحالة: D=مسودة، P=منشور
content TEXT -- المحتوى، طول غير محدود
);
💡 نصيحة: SQLite متساهل مع أنواع النصوص — يمكنك فعليًا تخزين نصوص بأي طول. ومع ذلك، لسهولة قراءة الشيفرة والتوافق عبر قواعد البيانات، يُوصى بتعريف الأنواع بشكل صحيح.
(3) أنواع التواريخ
| النوع | الوصف | الصيغة | الأفضل لـ |
|---|---|---|---|
DATE |
تاريخ | YYYY-MM-DD |
أعياد الميلاد، تاريخ التوظيف |
DATETIME |
تاريخ ووقت | YYYY-MM-DD HH:MM:SS |
أوقات الإنشاء، مواعيد التعيين |
TIMESTAMP |
طابع زمني | يُدار تلقائيًا | أوقات تعديل السجلات، سيناريوهات المناطق الزمنية المختلفة |
SQL
CREATE TABLE events (
id INTEGER PRIMARY KEY,
event_name TEXT,
event_date DATE, -- نهتم بالتاريخ فقط
created_at DATETIME DEFAULT CURRENT_TIMESTAMP -- تسجيل وقت الإنشاء تلقائيًا
);
💡 نصيحة: SQLite ليس لديه نوع تاريخ مخصص. عادة ما تُخزن التواريخ كـ
TEXT (صيغة ISO 8601 مثل '2024-01-15') أو INTEGER (طابع زمني Unix). دوال التاريخ المدمجة في SQLite (مثل DATE() و DATETIME()) يمكنها التعامل مع هذه الصيغ بشكل صحيح.
(4) الأنواع المنطقية
| النوع | الوصف | طريقة التخزين |
|---|---|---|
BOOLEAN |
صحيح/خطأ | يُخزن كـ INTEGER في SQLite: 0=خطأ، 1=صحيح |
BIT |
قيمة بت | تُستخدم في MySQL/SQL Server |
SQL
CREATE TABLE users (
id INTEGER PRIMARY KEY,
name TEXT,
is_active BOOLEAN DEFAULT 1 -- 1=مفعّل، 0=معطّل
);
-- إدراج قيم منطقية
INSERT INTO users (name, is_active) VALUES ('John', TRUE); -- يُخزن كـ 1
INSERT INTO users (name, is_active) VALUES ('Jane', FALSE); -- يُخزن كـ 0
-- استعلام باستخدام القيم المنطقية
SELECT * FROM users WHERE is_active = 1;
💡 نصيحة: في SQLite،
TRUE يساوي 1 و FALSE يساوي 0. لكن لسهولة قراءة الشيفرة، يُوصى باستخدام TRUE/FALSE بدلاً من كتابة الأرقام مباشرة.
(5) معنى NULL
يمثل NULL "مجهول" أو "مفقود" — ليس نصًا فارغًا ''، ليس الرقم 0، وليس بالتأكيد FALSE.
SQL
-- أي عملية تتضمن NULL تُنتج NULL
SELECT NULL + 1; -- النتيجة: NULL
SELECT NULL || 'hello'; -- النتيجة: NULL
-- للتحقق من NULL، يجب استخدام IS / IS NOT
SELECT * FROM employees WHERE department_id IS NULL; -- ✅ صحيح
SELECT * FROM employees WHERE department_id = NULL; -- ❌ يُرجع دائمًا فارغ
SELECT * FROM employees WHERE department_id IS NOT NULL; -- ✅ صحيح
💡 نصيحة: NULL هو أكبر فخ للمبتدئين. تذكر قاعدتين: ①استخدم
IS للتحقق من NULL، وليس =; ②أي عملية تتضمن NULL تُنتج NULL.
(6) أفضل الممارسات لاختيار النوع
| السيناريو | النوع الموصى به | السبب |
|---|---|---|
| معرّف المفتاح الرئيسي | INTEGER PRIMARY KEY AUTOINCREMENT |
الأعداد الصحيحة أسرع من النصوص؛ الزيادة التلقائية مريحة |
| المال/الأسعار | DECIMAL(10,2) |
تخزين دقيق، بدون أخطاء تقريب |
| أسماء المستخدمين/العناوين | VARCHAR(100) |
الطول المتغير يوفر المساحة؛ حد الطول يمنع الإساءة |
| محتوى المقال | TEXT |
طول غير محدود، مناسب للنصوص الكبيرة |
| التواريخ | DATE / DATETIME |
دلالات واضحة، دعم دوال التاريخ المدمجة |
| علامات نعم/لا | BOOLEAN |
دلالات واضحة، تخزين مدمج |
| حالات التعداد | CHAR(1) أو INTEGER |
أكثر مرونة من نوع ENUM |
3. أمثلة الشيفرة
▶ مثال: إنشاء جدول منتجات والتحقق من قيود الأنواع (الصعوبة ⭐)
أنشئ جدول منتجات لتجربة سلوك أنواع البيانات المختلفة.
SQL
-- إنشاء جدول المنتجات بأنواع الأعمدة المحددة
CREATE TABLE products_demo (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name VARCHAR(100) NOT NULL,
price DECIMAL(10, 2) NOT NULL,
stock INTEGER DEFAULT 0,
description TEXT,
is_active BOOLEAN DEFAULT 1,
created_at DATE
);
-- إدراج بيانات بأنواع مختلفة
INSERT INTO products_demo (name, price, stock, description, is_active, created_at)
VALUES ('Mechanical Keyboard', 299.50, 100, 'لوحة مفاتيح ميكانيكية بزر أزرق 87 مفتاح، ممتازة للطباعة', TRUE, '2024-01-15');
INSERT INTO products_demo (name, price, stock, description, is_active, created_at)
VALUES ('Wireless Mouse', 89.00, 200, NULL, TRUE, '2024-02-20');
-- عرض البيانات وسلوك الأنواع
SELECT name, price, stock, description, is_active, created_at
FROM products_demo;
الإخراج:
TEXT
📖 للعرض فقط
name price stock description is_active created_at
---------------- ------- ----- --------------------------------------------- --------- ----------
Mechanical Keyboard 299.50 100 لوحة مفاتيح ميكانيكية بزر أزرق 87 مفتاح... 1 2024-01-15
Wireless Mouse 89.00 200 (NULL) 1 2024-02-20
▶ مثال: التحقق من خصائص NULL الحسابية (الصعوبة ⭐⭐)
افهم السلوك الخاص لـ NULL من خلال استعلامات فعلية.
SQL
-- إنشاء جدول اختبار
CREATE TABLE null_test (
id INTEGER PRIMARY KEY,
value INTEGER
);
INSERT INTO null_test VALUES (1, 10);
INSERT INTO null_test VALUES (2, NULL);
INSERT INTO null_test VALUES (3, 20);
-- NULL في العمليات الحسابية
SELECT id, value, value + 100 AS add_result
FROM null_test;
الإخراج:
TEXT
📖 للعرض فقط
id value add_result
-- ----- ----------
1 10 110
2 (NULL) (NULL)
3 20 120
SQL
-- التحقق من NULL: IS مقابل =
SELECT id, value,
CASE WHEN value IS NULL THEN 'Is NULL' ELSE 'Not NULL' END AS check_result
FROM null_test;
الإخراج:
TEXT
📖 للعرض فقط
id value check_result
-- ----- ------------
1 10 Not NULL
2 (NULL) Is NULL
3 20 Not NULL
SQL
-- NULL ودوال التجميع: COUNT يستبعد NULL، SUM/AVG يتجاهلان NULL
SELECT COUNT(value) AS count_val, -- 2 (لا يُعد NULL)
COUNT(*) AS count_all, -- 3 (يُعد جميع الصفوف)
SUM(value) AS sum_val, -- 30 (يتجاهل NULL)
AVG(value) AS avg_val -- 15 (30/2، ليس 30/3)
FROM null_test;
الإخراج:
TEXT
📖 للعرض فقط
count_val count_all sum_val avg_val
--------- --------- ------- -------
2 3 30 15.0
4. سيناريوهات التطبيق الشائعة
(1) السيناريو 1: تصميم جدول تسجيل مستخدم
اختر الأنواع المناسبة بناءً على متطلبات العمل:
SQL
CREATE TABLE users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
username VARCHAR(50) NOT NULL UNIQUE, -- اسم المستخدم، فريد وغير فارغ
email VARCHAR(100) NOT NULL UNIQUE, -- البريد الإلكتروني
password_hash CHAR(64) NOT NULL, -- تجزئة SHA256، 64 حرفًا ثابتًا
age INTEGER CHECK (age >= 0 AND age <= 150), -- العمر، نطاق معقول
balance DECIMAL(12, 2) DEFAULT 0.00, -- رصيد الحساب، دقيق إلى السنت
bio TEXT, -- النبذة التعريفية، طول غير محدود
is_verified BOOLEAN DEFAULT 0, -- ما إذا تم التحقق من البريد الإلكتروني
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
(2) السيناريو 2: التعامل مع NULL مع القيم الافتراضية
استخدم دالة COALESCE لتوفير قيم افتراضية لـ NULL:
SQL
-- استعلام معلومات الموظف، عرض "غير معيّن" عندما يكون القسم NULL
SELECT e.name,
COALESCE(d.name, 'غير معيّن') AS department,
COALESCE(e.salary, 0) AS salary
FROM employees e
LEFT JOIN departments d ON e.department_id = d.id;
❓ أسئلة شائعة
س كيف أختار بين CHAR و VARCHAR؟
ج إذا كان طول البيانات ثابتًا (مثل: الجنس M/F، تجزئة MD5)، CHAR أكثر كفاءة. إذا كان الطول متغيرًا (مثل: الأسماء، العناوين)، VARCHAR يوفر مساحة أكثر. في الممارسة، VARCHAR يُستخدم بشكل أكثر.
س ما الفرق بين NULL ونص فارغ ''؟
ج NULL يعني "مجهول/بلا قيمة"، بينما النص الفارغ يعني "القيمة معروفة وهي فارغة." على سبيل المثال، عمود "الاسم الأوسط": قد لا يكون لدى أجنبي اسم أوسط (NULL)، بينما قد يكون لدى صيني اسم أوسط ولكنه نص فارغ (''). في دوال التجميع، COUNT(عمود) لا يُعد NULL لكن يُعد النصوص الفارغة.
📖 ملخص
- الأنواع الرقمية: استخدم INT/BIGINT للأعداد الصحيحة، DECIMAL للأرقام العشرية الدقيقة (يجب استخدامه للمال)، FLOAT للقيم التقريبية
- أنواع النصوص: استخدم CHAR للطول الثابت، VARCHAR للطول المتغير، TEXT للنصوص الكبيرة
- أنواع التواريخ: DATE يخزن التواريخ، DATETIME يخزن التواريخ مع الأوقات، TIMESTAMP يُدار تلقائيًا
- الأنواع المنطقية: BOOLEAN يخزن TRUE/FALSE؛ في SQLite هو فعليًا INTEGER 0/1
- NULL يعني "مجهول"؛ تحقق باستخدام
IS NULLوليس= NULL؛ العمليات التي تتضمن NULL لا تزال تُنتج NULL - مبدأ اختيار النوع: ضع في اعتبارك نطاق البيانات ومتطلبات الدقة وكفاءة التخزين؛ استخدم دائمًا DECIMAL للمال
📝 تمارين
(1) التمرين 1 (⭐)
صمم جدول "استعارة كتب" بالحقول التالية، واختر أنواع البيانات المناسبة:
- معرّف الاستعارة (مفتاح رئيسي)
- عنوان الكتاب (أقصى 200 حرف)
- ISBN (13 حرفًا ثابتًا)
- اسم المستعير
- تاريخ الاستعارة
- تاريخ الاستحقاق
- ما إذا تم الإرجاع
- ملاحظات (قابل للإلغاء)
(2) التمرين 2 (⭐⭐)
أنشئ الجدول من التمرين 1، وأدرج 5 سجلات، ثم اكتب استعلامات:
- استعلام جميع سجلات الاستعارة التي لم تُرجع
- استعلام السجلات whose ملاحظاتها NULL
- عدد جميع السجلات التي لم تُرجع (احذر من التعامل مع NULL)