DECLARE
v_id NUMBER := 200;
v_fname VARCHAR2(20);
v_lname VARCHAR2(20);
v_sal NUMBER; BEGIN
SELECT first_name, last_name, salary
INTO v_fname, v_lname, v_sal
FROM STAFF
WHERE id=v_id;
DBMS_OUTPUT.PUT_LINE(v_fname||' '||v_fname||' makes '||v_sal); END; /
Saw this code in a StackOverflow post. Wondering how do I print on the screen a message only in case the salary of the selected record is higher than 5000 pounds?
What would be the PL/SQL for that and where do I put it in the exi?
I am learning Oracle for a week now and trying to go through the documentation as much as I can. But having a hard time understanding everything.
Thanks in Advance
Simply this:
DECLARE
v_id NUMBER := 200;
v_fname VARCHAR2(20);
v_lname VARCHAR2(20);
v_sal NUMBER;
BEGIN
SELECT first_name, last_name, salary
INTO v_fname, v_lname, v_sal
FROM STAFF
WHERE id=v_id;
IF v_sal > 5000 THEN
DBMS_OUTPUT.PUT_LINE(v_fname||' '||v_fname||' makes '||v_sal);
END IF;
END;
/
Related
i have created the stored procedure ...in which getting employee_name ,salary and his manager_name .. procedure is created successfully but when i am executing giving an error of invalid parameter.. how do i execute this procedure ...
create or replace procedure employee_manager (
dept_id in number,
fname out varchar2,
v_sal out number,
fname1 out varchar2
)
is
begin
select a.first_name manager_name,
b.first_name employee_name,
b.salary
into fname,
fname1,
v_sal
from employees a join employees b on a.employee_id = b.manager_id
where a.department_id = dept_id;
end employee_manager ;
If would have helped if you showed us what exactly happened when you called the procedure, or - at least - posted ORA-xxxxx error code. With the info we have so far, we can only guess.
My guess is that you wrongly called it. As it accepts one IN parameter and three OUT ones, you'll have to declare three variables; something like this:
declare
l_fname employees.first_name%type;
l_sal employees.salary%type;
l_fname1 employees.first_name%type;
begin
employee_manager(dept_id => 10,
fname => l_fname,
v_sal => l_sal,
fname1 => l_fname1);
dbms_output.put_line('Values returned are: ' || l_fname ||', '|| l_sal ||', '|| l_fname1);
end;
/
I try to create plsql block but it doesnt work. Oracle says that i have error at line 2. I think it could be because substitution variable is not placed right !?
DECLARE
V_ENAME EMPLOYEES.LAST_NAME%TYPE := '&LNAME';
V_SAL EMPLOYEES.SALARY%TYPE;
BEGIN
SELECT LAST_NAME, SALARY
INTO V_ENAME, V_SAL
FROM employees WHERE LAST_NAME = V_ENAME;
IF V_SAL < 3000 THEN
v_sal := v_sal + 500;
DBMS_OUTPUT.PUT_LINE (v_ename || 'have increasement ');
ELSIF V_SAL > 3000 THEN
DBMS_OUTPUT.PUT_LINE (v_ename || 'do not have increasement ');
ELSE
DBMS_OUTPUT.PUT_LINE ('error');
END IF;
END;
Since there can be many employees with the last name passed by the user, you may use an implicit CURSOR FOR LOOP. Also, add first_name in the output for clarity.
DECLARE
v_ename employees.last_name%TYPE := '&LNAME';
v_sal employees.salary%TYPE;
BEGIN
for rec IN ( SELECT first_name,last_name,salary
FROM employees WHERE last_name = v_ename
)
LOOP
IF rec.salary < 3000 THEN
v_sal := rec.salary + 500;
dbms_output.put_line (rec.first_name||' '||rec.last_name ||
' has an increase');
ELSIF rec.salary > 3000 THEN
dbms_output.put_line (rec.first_name||' '||rec.last_name ||
' does not have an increase ');
ELSE dbms_output.put_line ('error');
END IF;
END LOOP;
END;
/
Execution
..
old:DECLARE
v_ename employees.last_name%TYPE := '&LNAME';
..
new:DECLARE
v_ename employees.last_name%TYPE := 'Grant';
..
Douglas Grant has an increase
Kimberely Grant does not have an increase
PL/SQL procedure successfully completed.
Not sure if it's your problem but there is really no need to select last_name into v_ename when you are already ensuring last_name is equal to v_ename in the where clause.
I have a simple stored proc...
create or replace
PROCEDURE GET_PERSON (aName VARCHAR2, p_data OUT sys_refcursor)
IS
BEGIN
OPEN p_data FOR SELECT * FROM people_table WHERE firstname = aName;
END;
However when I execute the stored proc it returns all of the records.
DECLARE
v_cur SYS_REFCURSOR;
v_1 number;
v_2 VARCHAR2(50);
v_3 VARCHAR2(200);
v_4 VARCHAR2(50);
v_5 VARCHAR2(50);
v_6 VARCHAR2(50);
BEGIN
GET_PERSON ('aaa#bbb.com', v_cur);
LOOP
FETCH v_cur INTO v_1, v_2, v_3, v_4, v_5, v_6;
EXIT WHEN v_cur%NOTFOUND;
dbms_output.put_line(v_2 || ' ' || v_3);
END LOOP;
CLOSE v_cur;
END;
If I run the simple statement
SELECT * FROM people_table WHERE firstname = 'aaa#bbb.com';
It correctly returns one record.
Why is the stored proc not behaving the same?
I found the issue..
My issue was name collision. When I altered the code above is when I noticed the issue. I originally has WHERE fistname = firstName. Once I changed the parameter to p_firstName as was well.
I tried to fix this for two days and I couldnt.
I know why the code happens but Im not sure where.
or why its happening...
This has to be done in PLSQL
its a homework assignment.
SET SERVEROUTPUT ON
DECLARE
V_IDNO PAYDATA1.IDNO%TYPE;
V_NAME PAYDATA1.NAME%TYPE;
V_SAL PAYDATA1.SALARY%TYPE;
V_JOB PAYDATA1.JOBCODE%TYPE;
V_PAY PAYDATA1.PAYHR%TYPE;
V_IDNO1 PAYTRAN1.IDNO%TYPE;
V_HOURSWK PAYTRAN1.HOURSWK%TYPE;
V_HOURS HOURSWKD.HOURSWK%TYPE;
V_CHECK NUMBER(10);
CURSOR paydata_cursor IS
SELECT IDNO, NAME, JOBCODE, SALARY, PAYHR FROM PAYDATA1
ORDER BY IDNO;
CURSOR paytran_cursor IS
SELECT IDNO, HOURSWK FROM PAYTRAN1
WHERE V_IDNO = IDNO
order by IDNO;
BEGIN
OPEN paydata_cursor;
LOOP
FETCH paydata_cursor INTO V_IDNO, V_NAME, V_CHECK, V_JOB, V_PAY;
EXIT WHEN paydata_cursor%NOTFOUND;
IF V_SAL > 0 THEN
V_CHECK := V_SAL / 52;
DBMS_OUTPUT.PUT_LINE(V_IDNO|| ' HAS A CHECK FOR: '||V_CHECK);
END IF;
IF V_SAL = 0 AND V_HOURSWK < 41 THEN
V_CHECK := V_PAY * V_HOURS;
DBMS_OUTPUT.PUT_LINE(V_IDNO|| ' HAS A CHECK FOR: '||V_CHECK);
ELSIF V_SAL = 0 AND V_HOURSWK > 40 THEN
V_CHECK := V_PAY * V_HOURS;
V_CHECK := V_SAL + ((V_HOURSWK * 1.5) * (V_HOURSWK - 40));
DBMS_OUTPUT.PUT_LINE(V_IDNO|| ' HAS A CHECK FOR: '||V_CHECK);
END IF;
END LOOP;
CLOSE paydata_cursor;
END;
/
SET SERVEROUTPUT OFF
IM GETTING THIS ERROR, TRIED TO FIX IT ALL DAY AND COULDN’T. ANY ADVICE?
SQL> # CURSOR5
DECLARE
*
ERROR at line 1:
ORA-06502: PL/SQL: numeric or value error: character to number conversion error
ORA-06512: at line 22
I can see a few issues with your code but without knowing much more info it's difficult to diagnose...but I'll try:
It looks like you're selecting into the wrong variables when opening your cursor.
You also haven't opened your paytran_cursor anywhere. You can add that code yourself but until you do, your check of V_HOURSWK won't be very useful etc.
Try this instead:
SET SERVEROUTPUT ON
DECLARE
V_IDNO PAYDATA1.IDNO%TYPE;
V_NAME PAYDATA1.NAME%TYPE;
V_SAL PAYDATA1.SALARY%TYPE;
V_JOB PAYDATA1.JOBCODE%TYPE;
V_PAY PAYDATA1.PAYHR%TYPE;
V_IDNO1 PAYTRAN1.IDNO%TYPE;
V_HOURSWK PAYTRAN1.HOURSWK%TYPE;
V_HOURS HOURSWKD.HOURSWK%TYPE;
V_CHECK NUMBER(10);
CURSOR paydata_cursor IS
SELECT IDNO, NAME, JOBCODE, SALARY, PAYHR
FROM PAYDATA1
ORDER BY IDNO;
CURSOR paytran_cursor IS
SELECT IDNO, HOURSWK
FROM PAYTRAN1
WHERE V_IDNO = IDNO
order by IDNO;
BEGIN
OPEN paydata_cursor;
LOOP
-- Changed the variables you were selecting into
FETCH paydata_cursor INTO V_IDNO, V_NAME, V_JOB, V_SAL, V_PAY;
EXIT WHEN paydata_cursor%NOTFOUND;
IF V_SAL > 0
THEN
V_CHECK := V_SAL / 52;
DBMS_OUTPUT.PUT_LINE(V_IDNO|| ' HAS A CHECK FOR: '||V_CHECK);
END IF;
IF V_SAL = 0 AND V_HOURSWK < 41
THEN
V_CHECK := V_PAY * V_HOURS;
DBMS_OUTPUT.PUT_LINE(V_IDNO|| ' HAS A CHECK FOR: '||V_CHECK);
ELSIF V_SAL = 0 AND V_HOURSWK > 40
THEN
V_CHECK := V_PAY * V_HOURS;
V_CHECK := V_SAL + ((V_HOURSWK * 1.5) * (V_HOURSWK - 40));
DBMS_OUTPUT.PUT_LINE(V_IDNO|| ' HAS A CHECK FOR: '||V_CHECK);
END IF;
END LOOP;
CLOSE paydata_cursor;
END;
/
SET SERVEROUTPUT OFF
Hope it helps.
EDIT:
I have tried to guess what you are trying to do with your code and think that this below might go some way to fixing your issues in a slightly more efficient manner:
SET SERVEROUTPUT ON
DECLARE
--
c_max_hours CONSTANT NUMBER := 40;
--
-- N.B.: I have assumed that there may be more than one entry per IDNO for
-- hours worked, if this is not the case then you can remove the SUM() and
-- the GROUP BY clause
--
CURSOR pay_cursor
IS
SELECT IDNO,
NAME,
JOBCODE,
SALARY,
PAYHR,
SUM(HOURSWK) AS HOURS_WORKED
FROM PAYDATA1
JOIN PAYTRAN1 USING (IDNO)
GROUP BY IDNO,
NAME,
JOBCODE,
SALARY,
PAYHR;
--
V_CHECK NUMBER;
pay_record pay_cursor%ROWTYPE;
--
BEGIN
-- Depending on the rows in your cursor you might want to increase the output buffer for DBMS_OUTPUT
DBMS_OUTPUT.ENABLE(1000000);
--
OPEN pay_cursor;
LOOP
-- Fetch the data into your cursor rowtype variable
FETCH paydata_cursor INTO pay_record;
EXIT WHEN pay_cursor%NOTFOUND;
--
-- ASSUMPTION: salary is not NULL (i.e. 0 or more).
--
IF pay_record.salary > 0
THEN
V_CHECK := pay_record.salary / 52;
ELSE
--
-- Salary must be zero
--
IF pay_record.hours_worked <= c_max_hours
THEN
V_CHECK := pay_record.payhr * pay_record.hours_worked;
ELSE
-- Must be > c_max_hours
V_CHECK := pay_record.payhr * pay_record.hours_worked;
V_CHECK := pay_record.salary + ((pay_record.hours_worked * 1.5) * (pay_record.hours_worked - 40));
END IF;
END IF;
--
-- Output your result
--
DBMS_OUTPUT.PUT_LINE(pay_record.idno|| ' HAS A CHECK FOR: '||V_CHECK);
END LOOP;
CLOSE paydata_cursor;
EXCEPTION
WHEN others
THEN
-- Close the cursor if it is still open
IF pay_cursor%ISOPEN
THEN
CLOSE pay_cursor;
END IF;
-- Re-raise the error
RAISE;
END;
/
SET SERVEROUTPUT OFF
I hope it's useful.
P.S. I couldn't check this in a real environment as I'm not at my usual PC so apologies for any syntax errors.
Problem is that your column paydata1.JOBCODE is not a number
and in this code FETCH paydata_cursor INTO V_IDNO, V_NAME, V_CHECK, V_JOB, V_PAY; you are assigning it to V_CHECK which is number
Change the order like this: FETCH paydata_cursor INTO V_IDNO, V_NAME, V_JOB, V_CHECK, V_PAY; and it should work but ensure that paydata1.salary is a number
Also i am not sure when you have declared V_SAL then why are you using V_CHECK in this cursor fetch.
at line 13 when you are defining your cursor paydata_cursor as columns like
SELECT IDNO, NAME, JOBCODE, SALARY, PAYHR FROM PAYDATA1
ORDER BY IDNO;
column sequence IDNO, NAME, JOBCODE, SALARY, PAYHR
but in line 23 i.e.
FETCH paydata_cursor INTO V_IDNO, V_NAME, V_CHECK, V_JOB, V_PAY;
you are actually fetching the columns like this
IDNO, NAME, JOBCODE, SALARY, PAYHR into
V_IDNO, V_NAME, V_CHECK, V_JOB, V_PAY
that means JOBCODE is going into V_CHECK
and SALARY is going into V_JOB
since salary must be number and v_check must be varchar
i think this is why u r getting this error
Thanks
Sid
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.