How to use External Procedures in Triggers on Oracle 11g - oracle

I want to fire a trigger whenever an insert command is fired..
The trigger will access a pl/sql file which can change anytime..
So the query is, if we design the trigger, how can we make sure this dynamic thing happens.. As during the stored procedure, it is not working..
I think - it should work for
1) External Procedures
2) Execute Statement
Please correct me, if I am wrong.. I was working on External Procedures but i am not able to find the way to execute the external procedure from here on..
SQL> CREATE OR REPLACE FUNCTION Plstojavafac_func (N NUMBER) RETURN NUMBER AS
2 LANGUAGE JAVA
3 NAME 'Factorial.J_calcFactorial(int) return int';
4 /
##########################################
SQL> CREATE OR REPLACE TRIGGER student_after_insert
2 AFTER INSERT
3 ON student
4 FOR EACH ROW
How to call the procedure from heree... And does my interpretations are right,, plz suggest..
Thanks.

either use procedure for inserting where you will handle your data and then quit procedure (cancel insert) or make successful insert, or do your data handling in trigger not in procedure

Related

Oracle deadlock trigger

I have a procedure P1.
TABLES T1,T2 and TRIGGER TRG1
Below is the Trigger Event:
CREATE OR REPLACE TRIGGER
AFTER UPDATE OF RECORD_STATUS
ON T1 WHEN (NEW.RECORD_STATUS='U')
BEGIN
.
--Calling Procedure
P1();
.
END;
I am calling a procedure with parameters. Inside procedure P1 using those parameters I am selecting the data from T1 and doing some validations and inserting into T2.
After Successful insert I am updating the RECORD_STATUS='I' in the the procedure.
Now I performed below statement:
UPDATE T1 SET RECORD_STATUS='U'
Since the trigger event occurs here it is calling my procedure and inside the procedure since I am updating the same column again trigger is firing and leads to dead lock. Please help me in this.
Thanks in advance.
First of all some advice, NEVER use triggers unless your desperate.
If your already updating the table in a stored procedure, add the logic into your P1 procedure, or create a second procedure with the additional functionality and call it from P1.
Good citizenship is part of database development. All transactions on those tables should follow the same order. Using a trigger to update the same table is not good citizenship.
If you really have to do something like this, one thing you can try, is to use an Autonomous Transaction

Select All records from a table using SP in Oracle SQL Developer

I'm using SQL Oracle to build a stored procedure. I'm trying to build a stored procedure of the SQL-query below.And I want to return those data to a C# program.
select * from employee_master
I have tried following. Is this correct?
CREATE OR REPLACE PROCEDURE EMPLOYEE_SELECTALL (p_recordset OUTSYS_REFCURSOR)AS
BEGIN
OPEN p_recordset FOR
SELECT
*
FROM
EMPLOYEE_MASTER;
END EMPLOYEE_SELECTALL;
If you wish to build a stored procedure that return such resultset first of all you should check if you really need to do this. It's incidental and not recommended way for Oracle. But if you really need so, you should use REF CURSOR.
after executing your stored procedure in SQL Developer, it automatically brings back any output for you to view, including one or more ref cursors.
Example code and screenshots here

Stored Procedure in Oracle giving error PLS-00428

