How to compare a negative number in pl/sql if statement - plsql

Here is the complete function
Function GetStatus_TecTrac( inquiry_id IN number )
RETURN VARCHAR2
IS
status VARCHAR2(12);
deptId number;
endDate date;
BEGIN
select DEPT_ID, END_DATE into deptId , endDate from (
select DEPT_ID, END_DATE
from TB_PROJECT_TRACKING_DURATION tp
where tp.INQUIRY_ID = inquiry_id
order by START_DATE desc
)
where rownum = 1;
if (deptId = -61 and endDate is not null) then
status := 'closed';
else
status := 'open';
end if;
RETURN status;
END;
It always returns the status as "closed" on each inquiry_id whatever the value of deptId and endDate is.
Help me to solve this.
Thanks in advance.
Farhan

Works for me. How did you test?
SQL> declare
deptid number := 44;
enddate date := sysdate;
status varchar2(10);
begin
if (deptId = -61 and endDate is not null) then
status := 'closed';
else
status := 'open';
end if;
dbms_output.put_line(status);
end;
/
open
PL/SQL procedure successfully completed.

Related

sys_refcursor result not visible

I created a procedure which will give the resultset in a SYS_REFCURSOR.
But I don't see the result set in the output, not even the count of records.
CREATE OR REPLACE PROCEDURE p_get_job_run_details_test (p_details OUT sys_refcursor) AS
l_start_date TIMESTAMP;
date1 TIMESTAMP;
l_end_date TIMESTAMP;
l_count INTEGER;
p_start_date date;
p_end_date date;
BEGIN
p_start_date := '11-JUN-2019';
p_end_date := '11-JUN-2019';
select to_timestamp_tz(p_start_date || ' 00:00:00 EUROPE/PARIS', 'DD-MON-YYYY HH24:MI:SS TZR')
into l_start_date
from dual;
select to_timestamp_tz(p_end_date || ' 23:59:59 EUROPE/PARIS', 'DD-MON-YYYY HH24:MI:SS TZR')
into l_end_date
from dual;
select count(*)
into l_count
FROM all_scheduler_job_run_details
WHERE job_name = 'RANDOM_JOB'
and log_date >= l_start_date
and log_date <= l_end_date
;
dbms_output.put_line(l_count);
OPEN p_details FOR
SELECT owner, log_date, job_subname,
status, error# as error, req_start_date, actual_start_date,
run_duration, additional_info
FROM all_scheduler_job_run_details
WHERE log_date >= l_start_date
AND log_date <= l_end_date
AND job_name = 'RANDOM_JOB'
ORDER BY log_date DESC;
END p_get_job_run_details_test;
I am expecting one row as an output.
If I do this separately
SELECT *--count(*) into l_count
FROM all_scheduler_job_run_details
WHERE log_date >= to_timestamp_tz('11-JUN-19' || ' 00:00:00 EUROPE/PARIS', 'DD-MON-YY HH24:MI:SS TZR')
AND log_date <= to_timestamp_tz('11-JUN-19' || ' 23:59:59 EUROPE/PARIS', 'DD-MON-YY HH24:MI:SS TZR')
AND job_name = 'RANDOM_JOB';
I can see the result : 1 row.
Your p_start_date and p_end_date variables are of the wrong datatype.
I ran your code, with the following line added after the to_timestamp_tz calls:
dbms_output.put_line(to_char(l_start_date, 'YYYY-MM-DD HH24:MI:SS') || '|' || to_char(l_end_date, 'YYYY-MM-DD HH24:MI:SS'));
The result was these nonsense dates with incorrect century:
0019-06-11 00:00:00|0019-06-11 23:59:59
The problem is these lines:
p_start_date date;
p_end_date date;
BEGIN
p_start_date := '11-JUN-2019';
p_end_date := '11-JUN-2019';
The variables are defined as DATE, so when a text literal is assigned to them, Oracle implicitly converts the literals to dates by applying your NLS_DATE_FORMAT. This is most likely not doing what you expect.
A simple fix would be to use proper DATE literals or TO_DATE conversions here:
p_start_date := DATE'2019-06-11';
p_end_date := DATE'2019-06-11';
-- or
p_start_date := TO_DATE('11-JUN-2019', 'DD-MON-YYYY');
p_end_date := TO_DATE('11-JUN-2019', 'DD-MON-YYYY');
Note that you also will have a problem in the to_timestamp_tz calls because Oracle will now implicitly convert your date variables to varchar2 in order to concatenate with ' 00:00:00 EUROPE/PARIS'.
Again, this will be done using your NLS_DATE_FORMAT setting, which is likely not what you expect.
Either use an explicit TO_CHAR conversion with date mask or make p_start_date and p_end_date proper varchar2 variables from the start.
Here's a version that works:
CREATE OR REPLACE PROCEDURE p_get_job_run_details_test (p_details OUT sys_refcursor) AS
l_start_date TIMESTAMP;
date1 TIMESTAMP;
l_end_date TIMESTAMP;
l_count INTEGER;
p_start_date varchar2(20);
p_end_date varchar2(20);
BEGIN
p_start_date := '11-JUN-2019';
p_end_date := '11-JUN-2019';
select to_timestamp_tz(p_start_date || ' 00:00:00 EUROPE/PARIS', 'DD-MON-YYYY HH24:MI:SS TZR')
into l_start_date
from dual;
select to_timestamp_tz(p_end_date || ' 23:59:59 EUROPE/PARIS', 'DD-MON-YYYY HH24:MI:SS TZR')
into l_end_date
from dual;
dbms_output.put_line(to_char(l_start_date, 'YYYY-MM-DD HH24:MI:SS') || '|' || to_char(l_end_date, 'YYYY-MM-DD HH24:MI:SS'));
select count(*)
into l_count
FROM all_scheduler_job_run_details
WHERE job_name = 'RANDOM_JOB'
and log_date >= l_start_date
and log_date <= l_end_date
;
dbms_output.put_line(l_count);
OPEN p_details FOR
SELECT owner, log_date, job_subname,
status, error# as error, req_start_date, actual_start_date,
run_duration, additional_info
FROM user_scheduler_job_run_details
WHERE log_date >= l_start_date
AND log_date <= l_end_date
AND job_name = 'RANDOM_JOB'
ORDER BY log_date DESC;
END p_get_job_run_details_test;

