SQL Statement Ignored and Missing Expression - sql

I am trying to debug a trigger in Oracle SQL Developer, but I don't really understand the compiler's errors. I trying to follow the templates that I have seen, but it doesn't seem to be working out no matter what I try.
CREATE OR REPLACE TRIGGER audit_movie_insert_trig
REFERENCING NEW AS newRow
AFTER INSERT ON audit_movie
FOR EACH ROW
BEGIN
INSERT INTO audit_movie VALUES(audit_seq.nextval, newRow.title, newRow.m_year, newRow.m_length, newRow.genre, newRow.studio_name, newRow.producer, SYSDATE, 'Insert');
END;
The errors that I am getting are:
Error(2,7): PL/SQL: SQL Statement ignored
Error(2,83): PL/SQL: ORA-00936: missing expression
Any help would be great.

You have clauses the wrong way round, as the syntax diagram shows. You should referencing clause after the after insert clause.
You also need to have a colon before newRow references. And you seem to be inserting in the same table the trigger is against, but it looks like your main table is probably just called movie?
CREATE OR REPLACE TRIGGER audit_movie_insert_trig
AFTER INSERT ON movie
REFERENCING NEW AS newRow
FOR EACH ROW
BEGIN
INSERT INTO audit_movie (id, title, m_year, m_length, genre, studio_name,
producer, when, what)
VALUES(audit_seq.nextval, :newRow.title, :newRow.m_year, :newRow.m_length,
:newRow.genre, :newRow.studio_name, :newRow.producer, SYSDATE, 'Insert');
END;
I've guessed the column names. As mentioned in a comment, you should specify the column names to avoid issues when the table definition is modified, and it makes it more obvious if you try to insert the wrong values into the wrong columns.

.m_length,
Please watch out.. it starts with a "." .. u miss the alias name!

Related

Oracle PL/SQL - BEFORE INSERT 'table does not exist' error?

I'm taking my first steps in Pl/SQL and am struggling with triggers. I've tried creating the trigger below but am receiving this error:
Error at line 2: PL/SQL: SQL Statement ignored
PL/SQL: ORA-00942: table or view does not exist
To clarify: I have checked the name of the table over and over, and it does exist. It is also in the same schema as the trigger I'm trying to create. The 'customer_seq.NEXTVAL' refers to a sequence created previously that runs without errors.
The code is as follows:
CREATE TRIGGER new_customer
BEFORE INSERT ON customer
FOR EACH ROW
BEGIN
INSERT INTO customer_id VALUES ('c-', customer_seq.NEXTVAL);
END;
Thanks in advance for any help.
You probably intend something like this:
CREATE TRIGGER new_customer
BEFORE INSERT ON customer
FOR EACH ROW
BEGIN
SELECT customer_seq.NEXTVAL INTO :NEW.customer_id
FROM dual;
END;
It is unclear what the purpose of 'C_' is. If it is part of the customer id, I would advise you to stick to numbers.
Also note that more recent versions of Oracle support generated always as identity -- which is much preferred over defining a sequence and trigger.

When is FOR EACH ROW not needed in a BEFORE INSERT TRIGGER in Oracle?

I am new to PLSQL in Oracle. When I am learning about triggers, I have read from this source https://www.techonthenet.com/oracle/triggers/before_insert.php which says that when I create a BEFORE INSERT Trigger in Oracle, the FOR EACH ROW is NOT always needed, hence the syntax is enclosed by square brackets [ ]. I have written this simple trigger:
CREATE OR REPLACE TRIGGER enroll_time
BEFORE INSERT
ON ENROLL
FOR EACH ROW
BEGIN
:new.addtime := sysdate;
END;
/
If I remove the FOR EACH ROW in the above, I actually get an error:
Error report -
ORA-04082: NEW or OLD references not allowed in table level triggers
04082. 00000 - "NEW or OLD references not allowed in table level triggers"
*Cause: The trigger is accessing "new" or "old" values in a table trigger.
*Action: Remove any new or old references.
From the error message, it seems like if I use :new.[column_name], then FOR EACH ROW must have to exist. Why is this? Is there any example that FOR EACH ROW is NOT needed in a BEFORE INSERT TRIGGER in Oracle?
Is there any example that FOR EACH ROW is NOT needed in a BEFORE INSERT TRIGGER in Oracle?
Simple example of statement level trigger:
CREATE TABLE test_table(col VARCHAR2(10));
CREATE OR REPLACE TRIGGER enroll_time
BEFORE INSERT
ON ENROLL
BEGIN
INSERT INTO test_table(col)
SELECT 1 FROM dual;
END;
/
I highly recommend to read about compound trigger to understand when each part is fired.
Basically, if you need to use :OLD or :NEW pseudotables, you need a row level trigger. An example of a statement level trigger would be inserting a record into a table when another table is effected.

Oracle Trigger Insert/update

