plsq collection type definition - plsql

I was trying to do insert based on the instruction provided in this site.
I can run this example
CREATE OR REPLACE PROCEDURE test_proc (p_array_size IN PLS_INTEGER DEFAULT 100)
IS
TYPE ARRAY IS TABLE OF all_objects%ROWTYPE;
l_data ARRAY;
CURSOR c IS SELECT * FROM all_objects;
BEGIN
OPEN c;
LOOP
FETCH c BULK COLLECT INTO l_data LIMIT p_array_size;
FORALL i IN 1..l_data.COUNT
INSERT INTO t1 VALUES l_data(i);
EXIT WHEN c%NOTFOUND;
END LOOP;
CLOSE c;
END test_proc;
/
Similarly, I have changed the table name for real use as below.
CREATE OR REPLACE PROCEDURE test_proc (p_array_size IN PLS_INTEGER DEFAULT 100)
IS
TYPE ARRAY IS TABLE OF web.salesline%ROWTYPE;
l_data ARRAY;
CURSOR c IS SELECT * FROM web.salesline;
BEGIN
OPEN c;
LOOP
FETCH c BULK COLLECT INTO l_data LIMIT p_array_size;
FORALL i IN 1..l_data.COUNT
INSERT INTO t2 VALUES l_data(i);
EXIT WHEN c%NOTFOUND;
END LOOP;
CLOSE c;
END test_proc;
/
But I'm getting following error, even though the table exists and accessing from the schema I was running.
SQL> show errors
Errors for PROCEDURE :
LINE/COL ERROR
-------- -----------------------------------------------------------------
6/4 PL/SQL: Item ignored
6/34 PLS-00201: identifier 'WEB.SALESLINE' must be declared
11/7 PL/SQL: SQL Statement ignored
16/9 PL/SQL: ORA-00942: table or view does not exist
20/5 PL/SQL: SQL Statement ignored
20/40 PLS-00597: expression 'OBJECTTABLE$' in the INTO list is of wrong
type
23/5 PL/SQL: SQL Statement ignored
23/27 PL/SQL: ORA-00904: : invalid identifier

Unless the procedure is created in the web schema, you are referring to another schema's table, and so that schema needs to give you direct permission to use it. Note that there are no roles in stored procedure.
As the WEB user:
grant select on salesline to devuser;
(or whatever schema the procedure resides in).
Typically we try to avoid hardcoding schema names and instead manage these references using synonyms, so as DEVUSER:
create or replace synonym salesline for web.salesline;
Roles come back into play if you define the procedure authid current_user (the default is authid definer), however this is generally not a good idea for procedures that perform DML.

Related

How to correctly make a procedure in Pl/SQL in which I create a TABLE and use a CURSOR

The assignment I am trying to do is
"Create a procedure that places the names of all presidents who were born in one specific
state, in a temporary table. Display the contents of this table."
The procedure complies but when I try to invoke it, it gives me:
00000 - "table or view does not exist"
Error(8,5): PLS-00103: Encountered the symbol "CREATE" when expecting one of the following: begin function pragma procedure subtype type current cursor delete exists prior
I have been stuck for a while now. Does anybody know what I am doing wrong?
My code so far is:
CREATE OR REPLACE PROCEDURE stateofpresident(p_state president.state_born%TYPE)
AS
CURSOR c_state IS
SELECT *
FROM president;
BEGIN
execute immediate 'CREATE TABLE presidentFromState;
(
president_name VARCHAR2
)';
FOR r_state IN c_state LOOP
IF(p_state = r_state.state_born) THEN
execute immediate 'INSERT INTO presidentFromState VALUES(r_state.pres_name)';
commit;
END IF;
END LOOP;
execute immediate 'DROP TABLE presidentFromState';
END stateofpresident;
/
SET SERVEROUT ON
BEGIN
stateofpresident('VIRGINIA');
END;
/
SELECT *
FROM presidentFromState;
The immediate cause of your error is the semi-colon (;) at "presidentFromState;" At run fhat terminates the statement and the SQL interpreter at that point does not know what is want, the create syntax is invalid. The statement compiles because at compile time it is a properly formatted string. That is why dynamic SQL should be avoid if at all possible. Your script also has an additional error. Your last select will fail as the table presidentFromState ws not only created but also dropped in the procedure. Finally, just an FYI, the entire FOR cursor and the cursor itself is entirely unnecessary, the entire operation can be completed is one statement: Look into the structure
Insert into table_name(columns)
Select columns ...
Since this obviously an assignment or tutorial I'll leave the exact for your research.

