So this is from a uni coursework and is my first time working with Oracle (and using triggers). We are supposed to be creating a database for an airlines.
Part of the database is
CREATE TABLE FLIGHT_BOOKING (
BOOKING_ID NUMBER(11) PRIMARY KEY,
BOOKING_TIME DATE NOT NULL,
EMPLOYEE_ID NUMBER(11) NOT NULL,
FLIGHT_ID NUMBER(11) NOT NULL,
TOTAL_COST NUMBER(4,2) NOT NULL
);
CREATE TABLE FLIGHT (
FLIGHT_ID NUMBER(11) PRIMARY KEY,
PLANE_ID NUMBER(11) NOT NULL,
START_ID NUMBER(11) NOT NULL,
DESTINATION_ID NUMBER(11) NOT NULL,
TRANSIT_ID NUMBER(11),
DEPARTURE_TIME DATE NOT NULL,
ARRIVAL_TIME DATE NOT NULL,
NUM_BOOKED NUMBER (4) NOT NULL
);
CREATE TABLE PASSENGER (
PASSENGER_ID NUMBER(11) PRIMARY KEY,
FIRST_NAME VARCHAR2(20) NOT NULL,
MIDDLE_NAME VARCHAR2(20) NULL,
LAST_NAME VARCHAR2(20) NOT NULL,
TELEPHONE NUMBER(11) NOT NULL,
BOOKING_ID NUMBER(11) NOT NULL
);
So what I want to do is create a trigger such that every time a new passenger is added to the PASSENGER table, the trigger finds the corresponding FLIGHT_ID from the FLIGHT_BOOKING table and increments NUM_BOOKED for the corresponding flight in the FLIGHT table.
I have tried going through the oracle documentation, but i could not find anything that describes a situation where two or more tables are concerned.
Any help would be really appreciated!
you can do it like this:
CREATE OR REPLACE TRIGGER update_flight_booking_info
AFTER INSERT ON PASSENGER
FOR EACH ROW
DECLARE
v_flight_id number;
v_booking_id number;
BEGIN
v_booking_id := :new.booking_id ;
select flight_id into v_flight_id
from flight_booking
where booking_id = v_booking_id;
update flight
set NUM_BOOKED = NUM_BOOKED + 1
where flight_id = v_flight_id;
END;
HTH.
I'd rather not store that number, and calculate it as needed, but okay, it is just course material. :)
When you create a trigger, inside it you can put all kinds of code, including update statements.
So you can write a trigger like this:
create or replace trigger TIDB_BOOKING
before insert or delete
for each row
declare
V_Increment int;
begin
-- Inc or dec, depending on insert or update.
-- Hasn't a booking got a number of seats?
-- Also, can bookings be updated/moved to other flights?
-- These problems aren't yet taken into account in this code.
V_Increment := 1;
if deleting then
V_Increment := -1;
update FLIGHT f
set f.NUM_BOOKED = f.NUM_BOOKED + V_Increment
where f.FLIGHT_ID = nvl(:new.FLIGHT_ID, :old.FLIGHT_ID);
end;
Related
I've three tables:
create table person(
id_per number(1) primary key not null,
name_per varchar(15) not null);
create table training(
id_training number(1) primary key not null,
start_training date not null,
final_training date not null);
create table training_person(
id_tp number(3) primary key not null,
id_per number(8) not null,
id_training number(1) not null);
I created a trigger whose function is verify that the user can't to insert in the table training_person if the user have a active training ... but when I want to insert a new register but the person don't have any training registered before, oracle show me the following error: "no data found".
This is my trigger:
CREATE OR REPLACE TRIGGER VERIFY_TRAINING
BEFORE INSERT OR UPDATE ON training_person
FOR EACH ROW
DECLARE
GET_FINAL_TRAINING DATE;
GET_START_TRAINING DATE;
BEGIN
select MAX(final_training) into GET_FINAL_TRAINING
from training t join training_person x on t.id_training=x.id_training join person e on e.id_per=x.id_per
WHERE e.id_per=:new.id_per;
select start_training into GET_START_TRAINING
from training t join training_person x on t.id_training=x.id_training
where t.id_training=:new.id_training;
IF (GET_FINAL_TRAINING > GET_START_TRAINING) THEN
RAISE_APPLICATION_ERROR(-20091,'U CANT INSERT TRAINING.');
END IF;
EXCEPTION
WHEN NO_DATA_FOUND THEN
INSERT INTO training_person values(:new.id_tp,:new.id_per,:new.id_training);
END;
I'm learning Oracle, so I dunno which is the problem. Thanks.
I am trying to create a trigger in Oracle whereby we move deleted records to another table. So when deleted column is set to 1, it should move the records from the patient_table to the deleted_patient_table.
Can you please help :)
CREATE TABLE Patient_Table(
PatientID NUMBER(6) Primary Key,
Title char(4) NOT NULL,
Forename varchar2(20) NOT NULL,
Surname varchar2(20) NOT NULL,
Gender char(1) NOT NULL CHECK (Gender in ('M','F')),
DOB date NOT NULL,
TelNo varchar(12) NOT NULL,
Conditions varchar(200) NOT NULL,
Deleted Number(1) NOT NULL CHECK (Deleted in ('0','1'));
-- Table that should contain deleted records --
Create Table Deleted_Patient_table(
PatientID NUMBER(6) Primary Key,
Title char(4) NOT NULL,
Forename varchar2(20) NOT NULL,
Surname varchar2(20) NOT NULL,
Gender char(1) NOT NULL CHECK (Gender in ('M','F')),
DOB date NOT NULL,
TelNo varchar(12) NOT NULL,
Conditions varchar(200) NOT NULL,
Deleted Number(1));
Create or replace trigger trg_del
Before delete on Patient_Table
for each row
Begin
Insert into Deleted_Patient_table value (:old.PatientID,...)
End;
It seems you're soft-deleting your rows. i.e. not deleting but updating related column(Deleted) from 0 to 1. The values of column can be one of two and not null, so you only need to compare only two values of them without nvl operator. During this update operation you can use below trigger to produce log records :
Create or Replace Trigger Trg_Del_Patient
After Update on Patient_Table
For Each Row
Begin
If ( :old.Deleted = 0 and :new.Deleted = 1 ) Then
Insert into Deleted_Patient_table
values(:old.PatientID,:old.Title,:old.Forename,:old.Surname,
:old.Gender,:old.DOB,:old.TelNo,:old.Conditions);
Delete Patient_Table where PatientID = :old.PatientID;
-- Include this Delete statement, if you want to remove after the row has been inserted to the Deleted_Patient_Table
End If;
End;
I have theses two tables:
TABLE ASSET_ENTRY_NOTE (
ID NUMBER NOT NULL, --PK
ASSETMDL_ID NUMBER NOT NULL, --FK
DEPT_ID NUMBER NOT NULL, --FK
LOCATION NVARCHAR2(100) NOT NULL,
ASSET_ID NUMBER, --FK TO ASSETS
ACCOUNT_ID NUMBER NOT NULL, --FK
TOTAL_DPRC_DURATION FLOAT(126) NOT NULL,
TOTAL_PROD_HRS FLOAT(126),
AMORTIZATION_PRCNTG FLOAT(126),
ACQUIRE_DATE DATE NOT NULL,
DESCRIPTION NVARCHAR2(200) NOT NULL,
APPRFLAG NUMBER DEFAULT 0 NOT NULL,
WRK_HRS FLOAT(126),
)
TABLE ASSETS (
ID NUMBER NOT NULL, --PK
ASSETMDL_ID NUMBER NOT NULL, --FK
DEPT_ID NUMBER NOT NULL,
LOCATION NVARCHAR2(100) NOT NULL, --FK
ACCOUNT_ID NUMBER NOT NULL,
ACQUIRE_DATE DATE NOT NULL,
TOTAL_DPRC_DURATION FLOAT(126),
BALANCE_CLOSING_DATE DATE,
SELL_VAL FLOAT(126),
RPLCMNT_DISCOUNT FLOAT(126),
DESCRIPTION NVARCHAR2(200) NOT NULL,
)
Note that there's a one to one relationship between the two tables (i.e. ASSET_ENTRY_NOTE.ASSET_ID is Unique.
When the ASSETS_ENTRY_NOTE.APPRFLAG is updated to 1 I have this trigger that:
gets a new primary key sequence for the ASSETS table.
insert data from ASSETS_ENTRY_NOTE to ASSETS.
updates the column ASSETS_ENTRY_NOTE.ASSET_ID to the same value as the primary key value on the sequence.
This is the latest try for my trigger:
CREATE OR REPLACE TRIGGER ENTRYNT_ASSET_TRIG
after UPDATE OF APPRFLAG ON ASSET_ENTRY_NOTE
for each row
when (new.apprflag = 1)
declare
v_asset_id number;
BEGIN
SELECT assets_PK_SEQ.NEXTVAL INTO v_asset_id
FROM DUAL d;
insert into assets (ID,
assets.assetmdl_id,
assets.dept_id,
assets.location,
assets.account_id,
assets.acquire_date,
assets.total_dprc_duration,
assets.description
)
values (v_asset_id,
assetmdl_id,
dept_id,
location,
account_id,
acquire_date,
total_dprc_duration,
description
);
update ASSET_ENTRY_NOTE set asset_id = v_asset_id where ;
END;
The thing is, I know that ASSET_ENTRY_NOTE is a mutating table and the last UPDATE statement is not allowed here, But nothing else is working for me.
What I've already tried:
creating a statement-level trigger to update one value only.
using before instead of after but that's incorrect because I need the values just to insert into the ASSETS.
using a cursor to go through each value changed but I had exact fetch error.
creating a procedure that handles inserting and updating.
Any help would be appreciated.
The design seems quite strange to me, but to answer the question about the trigger:
To change the asset_entry_note row in the trigger, you need a before update trigger. In there you can just assign the value to the asset_id column.
Your insert statement is also wrong. You can table-qualify column names in the column list of an insert statement. And the values clause needs to use the values from the inserted row. You are referencing the target table's columns which is not allowed).
You also don't need a select statement to obtain the sequence value.
Putting all that together, your trigger should look something like this:
CREATE OR REPLACE TRIGGER ENTRYNT_ASSET_TRIG
BEFORE UPDATE OF APPRFLAG ON ASSET_ENTRY_NOTE
for each row
when (new.apprflag = 1)
declare
v_asset_id number;
BEGIN
v_asset_id := assets_PK_SEQ.NEXTVAL;
insert into assets
(ID,
assetmdl_id,
dept_id,
location,
account_id,
acquire_date,
total_dprc_duration,
description)
values
(v_asset_id,
new.assetmdl_id, -- reference the inserted row here!
new.dept_id,
new.location,
new.account_id,
new.acquire_date,
new.total_dprc_duration,
new.description);
new.asset_id := v_asset_id;
END;
/
You have to change the design of the application to have only one table with sign to indicate the membership of a particular entity.
Another way is to create 'after statement' trigger to update all affected rows in ASSET_ENTRY_NOTE with proper values. These rows is to be collected in, for example, package collection in row-level trigger.
I fixed it and it worked:
changed to before.
edited the update statement to an assignment of new so that the last line would become :new.asset_id := v_asset_id ;
This is some kind of study database in sql file. I use oracle 11g and process it in sqlplus.
I wrote two function for check the course number and the department number, so its depend on the major and the minor department of each student.
For example, I am student of CS department (major) and BIO department (minor), so I can not enroll the course which is about math department.
When I call it in CHECK but I don't know why it told that.
This is output when I create all table, (from sqlplus)
....
....
....
table created.
ALTER TABLE sections ADD CONSTRAINT CK_course_depart CHECK (FindMYDeparture(stuid,find_dno_from_cno(cno)) = 'true');
ERROR at line 1:
ORA-0094: "FIND_DNO_FROM_CNO":invalid identifier
This is in .sql file
DROP TABLE department CASCADE CONSTRAINTS;
CREATE TABLE department (
dnumber number(4) not null,
dname varchar(25) not null,
primary key (dnumber)
);
DROP TABLE courses CASCADE CONSTRAINTS;
CREATE TABLE courses (
cno number(4) not null,
cname varchar(15) not null,
credit number(1) not null,
dnumber number(4) not null,
primary key (cno),
foreign key (dnumber) references department(dnumber),
CONSTRAINT credits CHECK (credit > 0 AND credit <= 5)
);
DROP TABLE student CASCADE CONSTRAINTS;
CREATE TABLE student (
stuid char(9) not null,
fname varchar(15) not null,
lname varchar(15) not null,
dMjno number(4) not null,
dMnno number(4),
primary key (stuid),
CONSTRAINT depart_M_n CHECK (dMjno <> dMnno),
CONSTRAINT dMinor_check CHECK (dMnno = 1 OR dMnno = 2 OR dMnno = 3)
);
DROP TABLE sections CASCADE CONSTRAINTS;
CREATE TABLE sections (
sno number(4) not null,
cno number(4) not null,
stuid char(9) not null,
semester varchar(6) not null,
year varchar(4) not null,
instructor varchar(15) not null,
CONSTRAINT combine_pk primary key (sno,stuid),
foreign key (cno) references courses(cno),
foreign key (stuid) references student(stuid),
CONSTRAINT cant_enroll CHECK (semester <> 'Spring' AND year <> 2007)
);
DROP TABLE grading CASCADE CONSTRAINTS;
CREATE TABLE grading (
sno number(4) not null,
stuid char(9) not null,
grade numeric(1,2),
foreign key (sno,stuid) references sections(sno,stuid),
foreign key (stuid) references student(stuid),
CONSTRAINT grading_check CHECK (grade >= 0 AND grade <= 4)
);
DROP FUNCTION FindMYDeparture;
CREATE OR REPLACE FUNCTION FindMYDeparture(stuid_in IN char,depart_course IN NUMBER)
RETURN NUMBER AS
departMa_no NUMBER;
departMi_no NUMBER;
report varchar(10);
CURSOR cdno is
SELECT dMjno,dMnno FROM student WHERE stuid = stuid_in;
BEGIN
OPEN cdno;
LOOP
FETCH cdno INTO departMa_no,departMi_no;
IF (departMa_no = depart_course OR departMi_no = depart_course)
THEN
report := 'true';
EXIT;
ELSE
report := 'flase';
END IF;
EXIT WHEN cdno%NOTFOUND;
END LOOP;
CLOSE cdno;
RETURN report;
END;
/
DROP FUNCTION find_dno_from_cno;
CREATE OR REPLACE FUNCTION find_dno_from_cno(cno_in IN NUMBER)
RETURN NUMBER AS
depart_no NUMBER;
CURSOR cdno is
SELECT dnumber FROM courses WHERE cno = cno_in;
BEGIN
OPEN cdno;
FETCH cdno INTO depart_no;
CLOSE cdno;
RETURN depart_no;
END;
/
ALTER TABLE sections ADD CONSTRAINT CK_course_depart CHECK (FindMYDeparture(stuid,find_dno_from_cno(cno)) = 'true');
Not going to happen. You are not allowed to use your pl/sql functions in check constraint by design:
•Conditions of check constraints cannot contain the following
constructs:
•Subqueries and scalar subquery expressions
•Calls to the functions that are not deterministic (CURRENT_DATE,
CURRENT_TIMESTAMP, DBTIMEZONE, LOCALTIMESTAMP, SESSIONTIMEZONE,
SYSDATE, SYSTIMESTAMP, UID, USER, and USERENV)
•Calls to user-defined functions
•Dereferencing of REF columns (for example, using the DEREF function)
•Nested table columns or attributes
•The pseudocolumns CURRVAL, NEXTVAL, LEVEL, or ROWNUM
•Date constants that are not fully specified
http://docs.oracle.com/cd/B19306_01/server.102/b14200/clauses002.htm
Try running every statement in that function, This is the case of non existent column for a table or using a not existing row.
I am new to oracle,
I have created two tables using following queries,
CREATE TABLE employee
(
emp_name VARCHAR(20) NOT NULL,
street VARCHAR(50) NOT NULL,
city VARCHAR(20) NOT NULL,
PRIMARY KEY(emp_name)
)
and
CREATE TABLE company
(
comp_name VARCHAR(20) NOT NULL,
city VARCHAR(20) NOT NULL,
PRIMARY KEY(comp_name)
)
Now I am trying to create another table using some foreign keys,
CREATE TABLE works
(
emp_name varchar(20) NOT NULL,
comp_name varchar(20) NOT NULL,
salary int(10) NOT NULL,
FOREIGN KEY(emp_name) REFERENCES employee(emp_name),
FOREIGN KEY(comp_name) REFERENCES company(comp_name)
)
Getting ERROR : ORA-00907: missing right parenthesis
I have also tried with
CREATE TABLE works
(
emp_name varchar(20) NOT NULL,
comp_name varchar(20) NOT NULL,
salary int(10) NOT NULL,
constraint wemployee FOREIGN KEY(emp_name) REFERENCES employee(emp_name),
constraint wcompany FOREIGN KEY(comp_name) REFERENCES company(comp_name)
)
But getting same error.
Can any one tell me that where I am doing mistake?
I'm no expert in oracle, but are you allowed to specify the (10) in salary int(10) NOT NULL?
1: you should have a table called "test" with two columns, id and testdata. (This is just a dumb quick example, so I won't bother to specify any constraints on id.)
create table test (id number, testdata varchar2(255));
2: Next we'll create a sequence to use for the id numbers in our test table.
create sequence test_seq
start with 1
increment by 1
nomaxvalue;
You could change "start with 1" to any number you want to begin with (e.g. if you already have 213 entries in a table and you want to begin using this for your 214th entry, replace with "start with 214"). The "increment by 1" clause is the default, so you could omit it. You could also replace it with "increment by n" if you want it to skip n-1 numbers between id numbers. The "nomaxvalue" tells it to keep incrementing forever as opposed to resetting at some point.i (I'm sure Oracle has some limitation on how big it can get, but I don't know what that limit is).
3: Now we're ready to create the trigger that will automatically insert the next number from the sequence into the id column.
create trigger test_trigger
before insert on test
for each row beginselect test_seq.nextval into :new.id from dual;
end;
/
There are two different ways to create a table with constraints:
1)
create table department(
deptno number(5) primary key,
deptname varchar2(30),
empno number(5) references emp(empno));
2)
create table department(
deptno number(5),
deptname varchar2(30),
empno number(5),
constraint pkey_deptno primary key(deptno),
constraint fkey_empno foreign key(empno) references Emp(empno));
When creating the index inline with the rest of the table creation statement try dropping the FOREIGN KEY part:
CREATE TABLE works
(
emp_name varchar(20) NOT NULL,
comp_name varchar(20) NOT NULL,
salary int(10) NOT NULL,
emp_name REFERENCES employee(emp_name),
comp_name REFERENCES company(comp_name)
)
See this question for more details:
ORA-00907: missing right parenthesis