You are on page 1of 15

‫‪Sql /sqllit‬‬ ‫‪yahi mohammed‬‬

‫بدهيات استعالمات ‪ SQL‬مع قواعد بيانات‪Sqlite‬‬


‫>‪<note warning‬هذه الصفحة ال تزال قيد اإلنشاء >‪</note‬‬

‫مقدمة‬
‫إن ‪ SQL‬وتعني لغة االستعالمات الهيكلية ‪ Structured Query Language‬وهي من وضع‬
‫( ‪IBM‬في نظام لهم اسمه النظام ‪ R‬يعود للسبعينات من القرن الماضي) وهي لغة عيارية منذ ‪ ٦٨٩١‬م‬
‫حيث تبنتها ‪ ANSI‬ثم ‪ ISO‬في معايير متالحقة‪.‬‬
‫يجدر بنا اإلشارة إلى أن ‪ SQL‬ليست لغة برمجة وإنما لغة للتحدث مع قواعد البيانات العالئقية‬
‫‪RDBMS.‬‬
‫ويوجد العديد من قوا عد البيانات التي يمكنك مخاطبتها بهذه اللغة سواء الحرة مثل ‪ MySql‬و‬
‫‪PostgreSQL‬أو المملوكة مثل الشهيرة ‪ Oracle‬وهناك قواعد بيانات تدعم ‪ SQL‬كميزة إضافية‬
‫غير أساسية‪.‬‬
‫بعكس ما قد يخطر ببالك ليس بالضرورة أن تكون قواعد البيانات برمجيات عبر شبكة فهناك منها ما هي‬
‫هيئة ملفات تستخدمها تماما كما تكتب قيم بينها فواصل ‪ CSV‬في ملف لكنها تكون أسرع وأكثر كفاءة‬
‫وفعالية‪ .‬منها قواعد بيانات ‪ SQLite‬التي أطلقت عام ‪ ١٠٠٦‬م بعد قيام مؤلفها بأبحاث لصالح البحرية‬
‫للتحكم بالمدمرات الصاروخية‪.‬‬
‫اخترنا ‪ SQLite‬لعدة أسباب‬

‫ال تحتاج التعقيدات المرتبطة بنموذج الخادم والعميل ‪ client/server‬فهي في النهاية مجرد‬ ‫‪‬‬
‫ملف‪.‬‬
‫مع أنها صممت كي تكون منضدة إال أنه يمكنها التعامل مع كم كبير من البيانات‬ ‫‪‬‬
‫تدعم معايير‪ ٨١ SQL-‬بشكل كبير‪.‬‬ ‫‪‬‬

‫كل ما يلزمنا في هذه الوثيقة برنامج صغير اسمه‪ (٣ sqlite‬في فيدورا‪/‬أعجوبة تجده في حزمة )‪sqlite‬‬
‫وهناك إضافة متصفح اإلنترنت لثعلب النار ‪ firefox‬تسمح لك بالتعامل رسوميا مع ملفات‪SQLite.‬‬

‫األساسيات‬
‫تتألف قاعدة البيانات من عدد من الجداول كل منها له مخطط ثابت ‪ schema‬يحدد ما يحتويه كل جدول‬
‫من حقول (أعمدة‪).‬‬

‫أنواع الحقول‬

‫في ‪ SQL‬القياسية يجب تعريف أنواع الحقول بشكل مسبق وااللتزام بها‪.‬‬

‫الحقول النصية‬ ‫‪‬‬


‫‪ o‬حرة الطول ذات حد أعلى ‪VARCHAR‬ونتبعها بعدد صحيح بين قوسين هو الحد‬
‫األعلى لطولها‪.‬‬
‫‪ o‬ثابت الطول ‪CHAR‬متبوع هو اآلخر بعدد بين قوسين توسّد محتوياته بمسافات إن‬
‫قل طولها عنه‪.‬‬

‫‪Formation 01 taghit‬‬
‫‪Sql /sqllit‬‬ ‫‪yahi mohammed‬‬

‫‪ o‬ومثلهما حقلي ‪NVARCHAR‬و ‪NCHAR‬لكنهما مع إضافة دعم المحارف‬


‫العالمية‪.‬‬
‫الحقول العددية‬ ‫‪‬‬
‫‪ o‬الصحيحة وهي ‪INTEGER‬و ‪SMALLINT‬‬
‫‪ o‬النسبية ذات الفاصلة العائمة ‪FLOAT‬و ‪REAL‬و ‪DOUBLE PRECISION‬‬
‫‪ o‬عدد من البتات ‪BIT‬و ‪VARBIT‬‬
‫حقول منطقية ‪BOOL‬و ‪BOOLEAN‬‬ ‫‪‬‬
‫حقول زمنية ‪DATETIME‬و ‪TIME‬و ‪DATE‬و ‪TIMESTAMP‬‬ ‫‪‬‬

‫>‪<note‬تسمح لك ‪ SQlite‬بعدم االلتزام بنوع الحقل المعرف في المخطط ‪ Schema‬كأن تضع نص‬
‫في حقل عددي وهو ما يعرف بميزة >‪ dynamic typing. </note‬من مرونة ‪ SQlite‬فإنها توفر‬
‫األنواع اإلضافية التالية‪:‬‬

‫حقل نصي عالمي حر الطول ‪TEXT‬وهو يدعم ‪ unicode‬دون الحاجة لتحديد أي طول‪.‬‬ ‫‪‬‬
‫(هذا النوع متوفر في ‪ MySQL‬و)‪PostgreSQL‬‬
‫حقل ثنائي ‪BLOB‬لحفظ سلسلة من البيانات (ليس بالضرورة أن تكون نصا كحفظ محتويات‬ ‫‪‬‬
‫ملف ‪ .jpg‬مثال)‬
‫حقل عددي صحيح ‪INTEGER‬‬ ‫‪‬‬
‫وحقل عددي نسبي ‪REAL‬‬ ‫‪‬‬

