CREATE TRIGGER Comparer_Prix
BEFORE UPDATE ON ARTICLE
FOR EACH ROW BEGIN
SELECT ARTICLE.PRIXVENTE, ARTICLE.N_PRODUIT, ARTICLE.N_FABRICANT, LIEN_FABRICANT_PRODUIT.PRIXFABRICANT, LIEN_FABRICANT_PRODUIT.N_PRODUIT, LIEN_FABRICANT_PRODUIT.N_FABRICANT
FROM ARTICLE, LIEN_FABRICANT_PRODUIT
WHERE ARTICLE.N_FABRICANT=LIEN_FABRICANT_PRODUIT.N_FABRICANT AND ARTICLE.N_PRODUIT=LIEN_FABRICANT_PRODUIT.N_PRODUIT;
IF (NEW.PRIXVENTE< PRIXFABRICANT) THEN RAISE_APPLICATION_ERROR(-20001, 'Refusé');
END IF;
END;
I am trying to create a trigger that codes the following rule: the sales price must always be higher than the manufacturing price.
Here the errors I get:
Error(2,3): PL/SQL: SQL Statement ignored
Error(2,69): PL/SQL: ORA-00904: "LIEN_FABRICANT_PRODUIT"."PRIXFABRICANT" : invalid identifier
Error(2.92): PLS-00302: The component "PRIXFABRICANT" must be declared.
Error(5,3): PL/SQL: Statement ignored
Error(5,10): PLS-00201: the identifier 'NEW.PRIXVENTE' must be declared.
It is not new, but :new (you're missing a colon).
Though, that's not the only issue here; you can't select from a table which is just being modified; mutating table error is expected. Lucky you, you don't have to select from article as you can reference its values using the same :new value.
ORA-00904 means that you've used a column name which doesn't exist in that table. As you didn't post tables' descriptions, I'm simply repeating what you wrote. Fix it yourself.
Something like this:
create or replace trigger comparer_prix
before update on article
for each row
declare
l_prixfabricant lien_fabricant_produit.prixfabricant%type;
begin
select prixfabricant
into l_prixfabricant
from lien_fabricant_produit
where n_fabricatn = :new.n_fabricant
and n_produit = :new.n_produit;
if :new.prixvente < l_prixfabricant then
raise_application_error(-20001, 'Refusé');
end if;
end;
/
Also, it wouldn't harm if you learnt how to properly format code and make it easier to read. Use table aliases (instead of those lengthy table names).
If You compare two tables use:
... WHERE ... AND EXISTS(SELECT * FROM <TAB_COMPARE>)
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.
Trying to create a trigger for populating an audit table with old data before changes are made to the base table BOOKS
CREATE OR REPLACE TRIGGER populate_audit_table
BEFORE INSERT OR UPDATE OF cost, retail OR DELETE
ON books
REFERENCING NEW as new OLD as old
FOR EACH ROW
DECLARE
dml_operation varchar2(1) :=
CASE WHEN UPDATING THEN 'U'
WHEN DELETING THEN 'D'
ELSE 'I'
END;
BEGIN
INSERT INTO cost_retail_history
(isbn
,title
,pubid
,pubdate
,cost
,retail
,discount
,category
,dml_operation)
SELECT
(old.isbn
,old.title
,old.pubid
,old.pubdate
,old.cost
,old.retail
,old.discount
,old.category
,new.dml_operation)
FROM BOOKS;
end;
I get the following errors:
Errors: TRIGGER POPULATE_AUDIT_TABLE
Line/Col: 8/7 PL/SQL: SQL Statement ignored
Line/Col: 20/13 PL/SQL: ORA-00907: missing right parenthesis
I also tried using VALUES on the INSERT INTO and not designating a source table ("FROM BOOKS")
....VALUES
(old.isbn
,old.title
,old.pubid
,old.pubdate
,old.cost
,old.retail
,old.discount
,old.category
,new.dml_operation);
end;
And I get the following errors:
Line/Col: 8/7 PL/SQL: SQL Statement ignored
Line/Col: 27/18 PL/SQL: ORA-00984: column not allowed here
I've read and re-read https://docs.oracle.com/cd/A64702_01/doc/server.805/a58225/ch4a.htm#1997457 so I feel like I'm missing something simple and just need a point in the right direction.
Thanks,
EDIT:
I dropped the dml_operation as this wasn't required and followed the advice below, but I am still getting errors:
Current version:
CREATE OR REPLACE TRIGGER cost_retail_history
BEFORE INSERT
OR UPDATE OF cost, retail
OR DELETE
ON books
REFERENCING NEW as new OLD as old
FOR EACH ROW
BEGIN
CASE
WHEN INSERTING THEN
INSERT INTO cost_retail_history
(isbn
,title
,pubid
,pubdate
,cost
,retail
,discount
,category)
VALUES
(:new.isbn
,:new.title
,:new.pubid
,:new.pubdate
,:new.cost
,:new.retail
,:new.discount
,:new.category)
WHEN UPDATING cost, retail OR DELETING THEN
INSERT INTO cost_retail_history
(isbn
,title
,pubid
,pubdate
,cost
,retail
,discount
,category)
VALUES
(:old.isbn
,:old.title
,:old.pubid
,:old.pubdate
,:old.cost
,:old.retail
,:old.discount
,:old.category);
END CASE;
END;
I'm getting the errors:
Errors: TRIGGER COST_RETAIL_HISTORY
Line/Col: 4/9 PL/SQL: SQL Statement ignored
Line/Col: 22/5 PL/SQL: ORA-00933: SQL command not properly ended
I can't tell exactly what line the error is on as this would indicate it's with:
...OR DELETE
and
... ,:new.title
which does not make sense to me.
If you were doing insert ... select ... then you should not have the parentheses around the column list; i.e.:
INSERT INTO cost_retail_history
(isbn
...
,dml_operation)
SELECT
old.isbn
...
,new.dml_operation
FROM BOOKS;
but you should not be selecting from the table the trigger is against - partly because you'll get a mutating table error, and you are attempting to insert an audit row for every row in the base table; but mostly because you already have all of the information you need.
With the values clase you need to prefix the old/new values with a colon:
....VALUES
(:old.isbn
,:old.title
,:old.pubid
,:old.pubdate
,:old.cost
,:old.retail
,:old.discount
,:old.category
,:new.dml_operation);
end;
Read more in the documentation.
Oracle has built-in audit tools but presumably this is an exercise.
I can't tell exactly what line the error is on as this would indicate...
This can be slightly confusing with triggers as they are a mix of SQL and PL/SQL. Because you are getting PL/SQL errors the line numbering starts from the beginning of the PL/SQL part, so here BEGIN is line 1, INSERT is line 4; WHEN UPDATING... is line 22.
Those new errors are just because you don't have a semicolon at the end of the first INSERT statement:
,:new.discount
,:new.category);
-----------------------^
WHEN UPDATING cost, retail OR DELETING THEN
INSERT INTO cost_retail_history
The error is reported against line 22 because that WHEN is where it's expecting to see the semicolon, and the first point it can see the previous SQL command hasn't been completed. The error against line 4 is saying where that not-ended command started; so you're getting two messages for one actual problem.
Im trying to populate my database using the builtin function executeSqlScript from AbstractTransactionalJUnit4SpringContextTests using the following external SQL file.
declare
id number;
begin
insert into table1 (field1) values ('V1') returning account__id into id;
insert into table2 (my_id, field2) VALUES (id, 'Value3');
end;
However im getting the following error. Im not sure what im allowed to do in a SQL file I would like to execute using executeSqlScript.
org.springframework.jdbc.datasource.init.ScriptStatementFailedException: Failed to execute SQL script statement at line 1 of resource class path resource [testdata.sql]: declare id number; nested exception is java.sql.SQLException: ORA-06550: line 1, column 17:
PLS-00103: Encountered the symbol "end-of-file" when expecting one of the following:
:= . ( # % ; not null range default character
Caused by: java.sql.SQLException: ORA-06550: line 1, column 17:
PLS-00103: Encountered the symbol "end-of-file" when expecting one of the following:
:= . ( # % ; not null range default character
So my questions are:
What am I allowed to express in the SQL file for executeSqlScript?
What is the cause of the error im reciving?
It appears that you are attempting to use features of PL/SQL in your script.
The executeSqlScript(..) methods in AbstractTransactionalJUnit4SpringContextTests internally delegate to ScriptUtils.executeSqlScript(..) behind the scenes, and ScriptUtils only supports pure SQL scripts.
So you'll likely need to switch to simple SQL statements and find a different mechanism for retrieving the value of the account__id from table1.
Another option (which I have not tried) would be to change the statement separator to something other than ";" (e.g., "end;"), but you cannot do that via AbstractTransactionalJUnit4SpringContextTests.executeSqlScript. Instead, you'd need to invoke ScriptUtils.executeSqlScript(..) or (perhaps preferably) use a ResourceDatabasePopulator.
I'm trying to create an INSERT stored procedure in my database using Oracle SQL Developer but I can't seem to figure out what's the problem with this code;
create or replace procedure insert_order
as
BEGIN
INSERT INTO ORDERS (ORDER_NUM, ORDER_DATE, CONDITION, STATUS, CUSTOMER_CUSTOMER_NUM, CUSTOMER_EMPLOYEE_NUM)
VALUES(1, '30/OCT/2007', 'BRANDNEW', 'ORDERD', 103, 1);
end insert_order;
Can you help please?
The error message PL/SQL: SQL Statement ignored, and Error(5,23): PL/SQL: ORA-00984: column not allowed here indicates that the error is with the value '30/OCT/2007' (line 5, column 23), since you are not using the standard format for dates.
You can try TO_DATE('30/OCT/2007') or '2007-10-30'.