What does "ORA-24344: success with compilation" error mean?

I am very new to pl/sql blocks.
When I run the below code it shows:
ORA-24344: success with compilation error
After executing the code it shows nothing as output
--Program definition: Create a procedure which will display the employees
--in descending order of employee name of the computer department
create or replace procedure proc_1(this_name in varchar2(50)) as
begin
loop
select name from enployee2 order by name desc;
commit;
select name into this_name;
end loop;
end;
variable k varchar2(50)
execute proc_1(:k);
Ok You've got lots going on here:
1> create or replace procedure proc_1(this_name in varchar2(50)) as
2> begin
3> loop
4> select name from enployee2 order by name desc;
5> commit;
6> select name into this_name;
7> end loop;
8> end;
On line 1 of your procedure you declare this_name as an IN parameter of type varchar2(50). However with procedure specs you don't specify the size of the parameters. so you can drop the (50) from the spec.
On line 4 you have select statement with no INTO clauses.
On line 5 you have a commit, but you haven't done any work in the procedure that warrants a commit;
On line 6 you attempt to select name into this_name, but your query has no from clause. In Oracle SQL a SELECT without a FROM is not accepted.
On line 6 your INTO clause attempts to store a value in the this_name parameter, but that was declared as an IN parameter not an OUT or IN OUT parameter.
On lines 3 and 7 you open and close a loop, but you have no exit condition so the loop is infinite.

Do I need to commit inside a subprogram that is called by an autonomous transaction procedure?

If I have a procedure that is AUTONOMOUS_TRANSACTION that does an insert and then it calls a procedure with an insert, does the second procedure need a commit, or will the procedure with the AUTONOMOUS_TRANSACTION handle the commit?
The answer is NO. The "second" procedure - invoked by the first - does not have to include a COMMIT statement. When you add this statement to the declaration section of a procedure or function...
PRAGMA AUTONOMOUS_TRANSACTION;
the following rule then applies:
Before the subprogram can be closed and control passed back to the
calling block, any DML changes made within that subprogram must be
committed or rolled back.
If there are any unsaved changes, the PL/SQL engine will raise the ORA-06519 exception, as shown below:
CREATE OR REPLACE FUNCTION nothing RETURN INTEGER
IS
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
UPDATE employees SET last_name = 'abc';
RETURN 1;
END;
/
BEGIN
DBMS_OUTPUT.put_line (nothing);
END;
/
ORA-06519: active autonomous transaction detected and rolled back
ORA-06512: at "STEVEN.NOTHING", line 10
ORA-06512: at line 2
OK, so that's the basic idea. Now let's move on the specific question. What if an autonomous transaction procedure calls another procedure, which does not include the pragma shown above but does execute a DML statement and does not commit? Will we see an ORA-06519 error? The code below shows that we will not.
CREATE TABLE me_and_my_lovelies (name VARCHAR2 (100));
BEGIN
INSERT INTO me_and_my_lovelies VALUES ('Grandpa Steven');
INSERT INTO me_and_my_lovelies VALUES ('Loey');
INSERT INTO me_and_my_lovelies VALUES ('Juna');
COMMIT;
END;
/
CREATE OR REPLACE PROCEDURE not_auton_no_commit
AUTHID DEFINER
IS
BEGIN
UPDATE me_and_my_lovelies
SET name = UPPER (name);
END not_auton_no_commit;
/
CREATE OR REPLACE PROCEDURE auton_commit
AUTHID DEFINER
IS
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
not_auton_no_commit ();
COMMIT;
END auton_commit;
/
BEGIN
auton_commit;
END;
/
SELECT COUNT(*) low_name
FROM me_and_my_lovelies
WHERE name <> UPPER (name)
/
LOW_NAME
--------
0
No error is raised. All rows have been updated. So let's go back to the rule:
Before the subprogram can be closed and control passed back to the calling block, any DML changes made within that subprogram must be committed or rolled back.
You might be thinking: But the UPDATE statement (the "DML change") was not made "within" auton_commit. Yes and no. Yes, the UPDATE statement is not part of the text of auton_commit. But the UPDATE statement was executed within the scope of auton_commit. And that's what counts. Any code executed by auton_commit, either "directly" in its executable section or "indirectly" by invoking another subprogram, is part of the autonomous transaction.
The only point at which the rule is applied is when PL/SQL attempts to close auton_commit and return control to the outer block.
LiveSQL script containing the above code here.
More information about autonomous transactions here.
Note: this Q&A was taken from by blog. Full post here.

