create procedure keyword won't work - plsql

if i write procedure creating code like this
declare
salary number :=20000;
employee_id number :=36325;
procedure give_bonus(emp_id in number,bonus in number) is
begin
dbms_output.put_line(emp_id);
dbms_output.put_line(bonus);
end;
begin
case
when salary >=10000 and salary <=20000 then
give_bonus(employee_id,1500);
when salary >= 20000 and salary <=40000 then
give_bonus(employee_id,1000);
when salary>40000 then
give_bonus(employee_id,500);
else
give_bonus(employee_id,0);
end case ;
end;
it writes on output
anonymous block completed
but if i write a head of procedure word this one
create or replace procedure give_bonus ,it writes errors,please help me why?
error is this
Error starting at line 1 in command:
declare
salary number :=20000;
employee_id number :=36325;
create or replace procedure give_bonus(emp_id in number,bonus in number) is
begin
dbms_output.put_line(emp_id);
dbms_output.put_line(bonus);
end;
begin
case
when salary >=10000 and salary <=20000 then
give_bonus(employee_id,1500);
when salary >= 20000 and salary <=40000 then
give_bonus(employee_id,1000);
when salary>40000 then
give_bonus(employee_id,500);
else
give_bonus(employee_id,0);
end case ;
end;
Error report:
ORA-06550: line 4, column 3:
PLS-00103: Encountered the symbol "CREATE" when expecting one of the following:
begin function pragma procedure subtype type <an identifier>
<a double-quoted delimited-identifier> current cursor delete
exists prior
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:

CREATE OR REPLACE only works for top-level objects. If you are declaring a procedure inside of another PL/SQL block, there is, by definition, nothing to replace. You aren't creating a procedure that will exist once the anonymous block finishes so there is nothing to replace. You're simply declaring a procedure that has the same scope as a local variable.
You could create a standalone procedure
create or replace procedure give_bonus(emp_id in number,bonus in number)
is
begin
dbms_output.put_line(emp_id);
dbms_output.put_line(bonus);
end;
and then reference that procedure in your anonymous PL/SQL block
declare
salary number :=20000;
employee_id number :=36325;
begin
case
when salary >=10000 and salary <=20000 then
give_bonus(employee_id,1500);
when salary >= 20000 and salary <=40000 then
give_bonus(employee_id,1000);
when salary>40000 then
give_bonus(employee_id,500);
else
give_bonus(employee_id,0);
end case ;
end;

Related

I want to use out parameter ,but I am not getting the proper syntax of doing so,:ORA-00900: invalid SQL statement

