How to count rows from two columns? - oracle

I try to create the function login that takes customer number(pnr) and password from same table. Its fine to create function but test crashes with following eror:
ORA-00904: "P_PASSWD": invalid identifier
create or replace function logga_in(
p_pnr bankkund.pnr%type,
p_passwd bankkund.passwd%type
)
return number
as
v_resultat number(1);
begin
select count(pnr) into v_resultat
from bankkund
where p_pnr = pnr
and p_passwd = passwd;
return 1;
exception
when no_data_found then
return 0;
end;

There is one other problem with your code not suggested in the comments, A count function from a select into will not raise a NO_DATA_FOUND exception. You may use an IF condition on count or do something like this, which is preferable
CREATE OR REPLACE FUNCTION logga_in (
p_pnr bankkund.pnr%TYPE,
p_passwd bankkund.passwd%TYPE
) RETURN NUMBER AS
v_resultat NUMBER(1);
BEGIN
SELECT 1 --do not use count if you wish to handle no_data_found
INTO v_resultat FROM
bankkund WHERE pnr = p_pnr AND
passwd = p_passwd
AND ROWNUM = 1; --Add this
RETURN 1;
EXCEPTION
WHEN no_data_found THEN
RETURN 0;
END;
Now, as far as calling the procedure is concerned, there are various options available including using bind variable
VARIABLE p_pnr number --use the datatype of bankkund.pnr%TYPE
VARIABLE p_passwd VARCHAR2(10) --use the datatype of bankkund.passwd
SELECT logga_in(:p_pnr,:p_passwd) FROM dual;
Or substitution variable
SELECT logga_in('&p_pnr','&p_passwd') FROM dual;
Give inputs when prompted.
Or use PL/SQL block
DECLARE
v_res INT;
v_pnr bankkund.pnr%type := 12892; --or appropriate value
p_passwd bankkund.passwd%type := some_passwd';
BEGIN
v_res := logga_in();
If v_res = 1 THEN
do_something_u_want; --call or execute appropriate action.
END IF;
END;
/

Related

PL/SQL "all_search" procedure is not a procedure or is undefined

This function is inside a package, but when I call the function the following error appears: PL/SQL "all_search" is not a procedure or is undefined. Someone can help me?
CREATE OR REPLACE PACKAGE employee_tab IS
FUNCTION all_search (ID_EMP in NUMBER) RETURN O_T_EMPL PIPELINED;
END employee_tab;
/
CREATE OR REPLACE TYPE O_T_EMPL AS TABLE OF O_EMPLOYEE;
/
CREATE OR REPLACE PACKAGE BODY employee_tab IS
FUNCTION all_search (ID_EMP in NUMBER) RETURN O_T_EMPL PIPELINED
IS
TAB_OBJC_EMP O_T_EMPL;
MY_QUERY_SEARCH VARCHAR2(400);
REF_C SYS_REFCURSOR;
MAX_ROW NUMBER := 25;
BEGIN
MY_QUERY_SEARCH := 'SELECT *
FROM EMPLOYEES
WHERE EMPLOYEE_ID = ID_EMP';
open REF_C for MY_QUERY_SEARCH using ID_EMP;
loop
--
fetch REF_C bulk collect into TAB_OBJC_EMP limit MAX_ROW;
exit when TAB_OBJC_EMP.count = 0;
for i in 1..TAB_OBJC_SEE.count
--
loop
pipe row(O_EMPLOYEE(TAB_OBJC_EMP(i).V_O_EMP_ID,
TAB_OBJC_EMP(i).V_O_HIRE_ID,
TAB_OBJC_EMP(i).V_O_DEP_ID)
);
end loop;
--
END loop;
--
CLOSE REF_C;
RETURN;
--
END all_search;
END employee_tab;
/
call function: employee_tab.all_search(1);
You need to assign the result of the function to something, try something like:
DECLARE
l_emp_id NUMBER;
BEGIN
SELECT EMP_ID
INTO l_emp_id
FROM TABLE(employee_tab.all_search(1))
WHERE rownum = 1;
DBMS_OUTPUT.put_line(TO_CHAR(EMP_ID));
END;
/