I am trying to create the following procedure in oracle:
CREATE OR REPLACE PROCEDURE SPBILL (SPCLIENT_ID VARCHAR2)
AS
BEGIN
SELECT C.CLIENT_NAME, B.ROOM_ID, R.ROOM_COST, T.TREAT_NAME, T.TREAT_COST, (ROOM_COST*(B_END_DATE-B_START_DATE)+TREAT_COST) AS INVOICE
FROM CLIENTS C, ROOMS R, TREATMENTS T, BOOKING B, PRESCRIPTION P
WHERE C.CLIENT_ID=B.CLIENT_ID
AND R.ROOM_ID=B.ROOM_ID
AND B.CLIENT_ID=P.CLIENT_ID
AND P.TREAT_ID=T.TREAT_ID
AND C.CLIENT_ID=SPCLIENT_ID;
END SPBILL;
I am getting a "Procedure created with compilation errors" and the errors is PLS-00428, which required an INTO satement, but i do not understand why and where do i need it as my sql statement works just the way i want it without the procedure. But i need to create a procedure so i can call a specific client id and only recieve their data as an output.
When you are running the SQL directly using a client (SQL Plus or SQL Developer or Toad) , data is returned to the client.
When you run the same query inside PL/SQL, you need to tell oracle what to do with that data. Usually programs store the output in Pl/SQL variables for further processing.
https://docs.oracle.com/cd/B19306_01/appdev.102/b14261/selectinto_statement.htm
So, in your case, you might need something along these lines..
CREATE OR REPLACE PROCEDURE SPBILL (SPCLIENT_ID VARCHAR2)
AS
l_client_name clients.client_name%type;
l_room_id rooms.room_id%type;
...
l_invoice number(5,2);
BEGIN
SELECT C.CLIENT_NAME, B.ROOM_ID, R.ROOM_COST, T.TREAT_NAME, T.TREAT_COST, (ROOM_COST*(B_END_DATE-B_START_DATE)+TREAT_COST)
into l_client_name, l_room_id...l_invoice
FROM CLIENTS C, ROOMS R, TREATMENTS T, BOOKING B, PRESCRIPTION P
WHERE C.CLIENT_ID=B.CLIENT_ID
AND R.ROOM_ID=B.ROOM_ID
AND B.CLIENT_ID=P.CLIENT_ID
AND P.TREAT_ID=T.TREAT_ID
AND C.CLIENT_ID=SPCLIENT_ID;
--further processing here based on variables above.
dbms_output.put_line(l_invoice);
END SPBILL;
Once you compile without errors, you can run the procedure..
set serveroutput on;
SPBILL(100);
Maybe you should use IS instead of AS
CREATE OR REPLACE PROCEDURE SPBILL (SPCLIENT_ID VARCHAR2)
IS
....
It looks like you have experience with MSSQL and expect Oracle would be the same. If so, it isn't true.
It looks like you try to return resultset from procedure as it usual in MSSQL. Oracle have no implicit resultsets at all. If you wish to do this, you should use explicit resultset eighter via returning REF CURSOR (http://www.orafaq.com/wiki/REF_CURSOR) or via TABLE FUNCTION (https://docs.oracle.com/cd/B19306_01/appdev.102/b14289/dcitblfns.htm).
But first of all, you should think if you really need this procedure at all. Generally, SELECT procedures in Oracle is part of doubtful design.

Oracle PL/SQL: Calling a procedure from a trigger

I get this error when ever I try to fire a trigger after insert on passengers table. this trigger is supposed to call a procedure that takes two parameters of the newly inserted values and based on that it updates another table which is the booking table. however, i am getting this error:
ORA-04091: table AIRLINESYSTEM.PASSENGER is mutating, trigger/function may not see it
ORA-06512: at "AIRLINESYSTEM.CALCULATE_FLIGHT_PRICE", line 11 ORA-06512: at
"AIRLINESYSTEM.CALCULATE_FLIGHT_PRICE", line 15 ORA-06512: at
"AIRLINESYSTEM.CALCULATE_FLIGHT_PRICE_T1", line 3 ORA-04088: error during execution of
trigger 'AIRLINESYSTEM.CALCULATE_FLIGHT_PRICE_T1' (Row 3)
I complied and tested the procedure in the SQL command line and it works fine. The problem seems to be with the trigger. This is the trigger code:
create or replace trigger "CALCULATE_FLIGHT_PRICE_T1"
AFTER
insert on "PASSENGER"
for each row
begin
CALCULATE_FLIGHT_PRICE(:NEW.BOOKING_ID);
end;​​​​​
Why is the trigger isn't calling the procedure?
You are using database triggers in a way they are not supposed to be used. The database trigger tries to read the table it is currently modifying. If Oracle would allow you to do so, you'd be performing dirty reads.
Fortunately, Oracle warns you for your behaviour, and you can modify your design.
The best solution would be to create an API. A procedure, preferably in a package, that allows you to insert passengers in exactly the way you would like it. In pseudo-PL/SQL-code:
procedure insert_passenger
( p_passenger_nr in number
, p_passenger_name in varchar2
, ...
, p_booking_id in number
, p_dob in number
)
is
begin
insert into passenger (...)
values
( p_passenger_nr
, p_passenger_name
, ...
, p_booking_id
, p_dob
);
calculate_flight_price
( p_booking_id
, p_dob
);
end insert_passenger;
/
Instead of your insert statement, you would now call this procedure. And your mutating table problem will disappear.
If you insist on using a database trigger, then you would need to avoid the select statement in cursor c_passengers. This doesn't make any sense: you have just inserted a row into table passengers and know all the column values. Then you call calculate_flight_price to retrieve the column DOB, which you already know.
Just add a parameter P_DOB to your calculate_flight_price procedure and call it with :new.dob, like this:
create or replace trigger calculate_flight_price_t1
after insert on passenger
for each row
begin
calculate_flight_price
( :new.booking_id
, :new.dob
);
end;
Oh my goodness... You are trying a Dirty Read in the cursor. This is a bad design.
If you allow a dirty read, it return the wrong answer, but also it returns an answer that never existed in the table. In a multiuser database, a dirty read can be a dangerous feature.
The point here is that dirty read is not a feature; rather, it's a liability. In Oracle Database, it's just not needed. You get all of the advantages of a dirty read—no blocking—without any of the incorrect results.
Read more on "READ UNCOMMITTED isolation level" which allows dirty reads. It provides a standards-based definition that allows for nonblocking reads.
Other way round
You are misusing the trigger. I mean wrong trigger used.
you insert / update a row in table A and a trigger on table A (for each row) executes a query on table A (through a procedure)??!!!
Oracle throws an ORA-04091 which is an expected and normal behavior, Oracle wants to protect you from yourself since it guarantees that each statement is atomic (i.e will either fail or succeed completely) and also that each statement sees a consistent view of the data
You would expect the query (2) not to see the row inserted on (1). This would be in contradiction
Solution: -- use before instead of after
CREATE OR REPLACE TRIGGER SOMENAME
BEFORE INSERT OR UPDATE ON SOMETABLE

oracle plsql: retrieve runtime parameter values when you call a procedure

I need a generalized method to get list of runtime parameters (values) when I call a procedure. I need something similar to the $$PLSQL_UNIT that returns the name of the running procedure.
(plsql Oracle 10g)
E.g. look at this sample procedure:
(it simply prints its own name and parameters )
CREATE OR REPLACE PROCEDURE MY_PROC(ow in varchar2, tn IN varchar2)
IS
BEGIN
dbms_output.put_line('proc_name: '||$$PLSQL_UNIT||' parameters: '|| ow||' '||tn );
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('ERRORE: ' ||SQLERRM);
END MY_PROC;
/
Running procedure produces the following output:
SQL>
1 BEGIN
2 IBAD_OWN.MY_PROC('first_par', 'second_par');
3 END;
4 /
proc_name: MY_PROC parameters: first_par second_par
PL/SQL procedure successfully completed.
I'm not satisfy because I can't copy and paste in all my procedures because I have to hard code each procedure to set their right parameter variables.
Thanks in advance for the help.
It isn't possible to dynamically retrieve the values of parameters passed to a procedure in Oracle PL/SQL. The language simply isn't designed to handle this kind of operation.
Incidentally, in a procedure that is located within a package, $$PLSQL_UNIT will only return the package's name. I find it's better to define a consistently-named constant within each procedure that contains the procedure's name.
When I wanted the same functionality as yours I didn't find any good built-in solution.
What I did is: wrote DB-level trigger which modifies original body of function/procedure/package.
This trigger adds immediatly after "begin" dynamically generated piece of code from "user_arguments".
Plus, after that I include into this trigger the code, that logs calls of procs when exception occures.
Plus, you can trace procs calls, and many more interisting things.
But this solution works fine only for preproduction because performance decreases dramatically.
PS. Sorry for my bad English.

Resources