PL/SQL: SQL Statement ignored with oracle function - sql

I try to compile the function but they show the error "PL/SQL: SQL Statement ignored" and mention the function "PO_PROD_CODE".
Could you please help to give some comment.
PL/SQL: SQL Statement ignored with oracle function (Function "PO_PROD_CODE")
FUNCTION PO_PROD_CODE (s_prod_code VARCHAR2) RETURN VARCHAR2 IS
v_po_prod_code_result VARCHAR2(100);
BEGIN
SELECT FLEX_VALUE
INTO v_po_prod_code_result
FROM apps.FND_FLEX_VALUES_VL
WHERE attribute1 IN ('BXX', 'EXX', 'GXX', 'HKXX', 'PDX', 'PSX', 'GPX')
AND FLEX_VALUE = s_prod_code ;
RETURN v_po_prod_code_result;
END;
/
FUNCTION PO_DOC_LOCATION_TEXT (N_ORG_ID NUMBER, N_PO_HEADER_ID NUMBER) RETURN VARCHAR2 IS
v_po_doc_location_text VARCHAR2(150);
s_prod_code VARCHAR2(20);
BEGIN
SELECT 'PO\'||PO_DIVISION_CODE||'\'||PO_PRODUCT_LINE||'\'||PO_NUM||'\' AS "DOC_TEXT"
INTO v_po_doc_location_text
FROM (SELECT poh.SEGMENT1 PO_NUM,
poh.ORG_ID,
poh.ATTRIBUTE14 AS "PO_PRODUCT_LINE",
poh.ATTRIBUTE15 AS "PO_DIVISION",
CASE (SELECT ffvv.attribute1 bs_group
FROM apps.fnd_flex_values_vl ffvv,
apps.fnd_flex_value_sets ffvs
WHERE ffvv.flex_value_set_id = ffvs.flex_value_set_id
AND ffvs.flex_value_set_name = 'XXX_PROD_LINES'
AND ffvv.enabled_flag = 'Y'
AND ((ffvv.attribute4 = 'Y' AND poh.ORG_ID = 83) OR (ffvv.attribute5 = 'Y' AND poh.ORG_ID = 87))
AND ffvv.flex_value = PO_PROD_CODE (v_po_prod_code_result, s_prod_code) --call the "PO_PROD_CODE" function get the sql feild "prod_line_code")
WHEN 'ABC' THEN 'AB' --FLEX_VALUE_ID,FLEX_VALUE PRO_CODE,
WHEN 'DEF' THEN 'DE'
WHEN 'GSD' THEN 'HK'
WHEN 'HIG' THEN 'HG'
WHEN 'PIG' THEN 'PG'
WHEN 'BCE' THEN 'BE'
WHEN 'GP' THEN 'HK'
ELSE ''
END PO_DIVISION_CODE
FROM APPS.PO_HEADERS_ALL poh
WHERE poh.ORG_ID = N_ORG_ID
AND poh.po_header_id = N_PO_HEADER_ID
);
EXCEPTION
WHEN OTHERS THEN
v_po_doc_location_text := 'PO\MO\';
END;
RETURN v_po_doc_location_text + s_prod_code;
END;
Complie success!
When I try to run the script, the detail as follow:
SELECT abc.XXX_util.PO_DOC_LOCATION_TEXT ('83','1145225') from dual;
The error message said
ORA-06502: PL/SQL: numeric or value error: character to number conversion error