‫ال توفر ‪ SQLite‬دعما حقيقيا لحفظ التاريخ والوقت لكن يمكنك محاكاة ذلك عبر استعمال ‪INTEGER‬‬
‫وحفظ عدد الثواني بعد ما يعرف ببزوغ فجر يونكس‪Unix epoch.‬‬
‫يمكنك استعمال أنواع ‪ SQL‬القياسية لكن اعلم أن ‪ SQLite‬ستدير الحجم ولن تحترم النوع أو الحد‬
‫الذي تطلبه‪.‬‬
‫>‪<note tip‬يفضل البعض استخدام حقول من قوى ‪ ١‬مثل(‪) ٦١٩ VARCHAR‬إال أن هذا في‬
‫‪SQLite‬ليس منه فائدة ألنها كلها من نوع>‪TEXT </note‬‬

‫إنشاء قاعدة بيانات‬

‫تختلف الطريقة من قاعدة بيانات إلى أخرى‪.‬‬

‫في‪SQLite‬‬

‫في ‪ sqlite‬يكفي تنفيذ‪ ٣ sqlite‬متبوعا باسم الملف المطلوب إنشاؤه ليكون قاعدة بيانات‬

‫‪sqlite3 my_db_file.db‬‬

‫وألغراض االختبار يمكنك استعمال جدول في الذاكرة المتطايرة ‪ RAM‬وذلك بتمرير ‪:memory:‬‬
‫عوضا عن اسم الملف هكذا‬

‫‪sqlite3 :memory:‬‬

‫يتوفر واجهة رسومية تتعامل مع ملفات ‪ sqlite‬وهي متوفرة بصيغتين أسهلهما إضافة لمتصفح اإلنترنت‬
‫( ‪firefox‬داخل قائمة أدوات )‪ tools‬أو برنامج مستقل (يتم تنفيذه عبر)‪xulrunner‬‬

‫‪https://addons.mozilla.org/en-US/firefox/addon/sqlite-manager/‬‬ ‫‪‬‬

‫‪Formation 01 taghit‬‬
Sql /sqllit yahi mohammed

http://code.google.com/p/sqlite-manager/ 

MySQL‫في‬

‫ نتصل مع خادم قاعدة البيانات مثال باألمر‬mysql ‫في‬

mysql --default-character-set=utf8 -u root

root.‫ يمكنك تحديد مستخدم غير‬.‫ حتى يسألك عن كلمة السر‬p ‫أضف الخيار‬
‫ثم ننشئ قاعدة البيانات باألمر‬

CREATE DATABASE testdb;

. </note> <note ‫ بأحرف كبيرة‬SQL ‫<جرت العادة أن تكتب الكلمات المحجوزة في‬note tip>
; </note>‫ بفاصلة منقوطة‬SQL ‫تتبع كل عبارات‬important>
‫حيث جدول بها هكذا‬SHOW DATABASES ‫ولعرض بقواعد البيانات المتوفرة نستعمل‬

mysql> show databases;


+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| testdb |
+--------------------+

Formation 01 taghit
‫‪Sql /sqllit‬‬ ‫‪yahi mohammed‬‬