Oracle read and return data from cursor

I'm trying to create a stored procedure in Oracle that has one input parameter and one output variable and, in case of results, return a dataset to my .Net Application. The main issue is that I can't change the signature of the procedure and need to do if condition to validate if exist records or not.
The main issue that i've being struggled is with cursors (to execute and return the information), and to count the results of the select.
Here is an example of what i'm doing to try to retrieve the data.
CREATE PROCEDURE SP_Testing (v_input IN VARCHAR2(50), v_OutID NUMBER(1))
AS
TYPE v_record_botoes IS RECORD (
v_dummy_col1 VARCHAR2(50),
v_dummy_col2 VARCHAR2(250)
);
TYPE table_botoes IS TABLE OF v_record_botoes;
tt_botoes table_botoes;
v_ref_cursor SYS_REFCURSOR;
CURSOR v_cursor IS
(SELECT dt.v_dummy_col1,
dt.v_dummy_col2
FROM dummy_table dt
WHERE v_dummy_col3 = v_input);
v_check NUMBER;
BEGIN
tt_botoes := table_botoes();
v_check := 0;
FOR v_row IN v_cursor
LOOP
tt_botoes.extend;
tt_botoes(tt_botoes.COUNT) := v_row;
END LOOP;
v_check := tt_botoes.COUNT;
-- condition that need to know the nr of records of the select
IF v_check = 0 THEN
v_OutID := 0;
ELSE
v_OutID := 1;
OPEN v_ref_cursor FOR
SELECT *
FROM tt_botoes; -- also tryed "FROM TABLE (tt_botoes)" and "FROM TABLE (cast(tt_botoes AS table_botoes))"
-- return dataset to .net application
DBMS_SQL.RETURN_RESULT(v_ref_cursor)
END IF;
END;
Already tryed to convert the v_cursor into a sys_refcursor to be outputed by the DBMS_SQL package but didn't get anywhere.
Also i've tried to create a temporary table to hold the information, but then have a concurrency issue.
Any idea what i'm doing wrong, or any other possible solution to solve this issue?
Thanks in advance
Completely untested because I do not have the environment to test it but I would structure this quite differently, see below (I am assuming that the missing out in the specification is just a typo)
CREATE PROCEDURE SP_Testing (v_input IN VARCHAR2(50), v_OutID **out** NUMBER(1))
AS
v_ref_cursor SYS_REFCURSOR;
v_check NUMBER;
BEGIN
select count(1)
into v_check
from dummy_table dt
WHERE v_dummy_col3 = v_input
-- condition that need to know the nr of records of the select
IF v_check = 0 THEN
v_OutID := 0;
ELSE
v_OutID := 1;
OPEN v_ref_cursor FOR
SELECT dt.v_dummy_col1,
dt.v_dummy_col2
FROM dummy_table dt
WHERE v_dummy_col3 = v_input
-- return dataset to .net application
DBMS_SQL.RETURN_RESULT(v_ref_cursor)
END IF;
END;

Oracle function, how to pass parameters to cursor and use it

