fork download
  1. /* =========================================================
  2.   TẠO LẠI CSDL DKYTINCHI
  3. ========================================================= */
  4.  
  5. DROP DATABASE IF EXISTS DkyTinChi;
  6. CREATE DATABASE DkyTinChi CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  7. USE DkyTinChi;
  8.  
  9. /* =========================================================
  10.   1. HEADQUARTER
  11.   Lưu thông tin trụ sở/cơ sở đào tạo
  12. ========================================================= */
  13.  
  14. CREATE TABLE headquarter
  15. (
  16. ID_headquarter varchar(20) NOT NULL,
  17. name_headquarter varchar(100) NOT NULL,
  18. address varchar(200) NOT NULL,
  19.  
  20. -- Chống trùng mã trụ sở
  21. CONSTRAINT PK_headquarter PRIMARY KEY (ID_headquarter),
  22.  
  23. -- Chống trùng tên trụ sở
  24. CONSTRAINT UQ_headquarter_name UNIQUE (name_headquarter)
  25. );
  26.  
  27. /* =========================================================
  28.   2. DEPARTMENT
  29.   Lưu thông tin khoa thuộc từng trụ sở
  30. ========================================================= */
  31.  
  32. CREATE TABLE department
  33. (
  34. ID_department varchar(20) NOT NULL,
  35. name_department varchar(100) NOT NULL,
  36. ID_headquarter varchar(20) NOT NULL,
  37.  
  38. -- Chống trùng mã khoa
  39. CONSTRAINT PK_department PRIMARY KEY (ID_department),
  40.  
  41. -- Mỗi khoa phải thuộc một trụ sở hợp lệ
  42. CONSTRAINT FK_department_headquarter
  43. FOREIGN KEY (ID_headquarter)
  44. REFERENCES headquarter(ID_headquarter),
  45.  
  46. -- Không trùng tên khoa trong cùng một trụ sở
  47. CONSTRAINT UQ_department_headquarter_name
  48. UNIQUE (ID_headquarter, name_department)
  49. );
  50.  
  51. /* =========================================================
  52.   3. SUBJECT
  53.   Danh mục môn học/học phần dùng chung toàn hệ thống
  54. ========================================================= */
  55.  
  56. CREATE TABLE subject
  57. (
  58. ID_subject varchar(20) NOT NULL,
  59. name_subject varchar(100) NOT NULL,
  60. number_of_credit int NOT NULL,
  61.  
  62. -- Chống trùng mã môn học
  63. CONSTRAINT PK_subject PRIMARY KEY (ID_subject),
  64.  
  65. -- Chống trùng tên môn học
  66. CONSTRAINT UQ_subject_name UNIQUE (name_subject),
  67.  
  68. -- Số tín chỉ phải lớn hơn 0
  69. CONSTRAINT CK_subject_credit CHECK (number_of_credit > 0)
  70. );
  71.  
  72. /* =========================================================
  73.   4. CURRICULUM
  74.   Chương trình đào tạo dùng chung toàn hệ thống
  75. ========================================================= */
  76.  
  77. CREATE TABLE curriculum
  78. (
  79. ID_curriculum varchar(20) NOT NULL,
  80. curriculum_name varchar(100) NOT NULL,
  81. total_credits_required int NOT NULL,
  82.  
  83. -- Chống trùng mã chương trình đào tạo
  84. CONSTRAINT PK_curriculum PRIMARY KEY (ID_curriculum),
  85.  
  86. -- Chống trùng tên chương trình đào tạo
  87. CONSTRAINT UQ_curriculum_name UNIQUE (curriculum_name),
  88.  
  89. -- Tổng tín chỉ yêu cầu phải lớn hơn 0
  90. CONSTRAINT CK_curriculum_total_credit CHECK (total_credits_required > 0)
  91. );
  92.  
  93. /* =========================================================
  94.   5. CURRICULUM_SUBJECT
  95.   Bảng trung gian giữa chương trình đào tạo và môn học
  96. ========================================================= */
  97.  
  98. CREATE TABLE curriculum_subject
  99. (
  100. ID_curriculum varchar(20) NOT NULL,
  101. ID_subject varchar(20) NOT NULL,
  102. is_required tinyint(1) NOT NULL,
  103.  
  104. -- Một môn không được lặp trong cùng một chương trình đào tạo
  105. CONSTRAINT PK_curriculum_subject
  106. PRIMARY KEY (ID_curriculum, ID_subject),
  107.  
  108. -- Chương trình đào tạo phải tồn tại
  109. CONSTRAINT FK_curriculum_subject_curriculum
  110. FOREIGN KEY (ID_curriculum)
  111. REFERENCES curriculum(ID_curriculum),
  112.  
  113. -- Môn học phải tồn tại
  114. CONSTRAINT FK_curriculum_subject_subject
  115. FOREIGN KEY (ID_subject)
  116. REFERENCES subject(ID_subject)
  117. );
  118.  
  119. /* =========================================================
  120.   6. PREREQUISITE
  121.   Lưu môn học tiên quyết
  122. ========================================================= */
  123.  
  124. CREATE TABLE prerequisite
  125. (
  126. ID_subject varchar(20) NOT NULL,
  127. ID_prereq_subject varchar(20) NOT NULL,
  128. min_grade float NULL,
  129. note varchar(200) NULL,
  130.  
  131. -- Chống trùng cặp môn học - môn tiên quyết
  132. CONSTRAINT PK_prerequisite
  133. PRIMARY KEY (ID_subject, ID_prereq_subject),
  134.  
  135. -- Môn học chính phải tồn tại
  136. CONSTRAINT FK_prerequisite_subject
  137. FOREIGN KEY (ID_subject)
  138. REFERENCES subject(ID_subject),
  139.  
  140. -- Môn tiên quyết cũng phải tồn tại trong bảng subject
  141. CONSTRAINT FK_prerequisite_prereq_subject
  142. FOREIGN KEY (ID_prereq_subject)
  143. REFERENCES subject(ID_subject),
  144.  
  145. -- Một môn không được là tiên quyết của chính nó
  146. CONSTRAINT CK_prerequisite_not_self
  147. CHECK (ID_subject <> ID_prereq_subject),
  148.  
  149. -- Điểm tối thiểu nếu có phải nằm trong khoảng 0 đến 10
  150. CONSTRAINT CK_prerequisite_min_grade
  151. CHECK (min_grade IS NULL OR min_grade BETWEEN 0 AND 10)
  152. );
  153.  
  154. /* =========================================================
  155.   7. TERM
  156.   Lưu học kỳ, năm học, thời gian mở/đóng đăng ký
  157. ========================================================= */
  158.  
  159. CREATE TABLE term
  160. (
  161. ID_term varchar(20) NOT NULL,
  162. name_term varchar(100) NOT NULL,
  163. year_start int NOT NULL,
  164. term_no int NOT NULL,
  165. start_date date NOT NULL,
  166. end_date date NOT NULL,
  167. reg_open datetime NOT NULL,
  168. reg_close datetime NOT NULL,
  169.  
  170. -- Chống trùng mã học kỳ
  171. CONSTRAINT PK_term PRIMARY KEY (ID_term),
  172.  
  173. -- Học kỳ chỉ nhận 1, 2 hoặc 3
  174. CONSTRAINT CK_term_no
  175. CHECK (term_no BETWEEN 1 AND 3),
  176.  
  177. -- Ngày bắt đầu phải trước ngày kết thúc
  178. CONSTRAINT CK_term_date
  179. CHECK (start_date < end_date),
  180.  
  181. -- Thời gian mở đăng ký phải trước thời gian đóng đăng ký
  182. CONSTRAINT CK_term_register_time
  183. CHECK (reg_open < reg_close)
  184. );
  185.  
  186. /* =========================================================
  187.   8. TIMESLOT
  188.   Lưu ca học dùng chung toàn hệ thống
  189. ========================================================= */
  190.  
  191. CREATE TABLE timeslot
  192. (
  193. ID_timeslot varchar(20) NOT NULL,
  194. shift_no int NOT NULL,
  195. start_time time NOT NULL,
  196. end_time time NOT NULL,
  197.  
  198. -- Chống trùng mã ca học
  199. CONSTRAINT PK_timeslot PRIMARY KEY (ID_timeslot),
  200.  
  201. -- Chống trùng số ca học
  202. CONSTRAINT UQ_timeslot_shift_no
  203. UNIQUE (shift_no),
  204.  
  205. -- Giờ bắt đầu phải trước giờ kết thúc
  206. CONSTRAINT CK_timeslot_time
  207. CHECK (start_time < end_time)
  208. );
  209.  
  210. /* =========================================================
  211.   9. TEACHER
  212.   Lưu thông tin giảng viên
  213. ========================================================= */
  214.  
  215. CREATE TABLE teacher
  216. (
  217. ID_teacher varchar(20) NOT NULL,
  218. name_teacher varchar(100) NOT NULL,
  219. degree varchar(100) NULL,
  220. address_teacher varchar(200) NULL,
  221. phone_teacher varchar(15) NULL,
  222. gender_teacher varchar(10) NULL,
  223. ID_department varchar(20) NOT NULL,
  224.  
  225. -- Chống trùng mã giảng viên
  226. CONSTRAINT PK_teacher PRIMARY KEY (ID_teacher),
  227.  
  228. -- Giảng viên phải thuộc một khoa hợp lệ
  229. CONSTRAINT FK_teacher_department
  230. FOREIGN KEY (ID_department)
  231. REFERENCES department(ID_department),
  232.  
  233. -- Chống trùng số điện thoại giảng viên (MySQL cho phép nhiều dòng NULL)
  234. CONSTRAINT UQ_teacher_phone UNIQUE (phone_teacher)
  235. );
  236.  
  237. /* =========================================================
  238.   10. STUDENT
  239.   Lưu thông tin sinh viên
  240. ========================================================= */
  241.  
  242. CREATE TABLE student
  243. (
  244. ID_student varchar(20) NOT NULL,
  245. name_student varchar(100) NOT NULL,
  246. date_of_birth date NULL,
  247. gender_student varchar(10) NULL,
  248. address_student varchar(200) NULL,
  249. phone_student varchar(15) NULL,
  250. year_of_admission int NOT NULL,
  251. ID_department varchar(20) NOT NULL,
  252. ID_curriculum varchar(20) NOT NULL,
  253.  
  254. -- Chống trùng mã sinh viên
  255. CONSTRAINT PK_student PRIMARY KEY (ID_student),
  256.  
  257. -- Sinh viên phải thuộc một khoa hợp lệ
  258. CONSTRAINT FK_student_department
  259. FOREIGN KEY (ID_department)
  260. REFERENCES department(ID_department),
  261.  
  262. -- Sinh viên phải theo một chương trình đào tạo hợp lệ
  263. CONSTRAINT FK_student_curriculum
  264. FOREIGN KEY (ID_curriculum)
  265. REFERENCES curriculum(ID_curriculum),
  266.  
  267. -- Năm nhập học không quá nhỏ
  268. CONSTRAINT CK_student_year_admission
  269. CHECK (year_of_admission >= 2000),
  270.  
  271. -- Chống trùng số điện thoại sinh viên (MySQL cho phép nhiều dòng NULL)
  272. CONSTRAINT UQ_student_phone UNIQUE (phone_student)
  273. );
  274.  
  275. /* =========================================================
  276.   11. ROOM
  277.   Lưu thông tin phòng học theo từng trụ sở
  278. ========================================================= */
  279.  
  280. CREATE TABLE room
  281. (
  282. ID_room varchar(20) NOT NULL,
  283. name_room varchar(50) NOT NULL,
  284. capacity int NOT NULL,
  285. ID_headquarter varchar(20) NOT NULL,
  286.  
  287. -- Chống trùng mã phòng
  288. CONSTRAINT PK_room PRIMARY KEY (ID_room),
  289.  
  290. -- Phòng học phải thuộc một trụ sở hợp lệ
  291. CONSTRAINT FK_room_headquarter
  292. FOREIGN KEY (ID_headquarter)
  293. REFERENCES headquarter(ID_headquarter),
  294.  
  295. -- Không trùng tên phòng trong cùng một trụ sở
  296. CONSTRAINT UQ_room_headquarter_name
  297. UNIQUE (ID_headquarter, name_room),
  298.  
  299. -- Sức chứa phòng phải lớn hơn 0
  300. CONSTRAINT CK_room_capacity
  301. CHECK (capacity > 0)
  302. );
  303.  
  304. /* =========================================================
  305.   12. CLASS
  306.   Lưu lớp học phần được mở trong từng học kỳ
  307. ========================================================= */
  308.  
  309. CREATE TABLE `class`
  310. (
  311. ID_class varchar(20) NOT NULL,
  312. ID_subject varchar(20) NOT NULL,
  313. ID_teacher varchar(20) NOT NULL,
  314. ID_term varchar(20) NOT NULL,
  315. group_number int NOT NULL,
  316. min_students int NOT NULL,
  317. max_students int NOT NULL,
  318.  
  319. -- Số lượng sinh viên đã đăng ký, mặc định là 0
  320. number_of_registration int NOT NULL DEFAULT 0,
  321.  
  322. -- Trạng thái lớp học phần, mặc định là OPEN
  323. class_status varchar(20) NOT NULL DEFAULT 'OPEN',
  324.  
  325. -- Chống trùng mã lớp học phần
  326. CONSTRAINT PK_class PRIMARY KEY (ID_class),
  327.  
  328. -- Lớp học phần phải thuộc một môn học hợp lệ
  329. CONSTRAINT FK_class_subject
  330. FOREIGN KEY (ID_subject)
  331. REFERENCES subject(ID_subject),
  332.  
  333. -- Lớp học phần phải có giảng viên phụ trách hợp lệ
  334. CONSTRAINT FK_class_teacher
  335. FOREIGN KEY (ID_teacher)
  336. REFERENCES teacher(ID_teacher),
  337.  
  338. -- Lớp học phần phải thuộc một học kỳ hợp lệ
  339. CONSTRAINT FK_class_term
  340. FOREIGN KEY (ID_term)
  341. REFERENCES term(ID_term),
  342.  
  343. -- Nhóm lớp học phần phải lớn hơn 0
  344. CONSTRAINT CK_class_group_number
  345. CHECK (group_number > 0),
  346.  
  347. -- Sĩ số tối thiểu không được âm
  348. CONSTRAINT CK_class_min_students
  349. CHECK (min_students >= 0),
  350.  
  351. -- Sĩ số tối đa phải lớn hơn 0
  352. CONSTRAINT CK_class_max_students
  353. CHECK (max_students > 0),
  354.  
  355. -- Sĩ số tối thiểu không được lớn hơn sĩ số tối đa
  356. CONSTRAINT CK_class_min_max
  357. CHECK (min_students <= max_students),
  358.  
  359. -- Số lượng đăng ký không được âm và không được vượt sĩ số tối đa
  360. CONSTRAINT CK_class_number_registration
  361. CHECK (number_of_registration >= 0 AND number_of_registration <= max_students),
  362.  
  363. -- Trạng thái lớp chỉ được thuộc các giá trị hợp lệ
  364. CONSTRAINT CK_class_status
  365. CHECK (class_status IN ('OPEN', 'CLOSED', 'CANCELLED')),
  366.  
  367. -- Chống trùng lớp cùng môn, cùng học kỳ, cùng nhóm
  368. CONSTRAINT UQ_class_subject_term_group
  369. UNIQUE (ID_subject, ID_term, group_number)
  370. );
  371.  
  372. /* =========================================================
  373.   13. SESSION
  374.   Lưu lịch học/buổi học cụ thể của lớp học phần
  375. ========================================================= */
  376.  
  377. CREATE TABLE `session`
  378. (
  379. ID_session varchar(20) NOT NULL,
  380. study_date date NOT NULL,
  381. day_of_week tinyint NOT NULL,
  382. note varchar(200) NULL,
  383. ID_class varchar(20) NOT NULL,
  384. ID_room varchar(20) NOT NULL,
  385. ID_timeslot varchar(20) NOT NULL,
  386.  
  387. -- Chống trùng mã buổi học
  388. CONSTRAINT PK_session PRIMARY KEY (ID_session),
  389.  
  390. -- Buổi học phải thuộc một lớp học phần hợp lệ
  391. CONSTRAINT FK_session_class
  392. FOREIGN KEY (ID_class)
  393. REFERENCES `class`(ID_class),
  394.  
  395. -- Buổi học phải diễn ra tại một phòng hợp lệ
  396. CONSTRAINT FK_session_room
  397. FOREIGN KEY (ID_room)
  398. REFERENCES room(ID_room),
  399.  
  400. -- Buổi học phải thuộc một ca học hợp lệ
  401. CONSTRAINT FK_session_timeslot
  402. FOREIGN KEY (ID_timeslot)
  403. REFERENCES timeslot(ID_timeslot),
  404.  
  405. -- Thứ trong tuần từ 2 đến 8
  406. CONSTRAINT CK_session_day_of_week
  407. CHECK (day_of_week BETWEEN 2 AND 8),
  408.  
  409. -- Một phòng không được xếp cho 2 lớp cùng ngày, cùng ca
  410. CONSTRAINT UQ_session_room_time
  411. UNIQUE (ID_room, study_date, ID_timeslot)
  412. );
  413.  
  414. /* =========================================================
  415.   14. REGISTRATION
  416.   Lưu thông tin đăng ký học phần của sinh viên
  417. ========================================================= */
  418.  
  419. CREATE TABLE registration
  420. (
  421. ID_registration varchar(20) NOT NULL,
  422. ID_student varchar(20) NOT NULL,
  423. ID_class varchar(20) NOT NULL,
  424.  
  425. -- Thời gian đăng ký, mặc định là thời điểm hiện tại
  426. registered_at datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  427.  
  428. cancelled_at datetime NULL,
  429.  
  430. -- Trạng thái đăng ký, mặc định là REGISTERED
  431. registration_status varchar(20) NOT NULL DEFAULT 'REGISTERED',
  432.  
  433. -- Cột ảo thay thế Filtered Index của SQL Server để kiểm soát trùng lặp khi trạng thái là REGISTERED
  434. active_uid varchar(50) GENERATED ALWAYS AS (
  435. CASE WHEN registration_status = 'REGISTERED' THEN CONCAT(ID_student, '_', ID_class) ELSE NULL END
  436. ) VIRTUAL,
  437.  
  438. -- Chống trùng mã đăng ký
  439. CONSTRAINT PK_registration PRIMARY KEY (ID_registration),
  440.  
  441. -- Đăng ký phải thuộc sinh viên hợp lệ
  442. CONSTRAINT FK_registration_student
  443. FOREIGN KEY (ID_student)
  444. REFERENCES student(ID_student),
  445.  
  446. -- Đăng ký phải thuộc lớp học phần hợp lệ
  447. CONSTRAINT FK_registration_class
  448. FOREIGN KEY (ID_class)
  449. REFERENCES `class`(ID_class),
  450.  
  451. -- Trạng thái đăng ký chỉ nhận giá trị hợp lệ
  452. CONSTRAINT CK_registration_status
  453. CHECK (registration_status IN ('REGISTERED', 'CANCELLED')),
  454.  
  455. -- Nếu có thời gian hủy thì thời gian hủy phải sau thời gian đăng ký
  456. CONSTRAINT CK_registration_cancelled_at
  457. CHECK (cancelled_at IS NULL OR cancelled_at >= registered_at),
  458.  
  459. -- Thực thi Unique ràng buộc qua cột ảo active_uid
  460. CONSTRAINT UQ_registration_active UNIQUE (active_uid)
  461. );
  462.  
  463. /* =========================================================
  464.   15. INDEX PHỤ TRỢ
  465. ========================================================= */
  466.  
  467. CREATE INDEX IX_department_headquarter ON department(ID_headquarter);
  468. CREATE INDEX IX_teacher_department ON teacher(ID_department);
  469. CREATE INDEX IX_student_department ON student(ID_department);
  470. CREATE INDEX IX_student_curriculum ON student(ID_curriculum);
  471. CREATE INDEX IX_room_headquarter ON room(ID_headquarter);
  472. CREATE INDEX IX_class_subject ON `class`(ID_subject);
  473. CREATE INDEX IX_class_teacher ON `class`(ID_teacher);
  474. CREATE INDEX IX_class_term ON `class`(ID_term);
  475. CREATE INDEX IX_session_class ON `session`(ID_class);
  476. CREATE INDEX IX_registration_student ON registration(ID_student);
  477. CREATE INDEX IX_registration_class ON registration(ID_class);
  478.  
  479.  
  480. /* =========================================================
  481.   16. PROCEDURE ĐĂNG KÝ HỌC PHẦN
  482. ========================================================= */
  483.  
  484. DELIMITER //
  485.  
  486. DROP PROCEDURE IF EXISTS usp_RegisterClass//
  487.  
  488. CREATE PROCEDURE usp_RegisterClass (
  489. IN p_ID_registration varchar(20),
  490. IN p_ID_student varchar(20),
  491. IN p_ID_class varchar(20)
  492. )
  493. BEGIN
  494. DECLARE msg TEXT;
  495.  
  496. -- Xử lý ngoại lệ để Rollback tự động và đẩy thông báo lỗi ra ngoài
  497. DECLARE EXIT HANDLER FOR SQLEXCEPTION
  498. BEGIN
  499. GET DIAGNOSTICS CONDITION 1 msg = MESSAGE_TEXT;
  500. ROLLBACK;
  501. SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = msg;
  502. END;
  503.  
  504. START TRANSACTION;
  505.  
  506. -- Kiểm tra sinh viên có tồn tại không
  507. IF NOT EXISTS (
  508. SELECT 1
  509. FROM student
  510. WHERE ID_student = p_ID_student
  511. ) THEN
  512. SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Sinh viên không tồn tại.';
  513. END IF;
  514.  
  515. -- Kiểm tra lớp có mở đăng ký và còn trong thời gian đăng ký không
  516. IF NOT EXISTS (
  517. SELECT 1
  518. FROM `class` c
  519. JOIN term t ON c.ID_term = t.ID_term
  520. WHERE c.ID_class = p_ID_class
  521. AND c.class_status = 'OPEN'
  522. AND NOW() BETWEEN t.reg_open AND t.reg_close
  523. ) THEN
  524. SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Lớp không mở đăng ký hoặc ngoài thời gian đăng ký.';
  525. END IF;
  526.  
  527. -- Chống sinh viên đăng ký trùng cùng một lớp học phần
  528. IF EXISTS (
  529. SELECT 1
  530. FROM registration
  531. WHERE ID_student = p_ID_student
  532. AND ID_class = p_ID_class
  533. AND registration_status = 'REGISTERED'
  534. ) THEN
  535. SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Sinh viên đã đăng ký lớp học phần này.';
  536. END IF;
  537.  
  538. -- Chống sinh viên đăng ký 2 lớp bị trùng lịch học
  539. IF EXISTS (
  540. SELECT 1
  541. FROM registration r
  542. JOIN `session` s_old ON r.ID_class = s_old.ID_class
  543. JOIN `session` s_new ON s_old.study_date = s_new.study_date
  544. AND s_old.ID_timeslot = s_new.ID_timeslot
  545. WHERE r.ID_student = p_ID_student
  546. AND r.registration_status = 'REGISTERED'
  547. AND s_new.ID_class = p_ID_class
  548. ) THEN
  549. SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Lịch học bị trùng với lớp học phần đã đăng ký.';
  550. END IF;
  551.  
  552. -- Tăng sĩ số nếu lớp còn chỗ (MySQL tự động Row Lock dòng này khi UPDATE)
  553. UPDATE `class`
  554. SET number_of_registration = number_of_registration + 1
  555. WHERE ID_class = p_ID_class
  556. AND class_status = 'OPEN'
  557. AND number_of_registration < max_students;
  558.  
  559. -- Nếu không update được dòng nào nghĩa là lớp đã đầy
  560. IF ROW_COUNT() = 0 THEN
  561. SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Lớp học phần đã đủ sĩ số.';
  562. END IF;
  563.  
  564. -- Thêm bản ghi đăng ký
  565. INSERT INTO registration (ID_registration, ID_student, ID_class)
  566. VALUES (p_ID_registration, p_ID_student, p_ID_class);
  567.  
  568. COMMIT;
  569. END//
  570.  
  571. DELIMITER ;
  572.  
  573.  
  574. /* =========================================================
  575.   17. PROCEDURE HỦY ĐĂNG KÝ
  576. ========================================================= */
  577.  
  578. DELIMITER //
  579.  
  580. DROP PROCEDURE IF EXISTS usp_CancelRegistration//
  581.  
  582. CREATE PROCEDURE usp_CancelRegistration (
  583. IN p_ID_registration varchar(20)
  584. )
  585. BEGIN
  586. DECLARE v_ID_class varchar(20) DEFAULT NULL;
  587. DECLARE msg TEXT;
  588.  
  589. -- Xử lý ngoại lệ để Rollback tự động
  590. DECLARE EXIT HANDLER FOR SQLEXCEPTION
  591. BEGIN
  592. GET DIAGNOSTICS CONDITION 1 msg = MESSAGE_TEXT;
  593. ROLLBACK;
  594. SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = msg;
  595. END;
  596.  
  597. START TRANSACTION;
  598.  
  599. -- Khóa bản ghi đăng ký cần hủy và lấy ID_class bằng FOR UPDATE
  600. SELECT ID_class INTO v_ID_class
  601. FROM registration
  602. WHERE ID_registration = p_ID_registration
  603. AND registration_status = 'REGISTERED'
  604. FOR UPDATE;
  605.  
  606. -- Nếu không tìm thấy đăng ký hợp lệ thì báo lỗi
  607. IF v_ID_class IS NULL THEN
  608. SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Không tìm thấy đăng ký hợp lệ để hủy.';
  609. END IF;
  610.  
  611. -- Cập nhật trạng thái hủy
  612. UPDATE registration
  613. SET registration_status = 'CANCELLED',
  614. cancelled_at = NOW()
  615. WHERE ID_registration = p_ID_registration;
  616.  
  617. -- Giảm sĩ số lớp sau khi hủy
  618. UPDATE `class`
  619. SET number_of_registration = number_of_registration - 1
  620. WHERE ID_class = v_ID_class
  621. AND number_of_registration > 0;
  622.  
  623. COMMIT;
  624. END//
  625.  
  626. DELIMITER ;
