How put a condition in the where clause in the procedure? - oracle

I want to put a condition in the where clause according to the null condition of the parameter in the procedure. But the procedure I made has some problem. There's problem is in IF clause.
How I can put a condition in the where clause in the procedure?
CREATE OR REPLACE PROCEDURE SP_PROCEDURE(START_DATE, END_DATE)
IS
START_DATE DATE;
END_DATE DATE;
BEGIN
START_DATE := TO_DATE(START_DATE, 'YYYYMMDD');
END_DATE := TO_DATE(END_DATE, 'YYYYMMDD');
INSERT INTO USER
(
USR_KEY,
USR_NAME
)
SELECT
USR_KEY,
USR_NAME
FROM
USER
WHERE
1 = 1
IF START_DATE THEN --I think there's problem here..
AND USR_CRT_DATE >= START_DATE
END IF;
COMMIT;
EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
END;

If I'm reading your requirements correctly, this should do the trick
CREATE OR REPLACE PROCEDURE SP_PROCEDURE(START_DATE, END_DATE)
IS
START_DATE DATE;
END_DATE DATE;
BEGIN
START_DATE := TO_DATE(START_DATE, 'YYYYMMDD');
END_DATE := TO_DATE(END_DATE, 'YYYYMMDD');
INSERT INTO USER
(
USR_KEY,
USR_NAME
)
SELECT
USR_KEY,
USR_NAME
FROM
USER
WHERE (USR_CRT_DATE >= START_DATE
or START_DATE is null );
COMMIT;
END;
You don't need that exception handler. By default if a PL/SQL unit fails, it will rollback changes to the commencement point of the procedure.

You are missing the data types in the signature of the procedure.
Never use TO_DATE on a value that is already a DATE (as it will implicitly convert it from the date to a string and then back to a date and is likely to introduce errors in the conversion). If you want to remove the time component of a date then use TRUNC instead of trying to use TO_DATE.
It is bad practice to use COMMIT in a procedure as it does not allow you to chain multiple procedures together and then if one fails you can ROLLBACK them all; instead you should COMMIT in the transaction that calls the procedure.
USER is a keyword and cannot be used as an unquoted identifier; if you try you will get the exception ORA-00903: invalid table name. Best practice would be to name the table something that is not a keyword but you could also use quoted identifiers (which is not considered best practice).
CREATE OR REPLACE PROCEDURE SP_PROCEDURE(
START_DATE IN DATE,
END_DATE IN DATE
)
IS
BEGIN
INSERT INTO "USER" (
USR_KEY,
USR_NAME
)
SELECT USR_KEY,
USR_NAME
FROM "USER"
WHERE (START_DATE IS NULL OR USR_CRT_DATE >= TRUNC(START_DATE));
END;
/
fiddle

Related

Can I create parameterized views in oracle

