I am trying to take two comma separated strings and split them into two separate tables to use later for comparison reasons. Below is as close as I have gotten to this point. Both strings are being put into the same table, which honestly would work in the case I need it for, but it is a very clunky solution.
I tried to change the name of the table from 'TEST' to something else in the second loop, but I always got a compile error. Does someone know a more elegant solution?
DECLARE
L_INPUT_LOG VARCHAR2(25) := 'Error,Audit';
L_INPUT_MOD VARCHAR(4000) := 'MODULE1,MODULE2';
L_COUNT BINARY_INTEGER;
LOG_TYPE_ARRAY DBMS_UTILITY.LNAME_ARRAY;
APP_MODULE_ARRAY DBMS_UTILITY.LNAME_ARRAY;
BEGIN
DBMS_UTILITY.COMMA_TO_TABLE(LIST => REGEXP_REPLACE(L_INPUT_LOG, '(^|,)', '\1x'), TABLEN => L_COUNT, TAB => LOG_TYPE_ARRAY);
DBMS_UTILITY.COMMA_TO_TABLE(LIST => REGEXP_REPLACE(L_INPUT_MOD, '(^|,)', '\1x'), TABLEN => L_COUNT, TAB => APP_MODULE_ARRAY);
FOR I IN 1 .. L_COUNT
LOOP
INSERT INTO TEST VALUES
(SUBSTR(LOG_TYPE_ARRAY(I), 2) );
COMMIT;
END LOOP;
FOR I IN 1 .. L_COUNT
LOOP
INSERT INTO TEST VALUES
(SUBSTR(APP_MODULE_ARRAY(I), 2) );
COMMIT;
END LOOP;
END;
UPDATE: Below is the error that I am getting when I try to change the table TEST in the second loop. Asked for by MaxU
Error starting at line : 1 in command -
DECLARE
L_INPUT_LOG VARCHAR2(25) := 'Error,Audit';
L_INPUT_MOD VARCHAR(4000) := 'MODULE1,MODULE2';
L_COUNT BINARY_INTEGER;
LOG_TYPE_ARRAY DBMS_UTILITY.LNAME_ARRAY;
APP_MODULE_ARRAY DBMS_UTILITY.LNAME_ARRAY;
BEGIN
DBMS_UTILITY.COMMA_TO_TABLE(LIST => REGEXP_REPLACE(L_INPUT_LOG, '(^|,)', '\1x'), TABLEN => L_COUNT, TAB => LOG_TYPE_ARRAY);
DBMS_UTILITY.COMMA_TO_TABLE(LIST => REGEXP_REPLACE(L_INPUT_MOD, '(^|,)', '\1x'), TABLEN => L_COUNT, TAB => APP_MODULE_ARRAY);
FOR I IN 1 .. L_COUNT
LOOP
INSERT INTO TEST VALUES
(SUBSTR(LOG_TYPE_ARRAY(I), 2) );
COMMIT;
END LOOP;
FOR I IN 1 .. L_COUNT
LOOP
INSERT INTO GRIM VALUES
(SUBSTR(APP_MODULE_ARRAY(I), 2) );
COMMIT;
END LOOP;
END;
Error report -
ORA-06550: line 18, column 18:
PL/SQL: ORA-00942: table or view does not exist
ORA-06550: line 18, column 6:
PL/SQL: SQL Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
There can be multiple reasons for which the issue can arise.
1) If the 'TEST' table created in the same schema from where you
executing the script?
If NO Try providing schema_name.TEST and if you are relying on ROLES
for GRANT here it wont work. So you need to provide the DIRECT OBJECT
level GRANTS to access the table.
Try GRANT SELECT,insert,update,delete ON SCHEMA.TEST TO <USER>;
Hope this helps.
Related
I'm trying to create reschedule procedure for AQ queues. So i have created procedure with one IN parameter where our operator will enter just a name of queue, and i hit error when i execute create of procedure
CREATE OR REPLACE PROCEDURE RESCHEDULE1 (p_queue IN VARCHAR2)
AS
BEGIN
SYS.DBMS_AQADM.STOP_QUEUE (p_queue);
END;
DECLARE
CURSOR upit
IS
SELECT destination
FROM USER_QUEUE_SCHEDULES
WHERE qname = p_queue;
BEGIN
FOR dest_rec IN upit
LOOP
DBMS_AQADM.UNSCHEDULE_PROPAGATION (queue_name => p_queue,
destination => dest_rec.destination);
DBMS_AQADM.SCHEDULE_PROPAGATION (queue_name => p_queue,
destination => dest_rec.destination,
start_time => SYSDATE);
END LOOP;
END;
;
BEGIN
SYS.DBMS_AQADM.START_QUEUE (p_queue);
END;
/
Error is
ORA-06550: line 7, column 39:
PL/SQL: ORA-00904: "P_QUEUE": invalid identifier
ORA-06550: line 5, column 4:
PL/SQL: SQL Statement ignored
ORA-06550: line 14, column 54:
PLS-00201: identifier 'P_QUEUE' must be declared
ORA-06550: line 14, column 2:
PL/SQL: Statement ignored
ORA-06550: line 17, column 52:
PLS-00201: identifier 'P_QUEUE' must be declared
ORA-06550: line 17, column 2:
PL/SQL: Statement ignored
p_queue is out of scope everywhere, except in RESCHEDULE1 procedure. You have to pass its value, somehow.
One option is this: instead of using an anonymous PL/SQL blocks, switch to procedures (and - of course - declare the p_queue parameter).
I think your procedure has improper use of BEGIN..END and DECLARE
Try following code:
CREATE OR REPLACE PROCEDURE RESCHEDULE1 (p_queue IN VARCHAR2)
AS
-- all declarations should go here
CURSOR upit
IS
SELECT destination
FROM USER_QUEUE_SCHEDULES
WHERE qname = p_queue;
BEGIN -- starting of procedure
BEGIN -- starting of this block -- can be removed
SYS.DBMS_AQADM.STOP_QUEUE (p_queue);
END; -- ending of this block -- can be removed
FOR dest_rec IN upit -- loop started from here
LOOP
DBMS_AQADM.UNSCHEDULE_PROPAGATION (queue_name => p_queue,
destination => dest_rec.destination);
DBMS_AQADM.SCHEDULE_PROPAGATION (queue_name => p_queue,
destination => dest_rec.destination,
start_time => SYSDATE);
END LOOP; -- loop ends here
BEGIN -- starting of this block -- can be removed
SYS.DBMS_AQADM.START_QUEUE (p_queue);
END; -- ending of this block -- can be removed
END RESCHEDULE1; -- end of procedure
/
Note: You can remove unnecessary BEGIN and END from code if you dont want to handle exceptions.
I have kept all BEGIN and END in procedure as it is, considering tht you actually need it for future development.
Cheers!!
Please sorry i didnt post that i have found answer, problem was with bad begin and end. Now this works
CREATE OR REPLACE PROCEDURE AQADMIN.RESCHEDULE1 (p_queue in varchar2)
is
begin
begin
DBMS_AQADM.STOP_QUEUE(p_queue);
end;
declare
cursor upit
is
SELECT destination
FROM USER_QUEUE_SCHEDULES
WHERE qname = p_queue ;
begin
for dest_rec in upit
loop
DBMS_AQADM.UNSCHEDULE_PROPAGATION (queue_name => p_queue,
destination => dest_rec.destination);
DBMS_AQADM.SCHEDULE_PROPAGATION (queue_name => p_queue,
destination => dest_rec.destination,
start_time => SYSDATE);
end loop;
end;
begin
DBMS_AQADM.START_QUEUE (p_queue);
end;
end;
/
Thank you for all your help!
First, I have read the PL/SQL documentation repeatedly, no help. Second, I have googled for hours (usually being led here) and still cannot figure this out.
I have created an index table, which seems to have been successful - at least it did not throw any errors...
DECLARE
CURSOR cur_emps IS
SELECT employee_id, last_name, job_id, salary FROM employees ORDER BY employee_id;
TYPE t_emp_rec IS TABLE OF cur_emps%ROWTYPE
INDEX BY BINARY_INTEGER;
v_emp_rec_tab t_emp_rec;
BEGIN
FOR emp_rec IN cur_emps LOOP
v_emp_rec_tab(emp_rec.employee_id) := emp_rec;
END LOOP;
However, when I try to show what is in my index table. I fail...
Documentation says do something like this...
DECLARE
CURSOR cur_emps IS
SELECT employee_id, last_name, job_id, salary FROM employees ORDER BY employee_id;
TYPE t_emp_rec IS TABLE OF cur_emps%ROWTYPE
INDEX BY BINARY_INTEGER;
v_emp_rec_tab t_emp_rec;
BEGIN
FOR emp_rec IN cur_emps LOOP
v_emp_rec_tab(emp_rec.employee_id) := emp_rec;
END LOOP;
FOR i IN v_emp_rec_tab.FIRST..v_emp_rec_tab.LAST LOOP
IF v_emp_rec_tab.EXISTS(i)
THEN DBMS_OUTPUT.PUT_LINE(v_emp_rec_tab(i));
END IF;
END LOOP;
END;
... which gives me this...
ORA-06550: line 13, column 12:
PLS-00306: wrong number or types of arguments in call to 'PUT_LINE'
ORA-06550: line 13, column 12:
PL/SQL: Statement ignored
In place of
THEN DBMS_OUTPUT.PUT_LINE(v_emp_rec_tab(i));
. I have tried
emp_rec.last_name, v_emp_rec.last_name, cur_emps.last name
... it has been days now trying, can anyone help?
Thanks.
Daniel
You should iterate over an indexed table like this:
l_idx := v_emp_rec_tab.first;
while (l_idx is not null) loop
dbms_output.put_line( v_emp_rec_tab(l_idx).last_name );
l_idx := v_emp_rec_tab.next(l_idx);
end loop;
Otherwise you will get an exception when your table indexes are not consecutive.
See here
v_emp_rec_tab is of rowtype, and it's not possible to call as
DBMS_OUTPUT.PUT_LINE(v_emp_rec_tab(i));
but you can call as :
DBMS_OUTPUT.PUT_LINE(v_emp_rec_tab(i).last_name);
with only one column or you might concatenate like :
DBMS_OUTPUT.PUT_LINE(v_emp_rec_tab(i).last_name||' '||v_emp_rec_tab(i).employee_id);
for multiple columns.
I have a stored procedure and I need to call it several times with different sets of input. It looks like a script could do the job. How to generate the script? Ask Oracle SQL Developer (Version 4.2.0.17.089)! , So I bring up the following:
(By the way, what is this window called? And can this be accessible from menu bar?)
I select the right stored procedure, specify the correct parameter and click 'Save File'. Here is the saved SQL file:
DECLARE
I_MENU VARCHAR2(200);
ERRMSG VARCHAR2(200);
P_RETURNCUR SYS_REFCURSOR;
BEGIN
I_MENU := '4';
CMS_ACCESS_CONTROL.GETCMSMENUITEMINFO(
I_MENU => I_MENU,
ERRMSG => ERRMSG,
P_RETURNCUR => P_RETURNCUR
);
/* Legacy output:
DBMS_OUTPUT.PUT_LINE('ERRMSG = ' || ERRMSG);
*/
:ERRMSG := ERRMSG;
/* Legacy output:
DBMS_OUTPUT.PUT_LINE('P_RETURNCUR = ' || P_RETURNCUR);
*/
:P_RETURNCUR := P_RETURNCUR; --<-- Cursor
--rollback;
END;
I want to copy and paste the lines between BEGIN and END several times. Each time specify its set of input parameters (different I_MENU). But before doing so, I try to execute the file in SQL Developer. I have not made any modification but get this error:
Error report -
ORA-06550: Line 20, column 22
PLS-00382: expression is of wrong type
ORA-06550: Line 20, column 4
PL/SQL: Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
Questions: 1) Why do I get this error? 2) How to call same stored procedure multiple times with different set of parameters? I want a script to do so as I have to pass the script to another person to execute.
Here is the stored procedure (there is absolutely no / after end getCMSMenuItemInfo)
Procedure getCMSMenuItemInfo(
i_menu in varchar2,
ERRMSG out varchar2,
P_RETURNCUR out SYS_REFCURSOR)
as
begin
open P_RETURNCUR for
SELECT menu_item, menu_url
FROM someMenu
WHERE menuID = i_menu;
end getCMSMenuItemInfo;
Using :ERRMSG and :P_RETURNCUR leading to your error. You're trying to assign value to variable with syntax :variable_a := variable_b which is not allowed in query worksheet. Uncomment legacy output DBMS_OUTPUT.PUT_LINE(); to testing your procedure.
Looking for another answer.
I am giving this solution based on a assumption that you have certain criteria of selecting different menuid's which you will be passing to your procedure "CMS_ACCESS_CONTROL.GETCMSMENUITEMINFO". I will tell you my approach both theoretically and will provide you the code as well.
Solution:
Theoretical Approach:
You can store your menuid's in a different table and loop over that table while calling the procedure. Now you have to decide how many and what different values you want to pass to your procedure.
Sampe Code:
create table store_id
(
id number
);
insert into store_id select distinct menuID from someMenu;
You can insert the different menuid's based on your business requirement.
DECLARE
I_MENU VARCHAR2(200);
ERRMSG VARCHAR2(200);
P_RETURNCUR SYS_REFCURSOR;
BEGIN
for i in (select id from store_id ) loop
I_MENU := i.id;
GETCMSMENUITEMINFO(
I_MENU => I_MENU,
ERRMSG => ERRMSG,
P_RETURNCUR => P_RETURNCUR
);
/* Legacy output:
DBMS_OUTPUT.PUT_LINE('ERRMSG = ' || ERRMSG);
*/
ERRMSG := ERRMSG;
/* Legacy output:
DBMS_OUTPUT.PUT_LINE('P_RETURNCUR = ' || P_RETURNCUR);
*/
P_RETURNCUR := P_RETURNCUR; --<-- Cursor
--rollback;
end loop;
END;
I hope this helps.
my goal is to run a select to a table and based on the certain rows dynamically create an audit trail or policy on them.
so..
create a set_policy function that gets called/Looped:
create or replace
function set_policy
( sch VARCHAR2 ,
tab VARCHAR2,
colm VARCHAR2,
pred VARCHAR2,
emailer VARCHAR2
)
return VARCHAR2 is
policy_sql_stmt varchar2(1000);
BEGIN
policy_sql_stmt :=
'BEGIN
SYS.DBMS_FGA.ADD_POLICY (
object_schema => :s,
object_name => :t,
policy_name => ''CHK_:s_:t'',
audit_column => :c,
audit_condition => :p,
handler_schema => ''SYSADMIN_FGA'',
handler_module => '''||emailer||'(:s,:t,''''CHK_:s_:t'''')'',
enable => TRUE,
statement_types => ''SELECT, UPDATE'',
audit_trail => SYS.DBMS_FGA.DB + SYS.DBMS_FGA.EXTENDED);
END;';
--DBMS_OUTPUT.PUT_LINE('policy_sql_stmt = :' || policy_sql_stmt);
BEGIN
EXECUTE IMMEDIATE policy_sql_stmt USING sch,tab,colm,pred;
--EXECUTE IMMEDIATE policy_sql_stmt USING pred;
EXCEPTION
WHEN OTHERS THEN
BEGIN
--dbms_output.put_line('set_policy error code: '||SQLCODE);
--dbms_output.put_line(DBMS_UTILITY.FORMAT_CALL_STACK);
RETURN ('set_policy error code: '||SQLCODE);
END;
END;
RETURN 'success';
END;
Then a procedure that calls the function...
CREATE OR REPLACE PROCEDURE audit_slac_tables
AS
--DECLARE
emailer VARCHAR2(40):='audit_email_alert';
isSuccess VARCHAR2(40);
CURSOR myCursor
IS
SELECT SCHEMA AS sch,
TABLE_NAME AS tab,
FILTER_COLUMN AS colm,
WHERE_COND AS pred
FROM SLAC_REDACTION_TABLE slac;
--WHERE slac.table_name IN ('RECIPIENT','CARD');
BEGIN
FOR curRec IN myCursor
LOOP
BEGIN
--emailer := getEmailer(curRec.sch ,curRec.tab);
isSuccess := set_policy(curRec.sch ,curRec.tab, curRec.colm, curRec.pred, emailer);
DBMS_OUTPUT.PUT_LINE('Proc isSuccess = :' || isSuccess);
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line('Proc error code: '||SQLCODE);
dbms_output.put_line('Proc error msg: '||SQLERRM);
--dbms_output.put_line(DBMS_UTILITY.FORMAT_CALL_STACK);
--dbms_output.put_line('================================================');
CONTINUE;
END;
--dbms_output.put_line('================================================');
END LOOP;
COMMIT;
END audit_slac_tables;
if I call it...
exec AUDIT_SLAC_TABLES;
I get the following bewildering error
Error starting at line : 6 in command -
exec AUDIT_SLAC_TABLES
Error report -
ORA-06550: line 12, column 18:
PLS-00201: identifier 'SYS.DBMS_FGA' must be declared
ORA-06550: line 2, column 3:
PL/SQL: Statement ignored
ORA-06512: at "GAPLITE.SET_POLICY", line 51
ORA-06512: at "GAPLITE.AUDIT_SLAC_TABLES", line 27
ORA-06512: at line 1
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
Why a reference problem where the script DBMS_FGA.ADD_POLICY never had a problem?
I can run this script ( listed 1st above ) but not dynamically... it loses trhe contextual reference to the SYS packages somehow ??
I am having some trouble with my procedure, I have the code working i think, the procedure runs and asks the user for input, the user enters the data which is stored in variables in the procedure which are then inserted into the table. But when I enter everything I am faced with an error. is it even possible to use an insert in a procedure or should I be going a different route? thanks
My procedure
create or replace PROCEDURE AD_AGENCY_INFO(
v_agency_id IN OUT AD_AGENCY.AGENCY_ID%TYPE,
v_no_of_ad_runs IN OUT AD_AGENCY.NO_OF_AD_RUNS%TYPE,
v_credit_worthy IN OUT AD_AGENCY.CREDIT_WORTHY%TYPE,
v_available_slots IN OUT AD_AGENCY.AVAILABLE_SLOTS%TYPE,
v_status IN OUT AD_AGENCY.STATUS%TYPE
) AS
BEGIN
SELECT AGENCY_ID, NO_OF_AD_RUNS, CREDIT_WORTHY, AVAILABLE_SLOTS, STATUS
INTO
v_agency_id, v_no_of_ad_runs, v_credit_worthy, v_available_slots, v_status
FROM AD_AGENCY;
INSERT INTO AD_AGENCY (AGENCY_ID, NO_OF_AD_RUNS, CREDIT_WORTHY, AVAILABLE_SLOTS, STATUS)
VALUES (AGENCY_ID, NO_OF_AD_RUNS, CREDIT_WORTHY, AVAILABLE_SLOTS, STATUS);
INSERT INTO AD (AGENCY_ID) VALUES (AGENCY_ID);
END AD_AGENCY_INFO;
How I am calling the procedure
DECLARE
V_AGENCY_ID NUMBER:='&Enter_Agency_ID';
V_NO_OF_AD_RUNS NUMBER:='&Enter_No_of_Ad_Runs';
V_CREDIT_WORTHY CHAR(3):='&Enter_Cedit_Worthy';
V_AVAILABLE_SLOTS NUMBER:='&Enter_Available_Slots';
V_STATUS CHAR(1):='&Enter_Status';
BEGIN
V_AGENCY_ID := NULL;
V_NO_OF_AD_RUNS := 0;
V_CREDIT_WORTHY := NULL;
V_AVAILABLE_SLOTS := NULL;
V_STATUS := NULL;
AD_AGENCY_INFO(
V_AGENCY_ID => V_AGENCY_ID,
V_NO_OF_AD_RUNS => V_NO_OF_AD_RUNS,
V_CREDIT_WORTHY => V_CREDIT_WORTHY,
V_AVAILABLE_SLOTS => V_AVAILABLE_SLOTS,
V_STATUS => V_STATUS
);
END;
/
The error report
Error report -
ORA-06550: line 14, column 3:
PLS-00905: object DT2113A.AD_AGENCY_INFO is invalid
ORA-06550: line 14, column 3:
PL/SQL: Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
There are probably some typos here:
INSERT INTO AD_AGENCY (AGENCY_ID, NO_OF_AD_RUNS, CREDIT_WORTHY, AVAILABLE_SLOTS, STATUS)
VALUES (AGENCY_ID, NO_OF_AD_RUNS, CREDIT_WORTHY, AVAILABLE_SLOTS, STATUS);
-- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Values are ... well values, not column names. Maybe were you thinking to:
INSERT INTO AD_AGENCY (AGENCY_ID, NO_OF_AD_RUNS, CREDIT_WORTHY, AVAILABLE_SLOTS, STATUS)
VALUES (v_agency_id, v_no_of_ad_runs, v_credit_worthy, v_available, v_status);
BTW, the rest of the code probably still need some thoughts ;)
For example, that code will not work as soon as you will have more than one row in your table:
SELECT AGENCY_ID, NO_OF_AD_RUNS, CREDIT_WORTHY, AVAILABLE_SLOTS, STATUS
INTO
v_agency_id, v_no_of_ad_runs, v_credit_worthy, v_available_slots, v_status
FROM AD_AGENCY;
Maybe the WHERE clause is missing? And even if so, it will overwrite the IN parameter values. Probably not a thing you want at that point...
I'm not TOO familiar with plsql, but it seems that you are incorrectly calling the procedure from your second block. Try writing:
CALL AD_AGENCY_INFO(
...
);
Or use Exec, I'm not too sure which:
EXEC AD_AGENCY_INFO(
...
);