Reputation: 8804
I want to dynamically create query to accept parameters dynamically to send notifications 1,3,5,10,15 and 20 days the password is going expire. I already went through link how to get the 30 days before date from Todays Date.
These date values must be configurable and should be passed through code to method.
I've developed a query, but is there any better ways to pass this values? How to dynamically accept the days value?
SELECT * FROM PASS_EXPIRE
WHERE TRUNC(EXPIRY_DT) = TRUNC(SYSDATE + 1) OR TRUNC(EXPIRY_DT) = TRUNC(SYSDATE + 3) OR TRUNC(EXPIRY_DT) = TRUNC(SYSDATE + 5)
OR TRUNC(EXPIRY_DT) = TRUNC(SYSDATE + 7) OR TRUNC(EXPIRY_DT) = TRUNC(SYSDATE + 15) OR TRUNC(EXPIRY_DT) = TRUNC(SYSDATE + 20);
Upvotes: 0
Views: 154
Reputation: 168311
You can use:
SELECT *
FROM PASS_EXPIRE
WHERE TRUNC(EXPIRY_DT) IN (
WITH days (day) AS (
SELECT 1 FROM DUAL UNION ALL
SELECT 3 FROM DUAL UNION ALL
SELECT 5 FROM DUAL UNION ALL
SELECT 7 FROM DUAL UNION ALL
SELECT 15 FROM DUAL
)
SELECT TRUNC(SYSDATE) + day
FROM days
)
Or, use a collection (which could be passed as a bind parameter):
SELECT *
FROM PASS_EXPIRE
WHERE TRUNC(EXPIRY_DT) IN (
SELECT TRUNC(SYSDATE) + COLUMN_VALUE
FROM TABLE(SYS.ODCINUMBERLIST(1, 3, 5, 7, 15))
)
or you can JOIN
(and, again, the collection could be passed to the query as a bind variable):
SELECT p.*
FROM PASS_EXPIRE p
INNER JOIN TABLE(SYS.ODCINUMBERLIST(1, 3, 5, 7, 15)) t
ON ( p.expiry_dt >= TRUNC(SYSDATE) + t.COLUMN_VALUE
AND p.expiry_dt < TRUNC(SYSDATE) + t.COLUMN_VALUE + 1 )
Note: This query would allow you to use an index on expiry_dt
; in contrast, comparing on TRUNC(expiry_dt)
would not allow an index to be used as Oracle would need a separate function-based index on TRUNC(expiry_dt)
.
db<>fiddle here
Upvotes: 3
Reputation: 4129
The idea I have is to create another table with days to expire:
days |
---|
1 |
3 |
5 |
and so on
and then just use cross join for retrieval passwords that are going to expire
select 'password expires in ' || ds.days || case when ds.days = 1 then ' day' else ' days' end
from PASS_EXPIRE pe
cross join days ds
where pe.expiry_dt = (trunc(sysdate) - ds.days);
Thus, all you need to do in the application is to set up a dialog to maintain that table
Upvotes: 0
Reputation: 231771
I'd probably declare a collection, pass that collection to your procedure, and then use the member of
operator to return only the rows from the table that match an element from the collection
create type date_tbl is table of date;
declare
-- You'd pass in l_dates
l_dates date_tbl := date_tbl( trunc(sysdate+1), trunc(sysdate+3), trunc(sysdate+5),
trunc(sysdate+10), trunc(sysdate+15), trunc(sysdate+20));
begin
-- Your query goes here. Use the `member of` function to restrict yourself to
-- rows from the table that are in the collection
for i in (select d.*
from (select trunc(sysdate) + level dt
from dual
connect by level <= 30) d
where d.dt member of l_dates )
loop
dbms_output.put_line( i.dt );
end loop;
end;
Prints out (when run on 2021-09-02)
03-SEP-21
05-SEP-21
07-SEP-21
12-SEP-21
17-SEP-21
22-SEP-21
See this fiddle
Upvotes: 1