"ORA-01843: not a valid month" error

I am experiencing this error when trying to run the procedure from the codes.
"ORA-01843: not a valid month ORA-06512: at "NOSTAS_OWNER.INSERT_EXPORTMATRIX", line 68 ORA-06512: at line 1"
I'm passing the date as "DD/MM/YYYY" string. Not sure what caused the error. When running it in SQL Developer, it gives this error
ORA-06502: PL/SQL: numeric or value error: character to number conversion error
ORA-06512: at "NOSTAS_OWNER.INSERT_EXPORTMATRIX", line 68
ORA-06512: at line 17
create or replace PROCEDURE INSERT_EXPORTMATRIX
(
keyClass export_matrix.EXM_KEY_CLASS%type,
keyClassValue export_matrix.EXM_KEYCLASS_VALUE%type,
changedClass export_matrix.EXM_CHANGED_CLASS%type,
changedClassValue export_matrix.EXM_CHANGEDCLASS_VALUE%type,
dtTo IN VARCHAR2,
dtFrom IN VARCHAR2,
-- dtTo export_matrix.EXM_DATEFROM%type,
-- dtFrom EXPORT_MATRIX.EXM_DATETO%type,
vresult OUT NUMBER
) AS
iskeyClass number;
--today varchar2(50);
--today date;
fvvECCN number;
fvvALNR number;
BEGIN
iskeyClass := 0;
fvvECCN := 0;
fvvALNR := 0;
SAVEPOINT start_tran;
SELECT count(*) into iskeyClass FROM EXPORT_MATRIX
WHERE EXM_KEY_CLASS=keyClass and EXM_KEYCLASS_VALUE=keyClassValue;
-- SELECT to_date(SYSDATE,'DD/MM/YYYY') into today FROM DUAL;
SELECT count(*) into fvvECCN FROM FIELDS_VALUE_VALIDATION WHERE
--FVV_FAVL_NAME = 'ECCN' and FVV_VALUE = keyClassValue and (dtTo > trunc(sysdate));
FVV_FAVL_NAME = 'ECCN' and FVV_VALUE = keyClassValue and (sysdate between dtFrom and dtTo) or dtTo is null;
SELECT count(*) into fvvALNR FROM FIELDS_VALUE_VALIDATION WHERE
FVV_FAVL_NAME = 'ALNR' and FVV_VALUE = changedClassValue and (sysdate between dtFrom and dtTo) or dtTo is null;
BEGIN
-- if (iskeyClass = 1 and (dtTo < trunc(sysdate))) or iskeyClass = 0 then
if (iskeyClass = 1 and (dtTo between DtFrom and sysdate)) or iskeyClass = 0 then
Insert into EXPORT_MATRIX (EXM_KEY_CLASS, EXM_KEYCLASS_VALUE, EXM_CHANGED_CLASS,
EXM_CHANGEDCLASS_VALUE, EXM_DATEFROM)
values (keyClass,keyClassValue,changedClass,changedClassValue,trunc(sysdate));
if fvvECCN = 0 then
Insert into FIELDS_VALUE_VALIDATION (FVV_FAVL_NAME,FVV_VALUE,FVV_DATEFROM)
values ('ECCN',keyClassValue,trunc(sysdate));
end if;
if fvvALNR = 0 then
Insert into FIELDS_VALUE_VALIDATION (FVV_FAVL_NAME,FVV_VALUE,FVV_DATEFROM)
values ('ALNR',changedClassValue,trunc(sysdate));
end if;
end if;
-- if keyClass = 1 and (dtTo > trunc(sysdate)) then
if keyClass = 1 and (sysdate between dtFrom and dtTo) or dtTo is null then
update EXPORT_MATRIX set
EXM_DATETO=to_date(dtTo)
WHERE EXM_KEY_CLASS=keyClass and EXM_KEYCLASS_VALUE=keyClassValue;
end if;
END;
commit;
vresult := 1;
EXCEPTION
WHEN OTHERS THEN
ROLLBACK TO start_tran;
RAISE;
END INSERT_EXPORTMATRIX;
You should add a mask when you convert a string to date:
to_date(dtTo,'DD/MM/YYYY')
Moreover, you should also convert string to date when you comparing with sysdate, so:
sysdate between to_date(dtFrom,'DD/MM/YYYY') and to_date(dtTo,'DD/MM/YYYY')