‫)‪3 rows in set (0.00 sec‬‬

‫>‪mysql‬‬

‫الختيار قاعدة بيانات نستعمل ‪USE‬متبوعا باسم قاعدة البيانات ويمكن عمل هذا االختيار عند االتصال‬
‫بخادم ‪ mysql‬بكتابة اسم قاعدة البيانات في نهاية األمر‬

‫‪mysql --default-character-set=utf8 -u root -p testdb‬‬

‫إنشاء الجداول‬

‫إلنشاء جدول نستخدم ‪ CREATE TABLE‬ويمكن إنشاء جدول مؤقت متطاير المحتوى عبر‬
‫‪CREATE TEMPORARY TABLE‬وهو جدول حذف تلقائيا عند إنهاء االتصال (إغالق‬
‫البرنامج‪).‬‬
‫ويمكن أن نضيف أيضا ‪ IF NOT EXISTS‬حتى ال يعطي خطأ إن كان الجدول موجودا مسبقا‪ .‬بعدها‬
‫نذكر اسم الجدول وبين قوسين نكتب تعريف لألعمدة الموجودة فيه‬

‫( ‪CREATE TABLE addressbook‬‬


‫(‪), ٠٣name VARCHAR‬‬
‫(‪), ٠٣email VARCHAR‬‬
‫(‪)٠٣phone VARCHAR‬‬
‫;)‬

‫>‪<note tip‬تعتبر لغة ‪ SQL‬من اللغات حرة التنسيق ‪ Free form‬لهذا يجوز أن تكتب العبارة‬
‫الواحدة على عدة أسطر>‪. </note‬‬
‫يمكنك وصف عمود ما بأنه معرّف أساسي ‪ PRIMARY KEY‬أو بأنه فريد ‪ UNIQUE‬أو مفهرس‬
‫‪KEY‬أو أنه ال ينبغي أن يكون خاليا ‪ NOT NULL‬كما يمكنك أن تعطيه قيمة أولية كذلك يمكن جعله‬
‫ذاتي الزيادة( ‪ AUTOINCREMENT‬أو كما في ‪ mysql‬يكتب ‪AUTO_INCREMENT‬‬
‫بعالمة تحتية _) وسيأتي تفصيل ذلك‪.‬‬

‫( ‪CREATE TABLE addressbook‬‬


‫‪id INTEGER PRIMARY KEY,‬‬
‫(‪) UNIQUE, ٠٣name VARCHAR‬‬
‫(‪) NOT NULL, ٠٣email VARCHAR‬‬
‫(‪) DEFAULT "NA"٠٣phone VARCHAR‬‬
‫;)‬

‫>‪<note tip‬يسمى األمر السابق باسم ‪ Data Definition Language‬أو ‪ DDL‬اختصارا ‪.‬‬
‫>‪</note‬‬

‫إضافة الصفوف‬

‫‪Formation 01 taghit‬‬
‫‪Sql /sqllit‬‬ ‫‪yahi mohammed‬‬

‫يمكننا إضافة الصفوف إلى الجدول عبر ‪ INSERT INTO‬متبوعة باسم الجدول ثم ‪ VALUES‬ثم‬
‫القيم بين قوسين‬

‫( ‪٠٠٠٩١٣٣٣-٦-٢٦٩, 'omar','omar@gmail.com', '+١INSERT INTO addressbook VALUES‬‬


‫;)'‬

‫لكن إن كنت تريد تحديد قيم ألعمدة بعينها وترك الباقية للقيم التلقائية (مثل المعرف ذاتي الزيادة) يمكنك‬
‫تحديد األعمدة التي تريدها بين قوسين بعد اسم الجدول هكذا‬

‫‪INSERT INTO addressbook (name, email, phone) VALUES ('ahmad','ahmad@gmail.c‬‬


‫‪');٠٠٠٩١٣٣٣-٦-٢٦٩om', '+‬‬
‫;)'‪INSERT INTO addressbook (name, email) VALUES ('ali','ali@gmail.com‬‬

‫عرض كل الصفوف‬

‫لعرض كل الصفوف من جدول ما (مثل جدول ‪ addressbook‬من المثال السابق) يمكننا كتابة‬
‫‪ SELECT‬متبوعة بأسماء األعمدة أو * الختيار كل األعمدة متبوعة بكلمة ‪ FROM‬متبوعة باسم‬
‫الجدول هكذا‬

‫;‪SELECT * FROM addressbook‬‬

‫والتي تعطي النتيجة التالية‬


‫‪id‬‬ ‫‪name‬‬ ‫‪email‬‬ ‫‪phone‬‬
‫‪١‬‬ ‫‪omar‬‬ ‫‪omar@gmail.com‬‬ ‫‪٠٠٠٩١٣٣٣-٦-٢٦٩+‬‬
‫‪٩‬‬ ‫‪ahmad‬‬ ‫‪ahmad@gmail.com‬‬ ‫‪٠٠٠٩١٣٣٣-٦-٢٦٩+‬‬
‫‪٠‬‬ ‫‪ali‬‬ ‫‪ali@gmail.com‬‬ ‫‪NA‬‬
‫فإن حددنا األعمدة مثال عمودي ‪ name‬و‪phone‬‬

‫;‪SELECT name, phone FROM addressbook‬‬

‫والتي تعطي النتيجة التالية‬


‫‪name‬‬ ‫‪phone‬‬
‫‪omar‬‬ ‫‪٠٠٠٩١٣٣٣-٦-٢٦٩+‬‬
‫‪ahmad‬‬ ‫‪٠٠٠٩١٣٣٣-٦-٢٦٩+‬‬
‫‪ali‬‬ ‫‪NA‬‬

‫استخراج ‪ dump‬من قاعدة البيانات‬

‫ألغراض النسخ االحتياطي أو التصدير يمكنك استخراج أوامر ‪ SQL‬التي تلزم إلعادة بناء قاعدة البيانات‬
‫بكل جداولها بكل صفوفها ويسمى هذا‪dump.‬‬
‫في ‪ SQLite‬يكون ذلك عبر األمر الخاص( ‪ .dump‬أي نقطة متبوعة بكلمة )‪ dump‬اكتبه في محث‬
‫‪ ٣sqlite‬ثم اضغط ‪ ENTER‬دون وضع فاصلة منقوطة‪.‬‬
‫ويعمل أيضا من سطر األوامر مثال في سطر أوامر نظام التشغيل (وليس )‪ SQLite‬اكتب‬

‫‪Formation 01 taghit‬‬
‫‪Sql /sqllit‬‬ ‫‪yahi mohammed‬‬

‫‪sqlite3 my_db_file.db .dump‬‬

‫عرض بنية قاعدة البيانات‬

‫إن كنت تحتاج عرض مخطط قاعدة البيانات بكل جداولها لكن دون الصفوف اكتب في محث‪٣ sqlite‬‬
‫األمر الخاص( ‪ .schema‬أي نقطة متبوعة بكلمة ‪ schema‬متبوعة بالضغط على)‪ENTER‬‬

‫حذف جدول‬

‫لحذف جدول (الصفوف والمخطط) نستخدم األمر ‪ DROP TABLE‬هكذا‬

‫;‪DROP TABLE addressbook‬‬

‫إنشاء الجداول وفهرستها‬


‫الفهارس‬

‫لتسريع الوصول لصف يحتوي على قيمة معينة لحقل ما في جدول ما يجب أن يكون ذلك الحقل مفهرسا‬
‫مثال للحصول على الصف الذي يحتوي القيمة ‪ omar‬لعمود ‪ name‬في جدول ‪ addressbook‬فإن‬
‫قاعدة البيانات ستسير على كل الصفوف بحثا عن تلك القيمة في الجدول لكن إن كان هناك فهرس على‬
‫حقل االسم فإنها ستجده مباشرة دون المرور على كل الصفوف‪ .‬ليس المساواة فقط بل المقارنة مثال‬
‫للحصول على كل الصفوف في جدول العالمات التي تزيد تزيد العالمة عن ‪ ٩٠‬فإن كانت العالمة‬
‫مفهرسة لن يتم مقارنة كل الصفوف بل يتم استخدام الفهرس لمعرفة تلك الصفوف مباشرة‪ .‬أيضا تفيد‬
‫الفهرسة تسريع في الترتيب التصاعدي أو التنازي للحقل المفهرس‪.‬‬
‫يكون إنشاء الفهرس عبر استخدام ‪ CREATE INDEX‬أو ‪ CREATE UNIQUE INDEX‬ثم‬
‫اسم الفهرس (اسم فريد ضمن نفس الجدول يجوز أن يكون اسم الحقل) ثم كلمة ‪ ON‬ثم بين قوسين‬
‫الحقول التي تعمل الفهرسة عليها مثال‪:‬‬

‫( ‪CREATE TABLE tags‬‬


‫(‪) UNIQUE, ٠٣name VARCHAR‬‬
‫(‪) NOT NULL,٠٣n VARCHAR‬‬
‫;)‬
‫;)‪CREATE INDEX n ON tags (n‬‬

‫هنا عملنا فهرسا فريدا ضمنيا على حقل االسم ألننا استعملنا كلمة ‪ UNIQUE‬عند انشاء الجدول‪ .‬وعملنا‬
‫فهرسا غير فريد على حقل التكرار ‪ n‬عبر ‪ CREATE INDEX‬بعد إنشاء الجدول‪.‬‬
‫>‪<note warning‬من األخطاء الشائعة عند تعلم إنشاء الفهارس في ‪ SQL‬هو أن األقواس بعد‬
‫‪ ON‬تسمح لك بعمل أكثر من فهرس على أكثر من حقل وهذا خطأ بل هي تعمل فهرس واحد مركب‬
‫من تجميع الحقول >‪. </note‬الحظ هذا المثال‬
‫لكن لو أردنا أن نعمل فهرسا فريدا لالسم األول وآخر لالسم الثاني‬

‫( ‪CREATE TABLE users‬‬

‫‪Formation 01 taghit‬‬
Sql /sqllit yahi mohammed

),٠٣first_name VARCHAR(
),٠٣last_name VARCHAR(
UNIQUE (first_name),
UNIQUE (last_name)
);
CREATE UNIQUE INDEX first_name ON users (first_name)
CREATE UNIQUE INDEX last_name ON users (last_name);

:‫والذي يكافئ‬

CREATE TABLE users (


),٠٣first_name VARCHAR(
),٠٣last_name VARCHAR(
UNIQUE (first_name),
UNIQUE (last_name)
);

:‫ لكن المثال التالي‬.‫لكن هذا ليس ما نريده فهو يمنع تكرار االسم األول حتى لو اختلف االسم الثاني‬

CREATE TABLE users (


),٠٣first_name VARCHAR(
)٠٣last_name VARCHAR(
);
CREATE UNIQUE INDEX first_last_name ON users (first_name, last_name);

‫هنا الفريد ليس الحقل األول أو الثاني بل تركيبهما معا أي يجوز أن يكون االسم األول مكررا إن اختلف‬
‫ الجدول السابق يمكن إنشاؤه بأمر واحد هكذا‬.‫الثاني‬

CREATE TABLE users (


),٠٣first_name VARCHAR(
),٠٣last_name VARCHAR(
UNIQUE (first_name, last_name)
);

‫ يكون سريعا كذلك الوصول‬ahmad ‫ والثاني‬omar ‫هنا الحصول على الصف الذي فيه االسم األول‬
‫ مهما كان االسم الثاني أيضا يكون سريعا‬ali ‫لكل الصفوف التي فيها االسم األول‬
‫ ثم‬b ‫ ثم‬a ‫<ترتيب الحقول مهم في الفهرس فإن كان عندك فهرس واحد على ثالث حقول هي‬note>
‫ بسرعة لكن ليس‬c ‫ وال‬b ‫ دون تحديد‬a ‫فإنك تستطيع البحث أو الترتيب بسرعة على السوابق أي قيم‬c
a. </note>‫دون تحديد‬b

Formation 01 taghit
‫‪Sql /sqllit‬‬ ‫‪yahi mohammed‬‬

‫المفتاح الرئيسي ‪PRIMARY KEY‬‬

‫المفتاح الرئيسي ما هو إال فهرس فريد يستخدم لجلب الحقول سريعا‪ .‬في الغالب يكون هذا الحقل حقل‬
‫رقمي متزايد تلقائيا‪ .‬ويجوز أن يكون على حقل عددي أو نصي أو حتى تركيب عدة الحقول (متجانسة‬
‫النوع أو غير متجانسة النوع‪).‬‬
‫هناك صيغتين لتعريفه بعد الحقل مباشرة هكذا‬

‫( ‪CREATE TABLE addressbook‬‬


‫‪uid INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,‬‬
‫(‪), ٠٣name VARCHAR‬‬
‫(‪), ٠٣email VARCHAR‬‬
‫(‪)٠٣phone VARCHAR‬‬
‫;)‬

‫أو بعد الحقول بطريقة تشبه تعريف الفهارس ويمكن أن تكون مركبة بذكر أكثر من حقل‬

‫( ‪CREATE TABLE addressbook‬‬


‫‪uid INTEGER NOT NULL AUTOINCREMENT,‬‬
‫(‪), ٠٣name VARCHAR‬‬
‫(‪), ٠٣email VARCHAR‬‬
‫(‪),٠٣phone VARCHAR‬‬
‫)‪PRIMARY KEY (uid‬‬
‫;)‬

‫>‪<note‬نذكر بأن الحقل ذاتي الزيادة في ‪ MYSQL‬يكتب ‪ AUTO_INCREMENT‬بعالمة تحتية‬


‫>‪_</note‬‬

‫االستعالم‬
‫االستعالم يكون عبر‪SELECT‬‬

‫تطبيق بعض الحسابات‬

‫يمكننا استخدام االستعالم باألمر ‪ SELECT‬من أجل القيام بحسابات هكذا‬

‫‪;١+١SELECT‬‬
‫(‪);١,-٠,٩,١SELECT MAX‬‬
‫;)"‪SELECT LENGTH("ojuba‬‬

