I have a problem with an UPDATE BEFORE TRIGGER - oracle

I have the following tables:
CREATE TABLE Categorie
(categ_id NUMBER(5,0),
tip VARCHAR2(20));
CREATE TABLE Reteta
(reteta_id NUMBER(3),
nume VARCHAR2(100),
descriere VARCHAR2(200),
categ_id NUMBER(3,0),
vegetariana VARCHAR2(1) CHECK (vegetariana IN ('D','N')),
timp_preparare NUMBER(20,1),
portii NUMBER(3,1));
CREATE TABLE Set_ingrediente
(reteta_id NUMBER(3,0),
ingred_id NUMBER(3,0),
cantitate NUMBER(5,2),
um VARCHAR2(10) NOT NULL CHECK (um IN ('gr','ml','buc','lingurita','cana')),
comentarii VARCHAR2(100)
);
CREATE TABLE Ingredient
(ingred_id NUMBER(3,0),
ingredient VARCHAR2(30));
And the following primary/foreign keys:
ALTER TABLE Categorie
MODIFY (categ_id CONSTRAINT categ_id_pk PRIMARY KEY NOT NULL);
ALTER TABLE Reteta
MODIFY(CONSTRAINT reteta_id_pk PRIMARY KEY (reteta_id));
ALTER TABLE Ingredient
MODIFY(CONSTRAINT ingred_id_pk PRIMARY KEY (ingred_id));
ALTER TABLE Set_ingrediente
MODIFY( CONSTRAINT reteta_id_fk FOREIGN KEY (reteta_id) REFERENCES Reteta(reteta_id) ON DELETE CASCADE);
ALTER TABLE Set_ingrediente
MODIFY( CONSTRAINT ingred_id_fk FOREIGN KEY (ingred_id) REFERENCES Ingredient(ingred_id) ON DELETE CASCADE);
I have to write a trigger which :
Ensure that the vegetarian column cannot be changed if the recipe uses the ingredient 'oil'.
This is the trigger which I tried and it's not working:
CREATE OR REPLACE TRIGGER tr_oil BEFORE UPDATE
ON Reteta
FOR EACH ROW BEGIN
DECLARE
ingredient_var ingredient.ingredient%type;
SELECT ingredient
INTO ingredient_var
FROM Ingredint
WHERE ingred_id=
(SELECT ingred_id
FROM Set_ingrediente
WHERE reteta_id=NEW.reteta_id);
IF ingredient_var='oil' THEN
SET NEW.vegetariana = OLD.vegetariana;
END IF;
END;

That's so strange; up to trigger code, everything you posted worked perfectly so I just can't imagine what went wrong when it came to the trigger which is full of errors (misplaced begin, invalid table name, missing colon with the :new pseudorecord, ...). As if two different people wrote two pieces of code you posted.
Anyway:
SQL> CREATE OR REPLACE TRIGGER tr_oil
2 BEFORE UPDATE ON Reteta
3 FOR EACH ROW
4 DECLARE
5 ingredient_var ingredient.ingredient%type;
6 BEGIN
7 SELECT ingredient
8 INTO ingredient_var
9 FROM Ingredient
10 WHERE ingred_id = (SELECT ingred_id
11 FROM Set_ingrediente
12 WHERE reteta_id = :NEW.reteta_id);
13
14 IF ingredient_var='oil' THEN
15 :NEW.vegetariana := :OLD.vegetariana;
16 END IF;
17 END;
18 /
Trigger created.
SQL>

Related

ORA-02264: name already used by an existing constraint how to get this solved?

