Checking if date falls in a specified month in Oracle - sql

procedure Charge(p_inputdate N VARCHAR2,//Date which accepts only MMYYYY format
inout_Cur OUT result_cur) IS
I need to validate the effective_date which is in date format (mm/dd/yyyy hh:mm:ss)
For example: The user enters 112013 as input and the effective date to check is 11/12/2013 09:13:22
Is it possible to find whether the effective date falls within the specified month?
can you please comment on this..
I tried below way:
V_INPUTDATE := to_char(TO_DATE(IN_INPUTDATE, 'MMYYYY','mmyyyy'));
v_effectiveDate := substr(V_INPUTDATE,1,2)+'/'+'01'+'/'+substr(V_INPUTDATE,3,4);
01 is nothing but month always start with 01(dd)
Is this rightway ..??

If date happens to be a VARCHAR2 you need to first convert it to DATE:
effective_date DATE; -- Put this line in the declare section
effective_date := to_date('11/12/2013 09:13:22', 'MM/DD/YYYY HH24:MI:SS');
When you have the date, the rest is easy:
IF p_inputdate = to_char(effective_date, 'MMYYYY') THEN
-- Date is ok.
ELSE
-- Date is not ok.
END IF;

Related

Working with dates in PL SQL

I have a simple PL SQL code. However it is failing at date level. The date column is CODT. I declared CODT as date. And in database level, it is date with format YYYY-MM-DD.
I also tried alter session set nls_date_format = 'YYYY-MM-DD'; But it is throwing error.
The error message is ORA-01830: date format picture ends before converting entire input string
00000 - "date format picture ends before converting entire input string"
Could you let me know where I need to change it to date format/ where I am making a mistake ?
DECLARE
RID VARCHAR2(100);
KY VARCHAR2(200);
CODT DATE;
CURSOR FETCH_DTLS IS
SELECT ROW_ID,
KEY,
CUT_OFF_DT,
FROM TMP1
WHERE RN = 1;
BEGIN
OPEN FETCH_DTLS;
LOOP
FETCH FETCH_DTLS
INTO RID,
KY,
CODT;
EXIT WHEN FETCH_DTLS%NOTFOUND;
INSERT INTO tmp2
VALUES
(RID,
KY,
CODT
);
END LOOP;
COMMIT;
CLOSE FETCH_DTLS;
COMMIT;
END;
if you have date column which defined varchar2 in db you should use it like this:to_date(your_column/*CUT_OFF_DT*/, 'yyyy-mm-dd')
when you use VARCHAR2 field and insert it in a table with DATE data-type, then you tell oracle to: Cast VARCHAR2 to DATE
So your mistake is casting without providing any format, here are some date format examples used in oracle:
'YYYY-MM-DD'
'YYYY-MM-DD HH24:MI:SS'
there is also another function in oracle called TO_DATE which will do the job, it simply casts the string(char or varchar) to date with provided date-format and also provided calendar! Here is some examples:
TO_DATE('2016-12-15','YYYY-MM-DD')--uses default calendar of session
TO_DATE('2016-12-15','YYYY-MM-DD', 'nls_calendar=gregorian')
TO_DATE('1395-09-25','YYYY-MM-DD', 'nls_calendar=persian')--Solar base date used in IRAN
and reverse function is TO_CHAR
TO_CHAR(SYSDATE,'YYYY-MM-DD')--SYSDATE is in Date type so this works
there is another data-type related to dates, which is called TIMESTAMP
TO_CHAR(SYSTIMESTAMP,'YYYY-MM-DD HH24:MI:SSxFF')--SYSTIMESTAMP is in TIMESTAMP type so this works
finally we can use INTERVAL type to calculate interval between 2 dates(Specially timestamps) and there is a useful function called numtodsinterval which converts numbers to intervals, you can use it like this:
SYSDATE+NUMTODSINTERVAL(1,'Minute')
and this is an example:
SELECT TO_CHAR(SYSDATE,'YYYY-MM-DD HH24:MI:SS'),
TO_CHAR(SYSDATE+NUMTODSINTERVAL(1,'Minute'),'YYYY-MM-DD HH24:MI:SS')
FROM DUAL
which outputs:
1 2016-12-15 15:05:10 2016-12-15 15:06:10
I hope it will be useful in your future usages of DATE, goodluck

Last dateof month using pl/sql

I want to write a programm using PL/SQL
If the date of birth of one person is 12th May 1978, so that the person retirement date should be 12th may 2038, but instead of 12th may 2038 the date of retirement of that person will be the last date of the same month (it will automatically redirect the last day of the same month).
Check function last_day
e.g.
select last_day(to_date('12/05/2038', 'dd/mm/yyyy')) from dual
Oracle has a last_day function that does exactly that:
select sysdate, last_day(sysdate) from dual;
SYSDATE LAST_DAY(SYSDATE)
--------- -----------------
19-DEC-13 31-DEC-13
From PL/SQL:
declare
month_end date;
begin
month_end := last_day(sysdate);
end;
... but pass in your adjusted date of birth value.

Test for time part existence in DATE data type

I have one field in my database of type DATE. I want to store date and time or only date in.
The problem is how to test that my DATE column contain date and time or just a date.
v_date DATE;
v_date := to_date('01-01-2013', 'DD-MM-YYYY');
v_text := to_char(v_date, 'HH24:Mi');
to_char('HH24:Mi') for only date returns '00:00', not null.
Is there any way to test that Date column contains date and time or only date.
The DATE datatype allways contain Date and Time.
And it's just a bad ideea to store time and date separate. You can just test against your DATE column whatever you want about Time part.
For example, to test if the column is at midnight you can use:
if trunc(your_column) = your_column
then blabla;
end if;
and use <> instead of = for the otherwise.