‫عرض حقول مخصوصة‬

‫‪Formation 01 taghit‬‬
‫‪Sql /sqllit‬‬ ‫‪yahi mohammed‬‬

‫يمكن عرض كل الحقول عبر * ويمكن تحديد الحقول المطلوبة عبر سردها مفصولة بعالمة‪,‬‬

‫;‪SELECT first_name, last_name FROM users‬‬

‫يمكن عمل كنية لكل حقل عبر ‪ AS‬هكذا‬

‫;‪SELECT first_name AS n1, last_name AS n2 FROM users‬‬

‫الترتيب‬

‫يمكنك ترتيب الصفوف عبر ‪ ORDER BY‬متبوعة باسم الحقل ثم( ‪ ASC‬وهو التلقائي) أو ‪DESC‬‬
‫للتصاعدي أو التنازلي على الترتيب‪.‬‬

‫;‪SELECT * FROM users ORDER BY last_name ASC‬‬

‫يجوز الترتيب على أكثر من حقل‬

‫;‪SELECT * FROM users ORDER BY first_name ASC, last_name ASC‬‬

‫في هذا المثال نرتب على االسم األول فإن تساوى على األخير‪.‬‬

‫الحد وتقليب الصفحات‬

‫يمكن وضع حد أعلى لعدد الصفوف المجلوبة عبر عبارة ‪ LIMIT‬مثال الستخراج صف واحد يمكنك‬
‫كتابة‬