Here is one of oracle functions. There is a cursor called c_adv_course_credit which receives 2 parameters. These 2 parameters are using the where statement:
WHERE
-- year
cc.year = p_year AND
-- rela_pk
cc.sequence_number = p_sequence_number AND
cc.closed_ind = 'N';
When I run it in oracle sql developer:
SET SERVEROUTPUT ON
variable res varchar2(200);
EXECUTE :res := advp_test_cursor(2018, 92919);
select :res from dual;
The result text is always "not working"
Here is the full function (not working):
CREATE OR REPLACE Function SISD_OWNER.advp_test_cursor (
p_sequence_number IN NUMBER, -- rela_pk
p_year IN NUMBER -- year
)
RETURN VARCHAR2
IS
v_return_var VARCHAR2(300) := 'not working';
CURSOR c_adv_course_credit (
p_sequence_number IN NUMBER,
p_year IN NUMBER
)
IS
SELECT
cc.EXTERNAL_COURSE_CD
FROM
adv_course_credit cc
WHERE
cc.year = p_year AND
-- rela_pk
cc.sequence_number = p_sequence_number AND
cc.closed_ind = 'N';
BEGIN
FOR v_at_rec IN c_adv_course_credit(p_sequence_number, p_year) LOOP
v_return_var := v_at_rec.EXTERNAL_COURSE_CD;
DBMS_OUTPUT.PUT_LINE('?output = ' || v_return_var);
EXIT;
END LOOP;
RETURN v_return_var;
END;
If I change the cursor to use hard-coded numbers the function works and returns actual result.
WHERE
-- year
cc.year = 2018 AND
-- rela_pk
cc.sequence_number = 92919 AND
cc.closed_ind = 'N';
Your function is defined as (ignoring the data types):
advp_test_cursor(p_sequence_number, p_year)
but you're calling it as
advp_test_cursor(2018, 92919);
which has the arguments the wrong way round. You either need to flip them:
advp_test_cursor(92919, 2018);
or use named parameter notation:
advp_test_cursor(p_year=>2018, p_sequence_number=>92919)
or indeed combine both:
advp_test_cursor(p_sequence_number=>92919, p_year=>2018)
You do not need to use cursors:
CREATE OR REPLACE Function SISD_OWNER.advp_test_cursor (
p_sequence_number IN adv_course_credit.sequence_number%TYPE,
p_year IN adv_course_credit.year%TYPE
) RETURN adv_course_credit.EXTERNAL_COURSE_CD%TYPE
IS
v_return_var adv_course_credit.EXTERNAL_COURSE_CD%TYPE;
BEGIN
SELECT EXTERNAL_COURSE_CD
INTO v_return_var
FROM adv_course_credit
WHERE year = p_year
AND sequence_number = p_sequence_number
AND closed_ind = 'N';
DBMS_OUTPUT.PUT_LINE('?output = ' || v_return_var);
RETURN v_return_var;
EXCEPTION
WHEN NO_DATA_FOUND THEN
RETURN 'Not working';
END;

Second statement in begin block is not executed

I have written this stored procedure in Oracle:
CREATE OR REPLACE FUNCTION GET_SOLVER_ID(username_in IN VARCHAR2)
RETURN NUMBER
IS
solver_id number(19);
system_user_id number(19);
BEGIN
SELECT id
INTO solver_id
FROM usr_solver
WHERE username = username_in;
select ID into system_user_id from USR_USER where USER_TYPE = 'X';
solver_id := nvl(solver_id, system_user_id);
RETURN(solver_id);
END;
When I call the function with username that doesn't exist in table usr_solver I get null for the result. I expect to get system_user_id instead.
It seems like the other select statement and nvl function in begin block didn't execute.
Could you help, I can't see the reason why...
Thanks,
mismas
This should do what you want
CREATE OR REPLACE FUNCTION GET_SOLVER_ID(
username_in IN VARCHAR2)
RETURN NUMBER
IS
some_id NUMBER(19);
BEGIN
BEGIN
SELECT id
INTO some_id
FROM usr_solver
WHERE username = username_in;
EXCEPTION
WHEN NO_DATA_FOUND THEN
SELECT ID
INTO some_id
FROM USR_USER
WHERE USER_TYPE = 'X';
END;
RETURN(some_id);
END;

Returning multiple values from a function in oracle