Select doesn't return expected result with Date type in Oracle DB

Table my_table is:
CREATE TABLE MY_TABLE(
ID NUMBER NOT NULL,
MY_DATE DATE NOT NULL);
Typing the following query:
select sysdate from dual
the result is:
10-MAG-12 21:22:32
note that mag = may.
Now, if I type this query:
select *
from my_table
where my_date <= sysdate
the result is:
9918 10-MAG-12 20:00:00
9915 10-MAG-12 21:00:00
9952 10-MAG-12 22:00:00
9951 10-MAG-12 23:00:00
Note that in my_table I have only these 4 records. Why I see all the records and not the first and second record only? Thanks.
I use Oracle SQL Developer.
Edit: please note that when I insert a record with PL/SQL I type something like:
nCount NUMBER;
myDate DATE;
stringDate VARCHAR2(255);
BEGIN
nCount := 0;
stringDate := substr(to_char(trunc(sysdate)),0,9);
myDate := to_date(stringDate || ' 20:00:00','dd-mm-yyyy hh24:mi:ss');
for t in (a cursor) loop
insert into MY_TABLE(ID,MY_DATE)
values (9918,myDate+(nCount/1440));
nCount := nCount + 60;
end loop;
END;
I suspect that the data being stored in your table does not have a year of 2012. It probably has a year of 0012 (two thousand years ago).
What do you see when you run the query
SELECT id, to_char( my_date, 'dd-mm-yyyy hh24:mi:ss' )
FROM my_table
I expect that the year will be 0012 rather than 2012. The reason for that is that the code you're using to insert the data is incorrectly converting a date to a string without using an explicit format mask then converts the string back to a date using an explicit format mask that happens not to match the session's NLS_DATE_FORMAT. In general, if you ever find yourself converting a date to a string and back to a date, you're probably doing something wrong. If you change your code to simply do date manipulation, it will be more efficient, more robust, and less error-prone.
DECLARE
nCount NUMBER;
myDate DATE;
BEGIN
nCount := 0;
myDate := trunc(sysdate) + interval '20' hour;
for t in (a cursor) loop
insert into MY_TABLE(ID,MY_DATE)
values (9918,myDate+(nCount/1440));
nCount := nCount + 60;
end loop;
END;
Walking through why the original code goes wrong
stringDate := substr(to_char(trunc(sysdate)),0,9);
This takes SYSDATE and truncates it to midnight on the current day. So far, so good. Then, it calls TO_CHAR without an explicit format mask. This causes Oracle to use the session's NLS_DATE_FORMAT, meaning that different users with different settings will get different results. If your session's NLS_DATE_FORMAT happens to be 'dd-mon-rr hh24:mi:ss', which I'm guessing based on the query results you posted, that will mean that the string has a 2-digit year. Your SUBSTR appears to assume that the output has just a two-digit year (if you have a different NLS_DATE_FORMAT, your SUBSTR will generate different bugs such as potentially cutting off the 12 from a year of 2012 leaving a year of just 20).
myDate := to_date(stringDate || ' 20:00:00','dd-mm-yyyy hh24:mi:ss');
Assuming stringDate is something like 10-MAG-12, this next line generates a string 10-MAG-12 20:00:00 and then tries to convert it to a date using the format mask dd-mm-yyyy hh24:mi:ss. This assumes that the string has a 4-digit year so when it only finds 2-digits, it assumes that you meant the year 12, not the year 2012.

Selecting first and last day of 2 separate months only given MM-YYYY date

I've been in the process of helping someone change crystal reports and both of us have semi knowledge on using it, at least enough to get by for this one-time help.
Something they've asked us to change was to remove the ability to enter a day in MM/YYYY-MM/YYYY format. We're trying to figure out how to select the first day of the first date section and the very last day/hour of the last date section.
I've seen a few functions like dateadd() with other functions inside which, in the end produce the last or first day of the current month. But i'm unsure how to enter the date we're given (MM/YYYY) into the function to grab the first/last days.
Assuming your parameter's name is {?dates}
{#starting_date} formula:
//extract MM/YYYY from 'MM/YYYY-MM/YYYY'
local stringvar MMYYYY := Split({?dates},"-")[1];
//extract MM from 'MM/YYYY'
local numbervar MM := ToNumber(Split(MMYYYY,"/")[1]);
//extract YYYY from 'MM/YYYY'
local numbervar YYYY := ToNumber(Split(MMYYYY,"/")[2]);
//return first day of selected date
Date(YYYY,MM,1);
{#ending_date} formula:
//extract MM/YYYY from 'MM/YYYY-MM/YYYY'
local stringvar MMYYYY := Split({?dates},"-")[2];
//extract MM from 'MM/YYYY'
local numbervar MM := ToNumber(Split(MMYYYY,"/")[1]);
//extract YYYY from 'MM/YYYY'
local numbervar YYYY := ToNumber(Split(MMYYYY,"/")[2]);
//calculate first day of selected month, add a month, subtract a day, return last day of selected month
DateAdd("m",1,Date(YYYY,MM,1))-1;
declare #date1 varchar(7),#date2 varchar(7)
set #date1='01/2011'
set #date2='05/2011'
-- First convert your dates to YYYYMM
set #date1=RIGHT(#date1,4)+LEFT(#date1,2)
set #date2=RIGHT(#date2,4)+LEFT(#date2,2)
-- Then calculate your limit dates
-- The final date is obtained by adding 1 month to the first day of this month
-- and then substracting 1 second to this date
select CONVERT(datetime, #date1+'01',112) InitialDate,
CONVERT(datetime, dateadd(ss,-1,dateadd(mm,1,#date2+'01')),112) FinalDate