I'm little lost trying to solve a problem. At first I've this 5 tables:
CREATE TABLE DOCTOR (
Doc_Number INTEGER,
Name VARCHAR(50) NOT NULL,
Specialty VARCHAR(50) NOT NULL,
Address VARCHAR(50) NOT NULL,
City VARCHAR(30) NOT NULL,
Phone VARCHAR(10) NOT NULL,
Salary DECIMAL(8,2) NOT NULL,
DNI VARCHAR(10) UNIQUE,
CONSTRAINT pk_Doctor PRIMARY KEY (Doc_Number),
CONSTRAINT ck_Salary CHECK (Salary >0)
);
CREATE TABLE PATIENT (
Pat_Number INTEGER,
Name VARCHAR(50) NOT NULL,
Address VARCHAR(50) NOT NULL,
City VARCHAR(30) NOT NULL,
DNI VARCHAR(10) UNIQUE,
CONSTRAINT pk_PATIENT PRIMARY KEY (Pat_Number)
);
CREATE TABLE VISIT (
Doc_Number INTEGER,
Pat_Number INTEGER,
Visit_Date DATE,
Price DECIMAL(7,2),
Last_Drug VARCHAR(50),
CONSTRAINT Visit_pk PRIMARY KEY (Doc_Number, Pat_Number, Visit_Date),
CONSTRAINT ck_Price CHECK (Price >0),
CONSTRAINT Visit_Doctor_fk FOREIGN KEY (Doc_Number) REFERENCES DOCTOR(Doc_Number),
CONSTRAINT Visit_PATIENT_fk FOREIGN KEY (Pat_Number) REFERENCES PATIENT(Pat_Number)
);
CREATE TABLE PRESCRIPTION (
Presc_Number INTEGER,
Drug VARCHAR(50) NOT NULL,
Doc_Number INTEGER NOT NULL,
Pat_Number INTEGER NOT NULL,
Visit_Date DATE NOT NULL,
CONSTRAINT Prescription_pk PRIMARY KEY (Presc_Number),
CONSTRAINT Prescription_Visit_fk FOREIGN KEY (Doc_Number, Pat_Number, Visit_Date) REFERENCES VISIT(Doc_Number, Pat_Number, Visit_Date)
);
CREATE TABLE VISITS_SUMMARY (
Doc_Number INTEGER,
Pat_Number INTEGER,
Year INTEGER,
Drugs_Number INTEGER,
Visits_Number INTEGER,
Acum_Amount DECIMAL(8,2),
Last_Drug VARCHAR(50),
CONSTRAINT ck_Visits_Number CHECK (Visits_Number >0),
CONSTRAINT ck_Acum_Amount CHECK (Acum_Amount >0),
CONSTRAINT Visits_Summary_pk PRIMARY KEY (Doc_Number, Pat_Number, Year),
CONSTRAINT Summary_Doctor_fk FOREIGN KEY (Doc_Number) REFERENCES DOCTOR(Doc_Number),
CONSTRAINT Summary_PATIENT_fk FOREIGN KEY (Pat_Number) REFERENCES PATIENT(Pat_Number)
);
I've filled the first 4 and I need to create a function to update the last one. The function must do:
- count the number of different drugs prescribed for one doctor to one patient in one year.
- count the number of visits of the patient with one doctor in a year
- add the total value of the visits for the patient with the doctor in a year
- return the last drug prescribed for one doctor to a patient in a year.
Also I need consider these possible errors:
- doctor doesn't exists
- patient doesn't exists
- no visits for this doctor to this patient in this year
And finally save the information in the VISITS_SUMMARY
table.
I've done the firsts 4 points separately in different functions using return and works:
CREATE OR REPLACE FUNCTION sum_visits (p_Doc_Number INTEGER, p_Pat_Number INTEGER, p_Year INTEGER)
RETURNS INTEGER AS $$
DECLARE
BEGIN
SELECT COUNT(Drug)INTO drugs_num
FROM PRESCRIPTION pr
WHERE pr.Doc_Number = p_Doc_Number AND pr.Pat_Number = p_Pat_Number AND
(SELECT EXTRACT(YEAR FROM pr.Visit_Date)) = p_Year;
RETURN drugs_num;
END;
$$LANGUAGE plpgsql;
And the same with this other using the same function parameters only changing the return type.
SELECT COUNT(Visit_Date)INTO visits
FROM VISIT v
WHERE v.Doc_Number = p_Doc_Number AND v.Pat_Number = p_Pat_Number AND
(SELECT EXTRACT(YEAR FROM v.Visit_Date)) = p_Year;
total_price = 0.0;
FOR visit_price IN SELECT Price FROM VISIT v
WHERE v.Doc_Number = p_Doc_Number AND v.Pat_Number = p_Pat_Number AND
(SELECT EXTRACT(YEAR FROM v.Visit_Date)) = p_Year LOOP
total_price := total_price + visit_price;
END LOOP;
SELECT Drug INTO last_drg FROM PRESCRIPTION pr
WHERE pr.Doc_Number = p_Doc_Number AND pr.Pat_Number = p_Pat_Number AND
(SELECT EXTRACT(YEAR FROM pr.Visit_Date)) = p_Year AND
Presc_Number = (SELECT MAX(Presc_Number)FROM PRESCRIPTION);
I've tried to do the exceptions using IF
conditions but it doesn't work. Here is a complete example for one of the different operations of the function:
CREATE OR REPLACE FUNCTION sum_visits (p_Doc_Number INTEGER, p_Pat_Number INTEGER, p_Year INTEGER)
RETURNS void AS $$
DECLARE
drugs_num INTEGER;
BEGIN
IF (PRESCRIPTION.Doc_Number NOT IN (p_Doc_Number))THEN
RAISE EXCEPTION
'Doctor % doesn"t exists';
ELSIF (PRESCRIPTION.Pat_Number NOT IN (p_Pat_Number))THEN
RAISE EXCEPTION
'Patient doesn"t exists';
ELSIF((SELECT EXTRACT(YEAR FROM PRESCRIPTION.Visit_Date)) NOT IN p_Year) THEN
RAISE EXCEPTION
'Date % doesn"t exists'
ELSE SELECT COUNT(Drug)INTO drugs_num
FROM PRESCRIPTION pr
WHERE pr.Doc_Number = p_Doc_Number AND pr.Pat_Number = p_Pat_Number AND
(SELECT EXTRACT(YEAR FROM pr.Visit_Date)) = p_Year;
end if;
update VISITS_SUMMARY
set Drugs_Number = drugs_num;
exception
when raise_exception THEN
RAISE EXCEPTION' %: %',SQLSTATE, SQLERRM;
END;
$$LANGUAGE plpgsql;
I need help to use the update statement because even not considering the exceptions seems like table don't update and some help with the control exceptions.
There are some examples to fill the firsts table and call the function with this parameters (26902, 6574405, 2011)
INSERT INTO DOCTOR (Doc_number,Name,Specialty,Address,City,Phone,Salary,DNI) values
(26902,'Dr. Alemany','Traumatologia','C. Muntaner, 55,','Barcelona','657982553',71995,'52561523T');
INSERT INTO PATIENT (Pat_Number, Name, Address, City, DNI) values
(6574405,'Sra. Alemany ','C. Muntaner, 80','Barcelona','176784267B');
INSERT INTO VISIT (Doc_Number, Pat_Number,Visit_Date,Price) values
(26902,6574405,'30/03/11',215);
INSERT INTO PRESCRIPTION (Presc_Number, Drug, Doc_Number, Pat_Number, Visit_Date) values
(44,'Diclofenac',26902,6574405,'30/03/11')
, (45,'Ibuprofè',26902,6574405,'30/03/11')
, (46,'Ibuprofè',26902,6574405,'30/03/11');
I have more inserts if you want.