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:

  1. Birin-birə (One-To-One)
  2. Birin-çoxa (One-To-Many)
  3. Ç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;

authorarticles 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 articlestags 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;

0

Şərh yazmaq üçün hesabınıza daxil olun.