Success #stdin #stdout #stderr 0.01s 5288KB
stdin
Standard input is empty
stdout
Standard output is empty
stderr
Error: near line 5: near "DATABASE": syntax error
Error: near line 6: near "DATABASE": syntax error
Error: near line 7: near "USE": syntax error
Error: near line 419: near "GENERATED": syntax error
Error: near line 476: no such table: main.registration
Error: near line 477: no such table: main.registration
Error: near line 484: near "DELIMITER": syntax error
Error: near line 497: near "DECLARE": syntax error
Error: near line 500: cannot rollback - no transaction is active
Error: near line 501: near "SIGNAL": syntax error
Error: near line 502: cannot commit - no transaction is active
Error: near line 504: near "START": syntax error
Error: near line 507: near "IF": syntax error
Error: near line 513: near "IF": syntax error
Error: near line 516: near "IF": syntax error
Error: near line 525: near "IF": syntax error
Error: near line 528: near "IF": syntax error
Error: near line 536: near "IF": syntax error
Error: near line 539: near "IF": syntax error
Error: near line 550: near "IF": syntax error
Error: near line 553: no such column: p_ID_class
Error: near line 560: near "IF": syntax error
Error: near line 562: near "IF": syntax error
Error: near line 565: no such table: registration
Error: near line 568: cannot commit - no transaction is active
Error: near line 569: near "/": syntax error
Error: near line 578: near "DELIMITER": syntax error
Error: near line 587: near "DECLARE": syntax error
Error: near line 590: near "DECLARE": syntax error
Error: near line 593: cannot rollback - no transaction is active
Error: near line 594: near "SIGNAL": syntax error
Error: near line 595: cannot commit - no transaction is active
Error: near line 597: near "START": syntax error
Error: near line 600: near "INTO": syntax error
Error: near line 607: near "IF": syntax error
Error: near line 609: near "IF": syntax error
Error: near line 612: no such table: registration
Error: near line 618: no such column: v_ID_class
Error: near line 623: cannot commit - no transaction is active
Error: near line 624: near "/": syntax error