I have a query like this
SELECT ID,REF_ID,BATCHNO FROM reporttbl
where POSTING_DT >= '06/01/2020' and POSTING_DT <= '06/30/2020'
and I need it every month, so I would like to put it in a view, but as the date changes every month, it would be great to have a date parameter that I can pass to the view when calling it. Is there a way on how can i achieved this?
I'm new to oracle, appreciate every help. Thank youu.
From 19.6 you can create parameterized views using SQL macros.
create or replace function get_month (
tab dbms_tf.table_t, start_date date, end_date date
) return varchar2 sql_macro as
retval int;
begin
return 'select * from tab
where dt >= start_date and dt < end_date + 1';
end get_month;
/
create table t (
c1 int, dt date
);
insert into t
with rws as (
select level c1, add_months ( date'2019-12-25', level ) dt
from dual
connect by level <= 10
)
select * from rws;
select * from get_month (
t, date'2020-06-01', date'2020-07-01'
);
C1 DT
6 25-JUN-2020 00:00:00
select * from get_month (
t, date'2020-08-01', date'2020-09-01'
);
C1 DT
8 25-AUG-2020 00:00:00
This query return the data for the previous month, i.e. the month befort the current month at the time of the query (= sysdate).
You use the trunc with 'MM' to get the months first and the arithmetic with add_months
SELECT ID,REF_ID,BATCHNO FROM reporttbl
where POSTING_DT >= add_months(trunc(sysdate,'MM'),-1) and POSTING_DT < trunc(sysdate,'MM')
Another way to do this is using a function that retrieves the parameters from a table, thereby you don't need to manipulate any DDL. The idea here is
Using a table to store the parameters, basically you need parameter value and a parameter description.
Using a function to retrieve the value of that parameter when the input is the parameter name
Using the function call inside the view.
You can then manipulate the view automatically by modifying the values of the parameter table.
Table
create table my_param_table
( param_description varchar2(100) ,
param_value varchar2(100),
enabled varchar2(1)
) ;
Function
create or replace function f_retr_param ( p_value in varchar2 )
return varchar2
is
declare
v_value my_param_table.value_param%type;
begin
select value into v_value from my_table_of_parameters
where upper(value_param) = upper(p_value) ;
return v_value;
exception when others then raise;
end;
/
View
create or replace force view my_view as
SELECT ID,REF_ID,BATCHNO FROM reporttbl
where POSTING_DT >= f_retr_param ( p_value => 'p_start_date' );
and POSTING_DT <= f_retr_param ( p_value => 'p_end_date' );
There are ways to "parameterize" a view e.g. using Oracle contexts, but they aren't often useful and certainly not for your case.
If your query really just selects from one table with just the dates as predicates then a view doesn't add much value either. You could create a SQL script (in a file e.g. myquery.sql) using bind variables:
SELECT ID,REF_ID,BATCHNO FROM reporttbl
where POSTING_DT >= to_date(:from_date) and POSTING_DT <= to_date(:to_date);
Then every month you can just open the file and run it, and it will prompt you for the 2 dates. Or you can run as a script like this and it will also prompt you:
#myquery.sql
Or if you use substitution strings '&1.' and '&2.' instead:
SELECT ID,REF_ID,BATCHNO FROM reporttbl
where POSTING_DT >= to_date('&1.') and POSTING_DT <= to_date('&2.');
Then you can pass the dates in on the command line like this:
#myquery '06/01/2020' '06/30/2020'
(Because &1. means first parameter on command line, etc.)

Date based select query not working inside cursor

I am working on a stored procedure which has the following date based select query inside cursor like below
CURSOR inv_cur ( v_hotel_id IN NUMBER, v_stay_date IN DATE)
IS
SELECT id,
start_date ,
room_count ,
booked_room_count
FROM inventory
WHERE hotel_id = v_hotel_id
AND TRUNC( start_date ) = TRUNC(v_stay_date);
For some reason it does not work and I am not getting records. But when i execute without the date comparison or execute the query in the stand alone manner like below, it works
SELECT id,
start_date ,
room_count ,
booked_room_count
FROM inventory
WHERE hotel_id = 1509622
AND TRUNC( start_date ) = TO_DATE('08-03-18', 'dd-mm-yy');
This is how I am invoking the cursor call
PROCEDURE (.....)
IS
v_date_temp DATE;
BEGIN
v_date_temp := p_check_in_date;
FOR inventory_rec IN inv_cur
(
v_hotel_id, v_room_type_id, v_date_temp
)
LOOP
v_room_count := inventory_rec.room_count;
v_book_room_count := NVL ( inventory_rec.booked_room_count,0 );
v_inventory_id := inventory_rec.id;
dbms_output.put_line(' Inv id' || v_inventory_id);
END LOOP;
Since there are no records returned, it is not going inside loop.
I think there is something wrong with the date comparison. Can someone help me figure out this puzzling issue with my date comparison ?

how to check what the value of Parameter in Oracle PLSQL Procedure