CREATE TABLE report(
report_id NUMBER(5),
description VARCHAR2(200) NOT NULL,
status VARCHAR2(200) NOT NULL,
bicycle_id NUMBER(5),
cust_id NUMBER(5),
staff_id NUMBER(5),
CONSTRAINT ad_reportid_pk PRIMARY KEY (report_id),
CONSTRAINT ad_bicycle_fk FOREIGN KEY (bicycle_id) REFERENCES bicycle(bicycle_id),
CONSTRAINT ad_custid_fk FOREIGN KEY (cust_id) REFERENCES customer(cust_id),
CONSTRAINT ad_staffid_fk FOREIGN KEY (staff_id) REFERENCES staff(staff_id)
);
Above is the SQL script when I'm creating a table and it thrown me error with ORA-02264. I am neither drop the table nor creating that table. Tried to run this script
SELECT * FROM user_constraints WHERE CONSTRAINT_NAME = 'ad_bicycleid_fk'
and it showed no data.
All object names are stored in uppercase unless you mention it in double quotes while creating an object.
Try this:
SELECT * FROM user_constraints
WHERE upper(CONSTRAINT_NAME) = upper('ad_bicycleid_fk');
Here's an example which shows one option you might do that.
First, "dummy" tables which are being referenced by columns in the report table (why do I need them? Because create table report would fail otherwise):
SQL> create table bicycle
2 (bicycle_id number(5) constraint pk_bic primary key);
Table created.
SQL> create table customer
2 (cust_id number(5) constraint pk_cus primary key);
Table created.
SQL> create table staff
2 (staff_id number(5) constraint pk_sta primary key);
Table created.
The report table:
SQL> create table report
2 (report_id number(5),
3 description varchar2(200) not null,
4 status varchar2(200) not null,
5 bicycle_id number(5),
6 cust_id number(5),
7 staff_id number(5),
8 --
9 constraint pk_rep primary key (report_id),
10 constraint fk_rep_bic foreign key (bicycle_id)
11 references bicycle (bicycle_id),
12 constraint fk_rep_cus foreign key (cust_id)
13 references customer (cust_id),
14 constraint fk_rep_sta foreign key (staff_id)
15 references staff (staff_id)
16 );
Table created.
SQL>
Everything is OK.
Note the way I named constraints, especially foreign keys whose names show - at least approximately - which table references which another table, e.g. FK_REP_BIC - it is a Foreign Key from table REPort and it references the BICycle table. I'm not saying that you must do it that way, but - Google a little bit, read about good practices and find the one you prefer the most.
As of the constraint you couldn't find:
SQL> select owner, constraint_type, table_name
2 from user_constraints
3 where constraint_name = 'FK_REP_BIC';
OWNER C TABLE_NAME
--------------- - ---------------
SCOTT R REPORT
SQL>

Alter Table , adding a Foreign key constraint at a column ORA-02253

Hello there i am studying for the Oracle Certification of SQL Associate .
And trying to do some Examples .
I have an issue where i cannot find easily a reference on this .
create table employees
(employee_id number NOT NULL,
first_name varchar(20),
last_name varchar(30),
constraint employee_pk primary key (employee_id));
create table employee_notes
(employee_notes_id number,
employee_notes varchar(500),
constraint pk_employee_notes primary key (employee_notes_id));
create sequence employee_notes_seq start with 1 increment by 1
Now i want to add a new column at employee_notes table with a foreign key constraint .
I can't find out in syntax where is the problem .
****alter table employee_notes
add employee_id number
constraint fk_employee_notes foreign key (employee_id) references employees (employee_id);****
i get this error
ORA-02253: constraint specification not allowed her
I also tried to alter the table and add column and then the constraint but cannot
alter table employee_notes
add employee_id number;
--
alter table employee notes
add constraint fk_employee_notes foreign key (employee_id) references employees (employee_id);
ORA-02253: constraint specification not allowed here
I would like to know how i can do this
and why this syntax is wrong :)
You did something wrong because - it works OK:
SQL> CREATE TABLE employees
2 (
3 employee_id NUMBER NOT NULL,
4 first_name VARCHAR (20),
5 last_name VARCHAR (30),
6 CONSTRAINT employee_pk PRIMARY KEY (employee_id)
7 );
Table created.
SQL>
SQL> CREATE TABLE employee_notes
2 (
3 employee_notes_id NUMBER,
4 employee_notes VARCHAR (500),
5 CONSTRAINT pk_employee_notes PRIMARY KEY (employee_notes_id)
6 );
Table created.
SQL> ALTER TABLE employee_notes ADD employee_id NUMBER;
Table altered.
SQL> ALTER TABLE employee_notes ADD CONSTRAINT fk_employee_notes
2 FOREIGN KEY (employee_id)
3 REFERENCES employees (employee_id);
Table altered.
SQL>
When you use ALTER TABLE ... ADD in order to add a column and a constraint in one statement, do the following:
-- notice the () and the comma!
alter table employee_notes
add (
employee_id number
, constraint fk_employee_notes
foreign key (employee_id) references employees (employee_id)
) ;
That should do the trick. See dbfiddle. The syntax is similar to CREATE TABLE, where you'd also write all column names, data types etc in (), separated by commas.

Trigger to assign primary key number from sequence to be shared by multiple tables

