-- Общая функция возвращения всех госпитализаций и периодов пациента CREATE OR REPLACE FUNCTION get_hospitalization_periods (p_patient_id int) RETURNS TABLE ( admission_datetime timestamp, discharge_datetime timestamp ) AS $$ BEGIN RETURN QUERY SELECT ha.admission_datetime, hd.discharge_datetime FROM hospital_admission ha LEFT JOIN hospital_discharge hd ON ha.hospital_admission_id = hd.hospital_admission_id WHERE ha.patient_id = p_patient_id; END; $$ LANGUAGE plpgsql; -- Триггер: запрещает новую госпитализацию при наличии незавершённой CREATE OR REPLACE FUNCTION check_active_hospitalization () RETURNS TRIGGER AS $$ DECLARE open_hospitalization boolean; BEGIN SELECT EXISTS ( SELECT 1 FROM get_hospitalization_periods (NEW.patient_id) WHERE discharge_datetime IS NULL) INTO open_hospitalization; IF open_hospitalization THEN RAISE EXCEPTION USING ERRCODE = 'P0001', MESSAGE = '10001: ACTIVE_HOSPITALIZATION_EXISTS'; END IF; RETURN NEW; END; $$ LANGUAGE plpgsql; -- Триггер: запрещает перекрытие госпитализаций CREATE OR REPLACE FUNCTION check_hospitalization_overlap () RETURNS TRIGGER AS $$ DECLARE overlap_found boolean; BEGIN SELECT EXISTS ( SELECT 1 FROM get_hospitalization_periods (NEW.patient_id) WHERE discharge_datetime IS NOT NULL AND NEW.admission_datetime < discharge_datetime AND NEW.admission_datetime > admission_datetime) INTO overlap_found; IF overlap_found THEN RAISE EXCEPTION USING ERRCODE = 'P0001', MESSAGE = '10002: HOSPITALIZATION_OVERLAP'; END IF; RETURN NEW; END; $$ LANGUAGE plpgsql; -- Подключение триггеров на hospital_admissions CREATE TRIGGER trg_check_active_hospitalization BEFORE INSERT ON hospital_admission FOR EACH ROW EXECUTE FUNCTION check_active_hospitalization (); CREATE TRIGGER trg_check_hospitalization_overlap BEFORE INSERT ON hospital_admission FOR EACH ROW EXECUTE FUNCTION check_hospitalization_overlap ();