create or replace package pachet_f_p is
function majorare_sal_manageri(sal in NUMBER, majorare in NUMBER) return NUMBER;
end pachet_f_p;
create or replace package body pachet_f_p
is
create or replace function majorare_sal_manageri(sal in NUMBER, majorare in NUMBER)
return INTEGER is
nr_angajati INTEGER :=0;
begin
dbms_output.put_line('Angajatii care primesc majorare de '|| majorare || 'au ID-urile urmatoare :');
/*
declare
cursor numara_ang_cccc is
select ID from MANAGERI where SALARIU = sal;
m_ID MANAGERI.ID%TYPE;
begin
open numara_ang_c;
loop
fetch numara_ang_c into m_ID;
exit when numara_angajati_cursor%NOTFOUND;
dbms_output.put_line(m_ID);
update MANAGERI
set
SALARIU = SALARIU + majorare
where ID = m_ID;
nr_angajati := nr_angajati +1;
end loop;
close numara_ang_cccc;
end;
*/
return nr_angajati;
end majorare_sal_manageri;
end pachet_f_p;
I can run the first 3 rows, but the rest of it gets an error:
Error(5,2): PLS-00103: Encountered the symbol "CREATE" when expecting one of the following: begin end function pragma procedure subtype type current cursor delete exists prior
Can someone, please, find what I did wrong?
First create package specifications and Package body next(two separate pl/sql blocks)this compiles with no errors in Sql Developer
create or replace package pachet_f_p is
function majorare_sal_manageri(sal in NUMBER, majorare in NUMBER)
return NUMBER;
end pachet_f_p;
-- add back slash here
/
create or replace package body pachet_f_p
is
--create or replace (comment or remove this)
function majorare_sal_manageri(sal in NUMBER, majorare in NUMBER)
return number is
nr_angajati number :=0;
begin
dbms_output.put_line('Angajatii care primesc majorare de '|| majorare || 'au ID-urile urmatoare :');
/*
declare
cursor numara_ang_cccc is
select ID from MANAGERI where SALARIU = sal;
m_ID MANAGERI.ID%TYPE;
begin
open numara_ang_c;
loop
fetch numara_ang_c into m_ID;
exit when numara_angajati_cursor%NOTFOUND;
dbms_output.put_line(m_ID);
update MANAGERI
set
SALARIU = SALARIU + majorare
where ID = m_ID;
nr_angajati := nr_angajati +1;
end loop;
close numara_ang_cccc;
end;
*/
return nr_angajati;
end majorare_sal_manageri;
end pachet_f_p;
/
Related
Is there a way to use a FOR LOOP variable in a FUNCTION call. For example, I have a simple function that returns a string. I call the function from a procedure, and pass two parameters which one of the parameters is a variable from a FOR LOOP:
create or replace package body TEST_JNS is
--
FUNCTION f_display_msg(var IN VARCHAR2,
num IN NUMBER)
RETURN VARCHAR2 IS
BEGIN
--
RETURN num || '#: ' || var || ' world';
END f_display_msg;
--
--
PROCEDURE main
AS
l_name VARCHAR2(100);
l_id NUMBER;
BEGIN
l_name := 'hello';
--
FOR f1 IN (SELECT TO_NUMBER(TRIM(REGEXP_SUBSTR('1,2,3', '[^,]+', 1, LEVEL))) AS "id"
FROM DUAL
CONNECT BY LEVEL <= LENGTH(REGEXP_REPLACE('1,2,3', '[^,]+')) + 1)
LOOP
--
dbms_output.put_line(f_display_msg(l_name, f1.id));
--
END LOOP;
END main;
--
end TEST_JNS;
I get error: component 'ID' must be declared. I also tried adding the FOR LOOP value to a local variable, but get the same result. Any ideas?
If it helps some one, IOT resolve the issue I just had to remove the double quotes surrounding id As "id".
Rather than using regular expressions to parse a delimited list, why not use a collection:
create or replace package body TEST_JNS is
FUNCTION f_display_msg(var IN VARCHAR2,
num IN NUMBER)
RETURN VARCHAR2 IS
BEGIN
RETURN num || '#: ' || var || ' world';
END f_display_msg;
PROCEDURE main
AS
TYPE numberlist IS TABLE OF INTEGER;
l_name VARCHAR2(100) := 'hello';
v_list numberlist := numberlist( 1, 2, 3 );
BEGIN
l_name := 'hello';
FOR i IN 1 .. v_list.COUNT LOOP
dbms_output.put_line( f_display_msg( l_name, v_list(i) ));
END LOOP;
END main;
end TEST_JNS;
When I run this code, the result should be 636790 but 63679 is only returned. Beating brains out on this one!!! Why the missing digit? Source table and column contain correct number of 636790.
create or replace package jt_types
as
type ttest is ref cursor;
end;
CREATE OR REPLACE FUNCTION jt_test
RETURN jt_types.ttest
IS
o_return jt_types.ttest;
BEGIN
OPEN o_return FOR
SELECT offn_id
FROM jt_offn_4
where offn_ID in (636790)
ORDER BY offn_id;
RETURN o_return;
END jt_test;
DECLARE
l_ids jt_types.ttest;
l_id NUMBER;
BEGIN
l_ids := jt_test;
LOOP
FETCH l_ids INTO l_id;
EXIT WHEN l_ids%NOTFOUND;
dbms_output.put_line('Rec: ' || l_id);
END LOOP;
CLOSE l_ids;
END;
The easiest way to do is to return sys_refcursor, here is the code:
create or replace
function jt_test
return sys_refcursor
is
o_return sys_refcursor;
begin
open o_return for
select offn_id
from jt_offn_4
where offn_ID = 636790;
return o_return;
end jt_test;
declare
l_ids sys_refcursor;
l_id number;
begin
l_ids := jt_test;
loop
fetch l_ids into l_id;
dbms_output.put_line('Rec: ' || l_id);
exit when l_ids%NOTFOUND;
end loop;
close l_ids;
end;
Hi I have the following procedure:
create or replace procedure
SP_DELETE_FROM_TABLE(pTableName in VARCHAR2, pFieldName in VARCHAR2,
pFieldValue in VARCHAR2,pFieldType in VARCHAR2) is
querystring VARCHAR2(500);
begin
queryString := 'DELETE FROM ' ||pTableName||
' WHERE '||pFieldName ||' = DECODE(:pFieldType,integer,:pFieldValue)' ;
EXECUTE IMMEDIATE queryString USING pFieldType,pFieldValue;
end SP_DELETE_FROM_TABLE;
all my Parameters are of Type VARCHAR2, What I am trying to do is: When I call the procedure with the following values ('users_table','users_id','11','integer')
so by using DECODE I would like to check if pFieldValue is of type pFieldTypeand if yes return pFieldValue
so if pFieldValue is:11 and pfieldType is:integer it should delete users_id 11 if fieldType is string do nothing..
I'd create a function that checks parameter has correct type
and then use it in main procedure
--main procedure
create or replace procedure SP_DELETE_FROM_TABLE(pTableName in VARCHAR2, pFieldName in VARCHAR2,pFieldValue in VARCHAR2,pFieldType in VARCHAR2) is
querystring VARCHAR2(500);
begin
if 'Y' = is_type_correct(pFieldValue, pFieldType ) then
queryString := 'DELETE FROM ' ||pTableName|| ' WHERE '
||pFieldName ||' = :pFieldValue';
EXECUTE IMMEDIATE queryString USING pFieldValue;
end
else
null; --incorrect type and parameter, do nothing
end;
end SP_DELETE_FROM_TABLE;
--check function
CREATE OR REPLACE FUNCTION is_type_correct( p_val IN VARCHAR2, p_type varchar2 )
RETURN VARCHAR2 DETERMINISTIC PARALLEL_ENABLE
IS
l_num NUMBER;
l_date date;
BEGIN
if 'integer' = p_type
then
l_num := to_number( p_val );
elsif 'date' = p_type then
l_date := to_date(p_val, 'YYYY.MM.DD');
elsif 'varchar2' then
null;//do nothing
else
return 'N'; //uknown type
end if;
RETURN 'Y';
EXCEPTION
WHEN value_error THEN
RETURN 'N';
END is_number;
Just try to convert a string to a number, and when an exception occurs, do nothing:
querystring VARCHAR2(500);
some_number number;
begin
some_number := to_number( pFieldValue ); /* trying to convert to a number */
queryString := 'DELETE FROM ' ||pTableName||
' WHERE '||pFieldName ||' = :x' ;
EXECUTE IMMEDIATE queryString USING some_number;
EXCEPTION
WHEN VALUE_ERROR THEN null; /* do nothing when pFieldValue is not a number*/
end SP_DELETE_FROM_TABLE;
I'm new to oracle. I've come across table functions. The code for the function is
CREATE TYPE t_tf_row AS OBJECT (
id NUMBER,
description VARCHAR2(50));
CREATE TYPE t_tf_tab IS TABLE OF t_tf_row;
CREATE OR REPLACE FUNCTION get_tab_tf (p_rows IN NUMBER) RETURN t_tf_tab AS
l_tab t_tf_tab := t_tf_tab();
BEGIN
FOR i IN 1 .. p_rows LOOP
l_tab.extend;
l_tab(l_tab.last) := t_tf_row(i, 'Description for ' || i);
END LOOP;
RETURN l_tab;
END;
Now, I want to create a procedure which will update the table type using for loop.
The code for the procedure is
create or replace procedure add_n_rows(n_rows in number) is
l_tab t_tf_tab := t_tf_tab();
begin
for i in t_tf_tab.count .. t_tf_tab.count + n_rows
loop
l_tab.extend;
l_tab(l_tab.last) := t_tf_row(i, 'Description for '|| i);
end loop;
end;
I'm getting error saying that COUNT should be declared.
ORA-06550: line 1, column 37:
PLS-00302: component 'COUNT' must be declared
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored
Could you help me out in using the right procedure for .count in for loop.Thanks
You need to use the variable name not the type.
create or replace procedure add_n_rows(
n_rows in number)
is
l_tab t_tf_tab := t_tf_tab();
begin
for i in l_tab.count .. 1_tab.count + n_rows
loop
l_tab.extend;
l_tab(l_tab.last) := t_tf_row(i, 'Description for '|| i);
end loop;
end;
/
I am trying to implement this procedure into a package however the package
will not allow me to use the cursor for some reason. Can anyone help? Thank you.
Also when I try to put the procedure into my package a 'enter bind variable' box appears
minus anywhere to input a bind variable and this error
Not found
The requested URL /apex/wwv_flow.show was not found on this server
My code is
PROCEDURE total_calc(p_order NUMBER)
IS
c_price product.unit_price%type;
c_prod_desc product.product_desc%type;
v_total_cost NUMBER := 0;
v_c1 REFCURSOR;
CURSOR c1 IS
SELECT product_desc, unit_price
FROM product
WHERE product_id IN (SELECT fk2_product_id
FROM order_line
WHERE fk1_order_id = p_order);
BEGIN
OPEN c1;
LOOP
FETCH c1 into c_prod_desc, c_price;
dbms_output.put_line(c_prod_desc || ': ' || c_price);
v_total_cost := v_total_cost + c_price;
EXIT WHEN c1%notfound;
END LOOP;
CLOSE c1;
dbms_output.put_line('Total Cost:' || v_total_cost);
END;
Here is the code for the rest of the package
CREATE OR REPLACE PACKAGE orders_salary_manage AS
FUNCTION tax_func (p_sal IN NUMBER)
RETURN NUMBER;
PROCEDURE reduce_price(p_product_id NUMBER, p_sub_price NUMBER);
PROCEDURE increase_price(p_product_id NUMBER, p_add_price NUMBER);
PROCEDURE remove_order(p_order_id NUMBER);
PROCEDURE add_order(p_order_id NUMBER,
p_order_date VARCHAR2,
p_delivery_date VARCHAR2,
p_customer_id NUMBER,
p_employee_id NUMBER,
p_order_type_id NUMBER);
END orders_salary_manage;
CREATE OR REPLACE PACKAGE BODY orders_salary_manage AS
tot_orders NUMBER;
FUNCTION tax_func (p_sal IN NUMBER)
RETURN NUMBER
IS
tax_rate NUMBER := 0;
v_netsal NUMBER := 0;
v_sal NUMBER;
BEGIN
v_sal := p_sal;
IF v_sal > 70000 THEN
tax_rate := (v_sal * 0.4);
v_netsal := v_sal - tax_rate;
END IF;
IF v_sal < 70000 THEN
tax_rate := (v_sal * 0.2);
v_netsal := v_sal - tax_rate;
END IF;
RETURN v_netsal;
END;
PROCEDURE reduce_price(p_product_id NUMBER, p_sub_price NUMBER)
IS v_price NUMBER;
e_invalid_price EXCEPTION;
BEGIN
SELECT unit_price
INTO v_price
FROM product
WHERE product_id = p_product_id;
v_price := v_price - p_sub_price;
IF v_price < 1 THEN
RAISE e_invalid_price;
ELSE
UPDATE product SET unit_price = v_price WHERE product_id = p_product_id;
END IF;
END;
PROCEDURE increase_price(p_product_id NUMBER, p_add_price NUMBER)
IS v_price NUMBER;
BEGIN
SELECT unit_price
INTO v_price
FROM product
WHERE product_id = p_product_id;
v_price := v_price + p_add_price;
UPDATE product SET unit_price = v_price WHERE product_id = p_product_id;
END;
PROCEDURE remove_order(p_order_id NUMBER)
IS
BEGIN
DELETE FROM placed_order WHERE order_id = p_order_id;
DELETE FROM order_line WHERE fk1_order_id = p_order_id;
END;
PROCEDURE add_order(p_order_id NUMBER,
p_order_date VARCHAR2,
p_delivery_date VARCHAR2,
p_customer_id NUMBER,
p_employee_id NUMBER,
p_order_type_id NUMBER)
IS new_order NUMBER;
BEGIN
INSERT INTO placed_order (order_id, order_date, delivery_date, fk1_customer_id, fk2_employee_id, fk3_order_type_id)
VALUES (p_order_id, p_order_date, p_delivery_date, p_customer_id, p_employee_id, p_order_type_id);
END;
END;
This is really confusing.
First off - dbms_output requires special settings for the environment in order to work. And a call to DBMS_OUTPUT.ENABLE, plus packages do have access to a terminal anyway. Packages do not have your process context, they run in the process context of the db -- which runs without a controlling terminal. If you have to write something use a file -- UTL_FILE package is meant for that.
Next
Since you are basically adding up an order, you need a function to return the value.
A procedure is not going to work. As you coded anyway.
Next
v_C1 is not used and makes no sense for your code. You are not returning a refcursor.
Next
You should consider using a schema for tables with generic table names like that when you decalre a variable.
example:
v_foo schema_owner.table_name.column_name%type;
Consider this:
function total_calc(p_order in NUMBER)
return NUMBER
is
c_price product.unit_price%type;
c_prod_desc product.product_desc%type;
v_total_cost NUMBER := 0;
-- lose this: v_c1 REFCURSOR;
CURSOR c1 IS
SELECT product_desc, unit_price
FROM product
WHERE product_id IN (SELECT fk2_product_id
FROM order_line
WHERE fk1_order_id = p_order);
BEGIN
OPEN c1;
LOOP
FETCH c1 into c_prod_desc, c_price;
-- lose this line: dbms_output.put_line(c_prod_desc || ': ' || c_price);
v_total_cost := v_total_cost + c_price;
EXIT WHEN c1%notfound;
END LOOP;
CLOSE c1;
-- lose this line: dbms_output.put_line('Total Cost:' || v_total_cost);
return v_total_cost;
END;
In order for this to work it has to inside a
CREATE OR REPLACE FUNCTION a statement. Then - Added to the db schema by a user with correct permissions to create it.
After all that, then you can run it. Also, there is more to all this package/function creation stuff like using PRAGMAS if somebody needs to run this from SQLPLUS.