Need help solving Pl/sql issue

I am trying to fill a database with random data, but the primary key needs to still be unique. I can fill the database with random data, but now I am trying to solve the primary key issue.
When running this code I get errors.
set SERVEROUTPUT on
create or replace
PROCEDURE fillDatabase(TableIn IN varchar2, Amount IN NUMBER) IS
columnData varchar2(50);
columnNR number(10);
str varchar2(500);
sqlStatement varchar2(500);
l_ran_time TIMESTAMP;
intlol NUMBER(38);
prmname varchar2(50);
prmtab varchar2(50);
prmkey number(10);
temp number(30);
tempstr varchar2(50);
lolnr number(10);
strq varchar2(50);
BEGIN
lolnr := 1;
select count(*) into columnNR
from user_tab_columns where table_name=TableIn;
FOR counter IN 1..Amount
LOOP
sqlStatement := 'insert into '|| TableIn ||' values (';
FOR counter2 IN 1..columnNR
LOOP
SELECT cols.table_name, cols.column_name into prmtab, prmname
FROM all_constraints cons, all_cons_columns cols
WHERE cols.table_name = TableIn
AND cons.constraint_type = 'P'
AND cons.constraint_name = cols.constraint_name
AND cons.owner = cols.owner
ORDER BY cols.table_name, cols.position;
tempstr := 'select count(*) into temp from '|| prmtab;
dbms_output.put_line('test');
dbms_output.put_line(temp);
EXECUTE IMMEDIATE tempstr;
IF temp = 0
THEN
strq := 'SELECT max(' || prmname || ') into prmkey from '|| prmtab || ' order by '|| prmname;
dbms_output.put_line(strq);
EXECUTE IMMEDIATE strq;
END IF;
select dbms_random.value(0, 20) into intlol from dual;
select dbms_random.string('U', 20) into str from dual;
SELECT SYSDATE + dbms_random.value(0, SYSDATE - SYSDATE+1)
INTO l_ran_time
FROM dual;
Select DATA_TYPE INTO columnData
FROM user_tab_columns
WHERE table_name= TableIn
AND COLUMN_ID = counter2;
dbms_output.put_line(columnData);
CASE
WHEN columnData = 'VARCHAR2' THEN sqlStatement := sqlStatement ||''''|| str ||''', ';
WHEN columnData = 'NUMBER' THEN sqlStatement := sqlStatement || intlol ||', ';
WHEN columnData = 'TIMESTAMP(6)' THEN sqlStatement := sqlStatement ||''''|| l_ran_time ||''', ';
ELSE sqlStatement := sqlStatement || NULL || ', ';
END CASE;
END LOOP;
sqlStatement := SUBSTR(sqlStatement, 0, LENGTH(sqlStatement) -2);
sqlStatement := sqlStatement || ')';
dbms_output.put_line(sqlStatement);
EXECUTE IMMEDIATE sqlStatement;
END LOOP;
END fillDatabase;
Can you guys help me solve this?
use the pattern
str := 'select x from t where...';
execute immediate str into var;
instead of
str := 'select x into var from t where...';
execute immediate str;

The insertion part is not getting executed