I'm on Oracle Database 18c Express Edition and APEX 19.1.
The requirement is to be able to link between items with same or different types:
logs with logs,
events with logs
...and so on.
e.g.
logs.item_id = 1
logs.item_id = 2
events.item_id = 5
logs.item_id = 2
logs.item_id = 1
events.item_id = 5
logs.item_id = 1
My idea is to have a shared ID sequence, that would be populated with every insert on - for example - logs table.
Having unique IDs for logs, events and other items, I could create links in separate links table
https://imgur.com/Dchz7De.jpg
After executing DDL script, my first
INSERT INTO events (dummy) VALUES ('D');
results with an error.
ORA-02291: integrity constraint (C##TEST.EVE_ITE_FK_1) violated - parent key not found
Following inserts assign sequence values starting from 3.
https://imgur.com/ru2aewG.jpg
DROP TABLE items CASCADE CONSTRAINTS;
DROP TABLE logs CASCADE CONSTRAINTS;
DROP TABLE events CASCADE CONSTRAINTS;
DROP TABLE links CASCADE CONSTRAINTS;
DROP SEQUENCE items_seq;
DROP TRIGGER logs_trg;
DROP TRIGGER events_trg;
/
CREATE TABLE logs (
item_id NUMBER(*,0) PRIMARY KEY
,dummy CHAR(1));
/
CREATE TABLE events (
item_id NUMBER (*,0) PRIMARY KEY
,dummy CHAR(1));
/
CREATE TABLE links (
id NUMBER(*,0) GENERATED ALWAYS AS IDENTITY PRIMARY KEY
,item_id_1 NUMBER(*,0)
,item_id_2 NUMBER(*,0));
/
CREATE TABLE items (
id NUMBER(*,0) PRIMARY KEY
,type CHAR(1 CHAR));
/
ALTER TABLE logs ADD CONSTRAINT log_ite_fk_1 FOREIGN KEY (item_id) REFERENCES items (id);
/
ALTER TABLE events ADD CONSTRAINT eve_ite_fk_1 FOREIGN KEY (item_id) REFERENCES items (id);
/
ALTER TABLE links ADD CONSTRAINT lin_ite_fk_1 FOREIGN KEY (item_id_1) REFERENCES items (id);
/
ALTER TABLE links ADD CONSTRAINT lin_ite_fk_2 FOREIGN KEY (item_id_2) REFERENCES items (id);
/
CREATE SEQUENCE items_seq START WITH 1;
/
CREATE OR REPLACE TRIGGER logs_trg FOR INSERT ON logs
COMPOUND TRIGGER
l_item_id PLS_INTEGER := items_seq.nextval;
co_item_type CONSTANT CHAR(1) := 'L';
BEFORE STATEMENT
IS
BEGIN
INSERT INTO items(id
,type)
VALUES (l_item_id
,co_item_type);
END BEFORE STATEMENT;
BEFORE EACH ROW
IS
BEGIN
SELECT l_item_id
INTO :NEW.item_id
FROM dual;
END BEFORE EACH ROW;
END;
/
CREATE OR REPLACE TRIGGER events_trg FOR INSERT ON events
COMPOUND TRIGGER
l_item_id PLS_INTEGER := items_seq.nextval;
co_item_type CONSTANT CHAR(1) := 'E';
BEFORE STATEMENT
IS
BEGIN
INSERT INTO items(id
,type)
VALUES (l_item_id
,co_item_type);
END BEFORE STATEMENT;
BEFORE EACH ROW
IS
BEGIN
SELECT l_item_id
INTO :NEW.item_id
FROM dual;
END BEFORE EACH ROW;
END;
/
Do you have any suggestions on what could I do to make it work with the 1st insert?
I expect
INSERT INTO events (dummy) VALUES ('D');
to produce items.id = 1 and events.item_id = 1.
EDIT:
Following Enrique's advice, I switched to non-compound trigger with returning clause - as below.
DROP TABLE items CASCADE CONSTRAINTS;
DROP TABLE logs CASCADE CONSTRAINTS;
DROP TABLE events CASCADE CONSTRAINTS;
DROP TABLE links CASCADE CONSTRAINTS;
DROP SEQUENCE items_seq;
/
CREATE TABLE logs (
item_id NUMBER(*,0) PRIMARY KEY
,dummy CHAR(1));
/
CREATE TABLE events (
item_id NUMBER (*,0) PRIMARY KEY
,dummy CHAR(1));
/
CREATE TABLE links (
id NUMBER(*,0) GENERATED ALWAYS AS IDENTITY PRIMARY KEY
,item_id_1 NUMBER(*,0)
,item_id_2 NUMBER(*,0));
/
CREATE TABLE items (
id NUMBER(*,0) PRIMARY KEY
,type CHAR(1 CHAR));
/
ALTER TABLE logs ADD CONSTRAINT log_ite_fk_1 FOREIGN KEY (item_id) REFERENCES items (id);
/
ALTER TABLE events ADD CONSTRAINT eve_ite_fk_1 FOREIGN KEY (item_id) REFERENCES items (id);
/
ALTER TABLE links ADD CONSTRAINT lin_ite_fk_1 FOREIGN KEY (item_id_1) REFERENCES items (id);
/
ALTER TABLE links ADD CONSTRAINT lin_ite_fk_2 FOREIGN KEY (item_id_2) REFERENCES items (id);
/
CREATE SEQUENCE items_seq START WITH 1;
/
CREATE OR REPLACE TRIGGER logs_trg FOR INSERT ON logs
COMPOUND TRIGGER
l_item_id PLS_INTEGER := items_seq.nextval;
co_item_type CONSTANT CHAR(1) := 'L';
BEFORE STATEMENT
IS
BEGIN
INSERT INTO items(id
,type)
VALUES (l_item_id
,co_item_type);
END BEFORE STATEMENT;
BEFORE EACH ROW
IS
BEGIN
SELECT l_item_id
INTO :NEW.item_id
FROM dual;
END BEFORE EACH ROW;
END;
/
CREATE OR REPLACE TRIGGER events_trg BEFORE INSERT ON events
FOR EACH ROW
DECLARE
co_item_type CONSTANT CHAR(1) := 'M';
BEGIN
INSERT INTO items(id
,type)
VALUES (items_seq.nextval
,co_item_type)
RETURNING id INTO :NEW.item_id;
DBMS_OUTPUT.PUT_LINE(systimestamp);
END;
/
INSERT INTO events (dummy) values ('D');
INSERT INTO events (dummy) values ('D');
Now the problem is different. The 1st insert on events table generates 2 values on items_seq
INSERT INTO events (dummy) VALUES ('D');
DBMS_OUTPUT:
08-MAY-19 11.08.29.301000000 +02:00
08-MAY-19 11.08.29.303000000 +02:00
Ongoing inserts behave as expected - 1 seq number for each insert. So 2 inserts generate 3 sequence values.
My desired outcome is to have items.id = 1 for first insert on events table.
Just use this
v_myid number;
insert into table(col1, col2)
values(value1, value2)
returning id into v_myid;

Cannot insert NULL into, ERROR during execution of trigger

I have created a Trigger on table Customers so that every time a record is deleted from table customers this same record is inserted in table Customer_Archives with the current date as Deletion_Date.
I am have to insert a new customer into table Customers and then delete it. The record must be inserted correctly into table Customers_Archive.
Here's script I have so far:
CREATE TABLE Customer_Archives
(
customer_id NUMBER NOT NULL,
customer_first_name VARCHAR2(50),
customer_last_name VARCHAR2(50) NOT NULL,
customer_address VARCHAR2(255) NOT NULL,
customer_city VARCHAR2(50) NOT NULL,
customer_state CHAR(2) NOT NULL,
customer_zip VARCHAR2(20) NOT NULL,
customer_phone VARCHAR2(30) NOT NULL,
customer_fax VARCHAR2(30),
deletion_date DATE,
CONSTRAINT customer_archives_pk
PRIMARY KEY (customer_id)
);
CREATE OR REPLACE TRIGGER Customers_before_insert
BEFORE DELETE ON Customers
FOR EACH ROW
DECLARE
ar_row Customers%rowtype;
BEGIN
INSERT INTO Customer_Archives
VALUES(ar_row.Customer_id,
ar_row.Customer_First_Name,
ar_row.Customer_Last_Name,
ar_row.Customer_Address,
ar_row.Customer_City,
ar_row.Customer_State,
ar_row.Customer_Zip,
ar_row.Customer_Phone,
ar_row.Customer_Fax,
sysdate());
dbms_output.put_line('New row is added to Customers_Archive
Table with Customer_ID:' ||ar_row.Customer_id ||'on date:' || sysdate());
END;
/
SELECT trigger_name, status FROM user_triggers;
INSERT INTO CUSTOMERS
(customer_id, customer_first_name, customer_last_name, customer_address,
customer_city, customer_state, customer_zip, customer_phone, customer_fax)
VALUES (27,'Sofia','Chen','8888 Cowden St.','Philadelphia','PA',
'19149',7654321234',NULL);
DELETE FROM CUSTOMERS
WHERE customer_id = 27;
When I try to delete the customer that I just inserted I get an error:
Error starting at line : 47 in command -
DELETE FROM CUSTOMERS
WHERE customer_id = 27
Error report -
ORA-01400: cannot insert NULL into ("TUG81959"."CUSTOMER_ARCHIVES"."CUSTOMER_ID")
ORA-06512: at "TUG81959.CUSTOMERS_BEFORE_INSERT", line 4
ORA-04088: error during execution of trigger 'TUG81959.CUSTOMERS_BEFORE_INSERT'
In your DELETE trigger you should be using the :OLD values when creating your archive record:
CREATE OR REPLACE TRIGGER CUSTOMERS_BEFORE_INSERT
BEFORE DELETE ON CUSTOMERS
FOR EACH ROW
BEGIN
INSERT INTO CUSTOMER_ARCHIVES
(CUSTOMER_ID,
CUSTOMER_FIRST_NAME,
CUSTOMER_LAST_NAME,
CUSTOMER_ADDRESS,
CUSTOMER_CITY,
CUSTOMER_STATE,
CUSTOMER_ZIP,
CUSTOMER_PHONE,
CUSTOMER_FAX,
DELETION_DATE)
VALUES
(:OLD.CUSTOMER_ID,
:OLD.CUSTOMER_FIRST_NAME,
:OLD.CUSTOMER_LAST_NAME,
:OLD.CUSTOMER_ADDRESS,
:OLD.CUSTOMER_CITY,
:OLD.CUSTOMER_STATE,
:OLD.CUSTOMER_ZIP,
:OLD.CUSTOMER_PHONE,
:OLD.CUSTOMER_FAX,
SYSDATE());
DBMS_OUTPUT.PUT_LINE('New row is added to Customers_Archive
Table with Customer_ID:' ||:OLD.Customer_id ||'on date:' || SYSDATE());
END;
In your original trigger you'd declared a row variable named ar_row but hadn't assigned anything to any of the fields - therefore they were all NULL. When a BEFORE trigger is invoked during a DELETE, the :OLD values have the values prior to the deletion, and the :NEW values are all NULL.
Best of luck.

Triggers in oracle PL/SQL

I am trying to do a trigger that updates a sum of all credits on update of the grade or a insert of a new one. That's my tables
create table Department (
Department_ID varchar(4) not null,
Name varchar(25) unique,
Department_Head_ID varchar(9),
College_ID varchar(4),
Credits_To_Degree NUMBER(3),
constraint pkDepartment primary key (Department_ID));
create table Enrollment (
Student_ID varchar(9) not null,
Course_ID varchar(5) not null,
Registered_Date date,Grade NUMBER,
Status varchar(4),constraint pkEnrollment primary key
(Student_ID, Course_ID));
create table Student (
Student_ID varchar(9) not null,
First_Name varchar(25),
Last_Name varchar(25),
Phone char(11),
Birth_Date date,
Street varchar(100),
Zip_Code char(5),
Department varchar(4),
Credits integer,
Eligible char(4), constraint pkStudent primary key
(Student_ID),constraint fkDeptId foreign key (Department)
references Department(Department_ID));
ALTER TABLE Department ADD FOREIGN KEY (Department_Head_ID)
REFERENCES Faculty(Faculty_Id) INITIALLY DEFERRED;
ALTER TABLE Department ADD FOREIGN KEY(College_ID) REFERENCES
College(College_ID) INITIALLY DEFERRED;
the trigger:
create or replace TRIGGER Credits
after INSERT OR UPDATE
ON enrollment
REFERENCING NEW AS New OLD AS Old
FOR EACH ROW
BEGIN
UPDATE STUDENT
SET CREDITS=(SELECT SUM(c.CREDITS) FROM COURSE c,ENROLLMENT e
WHERE c.COURSE_ID = e.COURSE_ID
and e.STUDENT_ID = :new.student_id
and e.GRADE>= 60 )
WHERE STUDENT.STUDENT_ID=:new.student_id;
END;
The trigger compiles but when i change value of the grade a get this error
UPDATE "FELIX"."ENROLLMENT" SET GRADE = '60' WHERE ROWID = 'AAAGUSAABAAALKJAAF' AND ORA_ROWSCN = '3540016'
ORA-20003: An error has occurred while performing credits trigger
ORA-06512: at "FELIX.CREDITS", line 5
ORA-04088: error during execution of trigger 'FELIX.CREDITS'
One error saving changes to table "FELIX"."ENROLLMENT":
Row 6: ORA-20003: An error has occurred while performing credits trigger
ORA-06512: at "FELIX.CREDITS", line 5
ORA-04088: error during execution of trigger 'FELIX.CREDITS'
line 5 is a FOR EACH ROW command
I figure out that the problem is in the :new.student_id. But how could i get the id of the row that the triggers fires upon.
Thanks in advance for the help.

Resources