لغة الاستعلامات الهيكلية SQL اختصار إلى Structured Query Language هي لغة برمجة متخصصة في إدارة قواعد البيانات العلائقية RDBMS اختصار إلى Relational database management system. كما تُستخدم اللغات المشتقة من SQL في أنظمة إدارة مجاري البيانات العلائقية RDSMS اختصار إلى Relational Data Stream Management Systems، أو في إدارة قواعد بيانات SQL الحصرية NoSQL.
تتألف SQL من ثلاث لغات فرعية أساسية، وهي:
- لغة تعريف البيانات DDL: تُستعمل لإنشاء وتعديل بنية قاعدة البيانات.
- لغة معالجة البيانات DML: تستعمل لتنفيذ عمليات قراءة البيانات وإدراجها وتحديثها وحذفها.
- لغة التحكم في البيانات DCL: تُستعمل للتحكم في الوصول إلى البيانات المخزّنة في قاعدة البيانات.
تتألف DML من أربع عمليات أساسية، وهي عمليات الإنشاء (Create) والقراءة (Read) والتحديث (Update) والحذف (Delete)، ويُطلق عليها اختصارًا CRUD، تُنفّذ هذه العمليات عبر التعليمات INSERT
و SELECT
و UPDATE
و DELETE
على التوالي.
أُضيفت مؤخرًا تعليمة MERGE
، والتي تنفّذ العمليات INSERT
و UPDATE
و DELETE
معًا.
تُقدَّم العديد من قواعد بيانات SQL على هيئة نُظم عميل / خادم (client/server systems). ويُطلق على هذه الخوادم مصطلح "خادم SQL".
أنشأت ميكروسوفت قاعدة بيانات تسمى "SQL Server". ورغم أنّها تُعدّ من لهجات SQL، إلا أنّنا لن نتحدث عنها في هذه السلسلة، إن كنت تريد تعلّمها فيمكنك الرجوع إلى توثيقها.
المعرفات identifiers
يستعرض هذا القسم موضوع المعرّفات (identifiers)، وتشرح قواعد تسمية الجداول والأعمدة وباقي كائنات قاعدة البيانات. سنحاول أن تغطي الأمثلة الاختلافات بين تقديمات SQL المختلفة.
المعرفات غير المقتبسة Unquoted identifiers
يمكن أن تحتوي المعرّفات غير المُقتبسة على الحروف (a
- z
) والأرقام (0
- 9
) والشرطة السفلية (_
)، وفي جميع الأحوال، ينبغي أن تبدأ بحرف.
اعتمادًا على تقديم SQL المُستخدم، و / أو إعدادات قاعدة البيانات، قد يجوز استخدام أحرف أخرى، وبعضها يمكن أن تُستخدم حرفًا أولًا للمعرّف.
هذه بعض الأمثلة على الأحرف الجائزة:
-
MS SQL:
@
و$
و#
وباقي محارف اليونيكود -Unicode - الأخرى، المصدر -
MySQL:
$،
المصدر -
Oracle:
$
و#
وبافي الأحرف من مجموعة أحرف قاعدة البيانات، المصدر -
PostgreSQL:
$
وباقي أحرف اليونيكود الأخرى، المصدر
المعرّفات غير المقتبسة غير حسّاسة لحالة الأحرف عمومًا. بيْد أنّ طريقة التعامل مع حالة الأحرف تختلف بحسب تقديم SQL، مثلًا:
- MS SQL: تحافظ على الحالة (Case-preserving)، إذ تُحدّد مسألة الحساسية لحالة الأحرف عبر مجموعة أحرف قاعدة البيانات (database character set)، لذا يمكن أن تكون حساسة لحالة الأحرف.
- MySQL: تحافظ على الحالة، وتعتمد الحساسية على إعدادات قاعدة البيانات ونظام الملفات الأساسي.
- Oracle: تُحوّل إلى أحرف كبيرة، ثم تُعامل كمعرفّات مقتبسة.
- PostgreSQL: تُحوّل إلى أحرف صغيرة، ثم تُعامل مثل المعرّفات المقتبسة.
- SQLite: تحافظ على الحالة. وعدم حساسيتها تقتصر على أحرف ASCII.
أنواع البيانات Data Types
DECIMAL و NUMERIC
يمثل النوعان DECIMAL
و NUMERIC
أعدادّا عشرية ذات دقة ثابتة، وهما متكافئان وظيفيًا. ويُصاغان على النحو التالي:
DECIMAL ( precision [ , scale] ) NUMERIC ( precision [ , scale] )
أمثلة:
SELECT CAST(123 AS DECIMAL(5,2)) --returns 123.00 SELECT CAST(12345.12 AS NUMERIC(10,5)) --returns 12345.12000
FLOAT و REAL
يمثل نوعًا الأعداد FLOAT و REAL الأعداد التقريبية، ويُستخدمان لتمثيل البيانات الرقمية ذات الفاصلة العائمة (floating point numeric data).
SELECT CAST( PI() AS FLOAT) --returns 3.14159265358979 SELECT CAST( PI() AS REAL) --returns 3.141593
الأعداد الصحيحة Integers
يمثل النوع Integers البيانات العددية الصحيحة.
نوع البيانات | النطاق | مساحة التخزين |
---|---|---|
bigint | -2^63 (-9,223,372,036,854,775,808) إلى 2^63-1 (9,223,372,036,854,775,807) | 8 بايتات |
int | -2^31 (-2,147,483,648) إلى 2^31-1 (2,147,483,647) | 4 بايتات |
smallint | -2^15 (-32,768) إلى 2^15-1 (32,767) | بايتان |
tinyint | من 0 إلى 255 | بايت واحد |
MONEY و SMALLMONEY
يمثل النوعان MONEY و SMALLMONEY البيانات التي تمثل القيم النقدية أو العملات.
نوع البيانات | النطاق | مساحة التخزين |
---|---|---|
money | -922,337,203,685,477.5808 إلى 922,337,203,685,477.5807 | 8 بايتات |
smallmoney | -214,748.3648 إلى 214,748.3647 | 4 بايتات |
BINARY و VARBINARY
يمثل النوعان BINARY و VARBINARY البيانات الثنائية ذات الطول الثابت أو المتغير. ويُصاغان على النحو التالي:
BINARY [ ( n_bytes ) ] VARBINARY [ ( n_bytes | max ) ]
يمكن أن يكون n_bytes
أي عدد محصور بين 1 إلى 8000 أثمون. وتشير قيمة max
إلى أنّ الحد الأقصى لمساحة التخزين هو 2^31-1
.
أمثلة:
SELECT CAST(12345 AS BINARY(10)) -- 0x00000000000000003039 SELECT CAST(12345 AS VARBINARY(10)) -- 0x00003039
CHAR و VARCHAR
يمثل النوعان CHAR و VARCHAR البيانات النصية ذات الطول الثابت أو المتغير. ويُصاغان على النحو التالي:
CHAR [ ( n_chars ) ] VARCHAR [ ( n_chars ) ]
أمثلة:
SELECT CAST('ABC' AS CHAR(10)) -- 'ABC ' (إزاحة بمسافات بيضاء إلى اليمين) SELECT CAST('ABC' AS VARCHAR(10)) -- 'ABC' (لا إزاحة) SELECT CAST('ABCDEFGHIJKLMNOPQRSTUVWXYZ' AS CHAR(10)) -- 'ABCDEFGHIJ' (تُقصّ إلى عشرة أحرف فقط)
NCHAR و NVARCHAR
يمثل النوعان NCHAR و NVARCHAR نصوص اليونيكود ذات الطول الثابت أو المتغير. ويُصاغان على النحو التالي:
NCHAR [ ( n_chars ) ] NVARCHAR [ ( n_chars | MAX ) ]
استخدم MAX
لأجل السلاسل النصية الطويلة التي يمكن أن تتجاوز 8000 حرفًا.
UNIQUEIDENTIFIER
يمثل هذا النوع مُعرّفا كونيا فريدًا (Universally Unique IDentifier أو UUID) أو معرّفًا عامّا فريدًا (globally unique identifier أو GUID) مُخزّنا على 16 أثمونًا.
DECLARE @GUID UNIQUEIDENTIFIER = NEWID(); SELECT @GUID -- 'E28B3BD9-9174-41A9-8508-899A78A33540' DECLARE @bad_GUID_string VARCHAR(100) = 'E28B3BD9-9174-41A9-8508-899A78A33540_foobarbaz' SELECT @bad_GUID_string, -- 'E28B3BD9-9174-41A9-8508-899A78A33540_foobarbaz' CONVERT(UNIQUEIDENTIFIER, @bad_GUID_string) -- 'E28B3BD9-9174-41A9-8508-899A78A33540'
الكلمة المفتاحية NULL
تمثل الكلمة المفتاحية NULL
في SQL، وكذلك في لغات البرمجة الأخرى، القيمة المعدومة، أو "لا شيء". وتُستخدم عادة في SQL للإشارة إلى "عدم وجود قيمة".
من المهم التمييز بينها وبين القيم الفارغة، مثل السلسلة النصية ''
الفارغة أو الرقم 0
، إذ لا يُعدّ أي منهما في الواقع معدومًا (NULL
). من المهم أيضًا تجنّب إحاطة NULL
بعلامات الاقتباس، على شاكلة 'NULL'
، والتي يمكن استخدامها في الأعمدة التي تقبل القيم النصية، بيد أنّها لا تمثّل القيمة NULL
، ويمكن أن تسبّب أخطاءً، وتفسد البيانات.
ترشيح NULL في الاستعلامات
تختلف صياغة ترشيح NULL
(أي عدم وجود قيمة) في كتل WHERE
عن ترشيح القيم الأخرى:
SELECT * FROM Employees WHERE ManagerId IS NULL ; SELECT * FROM Employees WHERE ManagerId IS NOT NULL ;
لاحظ أنّه لمّا لم تكن NULL
مساوية لأيّ شيء آخر، ولا حتى لنفسها، فستُعيد عوامل الموازنة = NULL
أو <> NULL
(أو != NULL
) دائمًا القيمة المنطقية الخاصة UNKNOWN
، والتي ترفضها WHERE
.
ترشِّح WHERE
كل الصفوف التي يساوي شرطها القيمة FALSE
أو UNKNOWN
، ولا تحتفظ إلا بالصفوف ذات الشرط الصحيح (TRUE
).
الأعمدة المعدومة في الجداول
عند إنشاء الجداول، يمكن جعل العمود قابلًا للإلغاء (nullable) أو غير قابل للإلغاء.
CREATE TABLE MyTable ( MyCol1 INT NOT NULL, -- non-nullable MyCol2 INT NULL -- nullable ) ;
افتراضيًا، تكون جميع الأعمدة قابلة للإلغاء (باستثناء تلك الموجودة في قيد المفتاح الأساسي - primary key constraint) ما لم نعيّن القيد عند القيمة NOT NULL
صراحة. وسينتج خطأ عن محاولة تعيين NULL
لعمود غير قابل للإلغاء.
INSERT INTO MyTable (MyCol1, MyCol2) VALUES (1, NULL) ; -- صحيح INSERT INTO MyTable (MyCol1, MyCol2) VALUES (NULL, 2) ;
لا يمكن إدراج القيمة NULL في العمود 'MyCol1' في الجدول 'MyTable' لأنّ العمود لا يسمح بالقيمة المعدومة، لذا ستفشل عملية الإدراج INSERT
.
إسناد NULL إلى حقل
إسناد القيمة NULL
إلى حقل يشبه إسناد أيّ قيمة أخرى:
UPDATE Employees SET ManagerId = NULL WHERE Id = 4
إدراج الصفوف التي تحتوي حقولًا معدومة (NULL fields)
على سبيل المثال، إدراج بيانات موظف بدون رقم هاتف، وبدون مدير في جدول الموظفين Employees:
INSERT INTO Employees (Id, FName, LName, PhoneNumber, ManagerId, DepartmentId, Salary, HireDate) VALUES (5, 'Jane', 'Doe', NULL, NULL, 2, 800, '2016-07-22') ;
أمثلة على قواعد البيانات والجداول
إليك بعض الأمثلة التوضيحية عن قواعد البيانات.
قاعدة بيانات متجر السيارات
سوف نستعرض في المثال التالي قاعدة بيانات لمتجر يبيع السيارات، سنخزّن في القاعدة قوائم تضمّ الأقسام والموظفين والعملاء وسيارات العملاء. وسنستخدم المفاتيح الخارجية (foreign keys) لإنشاء علاقات بين مختلف الجداول.
هذا تطبيق حي للمثال:
العلاقات بين الجداول
- يضم كل قسم 0 موظف أو أكثر،
- ولكل موظف مدير واحد أو أكثر،
- وقد يكون لكل عميل 0 سيارة أو أكثر
الجدول Departments:
Id | Name |
---|---|
1 | HR |
2 | Sales |
3 | Tech |
لننشئ الجدول عبر SQL:
CREATE TABLE Departments ( Id INT NOT NULL AUTO_INCREMENT, Name VARCHAR(25) NOT NULL, PRIMARY KEY(Id) ); INSERT INTO Departments ([Id], [Name]) VALUES (1, 'HR'), (2, 'Sales'), (3, 'Tech') ;
الجدول Employees:
Id | FName | LName | PhoneNumber | ManagerId | DepartmentId | Salary | HireDate |
---|---|---|---|---|---|---|---|
1 | James | Smith | 1234567890 | NULL | 1 | 1000 | 01-01-2002 |
2 | John | Johnson | 2468101214 | 1 | 1 | 400 | 23-03-2005 |
3 | Michael | Williams | 1357911131 | 1 | 2 | 600 | 12-05-2009 |
4 | Johnathon | Smith | 1212121212 | 2 | 1 | 500 | 24-07-2016 |
لننشئ الجدول:
CREATE TABLE Employees ( Id INT NOT NULL AUTO_INCREMENT, FName VARCHAR(35) NOT NULL, LName VARCHAR(35) NOT NULL, PhoneNumber VARCHAR(11), ManagerId INT, DepartmentId INT NOT NULL, Salary INT NOT NULL, HireDate DATETIME NOT NULL, PRIMARY KEY(Id), FOREIGN KEY (ManagerId) REFERENCES Employees(Id), FOREIGN KEY (DepartmentId) REFERENCES Departments(Id) ); INSERT INTO Employees ([Id], [FName], [LName], [PhoneNumber], [ManagerId], [DepartmentId], [Salary], [HireDate]) VALUES (1, 'James', 'Smith', 1234567890, NULL, 1, 1000, '01-01-2002'), (2, 'John', 'Johnson', 2468101214, '1', 1, 400, '23-03-2005'), (3, 'Michael', 'Williams', 1357911131, '1', 2, 600, '12-05-2009'), (4, 'Johnathon', 'Smith', 1212121212, '2', 1, 500, '24-07-2016')
الجدول Customers:
Id | FName | LName | PhoneNumber | PreferredContact | |
---|---|---|---|---|---|
1 | William | Jones | william.jones@example.com | 3347927472 | PHONE |
2 | David | Miller | dmiller@example.net | 2137921892 | |
3 | Richard | Davis | richard0123@example.com | NULL |
لننشئ الجدول:
CREATE TABLE Customers ( Id INT NOT NULL AUTO_INCREMENT, FName VARCHAR(35) NOT NULL, LName VARCHAR(35) NOT NULL, Email varchar(100) NOT NULL, PhoneNumber VARCHAR(11), PreferredContact VARCHAR(5) NOT NULL, PRIMARY KEY(Id) ); INSERT INTO Customers ([Id], [FName], [LName], [Email], [PhoneNumber], [PreferredContact]) VALUES (1, 'William', 'Jones', 'william.jones@example.com', '3347927472', 'PHONE'), (2, 'David', 'Miller', 'dmiller@example.net', '2137921892', 'EMAIL'), (3, 'Richard', 'Davis', 'richard0123@example.com', NULL, 'EMAIL') ;
الجدول Cars:
Id | CustomerId | EmployeeId | Model | Status | Total Cost |
---|---|---|---|---|---|
1 | 1 | 2 | Ford F-150 | READY | 230 |
2 | 1 | 2 | Ford F-150 | READY | 200 |
3 | 2 | 1 | Ford Mustang | WAITING | 100 |
4 | 3 | 3 | Toyota Prius | WORKING | 1254 |
تعليمات SQL لإنشاء الجدول:
CREATE TABLE Cars ( Id INT NOT NULL AUTO_INCREMENT, CustomerId INT NOT NULL, EmployeeId INT NOT NULL, Model varchar(50) NOT NULL, Status varchar(25) NOT NULL, TotalCost INT NOT NULL, PRIMARY KEY(Id), FOREIGN KEY (CustomerId) REFERENCES Customers(Id), FOREIGN KEY (EmployeeId) REFERENCES Employees(Id) ); INSERT INTO Cars ([Id], [CustomerId], [EmployeeId], [Model], [Status], [TotalCost]) VALUES ('1', '1', '2', 'Ford F-150', 'READY', '230'), ('2', '1', '2', 'Ford F-150', 'READY', '200'), ('3', '2', '1', 'Ford Mustang', 'WAITING', '100'), ('4', '3', '3', 'Toyota Prius', 'WORKING', '1254') ;
قاعدة بيانات المكتبة
سننشئ في هذا المثال قاعدة بيانات خاصة بمكتبة، ستحتوي القاعدة على جداول لتخزين المؤلفين والكتب والكتاب. هنا تجد مثالًا حيًّا للقاعدة.
يُعرف جدولَا المؤلفين والكتب بالجداول الأساسية (base tables)، لأنهما يحتويان على تعريف العمود، وكذا البيانات الخاصة بالكيانات الفعلية في النموذج العلائقي (relational model). ويُعرف الجدول BookAuthors باسم جدول العلاقة (relationship table)، لأنّه يحدّد العلاقة بين جدول الكتب Books والمؤلفين Authors.
العلاقات بين الجداول
- يمكن أن يكون لكل مؤلف كتاب واحد أو أكثر.
- كل كتاب يمكن أن يكون له مؤلف واحد أو أكثر
الجدول Authors (عرض الجدول):
Id | Name | Country |
---|---|---|
1 | J.D. Salinger | USA |
2 | F. Scott. Fitzgerald | USA |
3 | Jane Austen | UK |
4 | Scott Hanselman | USA |
5 | Jason N. Gaylord | USA |
6 | Pranav Rastogi | India |
7 | Todd Miranda | USA |
8 | Christian Wenz | USA |
لننشئ الجدول الآن:
CREATE TABLE Authors ( Id INT NOT NULL AUTO_INCREMENT, Name VARCHAR(70) NOT NULL, Country VARCHAR(100) NOT NULL, PRIMARY KEY(Id) ); INSERT INTO Authors (Name, Country) VALUES ('J.D. Salinger', 'USA'), ('F. Scott. Fitzgerald', 'USA'), ('Jane Austen', 'UK'), ('Scott Hanselman', 'USA'), ('Jason N. Gaylord', 'USA'), ('Pranav Rastogi', 'India'), ('Todd Miranda', 'USA'), ('Christian Wenz', 'USA') ;
الجدول Books ( عرض الجدول):
Id | Title |
---|---|
1 | The Catcher in the Rye |
2 | Nine Stories |
3 | Franny and Zooey |
4 | The Great Gatsby |
5 | Tender id the Night |
6 | Pride and Prejudice |
7 | Professional ASP.NET 4.5 in C# and VB |
عبارات SQL لإنشاء الجدول:
CREATE TABLE Books ( Id INT NOT NULL AUTO_INCREMENT, Title VARCHAR(50) NOT NULL, PRIMARY KEY(Id) ); INSERT INTO Books (Id, Title) VALUES (1, 'The Catcher in the Rye'), (2, 'Nine Stories'), (3, 'Franny and Zooey'), (4, 'The Great Gatsby'), (5, 'Tender id the Night'), (6, 'Pride and Prejudice'), (7, 'Professional ASP.NET 4.5 in C# and VB') ;
الجدول BooksAuthors (عرض الجدول):
BookId | AuthorId |
---|---|
1 | 1 |
2 | 1 |
3 | 1 |
4 | 2 |
5 | 2 |
6 | 3 |
7 | 4 |
7 | 5 |
7 | 6 |
7 | 7 |
7 | 8 |
تعليمات SQL لإنشاء الجدول:
CREATE TABLE BooksAuthors ( AuthorId INT NOT NULL, BookId INT NOT NULL, FOREIGN KEY (AuthorId) REFERENCES Authors(Id), FOREIGN KEY (BookId) REFERENCES Books(Id) ); INSERT INTO BooksAuthors (BookId, AuthorId) VALUES (1, 1), (2, 1), (3, 1), (4, 2), (5, 2), (6, 3), (7, 4), (7, 5), (7, 6), (7, 7), (7, 8) ;
الآن، إن أردت عرض جميع المؤلفين، فاكتب ما يلي (عرض المثال الحي):
SELECT * FROM Authors;
عرض جميع عناوين الكتب (عرض مثال حي):
SELECT * FROM Books;
عرض جميع الكتب ومؤلفيها (عرض مثال حي):
SELECT ba.AuthorId, a.Name AuthorName, ba.BookId, b.Title BookTitle FROM BooksAuthors ba INNER JOIN Authors a ON a.id = ba.authorid INNER JOIN Books b ON b.id = ba.bookid ;
جدول الدول
سننشئ في هذا المثال جدولًا للبلدان. يُستخدم جدول البلدان في العديد من المجالات، وخاصة في التطبيقات المالية التي تشمل العملات وأسعار الصرف.
هذا مثال حي.
تطلب بعض البرمجيات الخاصة بتحليل الأسواق مثل بلومبرج ورويترز أن تعطيهم رمزًا مؤلفًا من حرفين أو ثلاث يمثل الدولة، إلى جانب رمز العملة. يحتوي الجدول التالي على عمود يحتوي رموز ISO
المؤلفة من حرفين، وكذلك على عمود يحتوي رموز ISO3
المكونة من 3 أحرف، والتي تمثل الدول.
الجدول Countries (عرض الجدول):
Id | ISO | ISO3 | ISONumeric | CountryName | Capital | ContinentCode | CurrencyCode |
---|---|---|---|---|---|---|---|
1 | AU | AUS | 36 | Australia | Canberra | OC | AUD |
2 | DE | DEU | 276 | Germany | Berlin | EU | EUR |
2 | IN | IND | 356 | India | New Delhi | AS | INR |
3 | LA | LAO | 418 | Laos | Vientiane | AS | LAK |
4 | US | USA | 840 | United States | Washington | NA | USD |
5 | ZW | ZWE | 716 | Zimbabwe | Harare | AF | ZWL |
لننشئ جدول الدول في SQL:
CREATE TABLE Countries ( Id INT NOT NULL AUTO_INCREMENT, ISO VARCHAR(2) NOT NULL, ISO3 VARCHAR(3) NOT NULL, ISONumeric INT NOT NULL, CountryName VARCHAR(64) NOT NULL, Capital VARCHAR(64) NOT NULL, ContinentCode VARCHAR(2) NOT NULL, CurrencyCode VARCHAR(3) NOT NULL, PRIMARY KEY(Id) ) ; INSERT INTO Countries (ISO, ISO3, ISONumeric, CountryName, Capital, ContinentCode, CurrencyCode) VALUES ('AU', 'AUS', 36, 'Australia', 'Canberra', 'OC', 'AUD'), ('DE', 'DEU', 276, 'Germany', 'Berlin', 'EU', 'EUR'), ('IN', 'IND', 356, 'India', 'New Delhi', 'AS', 'INR'), ('LA', 'LAO', 418, 'Laos', 'Vientiane', 'AS', 'LAK'), ('US', 'USA', 840, 'United States', 'Washington', 'NA', 'USD'), ('ZW', 'ZWE', 716, 'Zimbabwe', 'Harare', 'AF', 'ZWL') ;
ترجمة -وبتصرّف- للفصول الخمسة الأولى من الكتاب SQL Notes for Professionals
اقرأ أيضًا:
- المقال التالي: جلب الاستعلامات عبر SELECT في SQL
- النسخة العربية الكاملة لكتاب ملاحظات للعاملين بلغة SQL 1.0.0
أفضل التعليقات
لا توجد أية تعليقات بعد
انضم إلى النقاش
يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.