‫‪١SELECT * FROM addressbook LIMIT‬‬

‫الستخراج أول ‪ ٥‬صفوف عند التريب حسب االسم األخير أبجديا‬

‫‪٠SELECT * FROM addressbook ORDER BY last_name LIMIT‬‬

‫يمكن تخطي عدد من الصفوف بواسطة عبارة اإلزاحة ‪ OFFSET‬متبوعة بعدد الصفوف المتخطاة‪.‬‬
‫مثال العبارة السابقة تكافئ‬

‫‪٣ OFFSET ٠SELECT * FROM addressbook ORDER BY last_name LIMIT‬‬

‫أما الصفحة الثالثة فتكون بتخطي ‪ ٦٠‬صفوف (‪ ٥‬في كل صفحة) لعرض الصفوف حتى الخامس عشر‪.‬‬

‫‪١٣ OFFSET ٠SELECT * FROM addressbook ORDER BY last_name LIMIT‬‬

‫ويمكن وضع فاصلة ‪ ,‬مكان عبارة ‪ OFFSET‬لكن ترتيب التعبيرين مقلوب (اإلزاحة أوال ثم الحد)‬

‫‪٠, ١٣SELECT * FROM addressbook ORDER BY last_name LIMIT‬‬

‫لعرض رقم آخر صف يمكن استخدام الترتيب العكسي مع وضع حد أعلى صف واحد‬

‫‪Formation 01 taghit‬‬
‫‪Sql /sqllit‬‬ ‫‪yahi mohammed‬‬

‫‪١SELECT rowid FROM addressbook ORDER BY rowid DESC LIMIT‬‬

‫الشرط‪WHERE‬‬

‫يمكن عرض الصفوف التي تطابق شرط معين عبر عبارة ‪ WHERE‬متبوعة بالشرط أو الشروط‬
‫المركبة عبر ‪ AND‬أو ‪ OR‬ويمكن استخدام األقواس‪.‬‬
‫مثال لعرض الصفوف التي يكون االسم األخير فيها ‪ omar‬نكتب االستعالم‬

‫;'‪SELECT * FROM addressbook WHERE last_name = 'omar‬‬

‫هناك الكثير من العبارات المرنة يمكن أن نستعملها بعد ‪ WHERE‬مثل‪:‬‬

‫فحص المساواة=‬ ‫‪‬‬


‫المقارنة <أو >‬ ‫‪‬‬
‫‪IS NULL‬‬ ‫‪‬‬
‫‪IS NOT NULL‬‬ ‫‪‬‬
‫‪ o‬مطابقة األنماط عبر الشبه ‪ LIKE‬حيث نستعمل ‪ %‬بمعنى أي شيء من أي طول‬

‫مثال لعرض األسماء التي تبدأ ب‪A‬‬

‫;‪SELECT * FROM addressbook WHERE last_name LIKE 'A%' ORDER BY last_name‬‬

‫>‪ <note tip‬مطابقة نمط السوابق (كما في المثال السابق) يستفيد من الفهارس أما اللواحق أو التوسط‬
‫فال يستفيد>‪. </note‬‬
‫>‪<note tip‬قبل أن تتندر على كود ‪ NULL=NULL‬تعطي ‪ FALSE‬عليك تخيل أن ‪ NULL‬تمثل‬
‫قيمة مجهولة خالية‪ .‬فإن القيمة المجهولة ال تساوي القيمة المجهولة األخرى‪ .‬لهذا نستعمل أداة ‪IS‬‬
‫>‪NULL </note‬‬

‫ربط الجداول‪JOIN‬‬
‫يمكن مقابلة جدولين أو أكثر كل صف في األول مع كل صفوف اآلخر كما في الضرب الديكارتي‪ .‬لنأخذ‬
‫المثال التالي‪:‬‬

