proiz_pract_script.sql 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. CREATE TABLE TourFirm (
  2. firm_id SERIAL PRIMARY KEY,
  3. firm_name VARCHAR(100) NOT NULL,
  4. people_count INT NOT NULL CHECK (people_count > 0)
  5. );
  6. CREATE TABLE RoomType (
  7. room_type_id SERIAL PRIMARY KEY,
  8. type_name VARCHAR(50) NOT NULL UNIQUE
  9. );
  10. CREATE TABLE Room (
  11. room_id SERIAL PRIMARY KEY,
  12. room_type_id INT NOT NULL REFERENCES RoomType(room_type_id)
  13. ON DELETE RESTRICT ON UPDATE CASCADE,
  14. room_number INT NOT NULL UNIQUE CHECK (room_number > 0),
  15. occupancy INT NOT NULL CHECK (occupancy > 0),
  16. rating DECIMAL(3,1) NOT NULL DEFAULT 0.0
  17. CHECK (rating >= 0.0 AND rating <= 5.0)
  18. );
  19. CREATE TABLE Client (
  20. client_id SERIAL PRIMARY KEY,
  21. firm_id INT NOT NULL REFERENCES TourFirm(firm_id)
  22. ON DELETE RESTRICT ON UPDATE CASCADE,
  23. last_name VARCHAR(60) NOT NULL,
  24. first_name VARCHAR(60) NOT NULL,
  25. patronymic VARCHAR(60),
  26. phone_number VARCHAR(20) NOT NULL
  27. );
  28. CREATE TABLE Booking (
  29. booking_id SERIAL PRIMARY KEY,
  30. client_id INT NOT NULL REFERENCES Client(client_id)
  31. ON DELETE RESTRICT ON UPDATE CASCADE,
  32. room_id INT NOT NULL REFERENCES Room(room_id)
  33. ON DELETE RESTRICT ON UPDATE CASCADE,
  34. check_in_date DATE NOT NULL,
  35. check_out_date DATE NOT NULL,
  36. price_per_night DECIMAL(10,2) NOT NULL CHECK (price_per_night > 0),s
  37. CHECK (check_out_date > check_in_date)
  38. );
  39. CREATE TABLE Service (
  40. service_id SERIAL PRIMARY KEY,
  41. service_name VARCHAR(100) NOT NULL UNIQUE
  42. );
  43. CREATE TABLE RoomTypeService (
  44. room_type_id INT NOT NULL REFERENCES RoomType(room_type_id)
  45. ON DELETE RESTRICT ON UPDATE CASCADE,
  46. service_id INT NOT NULL REFERENCES Service(service_id)
  47. ON DELETE RESTRICT ON UPDATE CASCADE,
  48. PRIMARY KEY (room_type_id, service_id)
  49. );
  50. SELECT * FROM booking
  51. --Расчетный атрибут — итоговая стоимость бронирования
  52. --total_cost = price_per_night * (check_out_date - check_in_date)
  53. CREATE OR REPLACE VIEW BookingCostView AS
  54. SELECT
  55. b.booking_id,
  56. c.last_name || ' ' || c.first_name || ' ' || COALESCE(c.patronymic, '') AS client_full_name,
  57. r.room_number,
  58. rt.type_name AS room_type,
  59. b.check_in_date,
  60. b.check_out_date,
  61. (b.check_out_date - b.check_in_date) AS nights,
  62. b.price_per_night,
  63. b.price_per_night * (b.check_out_date - b.check_in_date) AS total_cost
  64. FROM Booking b
  65. JOIN Client c ON c.client_id = b.client_id
  66. JOIN Room r ON r.room_id = b.room_id
  67. JOIN RoomType rt ON rt.room_type_id = r.room_type_id;
  68. --Проверочный запрос
  69. SELECT * FROM BookingCostView ORDER BY total_cost DESC LIMIT 10;
  70. --Возвращает итоговую стоимость конкретного бронирования
  71. --Использование в приложении: при отображении карточки брони
  72. CREATE OR REPLACE FUNCTION get_booking_cost(p_booking_id INT)
  73. RETURNS DECIMAL(10,2)
  74. LANGUAGE plpgsql
  75. AS $$
  76. DECLARE
  77. v_cost DECIMAL(10,2);
  78. BEGIN
  79. SELECT price_per_night * (check_out_date - check_in_date)
  80. INTO v_cost
  81. FROM Booking
  82. WHERE booking_id = p_booking_id;
  83. IF NOT FOUND THEN
  84. RAISE EXCEPTION 'Бронирование с ID % не найдено', p_booking_id;
  85. END IF;
  86. RETURN v_cost;
  87. END;
  88. $$;
  89. SELECT get_booking_cost(2);
  90. -- Создаёт новое бронирование
  91. CREATE OR REPLACE PROCEDURE create_booking(
  92. p_client_id INT,
  93. p_room_id INT,
  94. p_check_in_date DATE,
  95. p_check_out_date DATE,
  96. p_price_per_night DECIMAL(10,2)
  97. )
  98. LANGUAGE plpgsql
  99. AS $$
  100. BEGIN
  101. IF p_check_out_date <= p_check_in_date THEN
  102. RAISE EXCEPTION 'Дата выезда должна быть позже даты заезда';
  103. END IF;
  104. IF NOT EXISTS (SELECT 1 FROM Client WHERE client_id = p_client_id) THEN
  105. RAISE EXCEPTION 'Клиент с ID % не найден', p_client_id;
  106. END IF;
  107. IF NOT EXISTS (SELECT 1 FROM Room WHERE room_id = p_room_id) THEN
  108. RAISE EXCEPTION 'Комната с ID % не найдена', p_room_id;
  109. END IF;
  110. IF EXISTS (
  111. SELECT 1 FROM Booking
  112. WHERE room_id = p_room_id
  113. AND check_in_date < p_check_out_date
  114. AND check_out_date > p_check_in_date
  115. ) THEN
  116. RAISE EXCEPTION 'Комната % уже забронирована на указанные даты', p_room_id;
  117. END IF;
  118. INSERT INTO Booking (client_id, room_id, check_in_date, check_out_date, price_per_night)
  119. VALUES (p_client_id, p_room_id, p_check_in_date, p_check_out_date, p_price_per_night);
  120. RAISE NOTICE 'Бронирование успешно создано для клиента ID %', p_client_id;
  121. END;
  122. $$;
  123. CALL create_booking(3, 5, '2026-03-01', '2026-03-014', 2500.00);
  124. SELECT setval('tourfirm_firm_id_seq', (SELECT MAX(firm_id) FROM TourFirm));
  125. SELECT setval('client_client_id_seq', (SELECT MAX(client_id) FROM Client));
  126. SELECT setval('room_room_id_seq', (SELECT MAX(room_id) FROM Room));
  127. SELECT setval('roomtype_room_type_id_seq',(SELECT MAX(room_type_id) FROM RoomType));
  128. SELECT setval('service_service_id_seq', (SELECT MAX(service_id) FROM Service));
  129. SELECT setval('booking_booking_id_seq', (SELECT MAX(booking_id) FROM Booking));
  130. --Логирование бронирований
  131. CREATE TABLE AuditLog (
  132. log_id SERIAL PRIMARY KEY,
  133. tbl_name VARCHAR(50),
  134. action VARCHAR(10),
  135. changed_at TIMESTAMP DEFAULT NOW(),
  136. old_data JSONB,
  137. new_data JSONB
  138. );
  139. CREATE OR REPLACE FUNCTION audit_booking()
  140. RETURNS TRIGGER LANGUAGE plpgsql AS $$
  141. BEGIN
  142. INSERT INTO AuditLog (tbl_name, action, old_data, new_data)
  143. VALUES (
  144. TG_TABLE_NAME, TG_OP,
  145. CASE WHEN TG_OP = 'DELETE' THEN row_to_json(OLD)::jsonb ELSE NULL END,
  146. CASE WHEN TG_OP != 'DELETE' THEN row_to_json(NEW)::jsonb ELSE NULL END
  147. );
  148. RETURN NEW;
  149. END;
  150. $$;
  151. CREATE TRIGGER trg_audit_booking
  152. AFTER INSERT OR UPDATE OR DELETE ON Booking
  153. FOR EACH ROW EXECUTE FUNCTION audit_booking();