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

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.

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 permissions are needed for PLSQL execute immediate drop index

I have a standard DB procedure to drop indexes on a table (code below) created in user1 schema. When run as user2 the "execute immediate 'drop index" fails with ORA-01418: specified index does not exist.
I don't understand how the index can be returned by the cursor, but not exist when the drop command is run.
Can someone help explain the privs user2 needs on the user1 table/indexes and what AUTHID should be used?
create or replace procedure dropIndexes(pTableName IN VARCHAR2) AUTHID
CURRENT_USER IS
CURSOR c1(pTableName VARCHAR2) IS
select index_name
from all_indexes
where table_name = pTableName;
BEGIN
FOR c1Rec IN c1(pTableName) LOOP
execute immediate 'drop index user1.'||c1Rec.index_name;
END LOOP;
END dropIndexes;
I wonder why not construct the SQL using the owner field of all_indexes. Better yet, push user1 into the query so we only get the index names that belong to user1.

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
#

plsq collection type definition

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.

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