I am trying to write a PLSQL function that implements a constraint that an employee cannot be both a driver and a mechanic at the same time, in other words, the same E# from TRKEMPLOYEE cannot be in TRKDRIVER and TRKMECHANIC at the same time. If the contents of the DB violate that constraint, list the E# and NAME of all employees that are both mechanics and drivers. The abovementioned tables are something like as follows:
TRKEMPLOYEE(E# NUMBER(12) NOT NULL
NAME VARCHAR(50) NOT NULL,
DOB DATE ,
ADDRESS VARCHAR(300) NOT NULL,
HIREDATE DATE NOT NULL,
CONSTRAINT TRKEMPLOYEE_PKEY PRIMARY KEY(E#))
TRKDRIVER(E# NUMBER(12) NOT NULL
L# NUMBER(8) NOT NULL,
STATUS VARCHAR(10) NOT NULL,
CONSTRAINT TRKDRIVER_PKEY PRIMARY KEY(E#),
CONSTRAINT TRKDRIVER_FKEY FOREIGN KEY(E#) REFERENCES TRKEMPLOYEE(E#))
TRKMECHANIC(E# NUMBER(12) NOT NULL
L# NUMBER(8) NOT NULL,
STATUS VARCHAR(10) NOT NULL,
EXPERIENCE VARCHAR(10) NOT NULL,
CONSTRAINT TRKMECHANIC_PKEY PRIMARY KEY(E#),
CONSTRAINT TRKMECHANIC_FKEY FOREIGN KEY(E#) REFERENCES TRKEMPLOYEE(E#))
I have attempted to write a function but keep getting a compile error in line 1 column 7. Can someone tell me why my code doesn’t work? My code is as follows
CREATE OR REPLACE FUNCTION Verify()
IS DECLARE
E# TRKEMPLOYEE.E#%TYPE;
CURSOR C1 IS SELECT E# FROM TRKEMPLOYEE;
BEGIN
OPEN C1;
LOOP
FETCH C1 INTO EMPNUM;
IF(EMPNUM IN(SELECT E# FROM TRKMECHANIC )AND EMPNUM IN(SELECT E# FROM TRKDRIVER))
SELECT E#, NAME FROM TRKEMPLOYEE WHERE E#=EMPNUM;
ELSE
dbms_output.put_line(“OK”);
ENDIF
EXIT WHEN C1%NOTFOUND;
END LOOP;
CLOSE C1;
END;
/
Any help would be appreciated. Thanks.
You are creating a function but missing the
RETURNdeclaration. If you don’t want to return a result, the usecreate or replace procedure.Additionally, if you don’t have any parameters, remove the brackets
()and theDECLAREkeyword is not correct either.The the way you check the tables is not really efficient. You can get the count of all employees violating your business constraint with a single query:
Additionally the
EXIT WHEN C1%NOTFOUND;should be right after theFETCHstatement. Otherwise you are staying in the loop even though the cursor didn’t fetch anything.If you take my simplified statement, you can loop once through all employees and print OK, nor Not OK depending on the count:
Solving the problem without a stored procedure
I was thinking about a way how this business rule can be enforced with only constraints in the database:
The idea is to include the employee type in its foreign key, and to make sure that the dependent tables cannot use the wrong type. When inserting a new trkemployee the type must be specified. The check constraint on the detail tables will reject any row with the wrong type.
To “move” an employee from one type to the other (if this is possible at all), the old detail row must be deleted first. Only then the employee’s type can be changed to the other type. And finally the new detail could be inserted.