These are the following tables I have created:
CREATE TABLE Country
(
country_id NUMBER(3) PRIMARY KEY,
country_name VARCHAR(3) UNIQUE NOT NULL,
CONSTRAINT check_country_id CHECK (country_id > 0)
);
CREATE TABLE OG_Type
(
og_type_id NUMBER(3) PRIMARY KEY,
og_type_title VARCHAR(20) UNIQUE NOT NULL
);
CREATE TABLE Olympic_Game
(
og_id NUMBER(3) PRIMARY KEY,
og_type_id NUMBER(3) NOT NULL,
og_year NUMBER(4) NOT NULL,
og_website VARCHAR(150),
og_cancel VARCHAR(1) NOT NULL,
country_id NUMBER(3) NOT NULL,
CONSTRAINT check_og_id CHECK (og_id > 0),
CONSTRAINT check_og_year_og_type UNIQUE (og_type_id, og_year),
CONSTRAINT fk_og_type_id FOREIGN KEY(og_type_id) REFERENCES OG_Type(og_type_id),
CONSTRAINT fk_country_id FOREIGN KEY(country_id) REFERENCES Country(country_id)
);
CREATE TABLE Sport
(
sport_id NUMBER(3) PRIMARY KEY,
sport_title VARCHAR(100) UNIQUE NOT NULL,
CONSTRAINT check_sport_id CHECK (sport_id > 0)
);
CREATE TABLE Event
(
event_id NUMBER(6) PRIMARY KEY,
sport_id NUMBER(3) NOT NULL,
og_id NUMBER(3) NOT NULL,
event_title VARCHAR(100) NOT NULL,
event_team VARCHAR(1) NOT NULL,
no_per_team NUMBER(2) NOT NULL,
event_gender VARCHAR(1) NOT NULL,
CONSTRAINT check_event_id CHECK (event_id > 0),
CONSTRAINT check_event_title_sport_id_og_id_event_team_event_gender UNIQUE (event_title, sport_id, og_id, event_team, event_gender),
CONSTRAINT check_event_team CHECK (event_team IN ('Y','N')),
CONSTRAINT check_event_team_no_per_team CHECK ((event_team='N' AND no_per_team=1) OR (event_team='Y' AND no_per_team>1)),
CONSTRAINT check_event_gender CHECK (event_gender IN ('M','F')),
CONSTRAINT fk_sport_id FOREIGN KEY(sport_id) REFERENCES Sport(sport_id),
CONSTRAINT fk_og_id FOREIGN KEY(og_id) REFERENCES Olympic_Game(og_id)
);
After creating these 4 tables, I have inserted the values for these 4 tables:
insert into country(country_id,country_name) values (country_seq.nextval,'FRA');
insert into country(country_id,country_name) values (country_seq.nextval,'GBR');
insert into country(country_id,country_name) values (country_seq.nextval,'GRE');
insert into country(country_id,country_name) values (country_seq.nextval,'USA');
insert into og_type(og_type_id, og_type_title) values(og_type_seq.nextval,'Summer');
insert into og_type(og_type_id, og_type_title) values(og_type_seq.nextval,'Winter');
insert into og_type(og_type_id, og_type_title) values(og_type_seq.nextval,'Special');
insert into og_type(og_type_id, og_type_title) values(og_type_seq.nextval,'Youth');
insert into og_type(og_type_id, og_type_title) values(og_type_seq.nextval,'Senior');
insert into olympic_game(og_id,og_type_id,og_year,og_website,og_cancel,country_id) values(og_seq.nextval,1,1896,null,'N',3);
insert into olympic_game(og_id,og_type_id,og_year,og_website,og_cancel,country_id) values(og_seq.nextval,1,1900,null,'N',1);
insert into olympic_game(og_id,og_type_id,og_year,og_website,og_cancel,country_id) values(og_seq.nextval,1,1904,null,'N',4);
insert into olympic_game(og_id,og_type_id,og_year,og_website,og_cancel,country_id) values(og_seq.nextval,1,1908,'op1908.org','N',2);
insert into olympic_game(og_id,og_type_id,og_year,og_website,og_cancel,country_id) values(og_seq.nextval,2,1924,null,'N',1);
insert into olympic_game(og_id,og_type_id,og_year,og_website,og_cancel,country_id) values(og_seq.nextval,1,1944,null,'Y',2);
insert into olympic_game(og_id,og_type_id,og_year,og_website,og_cancel,country_id) values(og_seq.nextval,3,1944,null,'Y',2);
insert into olympic_game(og_id,og_type_id,og_year,og_website,og_cancel,country_id) values(og_seq.nextval,4,1944,null,'Y',2);
insert into olympic_game(og_id,og_type_id,og_year,og_website,og_cancel,country_id) values(og_seq.nextval,5,1944,null,'Y',2);
insert into olympic_game(og_id,og_type_id,og_year,og_website,og_cancel,country_id) values(og_seq.nextval,1,2012,'https://www.olympic.org/london-2012','N',2);
insert into sport(sport_id,sport_title) values(sport_seq.nextval, 'Track and Field');
insert into sport(sport_id,sport_title) values(sport_seq.nextval, 'Tennis');
insert into sport(sport_id,sport_title) values(sport_seq.nextval, 'Speed Skating');
insert into event(event_id,sport_id,og_id,event_title,event_team,no_per_team,event_gender) values(event_seq.nextval,1,1,'100m','N',1,'M');
insert into event(event_id,sport_id,og_id,event_title,event_team,no_per_team,event_gender) values(event_seq.nextval,2,1,'Double','Y',2,'M');
insert into event(event_id,sport_id,og_id,event_title,event_team,no_per_team,event_gender) values(event_seq.nextval,1,2,'200m','N',1,'M');
insert into event(event_id,sport_id,og_id,event_title,event_team,no_per_team,event_gender) values(event_seq.nextval,2,2,'Single','N',1,'M');
insert into event(event_id,sport_id,og_id,event_title,event_team,no_per_team,event_gender) values(event_seq.nextval,1,3,'400m','N',1,'F');
insert into event(event_id,sport_id,og_id,event_title,event_team,no_per_team,event_gender) values(event_seq.nextval,1,3,'100m','N',1,'F');
insert into event(event_id,sport_id,og_id,event_title,event_team,no_per_team,event_gender) values(event_seq.nextval,1,4,'1500m','N',1,'F');
insert into event(event_id,sport_id,og_id,event_title,event_team,no_per_team,event_gender) values(event_seq.nextval,3,5,'800m','N',1,'F');
insert into event(event_id,sport_id,og_id,event_title,event_team,no_per_team,event_gender) values(event_seq.nextval,1,10,'100m','N',1,'M');
insert into event(event_id,sport_id,og_id,event_title,event_team,no_per_team,event_gender) values(event_seq.nextval,1,10,'100m','N',1,'F');
Now this is the question:
Create a trigger called TR_event_on_cancelled_og. This trigger fires before inserting or updating a row in the Event table. The trigger should raise an application error with a meaningful message if og_id refers to a cancelled Olympic Game.
Now this is the solution I came up with:
CREATE OR REPLACE TRIGGER TR_event_on_cancelled
BEFORE INSERT OR UPDATE
ON Event
FOR EACH ROW
BEGIN
DECLARE
v_og_cancel Olympic_Game.og_cancel%TYPE;
BEGIN
SELECT og_cancel INTO V_og_cancel
FROM Olympic_Game, Event
WHERE Olympic_Game.og_id = Event.og_id
AND Olympic_Game.og_id = :NEW.og_id;
IF (v_og_cancel = 'N')
THEN
RAISE_APPLICATION_ERROR(-20001, 'This Olympic Game is cancelled already');
END IF;
END;
END;
Trigger TR_EVENT_ON_CANCELLED compiled
The trigger is compiled successfully but the problem is when I was trying to test the trigger I got the following error messages:
insert into event(event_id,sport_id,og_id,event_title,event_team,no_per_team,event_gender) values(event_seq.nextval,1,8,'400m','N',1,'F');
Error report -
SQL Error: ORA-01403: no data found
ORA-06512: at "OG_JC480454.TR_EVENT_ON_CANCELLED", line 5
ORA-04088: error during execution of trigger 'OG_JC480454.TR_EVENT_ON_CANCELLED'
01403. 00000 - "no data found"
*Cause: No data was found from the objects.
*Action: There was no data from the objects which may be due to end of fetch.
insert into event(event_id,sport_id,og_id,event_title,event_team,no_per_team,event_gender) values(event_seq.nextval,1,2,'400m','N',1,'F');
Error report -
SQL Error: ORA-01422: exact fetch returns more than requested number of rows
ORA-06512: at "OG_JC480454.TR_EVENT_ON_CANCELLED", line 5
ORA-04088: error during execution of trigger 'OG_JC480454.TR_EVENT_ON_CANCELLED'
01422. 00000 - "exact fetch returns more than requested number of rows"
*Cause: The number specified in exact fetch is less than the rows returned.
*Action: Rewrite the query or change number of rows requested
Where did I exactly go wrong ? ...
It would be really helpful if the trigger solution code is provided.
I think your problem is that your trigger code is selecting from EVENT. It doesn't need to do this because the rule applies only to the current event you're inserting or updating.
So:
SELECT og_cancel INTO V_og_cancel
FROM Olympic_Game
WHERE Olympic_Game.og_id = :NEW.og_id;
Incidentally, the next test looks wrong:
IF (v_og_cancel = 'N')
Unless you're using Y/N flags in an odd manner this would be testing if the Games have not been cancelled. Surely that should be = 'Y'?
" I want to get this error message"
I have created an Oracle LiveSQL with your data and my version of the trigger. Find it here (but you will need an OTN account to look at it).
When I attempt this INSERT ...
insert into event(event_id,sport_id,og_id,event_title,event_team,no_per_team,event_gender)
values(event_seq.nextval,2,9,'Double','Y',2,'M');
it fails on
ORA-20001: This Olympic Game is cancelled already
Quite rightly, because the games where og_id = 9 has og_cancel='Y'.
Now you say you're getting ORA-20977: the game was cancelled. That's a user-defined error (in the range -20999 to -20000. So it's some part of your codebase which is hurling it.
If you don't know what part it is you will need to dig into your data dictionary. I can't solve that for you. But here's a thought: have you got more than one trigger on the table? Your homework says to create a trigger called TR_event_on_cancelled_og but the code you published does CREATE OR REPLACE TRIGGER TR_event_on_cancelled. Perhaps you previously created a trigger with the other name, and that's what is raising the ORA-20977.
i am new to oracle , i am developing a hospital management system , i have this table to store patients :
create table patients(
p_id number not null primary key,
p_fullname full_name_ty,
p_gender char,
de_no number,
p_entry date ,
Diagnosis varchar2(25),
p_exit date,
constraint pdf foreign key (de_no) references department(dep_no)
);
where p_entry is the date when a patient enters the hospital , i made a trigger that calculates the residency time in the hospital on after the upadate of the (p_exit) date for the patient (setting this date means that the patient has left the hospital) , the trigger will simply calculate the difference between the two dates , and print it , here is the code of the trigger :
create or replace
trigger period_trig before update of p_exit on patients for each row
DECLARE
period Number(3);
enterr DATE;
exitt DATE;
BEGIN
enterr := :old.P_ENTRY;
exitt:= :NEW.P_EXIT;
Period :=exitt-enterr;
DBMS_OUTPUT.PUT_LINE('Duration:'||period);
update patients SET RESIDENCY= Period where P_ID = :old.P_ID;
end period_trig
put when i test the trigger and use an update statement like this :
update patients set p_exit = to_date('01/02/2001','dd/mm/yyyy') where p_id = 2;
and run it i get this error :
Error starting at line 1 in command:
update patients set p_exit = to_date('01/02/2001','dd/mm/yyyy') where p_id = 2
Error report:
SQL Error: ORA-04091: table SEM.PATIENTS is mutating, trigger/function may not see it
ORA-06512: at "SEM.UPDATEPAT", line 5
ORA-06512: at "SEM.PERIOD_TRIG", line 10
ORA-04088: error during execution of trigger 'SEM.PERIOD_TRIG'
04091. 00000 - "table %s.%s is mutating, trigger/function may not see it"
*Cause: A trigger (or a user defined plsql function that is referenced in
this statement) attempted to look at (or modify) a table that was
in the middle of being modified by the statement which fired it.
*Action: Rewrite the trigger (or function) so it does not read that table.
Error starting at line 1 in command:
update patients set p_exit = to_date('01/02/2001','dd/mm/yyyy') where p_id = 2
Error report:
SQL Error: ORA-04091: table SEM.PATIENTS is mutating, trigger/function may not see it
ORA-06512: at "SEM.PERIOD_TRIG", line 11
ORA-04088: error during execution of trigger 'SEM.PERIOD_TRIG'
04091. 00000 - "table %s.%s is mutating, trigger/function may not see it"
*Cause: A trigger (or a user defined plsql function that is referenced in
this statement) attempted to look at (or modify) a table that was
in the middle of being modified by the statement which fired it.
*Action: Rewrite the trigger (or function) so it does not read that table.
can anyone tell me how to fix it ? and thanks so much ..
You are modifying the very same table in the trigger that is currently being modified. As they error tells you:
*Cause: A trigger (or a user defined plsql function that is referenced in
this statement) attempted to look at (or modify) a table that was
in the middle of being modified by the statement which fired it.
*Action: Rewrite the trigger (or function) so it does not read that table.
There is actually no need in updating the table again, you can simply use a virtual column directly on the table that makes the entire trigger redundant:
CREATE TABLE patients(
p_id NUMBER NOT NULL PRIMARY KEY,
p_fullname VARCHAR2(255),
p_gender CHAR(1),
de_no NUMBER,
p_entry DATE,
Diagnosis VARCHAR2(25),
p_exit DATE,
RESIDENCY NUMBER GENERATED ALWAYS AS (p_exit-p_entry)
);
insert into patients (p_id, p_fullname, p_gender, de_no, p_entry, diagnosis) values (1, 'GVENZL', 'M', 1234, SYSDATE-1, 'healthy' );
commit;
select p_fullname, residency from patients;
update patients set p_exit = sysdate;
commit;
select p_fullname, residency from patients;
I created a table in Oracle with this code:
CREATE TABLE Roads (
TYPE VARCHAR2(40),
ADMN_CLASS VARCHAR2(20),
TOLL_RD VARCHAR2(10),
RTE_NUM1 VARCHAR2(3),
RTE_NUM2 VARCHAR2(3),
ROUTE VARCHAR2(40),
LOCATION MDSYS.SDO_GEOMETRY);
Then I wanted to add metadata to the LOCATION column which will hold the geometry:
INSERT INTO USER_SDO_GEOM_METADATA
(TABLE_NAME, COLUMN_NAME, DIMINFO, SRID)
VALUES
('ROADS', 'LOCATION',
MDSYS.SDO_DIM_ARRAY
( MDSYS.SDO_DIM_ELEMENT('X', -180, 180, 0.5),
MDSYS.SDO_DIM_ELEMENT('Y', -90, 90, 0.5)
),
8256
);
However, I get an error:
Error report -
SQL Error: ORA-13223: duplicate entry for ROADS.LOCATION in SDO_GEOM_METADATA
ORA-06512: at "MDSYS.MD", line 1723
ORA-06512: at "MDSYS.MDERR", line 17
ORA-06512: at "MDSYS.SDO_GEOM_TRIG_INS1", line 48
ORA-04088: error during execution of trigger 'MDSYS.SDO_GEOM_TRIG_INS1'
13223. 00000 - "duplicate entry for %s in SDO_GEOM_METADATA"
*Cause: There are duplicate entries for the given table and column
value pair in the USER_SDO_GEOM_METADATA view.
*Action: Check that the specified table and geometry column names
are correct. There should be only one entry per table, geometry
column pair in the USER_SDO_GEOM_METADATA view.
I am not sure why it says there are duplicate values because I have not created this table before. It also tells me to make sure that table and column name is correct and they are.
I've created your table and executed your insert statement OK.
Once executed again, I was able to reproduce your problem.
The error "SQL Error: ORA-13223: duplicate entry for ROADS.LOCATION in SDO_GEOM_METADATA" definitely points to duplicate data.
This trigger MDSYS.SDO_GEOM_TRIG_INS1 just performs a count(*) validation on the following MDSYS table and raise the -13223 exception when rowcount is != 0 .
SQL> desc mdsys.SDO_GEOM_METADATA_TABLE
Name Null? Type
----------------------------------------- -------- ----------------------------
SDO_OWNER NOT NULL VARCHAR2(32)
SDO_TABLE_NAME NOT NULL VARCHAR2(32)
SDO_COLUMN_NAME NOT NULL VARCHAR2(1024)
SDO_DIMINFO MDSYS.SDO_DIM_ARRAY
SDO_SRID NUMBER
Query mdsys.SDO_GEOM_METADATA_TABLE in order to validate its contents. You should find the duplicate record:
SQL> select * from mdsys.SDO_GEOM_METADATA_TABLE ;
USER1
ROADS
LOCATION
SDO_DIM_ARRAY(SDO_DIM_ELEMENT('X', -180, 180, .5), SDO_DIM_ELEMENT('Y', -90, 90,
.5))
8256
To workaround this issue just delete that record from mdsys.SDO_GEOM_METADATA_TABLE.
I think the problem is because some space characters on the column_name.
COR_NB_SC_LON,COR_CD_EW_ LON
I have fixed it and it works.
insert into user_sdo_geom_metadata (table_name, column_name, diminfo, srid)
values (
'COORD_REF',
'myuser.CONVERT_DMS_TO_GEOM(COR_NB_DG_LON,COR_NB_MN_LON,COR_NB_SC_LON,COR_ CD_EW_LON,COR_NB_DG_LAT,COR_NB_MN_LAT,COR_NB_SC_LAT,COR_CD_NS_LAT)',
sdo_dim_array (
sdo_dim_element('long', -180.0, 180.0, 0.5),
sdo_dim_element('lat', -90.0, 90.0, 0.5)
),
4326
);
commit;