procedure pod_tag_name (p_TAG_NAME in varchar2,
p_status out varchar2,
p_status_dtl out varchar2)
is
v_tag_name varchar2(100);
begin
v_tag_name := get_tag_name(p_TAG_NAME);
if v_tag_name = '' THEN
insert into pod_tagmaster (TAG_ID,TAG_NAME_NEW , CREATEDBY,
CREATEDDATE,UPDATED_BY, UPDATED_DATE,TAG_NAME_OLD)
values (POD_UNIQUE_VAL_SEQ.NEXTVAL,p_TAG_NAME , null ,
sysdate,null, sysdate, v_tag_name);
v_rec_cnt := sql%rowcount;
commit;
p_status_dtl := v_rec_cnt||' Record Inserted Successfully';
else
update pod_tagmaster
set TAG_NAME_NEW = p_TAG_NAME,
TAG_NAME_OLD = v_tag_name,
UPDATED_BY = null,
UPDATED_DATE = sysdate
where TAG_NAME_NEW = p_TAG_NAME;
v_rec_cnt := sql%rowcount;
commit;
p_status_dtl := v_rec_cnt||' Record Updated Successfully';
end if;
p_status := 'SUCCESS';
end;
function get_tag_name(p_TAG_NAME varchar2) return varchar2
is
v_tag_name varchar2(200);
begin
select TAG_NAME_NEW
into v_tag_name
from pod_tagmaster
where TAG_NAME_NEW = p_TAG_NAME ;
return v_tag_name;
exception
when others then
return '';
end;
end POD_PKG_TAG_MASTER;
Change
if v_tag_name = '' THEN
to
if v_tag_name IS NULL THEN
Also, change
return '';
to
RETURN NULL;
In Oracle a zero-length string is the same as NULL; thus, the equality comparison fails. You must use IS NULL in this case.
Share and enjoy.

TOAD Oracle SQL Return Row from UDF

have a function below that returns a cursor. However I need it to return just one row. I have read on google about returning the data as a %rowtype but I do not seem to be able to get it to work.
The reason I don't want a cursor returned is that when I select the function one cell is returned saying (cursor) instead of displaying one row with 4 columns of data.
create or replace function udf
(
i_ptf_code in varchar2
,i_begin_date in date
,i_end_date in date
)
return sys_refcursor
is
portf_code varchar2(50);
end_date date;
chain_linked_ptf_net float;
chain_linked_ptf_gross float;
chain_linked_bmk float;
end_mv float;
v_cursor sys_refcursor;
cursor c_return_series is
select p.portf_code
,gpr.end_date
,gpr.end_market_value
,gpr.portf_perf_gross as gross_ret
,gpr.portf_perf_net as net_ret
,(exp(sum(ln(1 + gpr.portf_perf_gross)) over (partition by p.portf_code order by end_date)) - 1) as chain_linked_ptf_gross
,(exp(sum(ln(1 + gpr.portf_perf_net)) over (partition by p.portf_code order by end_date)) - 1) as chain_linked_ptf_net
,(exp(sum(ln(1 + gpr.bmk_perf)) over (partition by p.portf_code order by end_date)) - 1) as chain_linked_bmk
from portfolio_returns gpr
inner join portfolio p on p.portf_id = gpr.portf_id and p.is_composite != 2 --2 means composite
where p.portf_code = i_ptf_code
and gpr.end_date between i_begin_date and i_end_date;
begin
select i_ptf_code, i_end_date into portf_code, end_date from dual;
for c1line in c_return_series loop
if c1line.end_date = i_end_date then
select c1line.chain_linked_ptf_gross
,c1line.chain_linked_ptf_net
,c1line.chain_linked_bmk
,c1line.end_market_value
into chain_linked_ptf_gross
,chain_linked_ptf_net
,chain_linked_bmk
,end_mv
from dual;
end if;
end loop;
open v_cursor for
select portf_code as portf_code
,end_date as end_date
,chain_linked_ptf_gross * 100 as period_ptf_gross
,chain_linked_ptf_net * 100 as period_ptf_net
,chain_linked_bmk * 100 as period_bmk
,end_mv * 100 as period_mv
from dual;
return v_cursor;
close v_cursor;
end;
/
I am a little lost but I think this is what you need:
[...]
open v_cursor for
select portf_code as portf_code
,end_date as end_date
,chain_linked_ptf_gross * 100 as period_ptf_gross
,chain_linked_ptf_net * 100 as period_ptf_net
,chain_linked_bmk * 100 as period_bmk
,end_mv * 100 as period_mv
from dual;
return v_cursor;
-- close v_cursor; -- not needed
end;
-
DECLARE
l_rc SYS_REFCURSOR;
l_portf_code VARCHAR2(30);
l_end_date VARCHAR2(30);
l_period_ptf_gross NUMBER;
l_period_ptf_net NUMBER;
l_period_bmk NUMBER;
l_period_mv NUMBER;
BEGIN
l_rc := udf; -- This returns an open cursor
fetch v_rc into l_portf_code, l_end_date, l_period_ptf_gross, l_period_ptf_net, l_period_bmk, l_period_mv;
DBMS_OUTPUT.PUT_LINE
(
l_portf_code || ' ' ||
l_end_date || ' ' ||
l_period_ptf_gross || ' ' ||
l_period_ptf_net || ' ' ||
l_period_bmk || ' ' ||
l_period_mv
);
CLOSE v_rc;
END;

Resources