how to call trigger in procedure plsql - plsql

Here i have created my trigger and it is working. how to call that trigger inside the procedure. please provide any solution for this.
below is my trigger
create or replace Trigger emp_trigger
Before update on Required_table
Begin
delete from log_table;
insert into log_table(employee_name,phone_number,company_name,location,currency)
(select employee_name,phone_number,company_name,location,currency
from Required_table);
end;
here is my procedure code and here i want to call that above trigger code
create or replace procedure excercise_one
is
cursor test_cur is
select employee_details.emp_name,employee_details.emp_mobile_no,company.company_name,
location.area,currency.currency
from
employee_details, company, location, currency
where
employee_details.id = company.emp_no and
company.location = location.country and
location.location_id = currency.location;
ename employee_details.emp_name%type;
emp_mob Employee_Details.Emp_Mobile_No%type;
cname company.company_name%type;
l_area location.area%type;
cur currency.currency%type;
begin
open test_cur;
loop
fetch test_cur into ename,emp_mob,cname,l_area,cur;
if test_cur%Found Then
insert into Required_table values (ename,emp_mob,cname,l_area,cur);
else
exit;
end if;
end loop;
close test_cur;
end;

You can't call a trigger in the stored procedure. Triggers run automatically and are executed or fired when some events occur.
For more details, please find the following link
https://www.oracletutorial.com/plsql-tutorial/oracle-trigger/

It can not be call a trigger from stored procedure.
But it can be call a stored procedure from a trigger.

Your Trigger fires only on Update!
For your Problem.
Write a Procedure to manipulate your logtable.
So you can call ist from a Procedure or a Trigger.
MfG
Ingo

Related

skip deleting records when a child record is found

i have a pl/sql procedure to modify/delete records based on a checkbox selection in my Apex application:
delete from s_objectif_operation where id_operation=:p124_id_operation;
for a in (select distinct id from s_objectif
where id in (
SELECT trim(regexp_substr(:P124_S_OBJECTIF, '[^:]+', 1, LEVEL)) str
FROM dual
CONNECT BY instr(:P124_S_OBJECTIF, ':', 1, LEVEL - 1) > 0
))
loop
insert into s_objectif_operation
(id_s_objectif, id_operation)
values
(a.id, :p124_id_operation);
end loop;
for every modification, this procedure deletes all the records and insert the correct ones back so i had to remove the "cascade on delete" option the foreign key constraint to suspend any child record removal but now the procedure is not working.
maybe "raise an exception" can work?
There is no need to delete all the records and re-inserting only the checked ones. That is a brute force approach and it works but it does not capture the real user action.
As an alternative you can just delete/insert the changes. To do that, create an additional page item P124_S_OBJECTIF_OLD and set it to the value P124_S_OBJECTIF with a computation after header (or any pre-rendering processing point after P124_S_OBJECTIF has been initialized). In your pl/sql code use APEX_STRING.SPLIT to process the checkbox values and the MULTISET operator to decide which values have been touched.
Then your pl/sql process code could look like this.
DECLARE
l_objectif_old apex_t_varchar2;
l_objectif_new apex_t_varchar2;
l_objectifs_added apex_t_varchar2;
l_objectifs_removed apex_t_varchar2;
BEGIN
l_objectif_old := apex_string.split(:P124_S_OBJECTIF_OLD,':');
l_objectif_new := apex_string.split(:P124_S_OBJECTIF,':');
l_objectifs_added := l_objectif_new MULTISET EXCEPT l_objectif_old;
l_objectifs_removed := l_objectif_old MULTISET EXCEPT l_objectif_new;
-- add new
FOR i IN 1 .. l_objectifs_added.COUNT LOOP
INSERT INTO s_objectif_operation (id_s_objectif, id_operation)
VALUES (l_objectifs_added(i), :P124_ID_OPERATION);
END LOOP;
-- delete old
FOR i IN 1 .. l_objectifs_removed.COUNT LOOP
BEGIN
DELETE FROM s_objectif_operation
WHERE id = l_objectifs_removed(i);
EXCEPTION WHEN OTHERS THEN
-- this will fire if there are child records. Add your own code.
NULL;
END;
END LOOP;
END;
Note that you might have to tweak the insert and delete statement to match your data structure.

i want to delete the data fetching from the cursor without using for update

I have set of data filtering from the select statement which I need to delete from the table 'SHOP_MATERIAL_ASSIGN_TAB'. I have used a cursor to delete. but this caused problems when executing. any idea to get it done without using 'for update' method.
DECLARE
CURSOR DELDATA_ IS
SELECT B.*
FROM IC_WQ_OLD_LOCATION_TAB A, SHOP_MATERIAL_ASSIGN_TAB B
WHERE A.LOCATION_NO = B.LOCATION_NO
AND A.SITE = B.CONTRACT
AND B.LOCATION_NO = 'HYLIN001'
FOR UPDATE;
TEMP_ DELDATA_%ROWTYPE;
BEGIN
OPEN DELDATA_;
LOOP
FETCH DELDATA_
INTO TEMP_;
EXIT WHEN DELDATA_%NOTFOUND;
DELETE FROM SHOP_MATERIAL_ASSIGN_TAB WHERE CURRENT OF DELDATA_;
END LOOP;
COMMIT;
END;
Don't use PL/SQL at all.
DELETE FROM shop_material_assign_tab
WHERE EXISTS
(SELECT NULL
FROM ic_wq_old_location_tab a
WHERE a.location_no = b.location_no
AND a.site = b.contract)
AND b.location_no = 'HYLIN001'