Ok so i am working on a homework assignment.
I have three tables, Movies (title, year, length, genre, studioName, producer) StarsIn (movieTitle, starName) MovieStar (name, address, gender, birthdate)
Basically i need to make sure when someone inserts or updates something in StarsIn those changes need to happen in MovieStar also.
So far i have something like this..
CREATE OR REPLACE TRIGGER testTrig
AFTER UPDATE OR INSERT ON STARSIN
DECLARE
l_name MOVIESTAR.NAME%TYPE;
BEGIN
SELECT NAME FROM MOVIESTAR INTO l_name;
FOR EACH ROW WHEN (new.STARSIN.STARNAME NOT IN l_name)
INSERT INTO MOVIESTAR(NAME) VALUES (new.STARSIN.STARNAME);
END;
I am getting a few compiler errors
Error(4,1): PL/SQL: SQL Statement ignored
Error(4,28): PL/SQL: ORA-00933: SQL command not properly ended
Error(5,10): PLS-00103: Encountered the symbol "ROW" when expecting one of
the following: in
I am very new to oracle and I am practicing Triggers. I know that this could be easily done using foreign keys, but the assignment is to use triggers.
I could really use some help with this. I have tried like a million different ways to make this happen, with no luck.
Thanks in advance for any help/advice.
I'd suggest specifying the trigger fire for each row. I find these a lot easier.
You can do a count to see if the MovieStar.Name value already exists and then insert if it doesn't; that's similar to the approach you have above. This will fail if another user inserts the movie star between the time you check and the time you insert, but it's probably good enough for a class assignment. There are accepted no-fail approaches for this but you may not have covered them in class yet.
Try something like this; it probably incorporates everything you've covered in class so far:
CREATE OR REPLACE TRIGGER TestTrig
AFTER UPDATE OR INSERT ON STARSIN
FOR EACH ROW
DECLARE
movieStarCount NUMBER;
BEGIN
SELECT COUNT(*) INTO movieStarCount
FROM MovieStar
WHERE Name = :NEW.StarName;
IF movieStarCount = 0 THEN
INSERT INTO MovieStar (Name) VALUES (:NEW.StarName);
END IF;
END;

Creating a INSERT TRIGGER in different table

I need help on creating a trigger on my table1
that will insert specific columns into table2 from table1.
How can i do that? I am using Oracle 11G XE .
Here is my code:
create trigger AllowanceTrigger
on ex_bulacan
after insert
as
insert into allowance VALUES (PLANT_ORIGIN,SO_NO, SO_STATUS,SO_REMARKS,DRIVER_NAME)
select plant_origin, sales_order_no, status,remarks, driver_name
from ex_bulacan;
go ;
When I run that command I get this error
ORA-04071: missing BEFORE, AFTER or INSTEAD OF keyword
The explanation is:
ORA-04071. 00000 - "missing BEFORE, AFTER or INSTEAD OF keyword"
*Cause: The trigger statement is missing the BEFORE/AFTER/INSTEAD OF clause.
*Action: Specify either BEFORE, AFTER or INSTEAD OF.
There is no "go" statement in PL/SQL, and you have not followed the correct syntax for a trigger definition (it is well documented)
Try this:
create trigger AllowanceTrigger
after insert on ex_bulacan
begin
insert into allowance (PLANT_ORIGIN,SO_NO, SO_STATUS,SO_REMARKS,DRIVER_NAME)
select plant_origin, sales_order_no, status,remarks, driver_name
from ex_bulacan;
end;
I'm not sure whether it does what you intended. It fires once per insert statement, not for each row, and it inserts all rows from ex_bulacan into allowance, not just the ones you just inserted. Maybe what you want is actually:
create trigger AllowanceTrigger
after insert on ex_bulacan
for each row
begin
insert into allowance (PLANT_ORIGIN,SO_NO, SO_STATUS,SO_REMARKS,DRIVER_NAME)
values (:new.plant_origin, :new.sales_order_no, :new.status, :new.remarks,
:new.driver_name);
end;
There is a syntax error in your code. You must specify the trigger in this order:
CREATE TRIGGER AllowanceTrigger
AFTER INSERT
ON ex_bulacan

SQL Oracle Trigger

I'm having problem with simple trigger command. This trigger operation will insert value into table address_rit when a person who studies at RIT is inserted into table person. Here's the syntax for the trigger command:
CREATE OR REPLACE TRIGGER addr
AFTER INSERT ON person
FOR EACH ROW
WHEN (NEW.college = 'RIT')
BEGIN
INSERT INTO address_rit (name, address, state)
VALUES (NEW.name, NEW.address, (SELECT name FROM states WHERE NEW.statecode = states.statecode));
END;
/
The trigger is compiled but with warning. However, further inspection shows that the trigger actually has error. Here's the error from the compilation.
PL/SQL: SQL Statement ignored ERROR
PL/SQL: ORA-00984: column not allowed here ERROR
I'm pretty sure the error is just a syntax error, but I just can't find any solution. Let me know if I need to add more detail. Thank you very much for your help.
At a minimum, you need a colon before NEW
CREATE OR REPLACE TRIGGER addr
AFTER INSERT ON person
FOR EACH ROW
WHEN (NEW.college = 'RIT')
BEGIN
INSERT INTO address_rit (name, address, state)
VALUES (:NEW.name,
:NEW.address,
(SELECT name
FROM states
WHERE :NEW.statecode = states.statecode));
END;
/
I'm also assuming that the query against the STATES table is always going to return exactly 1 row. If the database is properly normalized, though, I would expect that all the tables would have a STATECODE column rather than a STATE column and that there would be foreign keys between both PERSON and ADDRESS_RIT that reference the STATECODE column in STATES. But, if the database is properly normalized, I would also expect that you wouldn't have an ADDRESS_RIT table that duplicated the data in PERSON. Instead, ADDRESS_RIT really ought to be a view on the PERSON table.