I am trying to validate shuttle list values on a form with colon separated values that are stored in a table column along with date range (From and To date) columns in Oracle APEX. All the tables, form and interactive report are created in Oracle APEX but still providing detailed overview in the post as per the rules. Sharing Oracle APEX workspace details at end of this post.
Have below table for month calendar: Table Name: ACCT_CAL
+----+-------------+-------------+--------+
| ID | FROM_DATE | TO_DATE | STATUS |
+----+-------------+-------------+--------+
| 1 | 01-Jan-2023 | 31-Jan-2023 | C |
+----+-------------+-------------+--------+
| 2 | 01-Feb-2023 | 28-Feb-2023 | C |
+----+-------------+-------------+--------+
| 3 | 01-Mar-2023 | 31-Mar-2023 | C |
+----+-------------+-------------+--------+
| 4 | 01-Apr-2023 | 30-Apr-2023 | O |
+----+-------------+-------------+--------+
| 5 | 01-May-2023 | 31-May-2023 | F |
+----+-------------+-------------+--------+
| 6 | 01-Jun-2023 | 30-Jun-2023 | F |
+----+-------------+-------------+--------+
| 7 | 01-Jul-2023 | 31-Jul-2023 | F |
+----+-------------+-------------+--------+
| 8 | 01-Aug-2023 | 31-Aug-2023 | F |
+----+-------------+-------------+--------+
| 9 | 01-Sep-2023 | 30-Sep-2023 | F |
+----+-------------+-------------+--------+
| 10 | 01-Oct-2023 | 31-Oct-2023 | F |
+----+-------------+-------------+--------+
| 11 | 01-Nov-2023 | 30-Nov-2023 | F |
+----+-------------+-------------+--------+
| 12 | 01-Dec-2023 | 31-Dec-2023 | F |
+----+-------------+-------------+--------+
Assuming we are in the month of April 2023, then only that month status will be Open (O). Past months will have status Closed (C) and future months with status (F).
Shuttle List values: Table Name: TKT_DETAILS
+---------+
| TKT_NUM |
+---------+
| 10 |
+---------+
| 20 |
+---------+
| 30 |
+---------+
| 40 |
+---------+
| 50 |
+---------+
| 60 |
+---------+
| 70 |
+---------+
| 80 |
+---------+
| 90 |
+---------+
| 100 |
+---------+
Source SQL query for Shuttle List:
select TKT_NUM d, TKT_NUM r from TKT_DETAILS
order by TKT_NUM
Below is the table where assignment of tickets takes place for any period Table Name: TKT_ASSIGN
+----+----------+-------------+-------------+-------------+
| ID | TKT_NUM | ASSIGNED_TO | FROM_DATE | TO_DATE |
+----+----------+-------------+-------------+-------------+
| 1 | 10:20:30 | USER1 | 01-Apr-2023 | 30-Jun-2023 |
+----+----------+-------------+-------------+-------------+
| 2 | 10:60 | USER2 | 01-May-2023 | 30-Sep-2023 |
+----+----------+-------------+-------------+-------------+
| 3 | 50 | USER1 | 01-Aug-2023 | 31-Aug-2023 |
+----+----------+-------------+-------------+-------------+
| 4 | 60:70 | USER1 | 01-Sep-2023 | 30-Nov-2023 |
+----+----------+-------------+-------------+-------------+
Assuming records are inserted in the order of ID column.
From the above table, tkt_num column is the shuttle list values. If ID=1 is the first record inserted, then
ticket number 10 should not be assigned for ID=2 since From date of ID=2 overlap with date range of ID=1 From Date and To Date.
ID=3 is valid
ID=4 is invalid since ticket number 60 is assigned for ID=2 and the date range ID=4 overlap with date range of ID=2.
Also TO_DATE field can be null.
Below is the validation - Function Body (returning Error Text):
declare
v_cnt number;
begin
SELECT count(*) into v_cnt
FROM TKT_ASSIGN
where (exists (select * From apex_string.split(:P2_TKT_NUM,':')
where instr(tkt_num, column_value ) > 0 ) or :P2_TKT_NUM is null)
and ((:P2_FROM_DATE BETWEEN FROM_DATE AND TO_DATE)
OR (:P2_TO_DATE BETWEEN FROM_DATE AND TO_DATE)
or nvl(:P2_ID,0) <> ID);
if v_cnt <> 0 then
return 'Ticket already assigned to User for the date range';
end if;
return null;
end;
Below are the issues I'm having with validation.
Hence seeking experts help and advice.
Please find Oracle APEX details below:
Workspace: RICHADEMO
Username: DEMO
Password: dem01234
APP_ID: 83310
Thanks,
Richa
Thanks for the very complete sample case. The issue is the where clause:
Change
and ((:P2_FROM_DATE BETWEEN FROM_DATE AND TO_DATE)
OR (:P2_TO_DATE BETWEEN FROM_DATE AND TO_DATE)
or nvl(:P2_ID,0) <> ID);
to
and ((:P2_FROM_DATE BETWEEN FROM_DATE AND TO_DATE)
OR (:P2_TO_DATE BETWEEN FROM_DATE AND TO_DATE))
AND nvl(:P2_ID,0) <> ID;
The current row can never be included so that needs to be an AND
separated from all other predicates.
Steps to debug this:
apex_debug.info(
p_message => q'#kl debug: P2_TKT_NUM: %0#',
p0 => :P2_TKT_NUM);
apex_debug.info(
p_message => q'#kl debug: P2_FROM_DATE: %0#',
p0 => :P2_FROM_DATE);
apex_debug.info(
p_message => q'#kl debug: P2_TO_DATE: %0#',
p0 => :P2_TO_DATE);
apex_debug.info(
p_message => q'#kl debug: P2_ID: %0#',
p0 => :P2_ID);
Run page in debug, look for those debug messages, replace the values that are there in the sql statement
Run the sql statement in SQL Command and debug.
A couple of notes:
instr(tkt_num, column_value ) > 0 )
is a bug. If you have ticket number 2 and 22 it will give a false positive because INSTR('20:30','2') > 0
yields true but is not what you want.Here is how I would do it.
Type: No Rows returned Source:
SELECT 1
FROM TKT_ASSIGN
WHERE
(EXISTS (
SELECT 1 FROM apex_string.split(:P2_TKT_NUM,':') t
WHERE t.column_value IN
(SELECT column_value
FROM apex_string.split(tkt_num,':'))
OR :P2_TKT_NUM is null)
)
AND ((TO_DATE(:P2_FROM_DATE,'DD-MON-YYYY') BETWEEN FROM_DATE AND TO_DATE)
OR (TO_DATE(:P2_TO_DATE,'DD-MON-YYYY') BETWEEN FROM_DATE AND TO_DATE)
)
AND NVL(:P2_ID,0) <> ID