MySQL
Cədvəllər arasında əlaqə
Ötən dərsdə normallaşdırma, yəni məlumatların verilənlər bazasında düzgün təşkili prosesi ilə tanış olduq. Və məlum oldu ki, bu zaman cədvəlimizi normallaşdırmaq üçün onu bir neçə cədvələ bölmək lazım gələ bilər.
MySQL - bu, münasibətli verilənlər bazasıdır. Bu o deməkdir ki, verilənlər bazasında bir neçə cədvəldə yerləşən məlumatlar münasibətlər (relation) vasitəsilə bir-birilə əlaqələndirilə bilər.
Cədvəllər arasında əlaqə yaratmaq üçün açarlardan istifadə edilir. İki cədvəl bir-biri ilə əlaqələndirildikdə aşağıdakı 3 mümkün əlaqədən biri əmələ gəlir:
- Birin-birə (One-To-One)
- Birin-çoxa (One-To-Many)
- Çoxun-çoxa (Many-To-Many)
Birin-birə əlaqəsi
Birin-birə əlaqəsi zamanı birinci cədvəlin bir yazısı o biri cədvəlin yalnız bir yazısı ilə əlaqələnir. Bu ən sadə əlaqədir və ondan az-az hallarda istifadə olunur.
Gəlin işçilərin məlumatını özündə saxlayan employees
cədvəlini yaradan sorğunu icra edək:
CREATE TABLE `employees` (
`employee_id` int UNSIGNED NOT NULL AUTO_INCREMENT,
`fullname` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL,
`age` tinyint UNSIGNED NOT NULL,
PRIMARY KEY (`employee_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
İndi isə employees
cədvəlinə bir neçə işçi haqqında məlumat əlavə edən sorğunu icra edək:
INSERT INTO `employees` (`fullname`, `age`) VALUES
('Rasim', 32),
('Anar', 38),
('Tariyel', 37),
('Etibar', 42);
employees
cədvəlindən işçilərin məlumatını əldə edən sorğunu icra edək:
SELECT * FROM employees;
Bundan sonra işçilərin əmək haqlarını özündə saxlayan salary
cədvəlini yaradan sorğunu icra edək:
CREATE TABLE `salary` (
`id` int UNSIGNED NOT NULL AUTO_INCREMENT,
`salary` decimal(10,0) NOT NULL,
`employee_id` int UNSIGNED NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
salary
cədvəlinə işçilərin əmək haqlarını əlavə edən sorğu yazıb onu icra edək:
INSERT INTO `salary` (`salary`, `employee_id`) VALUES
('800', 1),
('600', 2),
('1000', 3),
('1200', 4);
salary
cədvəlindən işçilərin əmək haqlarını əldə edən sorğunu icra edək:
SELECT * FROM salary;
Hər iki cədvəldə (employees
, salary
) employee_id
sütunu mövcuddur. employees
cədvəlindəki employee_id
sütunu başlıca açar (primary key), salary
cədvəlində isə employee_id
sütunu xarici açardır (foreign key). Aşağıdakı şəkildə daha ətraflı izah etməyə çalışmışam:
İki və daha çox cədvəl arasındakı münasibətə əsaslanaraq onların sətirlərini birləşdirmək üçün INNER JOIN
operatorundan istifadə olunur. Sintaksisi aşağıdakı kimidir:
SELECT sütunların_adı FROM cədvəl1 INNER JOIN cədvəl2 ON birləşmə şərti
Nəhayət, bütün işçilər və onların əmək haqlarını əldə etmək üçün aşağıdakı sorğunu icra edək:
SELECT * FROM employees INNER JOIN salary ON employees.employee_id = salary.employee_id;
Əgər bəzi sütunları seçmək lazımdırsa, onda SELECT
operatorundan sonra sadalanan sütunların qarşısında cədvəlin adını yazmaq lazımdır:
SELECT employees.fullname, salary.salary FROM employees INNER JOIN salary ON employees.employee_id = salary.employee_id;
AS
(ALIAS) operatorunun köməyilə cədvəllərin adını konkret seçim üçün dəyişdirmək olar:
SELECT e.fullname, s.salary FROM employees AS e INNER JOIN salary AS s ON e.employee_id = s.employee_id;
Yuxarıdakı nümunədə employees
cədvəli üçün e
aliası, salary
cədvəli üçün isə s
aliası təyin edilib. Göründüyü kimi aliaslardan istifadə nəticəsində sorğumuz daha yığcam alınıb. Qeyd edim ki, aliaslar yalnız sorğu zamanı, yəni müvəqqəti mövcuddur.
Birin-çoxa əlaqəsi
Birin-çoxa əlaqəsi zamanı birinci cədvəlin bir yazısı ikinci cədvəlin çoxlu yazısı ilə əlaqələnir. Bu, geniş yayılmış əlaqədir.
Gəlin müəlliflərin adını özündə saxlayan authors
cədvəlini yaradan sorğunu icra edirik:
CREATE TABLE `authors` (
`id` int UNSIGNED NOT NULL AUTO_INCREMENT,
`fullname` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
Yaratdığımız authors
cədvəlinə iki müəllif əlavə edirik:
INSERT INTO `authors` (`fullname`) VALUES
('Emil Huseynov'),
('Zaur Huseynov');
authors
cədvəlindən müəllifləri əldə edirik:
SELECT * FROM authors;
Bundan sonra sayt üçün məqalələri özündə saxlayan articles
cədvəlini yaradırıq:
CREATE TABLE `articles` (
`id` int UNSIGNED NOT NULL AUTO_INCREMENT,
`user_id` int NOT NULL,
`title` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
`content` text COLLATE utf8mb4_unicode_ci NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
articles
cədvəlinə bir neçə məqalə əlavə edək:
INSERT INTO `articles`(`user_id`, `title`, `content`) VALUES (1, "HTTP protokolu", "HTTP - müxtəlif resursları, məsələn HTML sənədlərini əldə etməyə imkan verən protokoldur.");
INSERT INTO `articles`(`user_id`, `title`, `content`) VALUES (1, "Kompilyator nədir?", "Kompüterin ürəyi hesab edilən prosessor informasiyanı emal edir, istifadəçinin əmrlərini icra edir.");
INSERT INTO `articles`(`user_id`, `title`, `content`) VALUES (1, "Cron Jobs", "Cron - tapşırıqları müəyyən zaman aralığında dövri yerinə yetirmək üçün istifadə olunan klassik bir demondur.");
INSERT INTO `articles`(`user_id`, `title`, `content`) VALUES (2, "Dəyişənlər", "Dəyişən – bu, verilənlər üçün adlı yaddaş sahəsidir. ");
articles
cədvəlindən bütün məqalələri əldə edən sorğunu icra edirik:
SELECT * FROM articles;
author
və articles
cədvəlləri arasında münasibət (əlaqə) id
(başlıca açar) və user_id
(xarici açar) sütunları vasitəsilə yaradılır. Müəllif çoxlu məqalə yaza bilər, ancaq bir məqalə yalnız bir müəllifə məxsusdur. Bu, birin-çoxa münasibətidir. Aşağıdakı şəkildə bu deyilənləri daha ətraflı izah etməyə çalışmışam:
İndi isə məqalələri onların müəllifləri ilə birgə əldə edən sorğunu icra edək. Bəli, yenə də INNER JOIN operatorundan istifadə edirik:
SELECT fullname, content FROM articles AS a INNER JOIN authors AS u ON a.user_id = u.id;
Göründüyü kimi, Emil Huseynov 3, Zaur Huseynov isə 1 məqalənin müəllifidir.
Çoxun-çoxa əlaqəsi
Birinci cədvəlin çoxlu yazısı ikinci cədvəlin çoxlu yazısına uyğun gəldikdə çoxun-çoxa əlaqəsi yaranır. Cədvəlləri bir-biri ilə əlaqələndirmək üçün üçüncü cədvəldən (birləşdirici cədvəl) istifadə edilir. Bir sıra saytlarda, bloqlarda məqalələrə əlavə edilən teqləri (məsələn, burda məqaləyə PHP və Təhlükəsizlik teqləri əlavə edilib. Teqlər məqalələri həmin açar sözlər üzrə sıralamağa imkan verir) çoxun-çoxa əlaqəsinə nümunə göstərmək olar. Hər bir məqalə bir neçə teqdən ola bilər. Eyni zamanda bir teq bir neçə məqaləyə aid ola bilər.
Biz artıq birin-çoxa əlaqəsində articles cədvəli yaratmışdıq. Həmin cədvəli yenidən istifadə edəcəyik. Ona görə gəlin tags cədvəlini yaradaq:
CREATE TABLE `tags` (
`id` int UNSIGNED NOT NULL AUTO_INCREMENT,
`name` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
tags cədvəlinə bir neçə teq əlavə edən sorğunu icra edək:
INSERT INTO `tags`(`name`) VALUES
('http'),
('internet'),
('kompüter'),
('unix')
Teqlərin cədvələ əlavə edildiyinə əmin olaq:
SELECT * FROM tags;
Beləliklə, hazırda articles və tags cədvəlləri mövcuddur. İndi isə articles_tags birləşdirici cədvəlini yaradan sorğunu icra edək:
CREATE TABLE `articles_tags` (
`article_id` int UNSIGNED NOT NULL,
`tag_id` int UNSIGNED NOT NULL,
PRIMARY KEY (`article_id`,`tag_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
Yuxarıdakı sorğuda mürəkkəb başlıca açardan (PRIMARY KEY (`article_id`,`tag_id`)) istifadə edilib.
articles_tags cədvəlinə müvafiq məqalə və teqləri əlavə edək:
INSERT INTO `articles_tags`(`article_id`, `tag_id`) VALUES (1, 1);
INSERT INTO `articles_tags`(`article_id`, `tag_id`) VALUES (1, 2);
INSERT INTO `articles_tags`(`article_id`, `tag_id`) VALUES (2, 3);
INSERT INTO `articles_tags`(`article_id`, `tag_id`) VALUES (3, 4);
Nəticə:
İndi isə gəlin artıq bizə tanış olan INNER JOIN operatorunun köməyilə məqalə və ona əlavə edilmiş teqləri əldə edən sorğunu icra edək:
SELECT a.title, t.name FROM tags AS t
INNER JOIN articles_tags AS at ON at.tag_id = t.id
INNER JOIN articles AS a ON a.id = at.article_id;
Şərh yazmaq üçün hesabınıza daxil olun.