More on extracting year from date - Oracle - sql

I have a question about selecting year from a date. This is in Oracle database 12c.
Given that SELECT trunc(SYSDATE) FROM DUAL; returns 02/06/2020
These work proper and return current year of 2020 -
SELECT EXTRACT(YEAR FROM trunc(SYSDATE)) FROM DUAL;
SELECT TO_CHAR(trunc(SYSDATE,'YYYY')) FROM DUAL;
These do not work and give error -
SELECT EXTRACT(YEAR FROM '02/06/2019') FROM DUAL;
Gives error: ORA-30076: invalid extract field for extract source
SELECT TO_CHAR('02/06/2019','YYYY') FROM DUAL;
Gives error: ORA-01722: invalid number
The same format is being passed with sysdate and hard coded date of 02/06/2019. Why is it that one works and the other does not?
I know I could just select 2019 from dual but that is not the point or use case here.

You can't extract year from a string (which '02/06/2019' is). First convert it to date:
SQL> SELECT EXTRACT(YEAR FROM to_date('02/06/2019', 'dd/mm/yyyy')) year FROM DUAL;
YEAR
----------
2019
SQL>
Or, if you know that last 4 digits are valid year, then
SQL> select substr('02/06/2019', -4) year from dual;
YEAR
----
2019
SQL>

It comes down to the data type being passed. sysdate by default is a DATE field. A hard date like '02/06/2020' by default is considered a string.
To get around that, just cast the string as a date. All good.
SELECT TO_CHAR(cast('6-feb-2019' as date),'YYYY') FROM DUAL;

Related

how to get name of a month in sql oracle

Display the month name of date “14-jul-15” in full.
I have tried multiple ways but i am not able to get it to display the name of the month.
Use TO_CHAR function with appropriate format mask.
SQL> select to_char(sysdate, 'fm dd-Month-yyyy') result
2 from dual;
RESULT
------------------
25-March-2021
SQL>
Or, if all you have is a string '14-jul-15', the first convert it to a valid date value (using TO_DATE), and then apply TO_CHAR to it.
I'm using then NLS_DATE_LANGUAGE parameter as well because my database speaks Croatian so "jul" is invalid month for me. You might not need it.
SQL> with test (col) as
2 (select '14-jul-15' from dual)
3 select
4 to_char(
5 to_date(col, 'dd-mon-yy', 'nls_date_language = english'),
6 'fm dd-Month-yyyy', 'nls_date_language = english'
7 ) result
8 from test;
RESULT
------------------
14-July-2015
SQL>

ORA-01846: not a valid day of the week in procedure

Hello In my oracle sql procedure , I am trying to get first sunday of selected year with code below
select next_day(to_date('01.01.'||v_year,'DD.MM.YYYY'), 'Sunday') into v_py from dual;
v_year is number format like 2020 and v_py is date format
but this give me error like title.
When I wrote this query like below then I can see the result. Why isn't it working in procedure
select next_day(to_date('01.01.'||2020,'DD.MM.YYYY'), 'Sunday') from dual;
Thanks in advance
Your code is valid. However, the second argument to next_day() is language-dependent, so I suspect that your database is not English.
You can check the language of the database with the following query:
select * from v$nls_parameters where parameter = 'NLS_LANGUAGE';
From there on, you can change the second parameter from 'Sunday' to the corresponding day name in the database language.
It is also possible to build a language-indenendent expression, taking advantage of the fact that to_char() supports passing a language as last argument (unlike nextday()):
select trunc(to_date(v_year,'YYYY'), 'YYYY')
+ 7
- to_char(trunc(to_date(v_year,'YYYY'), 'YYYY'), 'D', 'NLS_DATE_LANGUAGE=ENGLISH')
into v_py from dual;
trunc(to_date(v_year,'YYYY'), 'YYYY') is just another way to get the first day of the year from the given parameter.
Function NEXT_DAY() depends on NLS_DATE_LANGUAGE, TRUNC(..., 'D') depends on NLS_TERRITORY, so either are not suitable for an NLS independent solution.
Use TRUNC(..., 'IW') which is based on ISO-8601 where begin of the week is always defined on Monday. Would be this:
v_py := TRUNC(TO_DATE('01.01.'||v_year, 'DD.MM.YYYY')+7, 'IW') - 1;
There is no need for SELECT ... INTO ... FROM dual

uisng to_date function still get date format picture ends before converting entire input string error