It is not FROM ... INTO, but INTO ... FROM:
FUNCTION PO_PROD_CODE (s_prod_code VARCHAR2) RETURN VARCHAR2 IS
v_po_prod_code_result VARCHAR2(100);
BEGIN
SELECT FLEX_VALUE
FROM apps.FND_FLEX_VALUES_VL --> this is
INTO v_po_prod_code_result --> wrong
WHERE attribute1 IN ('BXX', 'EXX', 'GXX', 'HKXX', 'PDX', 'PSX', 'GPX')
AND FLEX_VALUE = s_prod_code ;
RETURN v_po_prod_code_result;
END;
/
Should be
SELECT FLEX_VALUE
INTO v_po_prod_code_result
FROM apps.FND_FLEX_VALUES_VL
[EDIT]
The second function's CASE is invalid. That SELECT should be moved out of it, its tables used in main SELECT's FROM clause. Something like this (which is OK in syntax, I don't know whether it'll work):
FUNCTION PO_DOC_LOCATION_TEXT (N_ORG_ID NUMBER, N_PO_HEADER_ID NUMBER)
RETURN VARCHAR2
IS
v_po_doc_location_text VARCHAR2 (150);
BEGIN
SELECT 'PO\'
|| PO_DIVISION_CODE
|| '\'
|| PO_PRODUCT_LINE
|| '\'
|| PO_NUM
|| '\'
AS "DOC_TEXT"
INTO v_po_doc_location_text
FROM (SELECT poh.SEGMENT1 PO_NUM,
poh.ORG_ID,
poh.ATTRIBUTE14 AS "PO_PRODUCT_LINE",
poh.ATTRIBUTE15 AS "PO_DIVISION",
CASE ffvv.attribute1
WHEN 'ABC' THEN 'AB' --FLEX_VALUE_ID,FLEX_VALUE PRO_CODE,
WHEN 'DEF' THEN 'DE'
WHEN 'GSD' THEN 'HK'
WHEN 'HIG' THEN 'HG'
WHEN 'PIG' THEN 'PG'
WHEN 'BCE' THEN 'BE'
WHEN 'GP' THEN 'HK'
ELSE ''
END
PO_DIVISION_CODE
FROM APPS.PO_HEADERS_ALL poh,
apps.fnd_flex_values_vl ffvv,
apps.fnd_flex_value_sets ffvs
WHERE ffvv.flex_value_set_id = ffvs.flex_value_set_id
AND ffvs.flex_value_set_name = 'XXX_PROD_LINES'
AND ffvv.enabled_flag = 'Y'
AND ( ( ffvv.attribute4 = 'Y'
AND poh.ORG_ID = 83)
OR ( ffvv.attribute5 = 'Y'
AND poh.ORG_ID = 87))
AND ffvv.flex_value =
PO_PROD_CODE (v_po_prod_code_result, s_prod_code)
AND poh.ORG_ID = N_ORG_ID
AND poh.po_header_id = N_PO_HEADER_ID);
RETURN v_po_doc_location_text;
EXCEPTION
WHEN OTHERS
THEN
v_po_doc_location_text := 'PO\MO\';
END;

