以下是我创建的表格:
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)
);
创建这4个表后,我插入了这4个表的值:
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');
现在这是个问题: 创建一个名为TR_event_on_cancelled_og的触发器。在插入或更新Event表中的行之前触发此触发器。如果og_id引用取消的奥运会,触发器应该使用有意义的消息引发应用程序错误。
现在这是我提出的解决方案:
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
触发器编译成功但问题是当我尝试测试触发器时收到以下错误消息:
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
我哪里出错了? ... 如果提供了触发器解决方案代码,那将非常有用。
答案 0 :(得分:0)
我认为您的问题是您的触发器代码是从EVENT中选择的。它不需要这样做,因为该规则仅适用于您正在插入或更新的当前事件。
所以:
SELECT og_cancel INTO V_og_cancel
FROM Olympic_Game
WHERE Olympic_Game.og_id = :NEW.og_id;
顺便说一下,下一个测试看起来不对:
IF (v_og_cancel = 'N')
除非您以奇怪的方式使用Y / N标志,否则将测试游戏是否已取消 。当然应该是= 'Y'
?
“我想收到此错误消息”
我已经用您的数据和我的触发器版本创建了一个Oracle LiveSQL。 Find it here (but you will need an OTN account to look at it)
当我尝试这个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');
它失败了
ORA-20001: This Olympic Game is cancelled already
非常正确,因为og_id = 9
有og_cancel='Y'
的游戏。
现在你说你得到了ORA-20977: the game was cancelled
。这是一个用户定义的错误(在-20999到-20000的范围内。所以它是你的代码库的一部分,它正在抛出它。
如果您不知道它是什么部分,您需要深入研究数据字典。我无法为你解决这个问题。但这是一个想法:你有不止一个触发器在桌子上?你的作业说创建一个名为TR_event_on_cancelled_og
的触发器,但你发布的代码是CREATE OR REPLACE TRIGGER TR_event_on_cancelled
。也许您之前使用其他名称创建了一个触发器,这就是提升ORA-20977
的原因。