I'm trying to create my trigger but it's asking for binds EVERY time. It works the way I want it to when I click apply on the window that appears... However, it will log an error...
My trigger checks to see if a client is active or not and do NOT allow changes if it is found to be active...
CREATE Trigger Client_Activity
BEFORE Insert or Update or Delete ON Client
FOR EACH ROW
DECLARE
VAR_AC char(2);
BEGIN
IF UPDATING THEN
SELECT Activity INTO VAR_AC
FROM Client_Additionals
WHERE Activity = :Old.Activity;
IF Activity = 'AC'
THEN Raise_Application_Error(-20999, 'active')
END IF;
END;
/
ORACLE VERSION 12 USING SQLDEVELOPER
You have two syntax errors in your trigger:
The IF is missing an END IF
You need to compare the content of the variable var_ac
You are missing a ; after the Raise_Application_Error()
Putting that together, you can create the trigger without problems.
However, you need to use the "Run Script" button in SQL Developer to run a PL/SQL block like that.
SQL*Plus requires no special handling:
Related
I use a pl/sql code in a dynamic action (which is launched when I press a button).
I do an update table. after the update, I want to notify to the user if the update succeed or not.
I use the code :
if ( ) then
update ....
apex_application.g_print_success_message := '<span style="color:green">OK</span>';
end if;
but the code does not work. it does the update, but I do not see the notification.
thank for your help.
Hervé
Here's how I do that:
create a stored procedure which accepts certain parameters, do stuff and puts success (or failure) message into the OUT parameter. For example,
create or replace procedure p_upd (par_empno in number, par_msg out varchar2) as
begin
update ...
where empno = par_empno;
par_msg := 'Updated ' || sql%rowcount || ' rows';
end;
In Apex, create a hidden item (let's call it P1_MSG)
create a button which - when pushed - calls a process which utilizes previously mentioned stored procedure:
p_upd (:P1_EMPNO, :P1_MSG);
finally, set this as a Success process message:
&P1_MSG.
(note leading ampersand (&) and trailing dot (.) - without them, it won't work. The final result will be "Updated 17 rows" message displayed on the screen (just as you see the default "Action processed" message).
That's all.
Of course, instead of calling a procedure, you can write some PL/SQL code directly into the process, but I prefer a procedure, especially when there's a lot of things to be done (I rather do that in the database).
my suggestion is write your plsql code in process by selecting type as plsql code. from there you can set your success message as well. I also tried earlier with apex_application.g_print_success_message but it was not work for me. So I changed by process flow.
I want to code a Trigger to validate if a column have only a specific value, And if some user try to update or insert a row with the same value raise the trigger. But trigger doesn't compile fine. Do you have any idea? Do you know if Compound triggers are available in 10g?
NOTE: Only one "S" value is available for mon_oficial column. If some user try to insert a new record or update with a second "S" value trigger will fired.
Table:
Trigger:
CREATE OR REPLACE TRIGGER check_mon_oficial_trg
FOR INSERT OR UPDATE
ON monedas
COMPOUND TRIGGER
v_check_moneda NUMBER(8);
BEFORE STATEMENT IS
BEGIN
SELECT COUNT(:NEW.mon_oficial)
INTO v_check_moneda
FROM monedas
WHERE mon_oficial = 'S';
IF
v_check_moneda > 1 THEN
RAISE_APPLICATION_ERROR(-20010, 'Only one official money in table');
END IF;
END BEFORE STATEMENT;
END check_mon_oficial_trg;
Error:
Compound triggers were introduced in 11gR1
Compound Triggers
A compound trigger is a Database Manipulation Language (DML) trigger that can fire at more than one timing point.
The body of a compound trigger supports a common PL/SQL state that the code for all of its sections can access. The common state is established when the triggering statement starts and destroyed when the triggering statement completes, even when the triggering statement causes an error.
Before Release 11.1, application developers modeled the common state with an ancillary package. This approach was both cumbersome to program and subject to memory leak when the triggering statement caused an error and the after-statement trigger did not fire. Compound triggers make it easier to program an approach where you want the actions you implement for the various timing points to share common data.
I have a script in PL/SQL , that drop some tables , sequences , triggers, and creating them again in the same script , I need this script in my website for deleting all data from database (and I want to acces this script pressing one button on website) so I tried to do a function / procedure in PL/SQL that read line by line from the script file and executing every line with dynamic sql , everything went ok till one error at:
CREATE OR REPLACE TRIGGER players_bir BEFORE INSERT ON players FOR EACH ROW BEGIN SELECT players_seq.NEXTVAL INTO :new.id FROM dual END
this gave me the error:
ORA-24344: success with compilation error
I searched for solutions, but I didn't find anything.
You are missing the semi-colon after dual on your SELECT statement. This ORA error generally means you compiled some code, but that is has some issue.
CREATE OR REPLACE TRIGGER players_bir
BEFORE INSERT ON players
FOR EACH ROW
BEGIN
SELECT players_seq.nextval
INTO :new.id
FROM dual;
END
Looking in all_errors will show you what the issue is or you could manually compile this trigger in some IDE (like SQL Developer) and that should also make it obvious.
SELECT *
FROM all_errors e
WHERE e.name = 'PLAYERS_BIR'
AND e.type = 'TRIGGER';
Additionally if all you are using your trigger for is to set some identity column and you are on Oracle 12c you can use some of the new features to accomplish this. Triggers are inherently slow and the new identity feature performs about as good as referencing the sequence directly in your INSERT.
I have a view to fetch list of my project specific packages from all_objects in Oracle DB, which will fetch the name, status, created and last DDL for all objects with wildcard operator specific to my project requirement.
CREATE OR REPLACE FORCE VIEW ALL_XYZ_PACKAGES_VW
AS
SELECT object_name,status, object_type,created,last_ddl_time
FROM all_objects
WHERE object_name LIKE 'XYZ_%'
AND object_type IN ('PACKAGE', 'PACKAGE BODY');
And my requirement is to fire a trigger which sends an email notification when any of my package gets Invalid due to some DB Link missing or dependent object is missing or any wrong code deployed with logical errors.
So following is the trigger i have created:
CREATE OR REPLACE TRIGGER notify_invalidobjects_trigger
INSTEAD OF UPDATE ON ALL_XYZ_PACKAGES_VW
FOR EACH ROW
BEGIN
IF (:NEW.STATUS = 'INVALID') THEN
DBMS_OUTPUT.PUT_LINE ('Following mentioned Package is in INVALID state: '|| :OLD.OBJECT_NAME); -- Email notification part will e written here
ELSE
DBMS_OUTPUT.PUT_LINE ('In Else Block');
END IF;
END;
/
Issue:
1) When i am manually updating the package status as INVALID in my view with an update statement, trigger is getting fired.
BUT when the package is automatically getting Invalid, when i am making some dependent object as Invalid or by wrong code deployment,
TRIGGER IS NOT GETTING FIRED EVEN THE STATUS IS
GETTING INAVLID AUTOMATICALLY IN MY VIEW AND ALL_OBJECTS.
Could any one suggest me what i need to check or update in code.
Note: I thought of using After Update trigger, but its not allowing me to use the same on views.
The trigger on the view will not fire because the view is not updated. Your view is no more and no less then a stored select statement. If you don't need "live response" I'd suggest to just change to a procedure for query all_objects and send the mail and run it via job.
I was trying to do something like auto-increment in Oracle 11g Express and SQL Developer.
I know very little about Oracle and I am also new to triggers.
I tried running this, but I don't know how to do it properly.
CREATE TABLE theschema.thetable
(id NUMBER PRIMARY KEY,
name VARCHAR2(30));
CREATE SEQUENCE theschema.test1_sequence
START WITH 1
INCREMENT BY 1;
create or replace trigger insert_nums
before insert on theschema.thetable
for each row
begin
select test1_sequence.nextval into :new.id from dual;
end;
/
When I try to create the trigger, I get a screen which asks me for some "binds".
The dialog box has only one check box "null". What does this mean and how do I make
a script that works properly?
Any precautions to take while doing this kind of "auto-increment" ?
It seems that SQL Developer thinks that you are running a plain DML (data manipulation) script, not a DDL (data definition). It also thinks that :new.id is a bindable variable.
Why this happens, I don't know; I can't reproduce it in Oracle SQL Developer 2.1.
Try to open a new SQL worksheet window in the theschema schema and execute a "whole" script (not a statement) by pressing F5 (not F9).
This is how I have solved this problem, put "set define off;" before the command:
set define off;
create or replace trigger [...]
[...]
end;
/
Then highlight both commands and press F9 to run.
Or you could run all the commands with F5.
It seems, that if the commands are executed separetly with F9, then the set define off does not take affect.
For my case, solution was entering "newrow" for 'new' and "oldrow" for 'old' as values for the binds...
I am a novice at this so keep that in mind as I give my answer.
I think the issue is that the code
create or replace trigger insert_nums
before insert on theschema.thetable
for each row
begin
select test1_sequence.nextval into :new.id from dual;
end;
Is actually a script and not straight forward SQL statement. Hence you have to run the "Run Script". I discovered that when I had a worksheet open in SQL Developer that if I had anywhere in the worksheet the any code for trigger like above then even I just tried to run a statement that SQL Developer would look back in the worksheet and try to run the script. To stop that from happening I had to comment out the code.
And If I did want to run the code for the trigger than I had to open a new worksheet, place the code there and do a RUN SCRIPT.