There are several errors in your code and you'll have to correct them all:
You're supposed to write the SELECT INTO statement by writing the INTO part before writing the FROM (as you have written in your PO_DOC_LOCATION_TEXT function)
Your WHEN-THEN comparisons are missing the CASE word
In your PO_DOC_LOCATION_TEXT function you have called your PO_PROD_CODE function by passing two parameters, but it only accepts one parameter. You should only pass input parameter. If you want to fill local variable with the returning value from PO_PROD_CODE function, you should do it outside of SQL query.
You are missing one ) bracket in your query inside PO_DOC_LOCATION_TEXT function and I guess it's the one that got lost inside your call the "PO_PROD_CODE" function get the sql feild "prod_line_code" comment
You're ending your PO_DOC_LOCATION_TEXT function before the RETURN statement. You should add one more BEGIN before your SELECT INTO
I can also see that your PO_PROD_CODE function (as it's now written) always returns the input value (s_prod_code).
It's selecting fnd_flex_values_vl.flex_value into return variable just after saying that the very same flex_value must be equal to s_prod_code, which is your function's input parameter.
I guess this is the way you intended your code to be like:
FUNCTION PO_PROD_CODE (s_prod_code VARCHAR2)
RETURN VARCHAR2
IS
v_po_prod_code_result VARCHAR2 (100);
BEGIN
SELECT flex_value
INTO v_po_prod_code_result
FROM apps.fnd_flex_values_vl
WHERE attribute1 IN ('BXX',
'EXX',
'GXX',
'HKXX',
'PDX',
'PSX',
'GPX')
AND flex_value = s_prod_code; -- STILL JUST RETURNS THE INPUT PARAMETER
RETURN v_po_prod_code_result;
END;
/
FUNCTION PO_DOC_LOCATION_TEXT (N_ORG_ID NUMBER, N_PO_HEADER_ID NUMBER)
RETURN VARCHAR2
IS
v_po_doc_location_text VARCHAR2 (150);
s_prod_code VARCHAR2(20); -- NEEDS TO HAVE SOME VALUE ASSIGNED BEFORE PASSING IT TO "PO_PROD_CODE" FUNCTION BELOW IN CODE
BEGIN
BEGIN
SELECT 'PO\' || PO_DIVISION_CODE || '\' || PO_PRODUCT_LINE || '\' || PO_NUM || '\' AS "DOC_TEXT"
INTO v_po_doc_location_text
FROM (SELECT poh.SEGMENT1 PO_NUM,
poh.ORG_ID,
poh.ATTRIBUTE14 AS "PO_PRODUCT_LINE",
poh.ATTRIBUTE15 AS "PO_DIVISION",
CASE (SELECT ffvv.attribute1 bs_group
FROM apps.fnd_flex_values_vl ffvv, apps.fnd_flex_value_sets ffvs
WHERE ffvv.flex_value_set_id = ffvs.flex_value_set_id
AND ffvs.flex_value_set_name = 'XXX_PROD_LINES'
AND ffvv.enabled_flag = 'Y'
AND ( (ffvv.attribute4 = 'Y' AND poh.ORG_ID = 83) OR (ffvv.attribute5 = 'Y' AND poh.ORG_ID = 87))
AND ffvv.flex_value = PO_PROD_CODE (s_prod_code) --call the "PO_PROD_CODE" function get the sql feild "prod_line_code", "v_po_prod_code_result" removed because PO_PROD_CODE expects only one parameter and because only input parameters can be written here
)
WHEN 'ABC' THEN 'AB' --FLEX_VALUE_ID,FLEX_VALUE PRO_CODE,
WHEN 'DEF' THEN 'DE'
WHEN 'GSD' THEN 'HK'
WHEN 'HIG' THEN 'HG'
WHEN 'PIG' THEN 'PG'
WHEN 'BCE' THEN 'BE'
WHEN 'GP' THEN 'HK'
ELSE ''
END
PO_DIVISION_CODE
FROM APPS.PO_HEADERS_ALL poh
WHERE poh.ORG_ID = N_ORG_ID AND poh.po_header_id = N_PO_HEADER_ID);
EXCEPTION
WHEN OTHERS
THEN
v_po_doc_location_text := 'PO\MO\';
END;
RETURN v_po_doc_location_text;
END;
I hope I helped!

Related

function in plsql

I have created this function and it works:
create or replace function log_in(
p_ssnr in customer.ssnr%type,
p_password in customer.password%type)
return number
as
v_number number(1);
begin
if
(p_ssnr is not null and p_password is not null) then
v_number:= 1;
else
v_number:= 0;
end if;
return v_number;
end;
If I then type: select log_in('social security number','the password') from dual; then I get a "1"
so it works. But you could basically type whatever you want and it will work so it is not a clean code. Since you can't include subquery in the if statement, how can you create the function so you only return 1 when you actually type a social security number (ssnr) and a password that matches the actual customer table? and otherwise you return 0?
NOt sure if you can have multiple rows for same customer. If yes, then use this:
create or replace function log_in(
p_ssnr in customer.ssnr%type,
p_password in customer.password%type)
return number
as
v_number number(1);
begin
select case when count(*) > 0 then 1 else 0 end
into v_number
from customer
where ssnr = p_ssnr and password = p_password;
return v_number;
end;
If not then this should be fine:
create or replace function log_in(
p_ssnr in customer.ssnr%type,
p_password in customer.password%type)
return number
as
v_number number(1);
begin
count(*)
into v_number
from customer
where ssnr = p_ssnr and password = p_password;
return v_number;
end;

PL/SQL [SQL Statement ignored]

I'm having issues to add some code to my package file which is laying on the database. The issue that is being displayed by SQLPlus is "The SQL statement is ignored" but i am not able to track the issue.
It would be nice, if somebody of you out there, would help me, trying to figure out what the issue is.
Thanks in advance.
Function getLetterheadAndLayoutConf(p_invoice_type_code IN Varchar2,
p_admission_type_code IN Varchar2,
p_accounting_type_code IN Varchar2,
p_costbearer_id IN Number,
p_institute_id IN Number,
p_clearing_center_id IN Number,
p_deduction_defined_jn IN Varchar2,
p_letterhead_code OUT Varchar2,
p_layout_code OUT Varchar2)
Return Integer IS
v_Return Integer;
CURSOR cRechnungLetterheadLayout(p_p_invoice_type_code Varchar2,
p_p_admission_type_code Varchar2,
p_p_accounting_type_code Varchar2,
p_p_costbearer_id Integer,
p_p_institute_id Integer,
p_p_clearing_center_id Integer,
p_p_deduction_defined_jn Varchar2) IS
SELECT allc_letterhead_code, allc_layout_code
FROM acc_letterhead_layout_conf
WHERE ( ( allc_invoice_type_code = p_p_invoice_type_code
OR allc_invoice_type_code IS NULL
)
AND ( allc_admission_type_code = p_p_admission_type_code
OR allc_admission_type_code IS NULL
)
AND ( allc_accounting_type_code = p_p_accounting_type_code
OR allc_accounting_type_code IS NULL
)
AND ( allc_costbearer_id = p_p_costbearer_id
OR allc_costbearer_id IS NULL
)
AND ( allc_clearing_center_id = p_p_clearing_center_id
OR allc_clearing_center_id IS NULL
)
AND ( allc_deduction_defined_jn = p_p_deduction_defined_jn
OR allc_deduction_defined_jn IS NULL
)
)
AND nvl(allc_institute_id, p_p_institute_id)
ORDER BY allc_institute_id DESC, allc_sort_no ASC;
Begin
if cRechnungLetterheadLayout%ISOPEN Then CLOSE cRechnungLetterheadLayout; End
If;
OPEN cRechnungLetterheadLayout(p_invoice_type_code, p_admission_type_code, p_accounting_type_code,
p_costbearer_id, p_institute_id, p_clearing_center_id,
p_deduction_defined_jn);
FETCH cRechnungLetterheadLayout
into p_layout_code,
p_letterhead_code;
CLOSE cRechnungLetterheadLayout;
dbg.i(1, 'Vorgabe Letterhead = ''' || p_letterhead_code || '''');
dbg.i(1, 'Vorgabe Layout = ''' || p_layout_code || '''');
v_Return := 1;
End getLetterheadAndLayoutConf;

Error(3,34): PLS-00201: identifier XXX must be declared

I have this procedure in a Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production DB, bit I have this error everytime I try to recompile it. The procedure is a copy and paste from another DB, so there is now error, because in the other DB the package works properly... nevertheless I got this error:
Error(1,35): PLS-00304: cannot compile body of 'P_COUNTRY_PLATS' without its specification
.
create or replace PACKAGE "P_COUNTRY_PLATS" is
procedure createNew (p_msisdn IN lopes.country_plats.recipient_msisdn%TYPE
,p_channel IN lopes.country_plats.channel%TYPE
,p_message IN lopes.country_plats.message%TYPE
);
procedure createNew (p_msisdn IN lopes.country_plats.recipient_msisdn%TYPE
,p_channel IN lopes.country_plats.channel%TYPE
,p_message IN lopes.country_plats.message%TYPE
,p_request_date IN lopes.country_plats.request_date%TYPE
,p_action_history_id IN lopes.country_plats.action_history_id%TYPE
);
procedure createNew (p_msisdn IN lopes.country_plats.recipient_msisdn%TYPE
,p_channel IN lopes.country_plats.channel%TYPE
,p_message IN lopes.country_plats.message%TYPE
,p_request_date IN lopes.country_plats.request_date%TYPE
,p_action_history_id IN lopes.country_plats.action_history_id%TYPE
,p_ac_scheduled_action_id IN lopes.country_plats.ac_scheduled_action_id%TYPE
);
procedure getNextMsgToSend (p_channel IN lopes.country_plats.channel%TYPE
,p_ip_address IN OUT VARCHAR2
,p_message IN OUT lopes.country_plats.message%TYPE
,p_msg_id IN OUT lopes.country_plats.country_plats_id%TYPE
);
procedure getNextMsgToSendByImei(p_imei IN VARCHAR2, p_message IN OUT VARCHAR2, p_msg_id IN OUT NUMBER);
procedure setStatus(p_msg_id IN NUMBER, p_status IN VARCHAR2);
procedure cancel_scheduled_actions;
procedure cancel_scheduled_actions(p_msg_id IN number);
end;
/
create or replace PACKAGE BODY "P_COUNTRY_PLATS" is
procedure createNew (p_msisdn IN lopes.country_plats.recipient_msisdn%TYPE
,p_channel IN lopes.country_plats.channel%TYPE
,p_message IN lopes.country_plats.message%TYPE
)
is
begin
createNew(p_msisdn, p_channel, p_message, sysdate, null, null);
end;
procedure createNew (p_msisdn IN lopes.country_plats.recipient_msisdn%TYPE
,p_channel IN lopes.country_plats.channel%TYPE
,p_message IN lopes.country_plats.message%TYPE
,p_request_date IN lopes.country_plats.request_date%TYPE
,p_action_history_id IN lopes.country_plats.action_history_id%TYPE
)
is
begin
createNew(p_msisdn, p_channel, p_message, p_request_date, p_action_history_id, null);
end;
procedure createNew (p_msisdn IN lopes.country_plats.recipient_msisdn%TYPE
,p_channel IN lopes.country_plats.channel%TYPE
,p_message IN lopes.country_plats.message%TYPE
,p_request_date IN lopes.country_plats.request_date%TYPE
,p_action_history_id IN lopes.country_plats.action_history_id%TYPE ,
p_ac_scheduled_action_id IN lopes.country_plats.ac_scheduled_action_id%TYPE
)
is
PsdRetryNbroutgoing_psd number;
begin
PsdRetryNbr := of_owner.p_ru.getPsdRetryNbr(p_msisdn);
of_owner.p_db_trc.trc(1007, '-'||p_channel||'-'||p_msisdn||'-'||p_message||'-'||p_request_date||'-'||p_action_history_id||'-'||p_ac_scheduled_action_id||'-'||PsdRetryNbr);
insert into lopes.country_plats
(country_plats_id,channel,recipient_msisdn,message,request_date,status,action_history_id, ac_scheduled_action_id, remaining_retry_nbr) values (
lopes.SEQ_COUNTRY_PLATS_ID.nextval
,p_channel
,p_msisdn
,p_message
, p_request_date
,'R'
,p_action_history_id
,p_ac_scheduled_action_id
,PsdRetryNbr
);
end;
procedure getNextMsgToSend(p_channel IN lopes.country_plats.channel%TYPE
,p_ip_address IN OUT VARCHAR2
,p_message IN OUT lopes.country_plats.message%TYPE
,p_msg_id IN OUT lopes.country_plats.country_plats_id%TYPE
)
is
begin
select op.country_plats_id, op.message, of_owner.p_ru.getRemoteUnitCurrentIP(recipient_msisdn)
into p_msg_id, p_message, p_ip_address
from lopes.country_plats op
where ( (op.status ='R')
or ( (op.status = 'P')
and (op.outgoing_date+(of_owner.p_ru.getPsdRetryDelay(op.recipient_msisdn)/(60*24)) <= sysdate)
)
)
and rownum=1
order by request_date asc;
update lopes.country_plats
set outgoing_date = sysdate
, status = decode(remaining_retry_nbr, 0, 'F', 'P')
, remaining_retry_nbr = remaining_retry_nbr-1
where country_plats_id = p_msg_id;
exception when no_data_found then
p_msg_id := -1;
p_ip_address:= '';
p_message := '';
end;
procedure getNextMsgToSendByImei(p_imei IN VARCHAR2,
p_message IN OUT VARCHAR2,
p_msg_id IN OUT NUMBER
) is
p_vehicle_id number(10);
p_msisdn varchar2(50);
begin
p_msg_id := -1;
p_message := '';
select msisdn, vehicle_id
into p_msisdn, p_vehicle_id
from of_owner.remote_unit, of_owner.vehicle
where remote_unit.imei = p_imei
and remote_unit.remote_unit_id = vehicle.remote_unit_id(+);
begin
select op.country_plats_id, op.message
into p_msg_id, p_message
from lopes.country_plats op
where ( (op.status ='R')
or ( (op.status = 'P')
and (op.outgoing_date+(of_owner.p_ru.getPsdRetryDelay(op.recipient_msisdn)/(60*24)) <= sysdate)
)
)
and op.recipient_msisdn = p_msisdn
and rownum=1
order by request_date asc;
update lopes.country_plats
set outgoing_date = sysdate
, status = decode(remaining_retry_nbr, 0, 'F', 'P')
, remaining_retry_nbr = remaining_retry_nbr-1
where country_plats_id = p_msg_id;
exception when others then
null;
end;
-- Check if garmin message to send
if (p_msg_id=-1) and (p_vehicle_id is not null) then
p_msg_id := of_owner.p_gu_message.getNextMessageToSend(p_vehicle_id, p_message);
if (p_msg_id is null) then
p_msg_id:=-1;
end if;
end if;
exception when no_data_found then
p_msg_id := -1;
p_message := '';
end;
procedure setStatus(p_msg_id IN NUMBER, p_status IN VARCHAR2)
is
begin
update lopes.country_plats
set status = decode(p_status, 'S', 'S', decode(remaining_retry_nbr, 0, 'F', 'P'))
where country_plats_id = p_msg_id;
end;
procedure cancel_scheduled_actions is
begin
delete from lopes.country_plats
where status = 'R'
and ac_scheduled_action_id is not null;
end;
procedure cancel_scheduled_actions(p_msg_id IN number) is
begin
delete from lopes.country_plats
where country_plats_id = p_msg_id;
end;
end P_COUNTRY_PLATS;
/
The / character is a terminator for a PL/SQL block and your script is missing them.
Change:
end;
create or replace PACKAGE BODY "P_COUNTRY_PLATS" is
To:
end;
/
create or replace PACKAGE BODY "P_COUNTRY_PLATS" is
and change the final:
end;PLATS
to:
end P_COUNTRY_PLATS;
/

Oracle PL/SQL code return null

I write this function in oracle PL/SQL to return counter of employee in the university based on their sex and collage nationality,sex , grade and qualification ETC.
FUNCTION GET_EMP_COUNT_GENERIC (
P_ORGANIZATION_ID VARCHAR2,
P_GRADE VARCHAR2,
P_SEX VARCHAR2,
P_NAT_TYPE VARCHAR2,
P_DATE DATE,
P_EMP_TYPE VARCHAR2,
P_QUALIFIC_CAT VARCHAR2 )
RETURN NUMBER IS
V_COUNT NUMBER;
BEGIN
SELECT COUNT (EMP.PERSON_ID) INTO V_COUNT
FROM PER_ALL_ASSIGNMENTS_F ASS,
PER_ALL_PEOPLE_F EMP,
HR_ALL_ORGANIZATION_UNITS ORG,
PAY_PEOPLE_GROUPS PPG,
PER_GRADES GRD
WHERE ASS.PERSON_ID = EMP.PERSON_ID
AND ASS.ORGANIZATION_ID = ORG.ORGANIZATION_ID
AND ASS.PEOPLE_GROUP_ID = PPG.PEOPLE_GROUP_ID
AND ASS.GRADE_ID = GRD.GRADE_ID
AND EMP.PERSON_TYPE_ID = 1145
AND (ASS.ORGANIZATION_ID = P_ORGANIZATION_ID OR P_ORGANIZATION_ID IS NULL)
AND (GRD.NAME = P_GRADE OR P_GRADE IS NULL)
AND (EMP.SEX = P_SEX OR P_SEX IS NULL)
AND (PPG.SEGMENT2 = P_NAT_TYPE OR P_NAT_TYPE IS NULL)
AND (PPG.SEGMENT1 =P_EMP_TYPE OR P_EMP_TYPE IS NULL)
AND (XXPNU_HCM_PKG.GET_QUALIFICATION_NAME(EMP.PERSON_ID,EMP.BUSINESS_GROUP_ID)
= P_QUALIFIC_CAT OR P_QUALIFIC_CAT IS NULL)
AND P_DATE BETWEEN ASS.EFFECTIVE_START_DATE
AND ASS.EFFECTIVE_END_DATE
AND P_DATE BETWEEN EMP.EFFECTIVE_START_DATE
AND EMP.EFFECTIVE_END_DATE;
RETURN V_COUNT;
END GET_EMP_COUNT_GENERIC;
But when I call it in query, its return null or zero value??
i dont know what is my mistake
SELECT
XXPNU_HCM_PKG.GET_EMP_COUNT_GENERIC (null,null,'M',null,:P_DATE,'FACULTY',null) as FACULTY_M,
XXPNU_HCM_PKG.GET_EMP_COUNT_GENERIC (null,null,'F',null,:P_DATE,'FACULTY',null) as FACULTY_F
--------------------------------TABLES------------------------------------------
FROM PER_ALL_ASSIGNMENTS_F ASS,
PER_ALL_PEOPLE_F EMP,
HR_ALL_ORGANIZATION_UNITS ORG,
PAY_PEOPLE_GROUPS PPG,
PER_GRADES GRD
--------------------------------- CONDITIONS -----------------------------------
WHERE
ASS.PERSON_ID = EMP.PERSON_ID
AND ASS.ORGANIZATION_ID = ORG.ORGANIZATION_ID
AND ASS.PEOPLE_GROUP_ID = PPG.PEOPLE_GROUP_ID
AND ASS.GRADE_ID = GRD.GRADE_ID
AND EMP.PERSON_TYPE_ID = 1145
--------------------------------THIS YEAR DATE ---------------------------------
AND :P_DATE BETWEEN ASS.EFFECTIVE_START_DATE
AND ASS.EFFECTIVE_END_DATE
AND :P_DATE BETWEEN EMP.EFFECTIVE_START_DATE
AND EMP.EFFECTIVE_END_DATE ;
Your function will return 0 when it finds no rows that match your predicates in the function.
And because you use the function in the select-section of a select-statement it will return NULL when a exception occurs within the function.
Try using an exceptio handler returning -1. Then you know an exception occured.
remenber, an exception is not handled when a function is called within a select statement (in all DML I would say, but I don't know that for sure)

Cursor for loop to return output in proper format in oracle stored procedure

I have below procedure in which i want to return the output of variable value brand_name.BRAND_NAME. I am getting the correct output. But i want to return it in proper format. For example right now i am getting the output as
BRAND_NAMES:FNC
BRAND_NAMES:LIDL
But i want to return the output as:
BRAND_NAME: FNC,LIDL
Here is my stored procedure:
FUNCTION BUILD_ALERT_EMAIL_BODY
(
IN_ALERT_LOGS_TIMESTAMP IN TIMESTAMP
, IN_ALERT_LOGS_LOG_DESC IN VARCHAR2
, IN_KPI_LOG_ID IN NUMBER
) RETURN VARCHAR2 AS
BODY VARCHAR2(4000) := '';
V_KPI_DEF_ID NUMBER := '';
V_BRAND_NAME VARCHAR2(100) := '';
V_KPI_TYPE_ID NUMBER := '';
CURSOR brand_names_cur
IS
Select BR.NAME AS BRAND_NAME INTO V_BRAND_NAME FROM RATOR_MONITORING_CONFIGURATION.KPI_DEFINITION KD JOIN RATOR_MONITORING_CONFIGURATION.KPI_DEFINITION_BRAND KDB ON KD.KPI_DEF_ID = KDB.KPI_DEF_ID JOIN
RATOR_MONITORING_CONFIGURATION.BRAND BR ON KDB.BRAND_ID = BR.BRAND_ID WHERE KD.KPI_DEF_ID = V_KPI_DEF_ID;
BEGIN
Select KPI_DEF_ID INTO V_KPI_DEF_ID FROM KPI_LOGS WHERE KPI_LOG_ID = IN_KPI_LOG_ID;
Select KT.KPI_TYPE_ID INTO V_KPI_TYPE_ID FROM RATOR_MONITORING_CONFIGURATION.KPI_DEFINITION KD JOIN RATOR_MONITORING_CONFIGURATION.KPI_TYPE KT ON KD.KPI_TYPE = KT.KPI_TYPE_ID WHERE KD.KPI_DEF_ID = V_KPI_DEF_ID;
FOR brand_name IN brand_names_cur
LOOP
BODY := BODY || 'BRAND_NAME:' || brand_name.BRAND_NAME || Chr(10) || Chr(13);
END LOOP;
BODY := BODY || 'ALERT_DESCRIPTION:' || to_char(IN_ALERT_LOGS_LOG_DESC);
RETURN BODY;
END BUILD_ALERT_EMAIL_BODY;
Add V_FIRST_RECORD variable
V_FIRST_RECORD Boolean := true;
and use it in your loop like this
if v_first_record then
body := 'BRAND_NAME: '||brane_name.BRAND_NAME;
else
body := body ||','||brane_name.BRAND_NAME;
v_first_record := false;
end if;