I have the following code where I want to see if a date is less than a year ago:
select id
from mytable
where id= :p_id
and (to_date(trunc(sysdate), 'yyyy-mm-dd') - to_date(datewhen, 'yyyy-mm-dd')) < 365;
I keep getting the error:
ORA-01830: date format picture ends before converting entire input
string
Looking at other question with the same error on StackOverflow I see the solution usually is to use the to_date function which I am doing so I am unsure why this is occuring. The datewhen field is of type Date.
Do not use to_date() with the columnes of DATE data type. to_date() converts character string to a value of DATE data type. It makes no sense to convert the DATE to DATE. In a first step datewhen column of type DATE will be implicitly converted into a character data type by using the default date format (that's most probably not 'yyyy-mm-dd') and this is the culprit of the ORA-01830 error.
So your statement should look something like this:
select id from mytable where id = :p_id and (trunc(sysdate) - trunc(datewhen)) < 365;
I'd calculate the difference in the months or years instead of days:
... where months_between(sysdate, datewhen) < 12
If your datewhen column is char/varchar formatted as yyyy-mm-dd then you have to do the to_date conversion on datewhen, but not on SYSDATE: it's already a date and doesn't need to be converted.
To filter on a date within the past 365 days, compare it to SYSDATE - 365:
select id
from mytable
where id = :p_id
and to_date(datewhen, 'yyyy-mm-dd') > sysdate - 365;
But a year isn't always 365 days: on leap years it's 366 days. To get a one year ago value that's always correct, subtract an interval of one year from the current date:
select id
from mytable
where id = :p_id
and datewhen > sysdate - interval '1' year;
One more thing: the Oracle DATE type isn't just a date; it's a date and a time. SYSDATE returns the current date and time. Try this query:
select to_char(sysdate, 'yyyy-mm-dd hh24:mi:ss') from dual;
Unless you run this at exactly midnight you'll see a time component as well.
Say your query runs on 2 September 2017 at 10 AM and you're looking for a date within the past year. You'd expect to get the date 3 September 2016, but you wouldn't because at 10 AM SYSDATE is 3 September 2016 at 10:00:00. That's greater than the plain date 3 September 2016, which is 3 September 2016 at 0:00:00, so records with a datewhen of `2016-09-03' won't be included.
To ignore the time component of an Oracle DATE value, use TRUNC. Your final query should look something like this:
select id
from mytable
where id = :p_id
and datewhen > trunc(sysdate) - interval '1' year;
you use TO_DATE function when the value in character format
Syntax
The syntax for the TO_DATE function in Oracle/PLSQL is:
TO_DATE( string1 [, format_mask] [, nls_language] )

date conversion from DD-MM-YYYY to yyyymm

Below is the query i tried but iam getting error. Please correct me.
select to_char(to_date(01-03-2018, 'DD-MM-YYYY'), 'yyyymm') from dual;
Getting below exception
ORA-01847: day of month must be between 1 and last day of month
01847. 00000 - "day of month must be between 1 and last day of month"
select to_char(to_date('01-03-2018', 'DD-MM-YYYY'), 'yyyymm') from dual;
The first argument of TO_DATE function should be from the char group so you need to use quotes.
You missed quotes around date. That's why Oracle treats
01-03-2018 as a number and evaluates it to 1-3-2018 = -2020 and then tries to treat -2020 as the day number of the current month since no other date elements appear to be present.
Real query that oracle execute behind yours is:
select to_char(to_date(to_char(1-3-2018), 'DD-MM-YYYY'), 'yyyymm') from dual;
And the correct query is
select to_char(to_date('01-03-2018', 'DD-MM-YYYY'), 'yyyymm') from dual;
Thanks to #Alex Poole who corrected this explanation.

Get Exact timestamp value?

I am trying to subtract some days from 'current_timestamp' and converting that to timestamp using to_timestamp() function in Oracle. But I am always getting start of day time, that is 12 AM.
When I execute
select to_timestamp(current_timestamp - 3) from dual;
It will give me result like,
18-FEB-14 12.00.00.000000000 AM
But I need exact deduction of 3 days from current time.
Thanks!!!!
select current_timestamp - 3 ts from dual;
or
SELECT SYSTIMESTAMP - INTERVAL '3' DAY AS day FROM dual;
Will give you time as well:
select sysdate - 3 from dual;
Edit based on your comment:
select to_timestamp(to_char(sysdate-3,'DD-Mon-RR HH24:MI:SS'),'DD-Mon-RR HH24:MI:SS') from dual;
Or more simply:
select systimestamp - 3 from dual
An important difference is that SYSDATE gives you server time, and CURRENT_TIMESTAMP gives you session time.
Also, according to the documentation, TO_TIMESTAMP operates on CHAR, VARCHAR2, NCHAR, or NVARCHAR2 data types, not DATE. So I think you need to look elsewhere:
SELECT CAST (SYSDATE AS TIMESTAMP) from dual;