Switch user in pl/sql code block in sqlplus sessions - plsql

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';

Related

how to call trigger in procedure 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

Error reading a file using UTL_FILE

I am facing some issue in reading a file using utl_file.
The same code is working fine in some of the instances and failing in one instance.
Below is the issue:
Code:
procedure del_mul_tags(p_request_id in number)
is
fileID UTL_FILE.FILE_TYPE;
fileID1 UTL_FILE.FILE_TYPE;
line varchar2(32000);
l_dir varchar2(1000);
l_file varchar2(20);
l_file1 varchar2(20);
l_request_id number;
l_count number := 0;
l_count_t number :=0;
l_write boolean := TRUE;
cursor c_dir is
select substr(OUTFILE_NAME,1,instr(OUTFILE_NAME,'/',-1,1)-1),substr(OUTFILE_NAME,instr(OUTFILE_NAME,'/',-1,1)+1)
from fnd_concurrent_requests
where request_id = p_request_id;
begin
open c_dir;
fetch c_dir into l_dir,l_file;
close c_dir;
execute immediate 'create or replace directory W2_OUT_DIR as ''' || l_dir || '''';
begin
fileID1 := UTL_FILE.FOPEN ('W2_OUT_DIR', l_file, 'R'); -----Getting the error right here!!!-----------
loop
begin
UTL_FILE.GET_LINE (fileID1, line);
--Some Logic
EXCEPTION WHEN NO_DATA_FOUND THEN
UTL_FILE.FCLOSE(fileID1);
EXIT;
end;
end loop;
fileID := UTL_FILE.FOPEN ('W2_OUT_DIR', l_file, 'R');
loop
begin
UTL_FILE.GET_LINE (fileID, line);
--Some Logic
EXCEPTION WHEN NO_DATA_FOUND THEN
UTL_FILE.FCLOSE(fileID);
EXIT;
end;
end loop;
end;
EXCEPTION WHEN OTHERS THEN
fnd_file.put_line(fnd_file.log,'Error while deleting the xml tags: '||SQLERRM);
end;
................
In this instance file, l_file 'ACHAKR01.23067873' was created through another concurrent process. Its OS user is 'appsofde'.
And the unix permissions are as below:
-rw-r--r-- 1 appsofde dba 192092429 jan 27 05:00 ACHAKR01.23067873
The directory W2_OUT_DIR is created and the oracle user apps has EXECUTE,READ,WRITE privileges.
The file exists and the W2_OUT_DIR dir patch is correct.
Exact error coming is:
Error while deleting the xml tags: ORA-29283: invalid file operation
ORA-06512: at "SYS.UTL_FILE", line 536
ORA-29283: invalid file operation
Any thoughts here?
You will want to make sure the filesystem is presented to your Oracle DB host (not just your application server). I'm assuming it is otherwise you would get an invalid directory path error instead. I would suggest you double check however and also ensure the oracle account on the DB host has access to read the file in question. The account appsofde sounds as if its likely the application account.

Getting error PLS-00435: DML statement without BULK In-BIND cannot be used inside FORALL

I am getting
Error(68,3): PLS-00435: DML statement without BULK In-BIND cannot be used inside FORALL.
Please help me out with this.
My code is : -
create or replace PACKAGE BODY FIBRE_TOOLS AS
g_package_name varchar2(30):='FIBRE_TOOLS';
g_proc_name varchar2(30);
..
..
..
procedure prc_purge(p_nb_month IN number default 210) is
reqSelec VARCHAR2(4000);
reqDELDES VARCHAR2(4000);
reqDELINS VARCHAR2(4000);
TYPE Curseur IS REF CURSOR;
c_desinscription Curseur;
TYPE selREC IS RECORD (
EMAIL desinscription.EMAIL%type,
IDRA desinscription.IDRA%type,
D_DATE desinscription.desinscription_date%type
);
TYPE selTABLE IS TABLE OF selREC;
ListeFIB selTABLE;
BEGIN
reqSelec :='select EMAIL,IDRA,desinscription_date from desinscription where desinscription_date < trunc(add_months(sysdate,-'||p_nb_month||'))';
reqDELDES := 'DELETE FROM DESINSCRIPTION WHERE EMAIL=:1 AND IRDA=:2';
reqDELINS := 'DELETE FROM INSCRIPTION WHERE EMAIL=:1 AND IDRA=:2 AND INSCRIPTION_DATE < TRUNC(:3)';
prc_log('Begining of purging procedure');
open c_desinscription for reqSelec;
LOOP
fetch c_desinscription bulk collect into ListeFIB LIMIT 10000;
EXIT WHEN ListeFIB.count = 0;
FORALL i in ListeFIB.first.. ListeFIB.last
EXECUTE IMMEDIATE reqDELDES USING ListeFIB.EMAIL,ListeFIB.IRDA;
EXECUTE IMMEDIATE reqDELINS USING ListeFIB.EMAIL,ListeFIB.IDRA,ListeFIB.D_DATE;
COMMIT;
EXIT WHEN c_desinscription%NOTFOUND;
END LOOP;
close c_desinscription;
COMMIT;
prc_log('Ending of purging procedure');
end prc_purge;
end FIBRE_TOOLS;
I am trying to delete data from two tables based on the two columns getting selected on a criteria I.e. nb_months.
I think problem is with table type and record type. I am confused which way it can be done. As per my knowledge record type shall be used with FORALL. kindly help me on this, as it is very critical.
You're using a DML statement with a FORALL but without binding the collection used - Oracle doesn't allow for that.
Replace execute immediates with the binded collection, should work
EXECUTE IMMEDIATE reqDELDES USING ListeFIB(i).EMAIL,ListeFIB(i).IRDA;
EXECUTE IMMEDIATE reqDELINS USING ListeFIB(i).EMAIL,ListeFIB(i).IDRA,ListeFIB(i).D_DATE;
See more examples in these articles:
Oracle Magazine
Oracle Documentation

ORA-00905: missing keyword in SQL PLus

I am getting an ORA-00905: missing keyword error when running in the following procedure using the SQLPLUS command line. Strangely it compiles and works when I run it in via an SQL window in PL/SQL developer, unfortunately I need it to work via the command line as well:
CREATE OR REPLACE PROCEDURE PRO_INSERT_ALERT_END_DATE IS
CURSOR cur_InsertEndDate IS
SELECT cli_per_id,
date_ended,
date_started,
alertid
FROM CP_END_ALERT;
BEGIN
FOR rec_cur_InsertEndDate IN cur_InsertEndDate
LOOP
BEGIN
UPDATE vwe_alert_table
SET alert_inactive_on = rec_cur_InsertEndDate.date_ended,
alert_inac_reason = 'Deregistered'
WHERE vwe_alert_table.art_id = rec_cur_InsertEndDate.alertid AND
vwe_alert_table.art_per_id = rec_cur_InsertEndDate.cli_per_id AND
vwe_alert_table.art_alerted_on = rec_cur_InsertEndDate.date_started AND
vwe_alert_table.art_alert = 'AL02';
COMMIT;
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line('Error updating record ' || SUBSTR(SQLERRM, 1, 250));
ROLLBACK;
END;
END LOOP;
END PRO_INSERT_ALERT_END_DATE;
Any advice would be most welcome
It is probably due to the blank lines in the script. Tell SqlPlus to ignore them
set sqlblanklines on

DBMS_OUTPUT.PUT_LINE not printing

When executing the following code, it just says the procedure is completed and doesn't print the infomation i want it to (firstName, lastName) and then the other values from the select query in a table below.
CREATE OR REPLACE PROCEDURE PRINT_ACTOR_QUOTES (id_actor char)
AS
CURSOR quote_recs IS
SELECT a.firstName,a.lastName, m.title, m.year, r.roleName ,q.quotechar from quote q, role r,
rolequote rq, actor a, movie m
where
rq.quoteID = q.quoteID
AND
rq.roleID = r.roleID
AND
r.actorID = a.actorID
AND
r.movieID = m.movieID
AND
a.actorID = id_actor;
BEGIN
FOR row IN quote_recs LOOP
DBMS_OUTPUT.PUT_LINE('a.firstName' || 'a.lastName');
end loop;
END PRINT_ACTOR_QUOTES;
/
When setting server output on, I get
a.firstNamea.lastName
a.firstNamea.lastName
a.firstNamea.lastName
a.firstNamea.lastName
multiple times!
What is "it" in the statement "it just says the procedure is completed"?
By default, most tools do not configure a buffer for dbms_output to write to and do not attempt to read from that buffer after code executes. Most tools, on the other hand, have the ability to do so. In SQL*Plus, you'd need to use the command set serveroutput on [size N|unlimited]. So you'd do something like
SQL> set serveroutput on size 30000;
SQL> exec print_actor_quotes( <<some value>> );
In SQL Developer, you'd go to View | DBMS Output to enable the DBMS Output window, then push the green plus icon to enable DBMS Output for a particular session.
Additionally, assuming that you don't want to print the literal "a.firstNamea.lastName" for every row, you probably want
FOR row IN quote_recs
LOOP
DBMS_OUTPUT.PUT_LINE( row.firstName || ' ' || row.lastName );
END LOOP;
Ensure that you have your Dbms Output window open through the view option in the menubar.
Click on the green '+' sign and add your database name.
Write 'DBMS_OUTPUT.ENABLE;' within your procedure as the first line.
Hope this solves your problem.
Set Query as below at first line
SET SERVEROUTPUT ON
this statement
DBMS_OUTPUT.PUT_LINE('a.firstName' || 'a.lastName');
means to print the string as it is.. remove the quotes to get the values to be printed.So the correct syntax is
DBMS_OUTPUT.PUT_LINE(a.firstName || a.lastName);
For SQL Developer
You have to execute it manually
SET SERVEROUTPUT ON
After that if you execute any procedure with DBMS_OUTPUT.PUT_LINE('info'); or directly .
This will print the line
And please don't try to add this
SET SERVEROUTPUT ON
inside the definition of function and procedure, it will not compile and will not work.
In Oracle SQL Developer, you can follow steps by steps as the below image:
I am using Oracle SQL Developer,
In this tool, I had to enable DBMS output to view the results printed by dbms_output.put_line
You can find this option in the result pane where other query results are displayed.
so, in the result pane, I have 7 tabs. 1st tab named as Results, next one is Script Output and so on. Out of this you can find a tab named as "DBMS Output" select this tab, then the 1st icon (looks like a dialogue icon) is Enable DBMS Output. Click this icon. Then you execute the PL/SQL, then select "DBMS Output tab, you should be able to see the results there.
All of them are concentrating on the for loop but if we use a normal loop then we had to use of the cursor record variable. The following is the modified code
CREATE OR REPLACE PROCEDURE PRINT_ACTOR_QUOTES (id_actor char)
AS
CURSOR quote_recs IS
SELECT a.firstName,a.lastName, m.title, m.year, r.roleName ,q.quotechar from quote q, role r,
rolequote rq, actor a, movie m
where
rq.quoteID = q.quoteID
AND
rq.roleID = r.roleID
AND
r.actorID = a.actorID
AND
r.movieID = m.movieID
AND
a.actorID = id_actor;
recd quote_recs%rowtype;
BEGIN
open quote_recs;
LOOP
fetch quote_recs into recs;
exit when quote_recs%notfound;
DBMS_OUTPUT.PUT_LINE(recd.firstName||recd.lastName);
end loop;
close quote_recs;
END PRINT_ACTOR_QUOTES;
/

Resources