sql server update Insert statement

i have a stored procedure which first of all checks for some record whether it exists or not. if already exists then executes updates statement (if update statement works fine then returns affected row no else returns a variable with -1000 value) else it selects a variable with value -2000.
Problem is it works fine if i executes it in sql server but when i call it from C# then it returns current_indent('') or only -1 no -1000 or -2000 is returned.
USE [youfuntube]
GO
ALTER PROCEDURE [dbo].[usp_change_pass]
#e_mail varchar(60),
#old_pass varchar(27),
#new_pass varchar(27)
AS
BEGIN
declare #exist int;
Set #exist =0;
Select #exist=COUNT( userinfo_signup.e_mail) from userinfo_signup where userinfo_signup.e_mail=#e_mail;
if(#exist>0)
BEGIN
SET #exist=0;
SELECT #exist= COUNT ( userinfo_signup.e_mail) from userinfo_signup Where userinfo_signup.e_mail=#e_mail And userinfo_signup.password=#old_pass;
if(#exist>0)
Begin
UPDATE userinfo_signup
Set password=#new_pass
Where e_mail=#e_mail AND password=#old_pass;
Select IDENT_CURRENT( 'userinfo_signup');
End
ELSE
begin
Set #exist=-1000;
SELECT #exist;
end
END
ELSE
BEGIN
SET #exist=-2000;
Select #exist;
END
END
GO
I would try using the MERGE command instead of an if exists. Here is a simple introduction to the command: http://blog.sqlauthority.com/2008/08/28/sql-server-2008-introduction-to-merge-statement-one-statement-for-insert-update-delete/

PL/SQL Static cursor variable as ref cursor

I have a procedure that takes a SYS_REFCURSOR and converts it to JSON.
In a procedure that calls the above, I'm trying define a CURSOR as normal and supply that as a REF CURSOR.
I'm receiving PLS-00361.
I understand that I can use the OPEN FOR construct, but I need to use my Cursor elsewhere and don't like the duplication.
Any advice?
PROCEDURE LIST_EMPLOYEES
AS
l_ref_cursor SYS_REFCURSOR;
CURSOR c_emps
IS
SELECT email_address
FROM employees;
BEGIN
OPEN c_emps;
FETCH c_emps INTO l_ref_cursor;
json_utils.refcursor_to_json_via_http(l_ref_cursor,
'employees');
CLOSE l_ref_cursor;
EXCEPTION
WHEN others
THEN
log_error;
END LIST_EMPLOYEES;
Regards,
Laurence.
You wouldn't fetch the cursor into the REF CURSOR, you would simply OPEN it:
PROCEDURE LIST_EMPLOYEES AS
l_ref_cursor SYS_REFCURSOR;
BEGIN
OPEN l_ref_cursor FOR SELECT email_address FROM employees;
json_utils.refcursor_to_json_via_http(l_ref_cursor, 'employees');
CLOSE l_ref_cursor;
END LIST_EMPLOYEES;

Switch user in pl/sql code block in sqlplus sessions

I have a pl/sql script that I run from a sqlplus session as 'sysdba' .
During the execution of the script I would like to switch to another user so I can do some db link creation for that user. After this is done the script should return to 'sysdba' for some finishing up.
I tried to use the following:
BEGIN
<do some stuff as sysdba>
execute immediate 'connect ' || in_owner || '/' || v_password;
<create db link for user>
<switch back to sysdba>
END;
However it seems that 'connect' is a command that can not be run with 'execute immediate'.
Any idea how to accomplish this ?
Thanks!
I'm not aware of how you'd do this in Orcle but the simple solution is to put it in your SQL script rather than a PL/SQL block.
BEGIN
<do some stuff as sysdba>
END;
connect scott/tiger;
<create db link for user>
<switch back to sysdba>
BEGIN
<do other stuff>
END;
EDIT:
Based on your comment below I have another solution for you.
Still use an SQL script with some PLSQL rather than a pure PLSQL script.
This time, dynamically generate an SQL script to create the links then run it.
The complication may be on how to figure out the password for each user.
BEGIN
<do some stuff as sysdba>
END;
set serverout on;
spool create_links.sql
BEGIN
for <loop over each user> loop
dbms_output.put_line('connect ' || user || '/' || pass ';');
dbms_output.put_line('<create db link for user>;');
end loop;
END;
spool off;
##create_links.sql;
<switch back to sysdba>
BEGIN
<do other stuff>
END;
Finally, if this doesn't work, you can write a procedure that dynamically creates the trigger using "AUTHID CURRENT_USER". This makes a procedure run as the caller rather than the owner. See here for how to use the AUTHID keyword when defining procedures.
Could you change to a different schema before creating the dblink?
ALTER SESSION SET CURRENT_SCHEMA = in_owner;
<create db link for user>
ALTER SESSION SET CURRENT_SCHEMA = 'sysdba';

Resources