Can a with return cursor in DB2 be parameterized?

Below is my code
CREATE OR REPLACE PROCEDURE ds_grp_heatmap_product_test ()
SPECIFIC ds_grp_heatmap_product_test
LANGUAGE SQL
MODIFIES SQL DATA
DYNAMIC RESULT SETS 1
BEGIN
DECLARE c_hm_report(v_sal INTEGER)
CURSOR WITH RETURN FOR
select *
from emp where salary<v_sal;
open c_hm_report(2000);
END;
This code is giving compilation error any idea what i am doing wrong.
Your code is SQLPL (as distinct from PLSQL). Depending on your Db2 server version and configuration you can also write PLSQL (Oracle compatibility mode of Db2). You are getting compilation errors because the above syntax is not valid for SQLPL.
The code below might be what you seek: the parameter in this case is supplied as an input to the stored procedure, adjust the type as necessary, or you can set the variable v_sal via other means:
--#SET TERMINATOR #
CREATE OR REPLACE PROCEDURE ds_grp_heatmap_product_test (in v_sal integer)
SPECIFIC ds_grp_heatmap_product_test
LANGUAGE SQL
MODIFIES SQL DATA
DYNAMIC RESULT SETS 1
BEGIN
DECLARE c1 CURSOR WITH RETURN FOR
select *
from emp where salary < v_sal;
open c1;
END
#

bind variable substitution in oracle

The below simple procedure is suppose to provide grants to the user scott in oracle.
The value for &scott_SCHEMA is already defined in a seperate file(define_variable.sql) and the value is getting substituted correctly, but im getting the error(as specified in the bottom of the script), a help is much appreciated.
SET SERVEROUTPUT ON
declare
l_sql varchar2(3200);
begin
for i in ( select table_name as oname,'TABLE' as type from all_tables where owner='HR' AND table_name not like 'BIN$%' union all select view_name as oname,'VIEW' as type from all_views where owner='HR' and view_name not like 'BIN$%' )
loop
if i.type = 'TABLE' then
dbms_output.put_line(l_sql);
l_sql:= 'grant select,insert,update,delete on hr.'||i.oname||' to :owner with grant option';
execute immediate l_sql using '&scott_SCHEMA';
else
l_sql:= 'grant select on hr.'||i.oname||' to :owner with grant option';
end if;
end loop;
end;
/
*declare
*
ERROR at line 1:
ORA-00987: missing or invalid username(s)
ORA-06512: at line 12*
You can't use bind variables in place of identifiers (specifically schema or object names) in DDL or DML statements, they can only be used in place of value expressions.
Since you're using substitution variables, you could just place it in the sql statement itself:
l_sql:= 'grant select,insert,update,delete on hr.'||i.oname||' to &scott_SCHEMA with grant option';
and execute it with out passing it as a parameter:
execute immediate l_sql;
On a side note, your DBMS_OUTPUT line should come after you assignment to l_sql, otherwise you'll miss outputting one or more of the statements being processed. A good place would be between the assignment statement and the execute statement.

Resources