‫(‪) PRIMARY KEY, price DOUBLE, in_stock IN٩٣CREATE TABLE items (name VARCHAR‬‬
‫;)‪TEGER‬‬
‫(‪), NUMBER INTEGER);٩٣CREATE TABLE cart (item_name VARCHAR‬‬
‫‪);١٣٣٣, ٩.٠INSERT INTO items VALUES ('milk',‬‬
‫‪);٠٣٣٣, ٠.١INSERT INTO items VALUES ('chicken',‬‬
‫‪);٠INSERT INTO cart VALUES ('milk',‬‬
‫‪);١INSERT INTO cart VALUES ('milk',‬‬
‫‪);٩INSERT INTO cart VALUES ('chicken',‬‬

‫‪Formation 01 taghit‬‬
Sql /sqllit yahi mohammed

items‫جدول األصناف‬
name price in_stock
milk ٩.٠ ١٣٣٣
chicken ٠.١ ٠٣٣٣
cart‫جدول عربة التسوق‬
item_name number
milk ٠
milk ١
chicken ٩
‫مقابلة الجدولين تكون هكذا‬

SELECT *, price*NUMBER AS total_price FROM items JOIN cart;

‫والتي تعطي‬
name price in_stock item_name number total_price
milk ٩.٠ ١٣٣٣ milk ٠ ٥.٠
milk ٩.٠ ١٣٣٣ milk ١ ٩.٠
milk ٩.٠ ١٣٣٣ chicken ٩ ٠.٣
chicken ٠.١ ٠٣٣٣ milk ٠ ١٠.٠
chicken ٠.١ ٠٣٣٣ milk ١ ٠.١
chicken ٠.١ ٠٣٣٣ chicken ٩ ١٣.٩
!‫لكن هناك صفوف ال نريدها فلماذا نضرب عدد الدجاجات في سعر الحليب‬
‫ لمطابقة اسم الصنف‬WHERE ‫أول ما يخطر بالبال هو استعمال‬

SELECT *, price*NUMBER AS total_price FROM items JOIN cart WHERE name=item_


name;

‫حيث سنحصل على‬


name price in_stock item_name number total_price
milk ٩.٠ ١٣٣٣ milk ٠ ٥.٠
milk ٩.٠ ١٣٣٣ milk ١ ٩.٠
chicken ٠.١ ٠٣٣٣ chicken ٩ ١٣.٩
‫ متبوعا بشرط مطابقة الصفوف بين‬ON ‫ تأخذ بعدها مباشرة عبارة‬JOIN ‫لكن الداع لذلك فكل عبارة‬
:‫ كما في األمر التالي والذي يكافئ السابق‬JOIN ‫الجدولين يمين ويسار عبارة‬

SELECT *, price*NUMBER AS total_price FROM items JOIN cart ON name=item_nam


e;

‫إن كان هناك تشابه في األسماء فإننا بحاجة إلزالة الغموض وذلك بذكر اسم الجدول أو كنيته ثم نقطة ثم‬
name‫ عوضا عن‬items.name ‫اسم الحقل مثال‬

Formation 01 taghit
‫‪Sql /sqllit‬‬ ‫‪yahi mohammed‬‬

‫يمكنك أن تعطي الجدول أو الحقل كنية وذلك بذكر الكنية بعد عبارة ‪ AS‬كما فعلنا في حاصل ضرب‬
‫العدد في سعر ‪ price*number‬وسميناه السعر اإلجمالي‪total_price‬‬

‫أنواع الربط‬
‫الربط الداخلي( ‪ INNER JOIN‬النوع التلقائي)‬

‫لنضف حقول غير متقابلة في الجدولين‬

‫‪);٩٣٣٣, ٣.٠INSERT INTO items VALUES ('beans',‬‬


‫‪);١INSERT INTO cart VALUES ('cheese',‬‬

‫اآلن لننفذ أمر الربط السابق والذي يكافئ تحديد نوع الربط على أنه ‪ INNER JOIN‬ألنه التلقائي‬

‫‪SELECT *, price*NUMBER AS total_price FROM items INNER JOIN cart ON name=it‬‬


‫;‪em_name‬‬

‫نالحظ أن النتيج ة هي نفسها كما كانت قبل إضافة الحقول غير المتقابلة ولم نجد صنف ‪ beans‬ألنه لم‬
‫يظهر في عربة التسوق وال وجدنا الجبن الذي ظهر في العربة ولم يظهر في األضناف‬
‫لنقم اآلن بإضافة صفوف متقابلة لكن بقيمة خالية ‪ NULL‬في حقول التقابل‬

‫‪);٠٠٣٣, ٣.٥٠INSERT INTO items VALUES (NULL,‬‬


‫‪);١INSERT INTO cart VALUES (NULL,‬‬

‫وسنجد أن المقابلة الداخلية لم تشمل الصفوف الجديدة ألنها خالية‬


‫>‪<note tip‬تذكر أن الخالي ال يفحص بالتساوي ‪ NULL=NULL‬ألنه يعطي ‪ FALSE‬بل يفحص‬
‫ب>‪IS NULL </note‬‬

‫الربط الخارجي‪OUTER JOIN‬‬

‫وهو على ‪ ٣‬أنواع هي‬

‫التام‪FULL OUTER JOIN‬‬ ‫‪‬‬


‫األيسر ‪ LEFT OUTER JOIN‬أو ‪ LEFT JOIN‬اختصارا وهو الوحيد المدعوم في‬ ‫‪‬‬
‫‪SQLite‬‬
‫األيمن ‪ RIGHT OUTER JOIN‬أو ‪ RIGHT JOIN‬اختصارا‬ ‫‪‬‬

‫الربط الخارجي يربط الصفوف إن كان وإن كان أحد طرفي المقابلة خاليا ‪ NULL.‬أما الربط األيسر‬
‫فيمر على كل صفر في طرف المقابلة األيسر حتى وإن كان الطرف األيمن خال‪ .‬والمقابلة اليمنى بالعكس‪.‬‬

‫‪SELECT *, price*NUMBER AS total_price FROM items LEFT JOIN cart ON name=ite‬‬


‫;‪m_name‬‬

‫‪name‬‬ ‫‪price‬‬ ‫‪in_stock‬‬ ‫‪item_name‬‬ ‫‪number‬‬ ‫‪total_price‬‬


‫‪milk‬‬ ‫‪٩.٠‬‬ ‫‪١٣٣٣‬‬ ‫‪milk‬‬ ‫‪١‬‬ ‫‪٩.٠‬‬

‫‪Formation 01 taghit‬‬
‫‪Sql /sqllit‬‬ ‫‪yahi mohammed‬‬

‫‪name‬‬ ‫‪price‬‬ ‫‪in_stock‬‬ ‫‪item_name‬‬ ‫‪number‬‬ ‫‪total_price‬‬


‫‪milk‬‬ ‫‪٩.٠‬‬ ‫‪١٣٣٣‬‬ ‫‪milk‬‬ ‫‪٠‬‬ ‫‪٥.٠‬‬
‫‪chicken‬‬ ‫‪٠.١‬‬ ‫‪٠٣٣٣‬‬ ‫‪chicken‬‬ ‫‪٩‬‬ ‫‪١٣.٩‬‬
‫‪beans‬‬ ‫‪٣.٠‬‬ ‫‪٩٣٣٣‬‬ ‫‪NULL‬‬ ‫‪NULL‬‬ ‫‪NULL‬‬
‫‪NULL‬‬ ‫‪٣.٥٠‬‬ ‫‪٠٠٣٣‬‬ ‫‪NULL‬‬ ‫‪NULL‬‬ ‫‪NULL‬‬
‫وهنا علينا مالحظة ما يلي‪:‬‬

‫الحظ أن الجبن لم يكن بين النتائج ألنه في الطرف األيمن وال مقابل له في الطرف األيسر‪.‬‬ ‫‪‬‬
‫الصف األيسر الذي حقل المقابلة في خال ‪ NULL‬موجود لكنه لم يتم مقابلته مع األيمن الذي‬ ‫‪‬‬
‫حقل المقابلة فيه ‪ NULL‬بل كان ما يقابله حقول كلها خالية ذلك أن ‪ NULL‬ال تساوي ‪NULL‬‬
‫بل تفحصل ب‪IS NULL‬‬

‫>‪<note tip‬يمكن محاكة الربط األيمن بقلب الترتيب واستخادم األيسر>‪.</note‬‬


‫>‪<note tip‬الحظ أن الحليب موجود مرتين ذلك أن اسم الصنف في جدول ‪ items‬مفتاح أساسي فريد‬
‫أما في جدول عربة التسوق فهو حقل عادي غير فريد وهذا يقودنا الحقا لعمل عالقات واحد إلى أكثر‬
‫‪One to Many‬أما إن كان فريدا فتكون العالقة واحد لواحد ‪ One to One‬ويسمى اسم الصنف‬
‫‪item_name‬في جدول العربة المفتاح الخارجي>‪Foreign Key</note‬‬

‫تجميع الصفوف ‪GROUP BY‬‬


‫الحظ أن الحليب موجود مرتين في العربة يمكننا جمهما حيث تتيح لنا عبارة ‪ GROUP BY‬تحديد‬
‫عدد من الحقول إن تطابقت في أكثر من صف جمعا معا في صف واحد وذلك باستخدام الحقل المشترك‬
‫وأي عدد من دوال التجميع ‪ aggregation functions‬مثل المجموع ‪ SUM‬والمتوسط ‪AVG‬‬
‫وغيرها‪.‬‬

‫;‪SELECT item_name, SUM(NUMBER) AS total_number FROM cart GROUP BY item_name‬‬

‫والتي تعطي (حيث جمع مدخلتا الحليب في مدخلة واحدة عوضا عن ‪ ٦‬و ‪ ٣‬أصبحت مدخلة واحدة عددها‬
‫‪)٤‬‬
‫‪item_name‬‬ ‫‪total_number‬‬
‫‪NULL‬‬ ‫‪١‬‬
‫‪cheese‬‬ ‫‪١‬‬
‫‪chicken‬‬ ‫‪٩‬‬
‫‪milk‬‬ ‫‪٠‬‬
‫>‪<note important‬الحقول غير المذكورة في التجميع يجب أن تجلب عبر دالة تجميع وإال فإنها‬
‫ستكون واحد عشوائية من بين الصفوف المجمعة>‪. </note‬‬
‫إن استخدام أي دالة تجميع مثل ‪ SUM‬دون ذكر التجميع يؤدي إلى عملية تجميع لكل الصفوف‪ .‬لذا‬
‫يمكننا طباعة السعر اإلجمالي للفاتورة كاملة باالستعالم التالي‪:‬‬

‫;‪SELECT SUM(price*NUMBER) AS total FROM items JOIN cart ON name=item_name‬‬

‫االشتراط بعد التجميع عبر‪HAVING‬‬

‫‪Formation 01 taghit‬‬
‫‪Sql /sqllit‬‬ ‫‪yahi mohammed‬‬

‫ال يجوز استخدام أي من دوال التجميع مثل ‪ SUM‬في عبارة ‪ WHERE‬ألنها تنفذ قبل التجميع‬
‫‪GROUP BY‬وهنا جاءت الحاجة لعبارة ‪ HAVING‬والتي تذكر بعد‪GROUP BY‬‬
‫>‪<note tip‬ترتيب الشروط هو ‪ ON‬التي تستخدم مقرونة مع ‪ JOIN‬ثم ‪ WHERE‬والتي تحدث‬
‫قبل ‪ GROUP BY‬وأخيرا تنفذ>‪HAVING </note‬‬

‫اإلضافة من استعالم‬
‫يمكنك أخذ نواتج عملية االستعالم (بكل مزاياها) وتمريرها إلى ‪ INSERT INTO‬وذلك بوضع عبارة‬
‫‪SELECT‬مكان ‪ VALUES‬وذلك جائز سواء من نفس الجدول أو من جدول آخر أو من عملية دمج‬
‫… ‪JOIN‬إلخ‬

‫>‪;٠INSERT INTO t1 (col1, col2) SELECT t2.c1, t2.c2 FROM t2 WHERE t2.c1‬‬

‫ترحيل الحركات دفعة واحدة‪transactions‬‬


‫لنتخيل أن لدينا مجموعة من االستعالمات نريد تنفيذها دفعة واحدة (نسميها حركة )‪Transaction‬‬
‫وذلك بوضع ‪ BEGIN‬في قبل أول عملية و ‪ COMMIT‬بعد آخر واحدة هذا يجعلها أسرع بشكل كبير‬
‫جدا‬

‫;)‪CREATE TABLE t1 (col1 TEXT‬‬


‫;‪BEGIN‬‬
‫‪');١INSERT INTO t1 VALUES ('cell‬‬
‫‪');٩INSERT INTO t1 VALUES ('cell‬‬
‫‪');٠INSERT INTO t1 VALUES ('cell‬‬
‫‪');١INSERT INTO t1 VALUES ('cell‬‬
‫‪');٠INSERT INTO t1 VALUES ('cell‬‬
‫;‪COMMIT‬‬

‫لكن السرعة ليست هي الفائدة الوحيدة‪ .‬مثال فلتكن إضافة ‪ ٥‬صفوف لكن إضافة الصف الرابع فشلت‬
‫لسبب أو آلخر (كأن يكون حقل فريد مكرر) إن كنا نريد ضمان دخول الخمسة بحركة واحدة إما كلها‬
‫وإما ال شيء فإننا نستعمل ‪ ROLLBACK‬كي نعود إلى الحالة التي كان عليها قبل الحركة‪.‬‬
‫الحظ أن االستعالم في آخر المثال التالي لم يعد أي نتائج‪.‬‬

‫;)‪sqlite> DROP TABLE t1;CREATE TABLE t1 (col1 TEXT UNIQUE‬‬


‫;‪sqlite> BEGIN‬‬
‫‪');١sqlite> INSERT INTO t1 VALUES ('cell‬‬
‫‪');٩sqlite> INSERT INTO t1 VALUES ('cell‬‬
‫‪');٠sqlite> INSERT INTO t1 VALUES ('cell‬‬
‫‪');١sqlite> INSERT INTO t1 VALUES ('cell‬‬
‫‪Error: COLUMN col1 IS NOT UNIQUE‬‬

‫‪Formation 01 taghit‬‬
‫‪Sql /sqllit‬‬ ‫‪yahi mohammed‬‬

‫;‪sqlite> ROLLBACK‬‬
‫;‪sqlite> SELECT * FROM t1‬‬

‫هناك ‪ ٣‬أنواع من الحركات‬

‫المؤجل ‪ deferred‬وهو النوع التلقائي وهنا ال تففل قاعدة البيانات‪.‬‬ ‫‪‬‬


‫الفوري ‪ immediate‬هذا النوع يقفل عمليات الكتابة وال يقفل القراءة‬ ‫‪‬‬
‫الحصري ‪ exclusive‬هذا النوع يقفل كل شيء‬ ‫‪‬‬

‫العالقات‬
‫عالقة واحد إلى واحد‪One to One‬‬ ‫‪‬‬
‫عالقة واحد إلى العديد‪One to Many‬‬ ‫‪‬‬
‫عالقة العديد إلى واحد‪Many to One‬‬ ‫‪‬‬
‫عالقة العديد إلى العديد‪Many to Many‬‬ ‫‪‬‬

‫دعاة اسقاطها ‪NoSQL‬‬


‫ظهرت الكثير من الدعوات باسم ‪ NoSQL‬تدعو إلى التخلي عن ‪ SQL‬وهذا من أسوأ المصطلحات‬
‫في عالم الحاسوب فهي في الواقع ال تنتقد اللغة في حد ذاتها بل تنتقد الصفة العالئقية فيها ‪relational‬‬
‫ويقترح البعض تسميتها حركات‪NoREL.‬‬
‫قواعد البيانات العالقية ‪ RDBMS‬والتي نتخاطب معها بلغة ‪ SQL‬مبنية على مبدأ ‪ ACID‬أي‬

‫‪atomicity‬‬ ‫‪‬‬
‫‪consistency‬‬ ‫‪‬‬
‫‪isolation‬‬ ‫‪‬‬
‫‪durability‬‬ ‫‪‬‬

‫أما ‪ NoSQL‬فهي على مبدأ ‪ BASE‬أي‪:‬‬

‫‪Basically Available‬‬ ‫‪‬‬


‫‪Soft state‬‬ ‫‪‬‬
‫‪Eventual consistency‬‬ ‫‪‬‬

‫من أشهر العبارات التي تستخدم للدعوة إلى‪NoSQL‬‬

‫;‪SELECT fun, profit FROM real_world WHERE relational=FALSE‬‬

‫أحد أصدقائي محبي ‪ SQL‬رد عليهم‬

‫‪sec)٣.٣٣ ROWS selected (٣Query OK,‬‬

‫‪Formation 01 taghit‬‬

You might also like