Problem definition: Create a procedure which will display the employees in descending order of employee name of
computer department.
CREATE OR REPLACE PROCEDURE pr_disp (name OUT VARCHAR2,
age OUT NUMBER,
dep OUT VARCHAR,
salary OUT NUMBER)
AS
CURSOR c
IS
SELECT name,
age,
department,
salary
FROM enployee2
WHERE department = 'Computer'
ORDER BY name DESC;
this_name enployee2.name%TYPE;
this_age enployee2.age%TYPE;
this_dep enployee2.department%TYPE;
this_sal enployee2.salary%TYPE;
BEGIN
OPEN c1;
LOOP
FETCH c1
INTO this_name,
this_age,
this_dep,
this_sal;
DBMS_OUTPUT.put_line (
this_name || ' ' || this_age || ' ' || this_dep || '
' || this_sal);
EXIT WHEN c1%NOTFOUND;
END LOOP;
CLOSE c1;
END;
/
Maybe there is a problem in my execution part...
execution part:
variable nm varchar2(50);
variable age number
variable dep varchar2(50);
variable sal number;
execute pr_disp(nm,age,dep,sal);
.The error comes when I execute the code is :ORA-00900: invalid SQL statement
Your code has several errors. Please see below to find out what and where:
Table Creation:
create table enployee2( name VARCHAR2(100),
age NUMBER,
department VARCHAR2(100),
salary NUMBER
);
INSERT INTO enployee2 VALUES ('AAA',32,'Computer',2344);
INSERT INTO enployee2 VALUES ('BBB',42,'Computer',4400);
insert into enployee2 values ('CCC',21,'Computer',2454);
Procedure:
Create OR REPLACE PROCEDURE pr_disp(
name OUT VARCHAR2,
age OUT NUMBER,
dep OUT VARCHAR,
salary OUT NUMBER)
AS
CURSOR c --<-- Your cursor name is `C` but you used it as `C1` below while opening and closing
IS
SELECT name,
age,
department,
salary
FROM enployee2
WHERE department ='Computer'
ORDER BY name DESC;
this_name enployee2.name%type;
this_age enployee2.age%type;
this_dep enployee2.department%type;
this_sal enployee2.salary%TYPE;
BEGIN
OPEN c; --<--Opening `C1` while your cursor name is `C`
LOOP
FETCH c INTO this_name,this_age,this_dep,this_sal;
dbms_output.put_line(this_name||' '||this_age||' '||this_dep||' '||this_sal);
EXIT WHEN c%NOTFOUND; --<--Exiting `C1` while your cursor name is `C`
END LOOP;
CLOSE c; --<--Closing `C1` while your cursor name is `C`
END;
/
Execution:
DECLARE
nm VARCHAR2(50);
age NUMBER;
dep VARCHAR2(50);
sal NUMBER;
BEGIN
pr_disp(nm,age,dep,sal);
END;
You have to write a PL/SQL-Block like this:
DECLARE
nm VARCHAR2 (50);
age NUMBER; -- here you were missing a semi-colon
dep VARCHAR2 (50);
sal NUMBER;
BEGIN
pr_disp (nm,
age,
dep,
sal);
END;
I would assume your stored procedure is invalid because of compilation errors. Try compiling again and check the messages.
You can also check the status with:
select status from user_objects where object_name='PR_DISP';
If it's INVALID you should be able to obtain error messages also via:
select * from user_errors where name = 'PR_DISP';
Maybe your table is named employee2 (not enployee2)?
Btw: What are the out parameters for? You never use them.

PLSQL script not working with passing multiple values into IN() caluse

I am very new in PLSQL, i want to pass an array of number into IN() clause value, But Sqldeveloper throw following error messages:
Error report -
ORA-06550: line 11, column 60:
PLS-00382: expression is of wrong type
ORA-06550: line 11, column 53:
PL/SQL: ORA-22905: cannot access rows from a non-nested table item
ORA-06550: line 10, column 4:
PL/SQL: SQL Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
This is my code :
DECLARE
TYPE sc IS TABLE OF transactionhistory.NBSUBCOMPANY%TYPE INDEX BY PLS_INTEGER;
arr sc;
BEGIN
arr(0) := 000;
arr(1) := 111;
arr(2) := 222;
arr(3) := 333;
select count(th.CHCARDNUMBER) as transactions from transactionhistory th INNER JOIN cards ch on ch.NBATTMID=th.NBATTMID where th.dtdate>=to_date('01-oct-2016','dd-mon-yyyy') and th.dtdate<to_date('01-nov-2016','dd-mon-yyyy')
and ch.NBSUBCOMPANY IN (select column_value from table (arr))
and ((th.CHTRANSTYPE in ('2940', '2916', '2941', '2942', '2943', '2944', '2945', '2902', '2917', '2925') and th.NBBASEAMT < 0) or (th.CHTRANSTYPE in ('2922', '2923', '2926', '2950', '2951', '2952', '2953', '2954', '2955') and th.NBBASEAMT > 0) or (th.CHTRANSTYPE in ('1101', '1102', '1104', '1105', '1106', '1107', '1109') and th.BASEII_STATUS = 'C') or th.CHTRANSTYPE not in ('2940', '2916', '2941', '2942', '2943', '2944', '2945', '2902', '2917', '2925', '2922', '2923', '2926', '2950', '2951', '2952', '2953', '2954', '2955', '1101', '1102', '1104', '1105', '1106', '1107', '1109'));
END;
Please suggest me how can i pass this.
You will need to have a workaround.
SQL doesn't support local collection types to be used in the way you want.
Sample Procedure below which will help in resolving
CREATE OR REPLACE type TEST_TYPE
IS
TABLE OF NUMBER;
You will need to create a type in the database for this to work. Can be created inside a package, if you have one.
DECLARE
TEST_VAR TEST_TYPE := TEST_TYPE();
BEGIN
TEST_VAR.extend(1);
TEST_VAR(TEST_VAR.last) := 222;
TEST_VAR.extend(1);
TEST_VAR(TEST_VAR.last) := 333;
FOR rec IN
(SELECT column_value
FROM TABLE(TEST_VAR)
)
LOOP
dbms_output.put_line(rec.column_value);
END LOOP;
END;
Output
222
333
This way, you can use select column_value from table(test_var) for your IN() clause.
Also, you don't necessarily need to follow the extend(i) part. you can simply do the below as well
TEST_VAR TEST_TYPE := TEST_TYPE(222,333);
Have a read - local collection types not allowed in SQL statements
You can use MEMBER OF clause. See below:
As #Sudipta mentioned you cannot use a collection decalred in PLSQL block as you are doing, you need to declare it outside of the PLSQL block.
CREATE OR REPLACE TYPE sc IS TABLE OF NUMBER;
and then
DECLARE
-- TYPE sc IS TABLE OF NUMBER INDEX BY PLS_INTEGER;
arr sc:=sc();
num number;
BEGIN
arr.extend(4);
arr(1) := 0;
arr(2) := 1;
arr(3) := 2;
arr(4) := 3;
Select count(1)
into num
from employee
-- You can use either commented one or uncommented one. your choice.
--where employee_id in (select column_value from table(arr));
where employee_id member of arr;
END;

Procedure error with '&'

error screenshot I am trying to execute the below program in Toad.
create or replace procedure tst_excp as
var_sal number;
var_empid number;
var_excp exception;
begin
select sal into var_sal from emp
where empno = &var_empid;
if var_sal < 4500 then
raise var_excp;
end if;
exception
when var_excp then
dbms_output.put_line ('The salary is low');
end;
and I am getting an error at the line: where empno = &var_empid;
error message is:
PL/SQL: ORA-00936: missing expression
I am planning to pass the value to the variable while executing it.
the & is part of the sqlplus (and TOAD, SQL Developer and PL/SQL Developer) runtime variables. it will prompt you on execution (in your case while compiling the procedure) for an input to replace in the code.
if you want the get an input for the procedure, so it will be added to the where clause on every run, you need to receive it as an input variable:
create or replace procedure tst_excp (var_empid in number) as -- << changed here
var_sal number;
var_empid number;
var_excp exception;
begin
select sal into var_sal from emp
where empno = var_empid; -- << changed here too
if var_sal < 4500 then
raise var_excp;
end if;
exception
when var_excp then
dbms_output.put_line ('The salary is low');
end;

PL/SQL update statement error

--Student(id, company) Table schema
create or replace procedure student_update(
v_company IN VARCHAR2(10),
v_id IN NUMBER
)
IS
BEGIN
update student set company=v_company where id=v_id;
commit;
END student_update;
/
Error: Encountered the symbol '(' where expecting one of the following
Need to change the dataType of the parameters
create or replace procedure student_update(
v_company IN student.company%TYPE,
v_id IN student.id%TYPE
)
IS
BEGIN
update student set company=v_company where id=v_id;
END;
/
This works fine.
You cannot give a length to you parameters. If you really need to limit v_company to 10, you can do a length check inside the procedure.
You might also consider looking into using Native Dynamic SQL. You're at risk running code straight from inputs.
CREATE OR REPLACE PROCEDURE student_update
(
v_company IN VARCHAR2
,v_id IN NUMBER
) IS
BEGIN
IF LENGTH(v_company) > 10 THEN
raise_application_error(-20001, 'Company must be 10 Char or less.');
END IF;
UPDATE student SET company = v_company WHERE ID = v_id;
COMMIT;
END student_update;
/

retrieve recordset with more than one column value using refcursor in oracle

am creating a package in pl/sql . with in this i declared the ref cursor . With in procedure am using select statement with multiple column name . but am not able to get the result.
here i attached my code. Help me to correct the error. Am new to pl/sql
code
CREATE OR REPLACE PACKAGE types AS
TYPE cursor_type IS REF CURSOR;
END Types;
/
CREATE OR REPLACE
PROCEDURE get_CDR_rs (p_no IN zkv.FLD_callingPartyNumber%TYPE,
CDR_recordset OUT SYS_REFCURSOR) AS
BEGIN
OPEN CDR_recordset FOR
SELECT FLD_callingPartyNumber,
FLD_dateTimeConnect
FROM CISCOCUIC_TBL
WHERE FLD_callingPartyNumber= p_no
ORDER BY FLD_callingPartyNumber,;
END get_CDR_rs;
/
SET SERVEROUTPUT ON SIZE 1000000
DECLARE
l_cursor SYS_REFCURSOR;
l_callingPartyNumber zkv.FLD_callingPartyNumber%TYPE;
l_dateTimeConnect zkv.FLD_dateTimeConnect%TYPE;
BEGIN
LOOP
FETCH l_cursor
INTO l_callingPartyNumber, l_dateTimeConnect;
EXIT WHEN l_cursor%NOTFOUND;
END LOOP;
CLOSE l_cursor;
END;
/
Error
9/41 PL/SQL: ORA-00936: missing expression
5/5 PL/SQL: SQL Statement ignored
First thing is there is a syntax error in the procedure. It should be
CREATE OR REPLACE
PROCEDURE get_CDR_rs (p_no IN zkv.FLD_callingPartyNumber%TYPE,
CDR_recordset OUT SYS_REFCURSOR) AS
BEGIN
OPEN CDR_recordset FOR
SELECT FLD_callingPartyNumber,
FLD_dateTimeConnect
FROM CISCOCUIC_TBL
WHERE FLD_callingPartyNumber= p_no
ORDER BY FLD_callingPartyNumber; -- there was a comma which is not required or you
-- missed a column
END get_CDR_rs;
/
Secondly where is get_CDR_rs being called to retrieve the results?
Thirdly why do you need the following? because you are using sys_refcursor
CREATE OR REPLACE PACKAGE types AS
TYPE cursor_type IS REF CURSOR;
END Types;
/
If you would like to see the results of your procedure which returns sys_refcursor, do as follows
variable rset refcursor;
DECLARE
p_no zkv.FLD_callingPartyNumber%TYPE;
BEGIN
p_no := '123';
get_CDR_rs (p_no, :rset);
END;
/
print rset

Resources