I am in need of amending a procedure to include new data in which a parameter has been set. I need to check the value of the parameter so that I can test my code individually before it is implemented. below is portion of code which has parameter.
PROCEDURE Get_All_MT (i IN NUMBER)
AS
BEGIN
INSERT INTO mrr_reten_mt_obp_cli (
AMI_SCHEMA,
UAN,
PRODUCT_CLASS,
POL_NO
)
SELECT a.ami_schema,
a.uan,
a.product_class,
a.pol_no
FROM mrr_retention_c_cover_item a,
att_axa_uan agt,
amt_structure str
WHERE a.accident_date BETWEEN TRUNC (ADD_MONTHS (SYSDATE, i - 1), 'MONTH')
AND TRUNC (ADD_MONTHS (SYSDATE, i), 'MONTH')
- (1 / (60 * 60 * 24))
As you can see parameter "I" is been used in for accident_date range. I need to know what is the value of I so that it can be replaced while the code is been executed individually.
Log the value using DBMS_OUTPUT:
PROCEDURE Get_All_MT (i IN NUMBER)
AS
BEGIN
DBMS_OUTPUT.PUT_LINE( i );
INSERT INTO ...
I would create table log_params (param varchar2(30), value varchar2(200), log_time date); and procedure:
create or replace procedure log_param(param varchar2(30), value varchar2(200)) as
pragma autonomous transaction
begin
insert into log_params values (param, value, sysdate);
commit;
end;
/
And include in your code: log_param('i', i);. Then examinate results in table log_params

how to use date in where clause while inserting values into table using PLSQL store procedure

This is the code i used in stored procedure;
CREATE OR REPLACE PROCEDURE MY_STORE_PROCEDURE (new_date in date)
IS
BEGIN
execute immediate 'INSERT INTO TEMP_1 ( ID CHAR(10),
A_CNT NUMBER,
JOIN_DT DATE,
)
SELECT
L1.ID,
L1.A_CNT,
L1.JOIN_DT,
FROM ACTVY_1 L1
WHERE L1.JOIN_DT = new_date';
END;
===========================================================
Below is the code i used to call store procedure with passing value. value is date which store procedure reciece and used to pull date from a table. but it is giving me error.
DECLARE
a_date DATE;
BEGIN
a_date :=to_DATE ('01-NOV-2013', 'DD-MON-YYYY');
MY_STORE_PROCEDURE(a_date);
END;
Please suggest is there any syntax error or what is issue.
Based on your example, there is no reason to use dynamic SQL. You also have a bunch of errors. Try this:
CREATE OR REPLACE PROCEDURE MY_STORE_PROCEDURE (new_date IN DATE)
IS
BEGIN
INSERT INTO TEMP_1 (ID, A_CNT, JOIN_DT)
SELECT L1.ID, L1.A_CNT, L1.JOIN_DT
FROM ACTVY_1 L1
WHERE L1.JOIN_DT = new_date;
END;

oracle trigger query

I have a trigger which is sending data from a table to another table in another database. all s working fine.
The prob is that there is a new concept of END DATE, in which, if END DATE is present for a person, the row should reach the other table on that particular date..
eg.: if someones end date is 31st august, it should go on that day only, but ofcourse, my trigger is firing on event change (when enddate is set to 31st august)..
Could you please suggest me what I can do to SET the row to go on ENDDATE.?
It doesn't sound like you don't want a trigger. It sounds like you want a job. For example, if you create a procedure that transfers all the rows whose end_date is today
CREATE OR REPLACE PROCEDURE move_rows_with_end_date(
p_end_date IN DATE DEFAULT trunc(SYSDATE)
)
AS
BEGIN
INSERT INTO table_name#remote_database( <<list of columns>> )
SELECT <<list of columns>>
FROM table_name
WHERE end_date = trunc(sysdate);
END;
Then you can create a job that runs the procedure every day at midnight
DECLARE
l_jobno PLS_INTEGER;
BEGIN
dbms_job.submit( l_jobno,
'BEGIN move_rows_with_end_date; END;',
trunc(sysdate+1),
'trunc(sysdate+1)' );
commit;
END;

Resources