这些是我创建的表和序列,我插入了它们的值:
CREATE TABLE Ticket_Type
(
t_type_id NUMBER(1) PRIMARY KEY,
CONSTRAINT check_t_type_id CHECK(t_type_id > 0),
t_type VARCHAR(20) NOT NULL,
t_type_price NUMBER(4,2) NOT NULL,
CONSTRAINT check_t_type_price CHECK(t_type_price > 0),
t_type_start_date DATE NOT NULL,
t_type_end_date DATE,
CONSTRAINT check_t_type_end_date CHECK((t_type_end_date IS NULL) OR (t_type_end_date >= t_type_start_date)),
CONSTRAINT unique_t_type_t_type_start_date UNIQUE(t_type,t_type_start_date)
);
CREATE TABLE Screening
(
screening_id NUMBER(6) PRIMARY KEY,
CONSTRAINT check_screening_id CHECK(screening_id > 0),
plan_id NUMBER(4) NOT NULL,
theatre_id NUMBER(1) NOT NULL,
screening_date DATE DEFAULT CURRENT_DATE NOT NULL,
screening_start_hh24 NUMBER(2) NOT NULL,
CONSTRAINT check_start_hh24 CHECK(screening_start_hh24 BETWEEN 9 AND 22),
screening_start_mm60 NUMBER(2) NOT NULL,
CONSTRAINT check_start_mm60 CHECK(screening_start_mm60 BETWEEN 0 AND 59),
CONSTRAINT unique_theatre_id_screening_date_screening_start_hh24_screening_start_mm60 UNIQUE(theatre_id,screening_date,screening_start_hh24,screening_start_mm60)
);
CREATE TABLE Ticket
(
ticket_id NUMBER(8) PRIMARY KEY,
CONSTRAINT check_ticket_id CHECK(ticket_id > 0),
t_type_id NUMBER(1) NOT NULL,
CONSTRAINT fk_t_type_id FOREIGN KEY(t_type_id) REFERENCES Ticket_Type(t_type_id),
screening_id NUMBER(6) NOT NULL,
CONSTRAINT fk_screening_id FOREIGN KEY(screening_id) REFERENCES Screening(screening_id),
seat_id NUMBER(5) NOT NULL,
ticket_date DATE DEFAULT SYSDATE NOT NULL,
CONSTRAINT unique_screening_id_seat_id UNIQUE(screening_id,seat_id)
);
CREATE SEQUENCE ticket_type_seq
START WITH 1
INCREMENT BY 1
NOCACHE NOCYCLE;
CREATE SEQUENCE screening_seq
START WITH 1
INCREMENT BY 1
NOCACHE NOCYCLE;
CREATE SEQUENCE ticket_seq
START WITH 1
INCREMENT BY 1
NOCACHE NOCYCLE;
INSERT INTO ticket_type(t_type_id,t_type,t_type_price,t_type_start_date,t_type_end_date)
VALUES (ticket_type_seq.nextval,'Adult',13.95,to_date('1/06/2017', 'DD/MM/YYYY'),to_date('30/11/2017', 'DD/MM/YYYY'));
INSERT INTO ticket_type(t_type_id,t_type,t_type_price,t_type_start_date,t_type_end_date)
VALUES (ticket_type_seq.nextval, 'Concession',7,to_date('1/06/2017', 'DD/MM/YYYY'),to_date('30/11/2017', 'DD/MM/YYYY'));
INSERT INTO Ticket_Type (t_type_id,t_type,t_type_price,t_type_start_date)
VALUES (ticket_type_seq.NEXTVAL,'Student',7,TO_DATE('1/6/2017','DD/MM/YYYY'));
INSERT INTO Screening (screening_id,plan_id,theatre_id,screening_date,screening_start_hh24,screening_start_mm60)
VALUES (screening_seq.NEXTVAL,1,3,TO_DATE('11/9/2017','DD/MM/YYYY'),9,0);
INSERT INTO Screening (screening_id,plan_id,theatre_id,screening_date,screening_start_hh24,screening_start_mm60)
VALUES (screening_seq.NEXTVAL,1,3,TO_DATE('11/9/2017','DD/MM/YYYY'),11,0);
INSERT INTO Screening (screening_id,plan_id,theatre_id,screening_date,screening_start_hh24,screening_start_mm60)
VALUES (screening_seq.NEXTVAL,1,3,TO_DATE('11/9/2017','DD/MM/YYYY'),13,0);
INSERT INTO Screening (screening_id,plan_id,theatre_id,screening_date,screening_start_hh24,screening_start_mm60)
VALUES (screening_seq.NEXTVAL,1,2,TO_DATE('11/9/2017','DD/MM/YYYY'),13,0);
INSERT INTO Screening (screening_id,plan_id,theatre_id,screening_date,screening_start_hh24,screening_start_mm60)
VALUES (screening_seq.NEXTVAL,1,3,TO_DATE('11/9/2017','DD/MM/YYYY'),15,0);
INSERT INTO Screening (screening_id,plan_id,theatre_id,screening_date,screening_start_hh24,screening_start_mm60)
VALUES (screening_seq.NEXTVAL,1,3,TO_DATE('11/9/2017','DD/MM/YYYY'),17,0);
INSERT INTO Screening (screening_id,plan_id,theatre_id,screening_date,screening_start_hh24,screening_start_mm60)
VALUES (screening_seq.NEXTVAL,2,1,TO_DATE('11/9/2017','DD/MM/YYYY'),9,0);
INSERT INTO Screening (screening_id,plan_id,theatre_id,screening_date,screening_start_hh24,screening_start_mm60)
VALUES (screening_seq.NEXTVAL,2,1,TO_DATE('11/9/2017','DD/MM/YYYY'),12,0);
INSERT INTO Screening (screening_id,plan_id,theatre_id,screening_date,screening_start_hh24,screening_start_mm60)
VALUES (screening_seq.NEXTVAL,2,1,TO_DATE('11/9/2017','DD/MM/YYYY'),15,0);
INSERT INTO Screening (screening_id,plan_id,theatre_id,screening_date,screening_start_hh24,screening_start_mm60)
VALUES (screening_seq.NEXTVAL,2,2,TO_DATE('11/9/2017','DD/MM/YYYY'),9,0);
INSERT INTO Screening (screening_id,plan_id,theatre_id,screening_date,screening_start_hh24,screening_start_mm60)
VALUES (screening_seq.NEXTVAL,2,2,TO_DATE('11/9/2017','DD/MM/YYYY'),15,0);
INSERT INTO Screening (screening_id,plan_id,theatre_id,screening_date,screening_start_hh24,screening_start_mm60)
VALUES (screening_seq.NEXTVAL,3,4,TO_DATE('11/9/2017','DD/MM/YYYY'),9,0);
INSERT INTO Screening (screening_id,plan_id,theatre_id,screening_date,screening_start_hh24,screening_start_mm60)
VALUES (screening_seq.NEXTVAL,3,4,TO_DATE('11/9/2017','DD/MM/YYYY'),12,0);
INSERT INTO Screening (screening_id,plan_id,theatre_id,screening_date,screening_start_hh24,screening_start_mm60)
VALUES (screening_seq.NEXTVAL,3,4,TO_DATE('11/9/2017','DD/MM/YYYY'),15,0);
INSERT INTO Screening (screening_id,plan_id,theatre_id,screening_date,screening_start_hh24,screening_start_mm60)
VALUES (screening_seq.NEXTVAL,3,4,TO_DATE('11/9/2017','DD/MM/YYYY'),18,0);
INSERT INTO Screening (screening_id,plan_id,theatre_id,screening_date,screening_start_hh24,screening_start_mm60)
VALUES (screening_seq.NEXTVAL,4,1,TO_DATE('11/9/2017','DD/MM/YYYY'),18,0);
INSERT INTO Screening (screening_id,plan_id,theatre_id,screening_date,screening_start_hh24,screening_start_mm60)
VALUES (screening_seq.NEXTVAL,4,2,TO_DATE('11/9/2017','DD/MM/YYYY'),18,0);
INSERT INTO Screening (screening_id,plan_id,theatre_id,screening_date,screening_start_hh24,screening_start_mm60)
VALUES (screening_seq.NEXTVAL,4,3,TO_DATE('11/9/2017','DD/MM/YYYY'),19,0);
INSERT INTO Screening (screening_id,plan_id,theatre_id,screening_date,screening_start_hh24,screening_start_mm60)
VALUES (screening_seq.NEXTVAL,4,4,TO_DATE('11/9/2017','DD/MM/YYYY'),21,0);
现在这是作业中的问题:
创建一个名为TR_valid_15_min_ticket的触发器,它应该在Ticket表中插入行之前检查ticket_date。票证发行日期(ticket_date)不能大于当前日期和时间。此外,它不能大于筛选时间+ 15分钟。否则,对于每种情况,触发器都应该引发正确的错误。错误消息必须有意义。
提示:放映时间= screening_date +(screening_start_hh24)/ 24 +(screening_start_mm60)/(24 * 60)
注意:ticket_date位于Ticket表中,screening_date,screening_start_hh24,screening_start_mm60位于筛选表中
成功编译触发器后,编写SQL语句以将数据插入表中以测试触发器。两种情况:您应该在第一天(2016年9月11日)在一个影院中插入有效和无效的票证记录。
这就是我的尝试:
CREATE OR REPLACE TRIGGER TR_valid_15_min_ticket
BEFORE INSERT
ON Ticket
FOR
EACH ROW
DECLARE
screening_time NUMBER;
v_screening_date Screening.screening_date%TYPE;
v_screening_start_hh24 Screening.screening_start_hh24%TYPE;
v_screening_start_mm60 Screening.screening_start_mm60%TYPE;
BEGIN
SELECT screening_start_hh24,screening_start_mm60
INTO v_screening_start_hh24,v_screening_start_mm60
FROM Screening
WHERE screening_id = :NEW.screening_id;
screening_time := v_screening_date + (v_screening_start_hh24)/24 + (v_screening_start_mm60)/(24*60);
IF (:NEW.ticket_date > SYSDATE) OR (:NEW.ticket_date > (screening_time + 15))
THEN
RAISE_APPLICATION_ERROR(-20000,'Ticket date cannot be more than the current date nor can it have extra 15 minutes with addition to its screening time');
END IF;
END;
但是,我收到以下错误:
Error(95,1): PL/SQL: Statement ignored
Error(95,19): PLS-00382: expression is of wrong type
Error(96,1): PL/SQL: Statement ignored
Error(96,55): PLS-00306: wrong number or types of arguments in call to '>'
如果提供正确的解决方案触发器代码以纠正我在代码中犯的错误,那将非常有用。
根据我使用的逻辑: IF(:NEW.ticket_date> SYSDATE)或(:NEW.ticket_date>(screening_time + 15)),我知道我必须通过使用INSERT语句在Ticket表的ticket_date列中插入有效值和无效值来测试触发器。基于(:NEW.ticket_date> SYSDATE),我已经知道我需要测试哪些无效值或有效值(:NEW.ticket_date> SYSDATE)。但是对于(:NEW.ticket_date>(screening_time + 15)),我不知道,我不确定应该输入什么无效值和有效值来测试触发器。如果基于(:NEW.ticket_date>(screening_time + 15))提供有效值和无效值,那将非常有用,这样我就可以成功测试它。
< / LI> 醇>答案 0 :(得分:0)
演示中的错误:
CREATE TABLE Ticket_Type
无效,因为CONSTRAINT unique_t_type_t_type_start_date
名称太长 - 最多可包含30个字符,但长度为31个字符
CREATE TABLE Screening
无法编译,因为此名称太长:ONSTRAINT unique_theatre_id_screening_date_screening_start_hh24_screening_start_mm60 UNIQUE
,可以是最大值。 30个字符
此表达式会导致Error(121,19): PLS-00382: expression is of wrong type
screening_time := v_screening_date + (v_screening_start_hh24)/24
+ (v_screening_start_mm60)/(24*60);
screening_time
的类型为NUMBER v_screening_date
的类型为DATE v_screening_start_hh24
的类型为NUMBER v_screening_start_mm60
的类型为NUMBER DATE + NUMBER提供DATE,因此您无法将DATE值(表达式的结果)赋予NUMBER变量screening_time
。
这一行没有编译:
IF (:NEW.ticket_date > SYSDATE) OR (:NEW.ticket_date > (screening_time + 15))
因为这个表达式:
:NEW.ticket_date > (screening_time + 15))
此比较 DATE&gt; NUMBER 没有任何意义,例如这个表达式应该是什么结果:2017-04-20 > 15
?
我对是否使用感到困惑:NEW.ticket_date&gt; (screening_time + 15))或:NEW.ticket_date&gt; (screening_time +(15 * 24 * 60)))? -
尝试将这些规则分解为简单的步骤,ii将更容易理解和实现,如下例所示:
DECLARE
.....
.....
condition_1 BOOLEAN;
condition_2 BOOLEAN;
BEGIN
......
-- The ticket issued date (ticket_date) can not be greater than the current date and time.
condition_1 := :NEW.ticket_date <= SYSDATE;
-- In addition, it cannot be greater than screening time + 15 minutes.
condition_2 := :NEW.ticket_date <= screening_time + interval '15' minute;
-- Otherwise, for each case, the trigger should raise a proper error.
IF NOT ( condition_1 AND condition_2 )
THEN
-- The error messages must be meaningful.
RAISE_APPLICATION_ERROR(-20000,'Ticket date cannot be more than the current date nor can it have extra 15 minutes with addition to its screening time');
END IF;
此外,要求为for each case, the trigger should raise a proper error.
,因此每个条件都必须有两条单独的错误消息。