Ачааллж байна...
Түвшин 2-ын төгсгөлд хүрлээ. Энэ түвшинд та хүснэгтийг үүсгэх (CREATE TABLE), багана бүрд зөв төрөл сонгох, constraint-оор дүрэм тавих, PRIMARY KEY шийдэх, ALTER-ээр өөрчлөх, FOREIGN KEY-ээр хүснэгтүүдийг холбох, нэг-олон болон олон-олон харилцааг ялгах, ON DELETE журам сонгох, гурван дүрмээр давхардлаас зайлсхийх аргуудыг сурсан. Бид тэдгээрийг тус бүрд нь жижиг дасгалын хүснэгтүүд дээр туршиж, хичээл бүрийн төгсгөлд Revert Changes дарж арилгасаар ирсэн.
Энэ удаад бид юуг ч арилгахгүй. FastAPI сургалтад таны бүтээсэн Номын сангийн API-ийн өгөгдлийн санг энэ түвшний бүх мэдлэгээр эхнээс нь зохиож, жинхэнэ файлд хадгална. Тэр үед SQLModel хүснэгтүүдийг таны оронд үүсгэж байсан бол одоо та шийдвэр бүрийг өөрөө, учир шалтгаантайгаар гаргана. Энэ хичээлийн бүтээгдэхүүн бол Түвшин 3-ын бүх JOIN, тоо нэгтгэлт, тайлангийн query-ний суурь болох өгөгдлийн сан юм — тиймээс үүнийг анхааралтай хийгээрэй.
Мэргэжлийн хөгжүүлэгчид хүснэгт зохиохдоо гарнаас нь шууд код бичдэггүй. Тэд эхлээд цаасан дээр (эсвэл самбар дээр) "зүйл"-үүдийг олж, тэдгээрийн харилцааг өгүүлбэрээр ярьж, багана бүрийг шийдээд, зөвхөн дараа нь SQL бичдэг. Бид яг энэ дарааллыг дагана. Удирдамжтай дасгал тул алхам бүрийг дагахад хангалттай, шинээр зохион бодох зүйл байхгүй — гэхдээ шийдвэр бүрийн шалтгааныг уншаад, өөрөө ч ингэж шийдэх байсан эсэхээ бодоорой.
Номын сангийн өдөр тутмын ажлыг өгүүлбэрээр дүрслэе: "Гишүүд номын сангаас ном зээлдэг. Ном бүр нэг эсвэл хэд хэдэн зохиогчтой. Зээл бүр хэзээ авсан, хэзээ буцаах ёстой, хэзээ буцаасан гэсэн огноотой." Энэ өгүүлбэрүүдээс нэр үгсийг ялгавал: гишүүн, ном, зохиогч, зээл. Эдгээр нь Бүлэг 6-ийн Дүрэм 2-ын "зүйл"-үүд бөгөөд тус бүр өөрийн амьдралтай — гишүүн олон жил байна, ном олон удаа зээлэгдэнэ, зохиогч олон ном бичнэ, зээл бол нэг мөчийн үйл явдал. Тиймээс тус бүр өөрийн хүснэгттэй байна.
Одоо хос бүрийн харилцааг Бүлэг 5-ийн "нэг ... нэг" өгүүлбэрийн аргаар шалгая:
Гишүүн ба зээл: "Нэг гишүүн олон зээлтэй." "Нэг зээл нэг гишүүнтэй." Хоёр дахь өгүүлбэр "нэг"-ээр төгссөн тал — зээл — FOREIGN KEY-ийн гэр. → loans.member_id
Ном ба зээл: "Нэг ном олон удаа зээлэгддэг." "Нэг зээл нэг номтой." → loans.book_id
Ном ба зохиогч: "Нэг ном олон зохиогчтой байж болно." "Нэг зохиогч олон ном бичдэг." Хоёулаа "олон" — холбогч хүснэгт хэрэгтэй. → book_authors
Энд нэг сонирхолтой ажиглалт бий: зээл нь өөрөө гишүүд ба номнуудын хоорондох олон-олон харилцааны холбогч хүснэгт — нэг гишүүн олон ном, нэг ном олон гишүүнд. Бүлэг 5-ийн олон-олон хичээлд сурсанчлан ийм холбогч хүснэгт харилцааны өөрийн мэдээллийг (огноонууд) хадгалдаг. Гэхдээ нэг гишүүн нэг номыг хэд хэдэн удаа зээлж болох тул (book_id, member_id) хослолыг нийлмэл түлхүүр болгох боломжгүй — loans өөрийн id-тай байна. Цаасан дээрх бүтэц:
members ──< loans >── books ──< book_authors >── authors
──< гэдэг нь "нэг ... олон": зүүн талын нэг мөрт баруун талын олон мөрХүснэгт бүрийн баганыг Бүлэг 4-ийн асуултуудаар шийднэ: ямар төрөл вэ? Хоосон байж болох уу? Давхардаж болох уу? Ямар нөхцөл хангах ёстой вэ?
members. Нэр заавал (NOT NULL) — нэргүй гишүүн утгагүй. Имэйл давхардаж болохгүй (UNIQUE), гэхдээ хоосон байж болно — Тэмүүлэн имэйлгүй, Бүлэг 4-т сурсанчлан UNIQUE олон NULL-ийг зөвшөөрдөг. Хот хоосон байж болно. Элссэн огноо заавал, утга өгөөгүй бол өнөөдрийн огноо (DEFAULT CURRENT_DATE). Мөн Бүлэг 4-ийн ALTER хичээлийн soft delete: is_active нь 1 эсвэл 0 л байх ёстой — Бүлэг 2-ын IN-ийг CHECK дотор ашиглана.
authors. Зөвхөн нэр, заавал.
books. Нэр заавал. Он хоосон байж болно (зарим эртний бүтээлийн огноо маргаантай), гэвч байвал эерэг. Жанр хоосон байж болно. Хувийн тоо заавал, анхдагч нь 1, сөрөг байж болохгүй. ISBN давхардаж болохгүй, гэхдээ хоосон байж болно — Бүлэг 4-ийн PRIMARY KEY хичээлд сурсанчлан XIII зууны бүтээлд ISBN байхгүй, тиймээс ISBN нь PRIMARY KEY биш, UNIQUE энгийн багана. Номын сангийн "одоо байгаа хувь" гэх мэт баганыг санаатайгаар хийхгүй: энэ нь хувийн тоо ба буцаагаагүй зээлээс тооцоолж болох утга тул Бүлэг 6-ийн Дүрэм 3-ын дагуу хадгалахгүй, Бүлэг 8-д тооцоолно.
book_authors. Хоёр заалт, хоёулаа заавал, хослол нь нийлмэл PRIMARY KEY.
loans. Хоёр заалт, хоёулаа заавал. Зээлсэн огноо болон буцаах ёстой огноо заавал. Буцаасан огноо хоосон байж болно — NULL нь "хараахан буцаагаагүй" гэсэн үнэн. Хоёр CHECK: буцаах огноо зээлсэн огнооноос өмнө байж болохгүй; буцаасан огноо байвал зээлсэн огнооноос өмнө байж болохгүй. Огноонуудыг YYYY-MM-DD текстээр хадгалах тул Бүлэг 3-ын удирдамжтай дасгалд сурсанчлан текстийн харьцуулалт огнооны харьцуулалттай таарна.
Бүлэг 5-ийн сүүлийн хичээлийн асуулт: "заагдаж буй мөр алга болбол заалттай мөр ямар утгатай хэвээр үлдэх вэ?"
loans → members, loans → books: RESTRICT. Зээлийн түүх чухал. Зээлтэй гишүүн эсвэл номыг санамсаргүй устгах нь тэр түүхийг эвдэнэ. Гишүүн гарахдаа идэвхгүй болно (is_active = 0), бүрмөсөн устгах шаардлага гарвал хүн өөрөө зээлүүдийг нь шийднэ.
book_authors → books: CASCADE. "Энэ ном энэ зохиогчтой" гэсэн холбоос ном өөрөө байхгүй бол утгагүй — холбоос номын нэг хэсэг. Номыг устгавал түүний зохиогчийн холбоосууд хамт устна; зохиогчид өөрсдөө хөндөгдөхгүй.
book_authors → authors: RESTRICT. Номтой зохиогчийг устгахыг хориглоно — тэгэхгүй бол номнууд анзааралгүй зохиогчоо алдана.
DB Browser-т хадгалаагүй өөрчлөлт байхгүй эсэхийг шалгаад (Write Changes товч саарал), New Database дарна.
Documents\sql-course хавтсанд library2 нэрээр хадгална. Edit table definition цонхонд Cancel.
Edit Pragmas таб руу ороод Foreign Keys тэмдэглэгдсэн эсэхийг шалгана (Бүлэг 5, Хичээл 1). Тэмдэглэгдээгүй бол тэмдэглээд Save.
Шалгах цэг 4: Цонхны гарчигт library2.db, Database Structure таб хоосон, Foreign Keys асаалттай.
Бид library.db-д хүрэхгүй — тэр нь Түвшин 1-ийн дасгалын сан хэвээр үлдэнэ. Түвшин 3 бүхэлдээ шинэ library2.db дээр ажиллана.
Одоо цаасан дээрх бүх шийдвэрийг нэг скрипт болгоно. Скрипт Бүлэг 1-ийн бэлтгэлийн скриптийн нэгэн адил эхэндээ DROP TABLE IF EXISTS-тэй тул ирээдүйд хэдэн ч удаа ажиллуулж өгөгдлийн сангаа эхлэл байдалд нь буцааж болно. DROP-уудын дарааллыг анхаараарай: заалттай хүснэгтүүдийг (хүүхдүүдийг) эхэлж, заагдаж буй хүснэгтүүдийг (эцэг эхийг) сүүлд — Бүлэг 5-ийн дүрэм. CREATE ба INSERT нь эсрэг дарааллаар: эцэг эх эхэлж. Execute SQL табд бүхэлд нь буулгаад ажиллуулна:
sql
DROP TABLE IF EXISTS loans;
DROP TABLE IF EXISTS book_authors;
DROP TABLE IF EXISTS books;
DROP TABLE IF EXISTS authors;
DROP TABLE IF EXISTS members;
CREATE TABLE members (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
email TEXT UNIQUE,
city TEXT,
joined_on TEXT NOT NULL DEFAULT CURRENT_DATE,
is_active INTEGER NOT NULL DEFAULT 1 CHECK (is_active IN (0, 1))
);
CREATE TABLE authors (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL
);
CREATE TABLE books (
id INTEGER PRIMARY KEY,
title TEXT NOT NULL,
year INTEGER CHECK (year > 0),
genre TEXT,
copies INTEGER NOT NULL DEFAULT 1 CHECK (copies >= 0),
isbn TEXT UNIQUE
);
CREATE TABLE book_authors (
book_id INTEGER NOT NULL,
author_id INTEGER NOT NULL,
PRIMARY KEY (book_id, author_id),
FOREIGN KEY (book_id) REFERENCES books (id) ON DELETE CASCADE,
FOREIGN KEY (author_id) REFERENCES authors (id) ON DELETE RESTRICT
);
CREATE TABLE loans (
id INTEGER PRIMARY KEY,
book_id INTEGER NOT NULL,
member_id INTEGER NOT NULL,
loaned_on TEXT NOT NULL,
due_on TEXT NOT NULL,
returned_on TEXT,
CHECK (due_on >= loaned_on),
CHECK (returned_on IS NULL OR returned_on >= loaned_on),
FOREIGN KEY (book_id) REFERENCES books (id) ON DELETE RESTRICT,
FOREIGN KEY (member_id) REFERENCES members (id) ON DELETE RESTRICT
);
INSERT INTO members (id, name, email, city, joined_on)
VALUES
(1, 'Бат', 'bat@example.com', 'Улаанбаатар', '2023-02-14'),
(2, 'Сараа', 'saraa@example.com', 'Дархан', '2024-05-03'),
(3, 'Тэмүүлэн', NULL, 'Улаанбаатар', '2022-11-20'),
(4, 'Номин', 'nomin@example.com', 'Эрдэнэт', '2024-08-09'),
(5, 'Ану', 'anu@example.com', 'Улаанбаатар', '2025-01-17');
INSERT INTO authors (id, name)
VALUES
(1, 'Д.Нацагдорж'),
(2, 'Ч.Лодойдамба'),
(3, 'Robert C. Martin'),
(4, 'Eric Matthes'),
(5, 'Andrew Hunt'),
(6, 'David Thomas'),
(7, 'Al Sweigart');
INSERT INTO books (id, title, year, genre, copies, isbn)
VALUES
(1, 'Монголын нууц товчоо', 1240, 'Түүх', 2, NULL),
(2, 'Тунгалаг Тамир', 1962, 'Роман', 3, NULL),
(3, 'Учиртай гурван толгой', 1934, 'Жүжиг', 1, NULL),
(4, 'Clean Code', 2008, 'Програмчлал', 4, '978-0132350884'),
(5, 'Python Crash Course', 2015, 'Програмчлал', 5, '978-1593276034'),
(6, 'The Pragmatic Programmer', 1999, 'Програмчлал', 2, '978-0201616224'),
(7, 'Clean Architecture', 2017, 'Програмчлал', 1, NULL),
(8, 'Миний нутаг', 1933, 'Шүлэг', 2, NULL);
INSERT INTO book_authors (book_id, author_id)
VALUES
(2, 2), (3, 1), (4, 3), (5, 4), (6, 5), (6, 6), (7, 3), (8, 1);
INSERT INTO loans (id, book_id, member_id, loaned_on, due_on, returned_on)
VALUES
(1, 4, 1, '2026-09-03', '2026-09-17', '2026-09-15'),
(2, 5, 1, '2026-09-10', '2026-09-24', '2026-09-30'),
(3, 2, 2, '2026-09-12', '2026-09-26', '2026-09-25'),
(4, 2, 1, '2026-09-20', '2026-10-04', NULL),
(5, 4, 4, '2026-09-25', '2026-10-09', '2026-10-02'),
(6, 4, 2, '2026-10-01', '2026-10-15', NULL),
(7, 6, 3, '2026-10-03', '2026-10-17', NULL),
(8, 8, 4, '2026-10-05', '2026-10-19', '2026-10-12');Мессеж Execution finished without errors. гарсны дараа Write Changes дарна. Энэ бол Түвшин 2-т бид анх удаа жинхэнэ өгөгдлийг хадгалж байгаа мөч.
Скриптийн өгөгдлийг товч уншъя. Таван гишүүн, долоон зохиогч, найман ном, найман зээл. Өгөгдлийг Түвшин 3-ын асуултуудад санаатайгаар бэлдсэн: Ану гишүүн хэзээ ч ном зээлээгүй; "Монголын нууц товчоо", "Учиртай гурван толгой", “Clean Architecture” хэзээ ч зээлэгдээгүй; Clean Code гурван удаа зээлэгдсэн; "Монголын нууц товчоо" зохиогчийн холбоосгүй; Al Sweigart номгүй; “The Pragmatic Programmer” хоёр зохиогчтой; Robert C. Martin болон Нацагдорж тус бүр хоёр номтой. Батын хоёр дахь зээл хугацаанаасаа хоцорч буцаагдсан (9-р сарын 30, буцаах ёстой нь 24), Батын дөрөв дэх зээл (loan 4) одоо ч буцаагдаагүй. Эдгээр нь Түвшин 3-т "хэзээ ч зээлээгүй гишүүд", "хамгийн их зээлэгдсэн ном", "хоцорсон зээлүүд" гэх мэт асуултуудын хариулт болно.
Энэ өгөгдлийг Алхам 1-ийн "бүгдийг нэг дор" хүснэгттэй харьцуулаад үзээрэй. Гишүүн бүрийн имэйл ганцхан газар. Номын нэр ганцхан газар. Зээлийн хүснэгт зөвхөн тоонууд ба огноонуудаас бүрдэнэ. "Тунгалаг Тамир"-ыг хоёр өөр гишүүн зээлсэн ч номын нэр нэг л удаа бичигдсэн. Энэ бол Бүлэг 6-ийн гурван дүрмийн бодит үр дүн.
Шалгах цэг 5: Database Structure табд таван хүснэгт: authors, book_authors, books, loans, members. Write Changes товч саарал.
Schema-гийн дүрмүүд бодитоор ажиллаж байгааг дөрвөн санаатай зөрчлөөр шалгая. Тест бүрийн дараа хүснэгт өөрчлөгдөхгүй тул Write Changes шаардлагагүй.
Тест 1 — FOREIGN KEY:
sql
INSERT INTO loans (book_id, member_id, loaned_on, due_on)
VALUES (99, 1, '2026-10-10', '2026-10-24');Үр дүн: FOREIGN KEY constraint failed. Утга нь "гадаад түлхүүрийн дүрэм зөрчигдлөө" — 99-р ном байхгүй. Өнчин зээл төрөхгүй.
Тест 2 — огнооны CHECK:
sql
INSERT INTO loans (book_id, member_id, loaned_on, due_on)
VALUES (5, 3, '2026-10-10', '2026-10-01');Үр дүн: CHECK constraint failed: due_on >= loaned_on. Утга нь "буцаах огноо зээлсэн огнооноос багагүй байх шалгалт зөрчигдлөө" — буцаах ёстой огноо зээлсэн өдрөөс өмнө байж болохгүй.
Тест 3 — давхардсан имэйл:
sql
INSERT INTO members (name, email, city)
VALUES ('Болд', 'bat@example.com', 'Ховд');Үр дүн: UNIQUE constraint failed: members.email. Утга нь “members хүснэгтийн email давхардахгүй байх дүрэм зөрчигдлөө” — Батын имэйлийг өөр хүн эзэмшиж болохгүй.
Тест 4 — зээлтэй гишүүнийг устгах:
sql
DELETE FROM members WHERE id = 1;Үр дүн: FOREIGN KEY constraint failed. RESTRICT ажиллаж байна — Батын зээлийн түүх хамгаалагдсан.
Дөрвөн тест дөрвүүлээ татгалзагдсан нь schema тань хамгаалалтаа бүрэн гүйцэтгэж байгааг харуулж байна. SELECT COUNT(*) FROM loans; нь 8 гэж хариулах ёстой — тестүүд ямар ч ул мөр үлдээгээгүй.
Хүснэгт бүрийн мөрийн тоог шалгая:
sql
SELECT COUNT(*) FROM members;
SELECT COUNT(*) FROM authors;
SELECT COUNT(*) FROM books;
SELECT COUNT(*) FROM book_authors;
SELECT COUNT(*) FROM loans;Эдгээр query-г тус бүрд нь (мөрийг тодруулж F5 дарж) ажиллуулаарай. Хүлээгдэж буй хариултууд: 5, 7, 8, 8, 8. Мөн одоо буцаагаагүй байгаа зээлүүдийг харъя:
sql
SELECT id, book_id, member_id, loaned_on, due_on
FROM loans
WHERE returned_on IS NULL
ORDER BY due_on;Үр дүн:
id | book_id | member_id | loaned_on | due_on
---+---------+-----------+------------+-----------
4 | 2 | 1 | 2026-09-20 | 2026-10-04
6 | 4 | 2 | 2026-10-01 | 2026-10-15
7 | 6 | 3 | 2026-10-03 | 2026-10-17Энэ query юу гэж хэлж байна вэ гэвэл: “loans хүснэгтээс буцаасан огноо нь хоосон зээлүүдийг буцаах ёстой огноогоор нь эрэмбэлж харуул.” Гурван зээл гарт байна. Үр дүн нь дугааруудаас бүрдэж байгааг анзаараарай — “2-р номыг 1-р гишүүн” гэдгийг "Тунгалаг Тамирыг Бат" гэж уншихын тулд хоёр хүснэгтэд нэмэлт query бичих хэрэгтэй. Яг энэ хүндрэлийг Түвшин 3-ын эхний бүлэг шийднэ.
Энэ скрипт бол таны номын сангийн бүтцийн баримт бичиг юм — хэн нэгэн "манай өгөгдлийн сан ямар бүтэцтэй вэ" гэж асуувал хариулт нь энэ файл. Мөн Түвшин 3-т өгөгдлөө санамсаргүй эвдвэл энэ скриптийг дахин ажиллуулж бүх зүйлийг сэргээнэ. Execute SQL табд Алхам 5-ын бүтэн скрипт байгаа эсэхийг шалгаад (хэрэв тестүүдээр солигдсон бол дахин буулгаад), табын дээд талын Save SQL file товчоор Documents\sql-course хавтсанд library_schema.sql нэрээр хадгална. Хэрэв "Хөгжүүлэгчийн хэрэгсэл" сургалтын дадлаа үргэлжлүүлж байгаа бол git add library_schema.sql болон git commit -m "Add normalized library schema" хийнэ — ирээдүйд schema өөрчлөгдөх бүрт Git түүний түүхийг хадгална. Энэ санаа Бүлэг 13-ын migration-д бүрэн хэлбэрээ олно.
Эцсийн шалгах цэг: sql-course хавтсанд library2.db ба library_schema.sql бий. library2.db таван хүснэгт, нийт 36 мөр агуулна.
Хэрэв сонирхож байвал schema-гаа нэг алхмаар өргөтгөж үзээрэй — жишээ нь номын санд номын захиалга (reservation) нэмэх: гишүүн одоо зээлэгдсэн байгаа номыг дараалалд бичүүлж болно. Алхам 1-ийн аргаар эхлээд өгүүлбэрээ бич ("нэг гишүүн олон захиалга...", "нэг захиалга нэг ном..."), FOREIGN KEY-ийн гэрийг олж, багана бүрийг шийдээд, ON DELETE журам сонго. Цаасан дээр зураад, хүсвэл CREATE TABLE бичиж туршиж болно — гэхдээ library2.db-д хадгалахаасаа өмнө library_schema.sql-ийн хуулбар байгаа эсэхийг шалгаарай. Эдгээр нь зөвхөн санал бөгөөд дараагийн хичээлүүд тэдгээрийг хийсэн гэж тооцохгүй.
DROP-ийн дарааллыг буруу бичих. Хэрэв скриптийн эхэнд DROP TABLE IF EXISTS members;-ийг loans-ээс өмнө бичвэл скриптийг хоёр дахь удаа ажиллуулахад FOREIGN KEY constraint failed гарч болно — loans доторх зээлүүд members руу заасаар байхад гишүүдийн хүснэгт устах гэж оролдож байна. Хүүхдүүдийг эхэлж, эцэг эхийг сүүлд устгана.
INSERT-ийн дарааллыг буруу бичих. Эсрэгээр, loans-ийн INSERT-ийг members, books-оос өмнө бичвэл FOREIGN KEY constraint failed гарна — заагдах гишүүд, номнууд хараахан байхгүй. Эцэг эхийг эхэлж, хүүхдүүдийг сүүлд нэмнэ.
Foreign Keys тохиргоо унтраалттай байх. Тест 1 болон Тест 4 таны дээр алдаагүйгээр ажилласан бол энэ тохиргоог шалгаарай. Энэ үед тестүүд өгөгдлийн санд өнчин мөр нэмсэн эсвэл Батыг устгасан байх тул скриптийг дахин ажиллуулж, тохиргоог асаагаад Алхам 6-г давтаарай.
Скриптийг хэсэгчлэн ажиллуулах. Хэрэв скриптийн дунд нэг хэсгийг тодруулж ажиллуулбал зарим хүснэгт үүсч, зарим нь үүсэхгүй, эсвэл өгөгдөл хагас нэмэгдэж болно. Schema-гийн скриптийг үргэлж бүтнээр нь ажиллуулаарай — эхэнд DROP-ууд байгаа тул энэ нь үргэлж аюулгүй.
Огноог буруу хэлбэрээр бичих. Тест 2-ын CHECK нь огноог текстээр харьцуулдаг тул '2026-10-9' гэх мэт нэг оронтой өдөр бичвэл CHECK буруу шийдвэр гаргаж болно — '2026-10-9' нь текстийн хувьд '2026-10-10'-аас их. Бүлэг 3-ын удирдамжтай дасгалын дүрэм энд ч хүчинтэй: үргэлж YYYY-MM-DD, тэгээр нөхсөн хоёр оронтой сар, өдөр.
Энэ дасгалд та номын сангийн өгөгдлийн санг мэргэжлийн дарааллаар зохиолоо. Эхлээд өгүүлбэрээс "зүйл"-үүдийг олж — гишүүн, ном, зохиогч, зээл — "нэг ... нэг" өгүүлбэрүүдээр харилцаа бүрийн FOREIGN KEY-ийн гэрийг тогтоов. Дараа нь багана бүрийн төрөл, NOT NULL, UNIQUE, DEFAULT, CHECK-ийг учир шалтгаантайгаар шийдэж, тооцоолж болох "одоо байгаа хувь"-ийг санаатайгаар хадгалсангүй. ON DELETE журмуудыг өгөгдлийн утгаас хамааруулан сонгов: зээлийн түүхэд RESTRICT, номын нэг хэсэг болох зохиогчийн холбоосонд CASCADE. Бүх шийдвэрийг дахин ажиллуулж болох нэг скрипт болгож, library2.db-д хадгалж, дүрмүүдийг дөрвөн санаатай зөрчлөөр баталж, скриптийг library_schema.sql файл болгон Git-д хадгаллаа.
Ингээд Түвшин 2 — “Schema зохион байгуулалт” — бүрэн дууслаа. Та одоо өгөгдлийн санг зөвхөн ашиглаад зогсохгүй, зохиож чаддаг болсон. Гэвч Алхам 7-д харсанчлан сайн зохиосон, давхардалгүй өгөгдөл унших үед дугааруудаас бүрддэг — “2-р номыг 1-р гишүүн” гэж. Түвшин 3 яг энэ асуудлаар эхэлнэ. Бүлэг 7-д бид тусдаа хадгалсан хүснэгтүүдийг унших мөчид нь нэгтгэх хэрэгсэл болох JOIN-ийг сурч, Бүлэг 5-ийн урьдчилсан харагдацын query-г мөр бүрээр нь ойлгох болно.
Бүртгэлтэй болсноор энэ сургалтын бүх хичээлд хандах эрх авна.