I have the following table:
T_TYPE_ID T_TYPE T_TYPE_PRICE T_TYPE_START_DATE T_TYPE_END_DATE
1 student 10.95 01.04.2015 00:00:00 30.06.2015 00:00:00
2 Concession 5.5 01.04.2015 00:00:00 30.06.2015 00:00:00
I need to:
Create FUNC_get_ t_type_end_date function
This function should contain the following input parameter: t_type_p and the following output parameters: t_type_price_p and t_type_end_date_p. It should return 1 if having a record with t_type as t_type_p otherwise return 0. In addition, in the case of having a record, it should assign the latest t_type_end_date to t_type_end_date_p and t_type_price to t_type_price_p. Please note that t_type_end_date_p can be null; it means that the associated price is currently valid.
I have written the following code:
CREATE OR REPLACE FUNCTION FUNC_get_t_type_end_date
( t_type_p IN VARCHAR2)
RETURN NUMBER
AS
cnum NUMBER;
CURSOR cr1 IS
SELECT t_type
FROM ticket_type
WHERE t_type = t_type_p;
BEGIN
OPEN cr1;
FETCH cr1 INTO cnum;
IF cr1%NOTFOUND THEN
cnum := 0;
END IF;
CLOSE cr1;
RETURN cnum;
END;
I did not get any clue on how to return multiple values from a function. I am using oracle.
Hint:
create or replace FUNCTION FUNC_get_ t_type_end_date (…)
return number
as
-- define a variable to return a number and assign 0 to it
-- define a cursor to obtain t_type_price, t_type_end_date of the given t_type_p. The t_type_end_date values should be sorted in descending order – to do so the first record will contain either null or the latest of t_type_end_date
BEGIN
-- open cursor
-- fetch the first record from the cursor to t_type_price_p and t_type_end_date_p
-- if (having a record) then …
-- close cursor
RETURN …
END;
It is not possible to return more than one variable from function. However, it is possible to return a customized variable (i.e. record) type that contains multiple values. To do this, you need first to define type contains the three variables you want to return as follows:
TYPE new_type is record(cnum number, t_type_end_date_p timestamp, t_type_price_p timestamp);
Then you can use it in your function as follows:
CREATE OR REPLACE FUNCTION FUNC_get_t_type_end_date ( t_type_p IN VARCHAR2)
RETURN new_type AS
new_type_variable newtype;
CURSOR cr1 IS
SELECT t_type
FROM ticket_type
WHERE t_type = t_type_p;
BEGIN
OPEN cr1;
FETCH cr1 INTO cnum;
IF cr1%NOTFOUND THEN
SELECT 0, null, null into new_type_variable from dual;
ELSE
SELECT 1, cr1.t_type_end_date, cr1.t_type_price into new_type_variable from dual;
END IF;
CLOSE cr1;
RETURN new_type_variable ;
END;
Try this:
create or replace function func_get_t_type_end_date(t_type_p in varchar2, t_type_price_p out number, t_type_end_date_p out date) return number
as
cnum NUMBER;
CURSOR cr1 IS
SELECT t_type_price,t_type_end_date
FROM ticket_type t
WHERE t_type = t_type_p
and not exists (select 1
from ticket_type t2
where t2.t_type = t.t_type
and t2.t_type_end_date>t.t_type_end_date);
BEGIN
OPEN cr1;
FETCH cr1 INTO t_type_price_p,t_type_end_date_p;
IF cr1%NOTFOUND THEN
cnum := 0;
else
cnum := 1;
END IF;
CLOSE cr1;
RETURN cnum; end;
Example of using:
set serveroutput on
declare
v_result number;
v_type_price_p number;
v_type_end_date_p date;
begin
v_result:=func_get_t_type_end_date(t_type_p=>'student',t_type_price_p=>v_type_price_p,t_type_end_date_p=>v_type_end_date_p);
dbms_output.put_line('Result: '||v_result);
dbms_output.put_line('Price: '||v_type_price_p);
dbms_output.put_line('End date: '||v_type_end_date_p);
end;
/

Resources