getting sql error:hour must be between 1 and 12 - sql

There is a problem with a query I use to report.I get an error comparing a value stored as a timestamp with data saved yesterday.
query:
SELECT * FROM PIECE P, PIECE_ATTRB PA WHERE P.PIECE_NUM_ID=PA.PIECE_NUM_ID
AND PA.ATTRB_CODE='PRODUCTION_CUT_DATE'
AND PA.ATTRB_AN_VALUE >=cast(TRUNC(SYSDATE-1)+ INTERVAL '00:00:00' HOUR TO SECOND AS timestamp)
AND pa.ATTRB_AN_VALUE < CAST(TRUNC(SYSDATE)+ INTERVAL '00:00:00' HOUR TO SECOND AS timestamp)
Sample value for pa.attrb_an_value : 03-FEB-21 23:43:26,000000
But I get the following error.
hour must be between 1 and 12

you can first convert the date into timestamp. Instead of ATTRB_AN_VALUE please use
to_timestamp(substr(ATTRB_AN_VALUE,1,18),'DD.MM.YYYY HH24:MI:SSFF3')
This will convert the value into 03-FEB-21 11.43.26.000000 PM and it will eliminate the error.

Since the column attrb_an_value is not a DATE or TIMESTAMP but a VARCHAR2, you cannot compare it to a date without some casting. The TO_TIMESTAMP function will take a string and convert that to a timestamp value with a given format mask.
SELECT
*
FROM
piece p,
piece_attrb pa
WHERE
p.piece_num_id = pa.piece_num_id AND
pa.attrb_code = 'PRODUCTION_CUT_DATE' AND
TO_TIMESTAMP(pa.attrb_an_value,'DD-MON-YY HH24:MI:SS,FF6') >= TRUNC(systimestamp,'DD') - INTERVAL '1' DAY AND
TO_TIMESTAMP(pa.attrb_an_value,'DD-MON-YY HH24:MI:SS,FF6') < TRUNC(systimestamp,'DD')
Note 1: This will fail as soon as a row does not contain a string matching the DD-MON-YY HH24:MI:SS,FF6 format mask.
Note 2: As others pointed out, this is a serious design flaw. No date or timestamp data should be stored in VARCHAR2 columns.

I think your problem is about formatting the date. Here's the correct formatting. Also, I thought that you wanted result set that contained PA's ATTRB_AN_VALUE values in between the beginning of yesterday and today. So, the answer contains the simplified version of compared dates.
SELECT * FROM PIECE P, PIECE_ATTRB PA WHERE P.PIECE_NUM_ID=PA.PIECE_NUM_ID
AND PA.ATTRB_CODE='PRODUCTION_CUT_DATE'
AND to_timestamp(PA.ATTRB_AN_VALUE,'DD-MON-RR HH24:MI:SS,FF') >=to_timestamp(trunc(sysdate-1))
AND to_timestamp(pa.ATTRB_AN_VALUE,'DD-MON-RR HH24:MI:SS,FF') < to_timestamp(trunc(sysdate));

Related

fetch records between 'current date ' and next 5 days(future date) in oracle

Select * from dual where between to_date(date,'YYYY-MM-DD') = '2020-10-01'
and to_date(date,'YYYY-MM-DD') + 5
this is correct way to write query?
1.format of date is varchar2
2.required data between current date and next 5 days
3.first needs to convert into date format.
4. next 5 should be +5 in current day
You probably meant to write:
where to_date(mydate, 'yyyy-mm-dd') between trunc(sysdate)
and trunc(sysdate) + 5
Rationale:
date is a reserved word; I assume that's not the actual name of your column, so I used something else; if that's the real name, then you need to surround it with double quotes ("date", or "DATE", or else, depending on how it was initially defined)
mydate is a string so you need to turn it to a date: for this, you can use to_date()
you then compare it to the current date, without the time portion : trunc(sysdate), and the same date 5 days later
Note, however, that this would be more efficiently expressed as follows:
where mydate between to_char(trunc(sysdate), 'yyyy-mm-dd')
and to_char(trunc(sysdate + 5), 'yyyy-mm-dd')
This avoids the date conversion on the string column, and instead converts the interval bounds. Here, string comparison is possible, because the format of the string you are storing allows it (it it was stored as dd-mm-yyyy' for example, this would not be possible).
Let me, however, strongly suggest to store your dates as dates rather than string. You should always use the proper datatype, for many reason, such as data integrity and efficency.

How to extract month number from date in Oracle

I have ID_BB_SECURITY column where the date value is stored in this column for example '20190801'.
I want to get month number from this field for example for August date i want to get 8.
I tried below query but it throws an error 'literal does not match':
select to_number(to_date(ID_BB_SECURITY),'mm') from BT_EXPORT
I am not sure if i have to ignore null values so as to avoid the error
If the value is a number or string then you can convert it to a date with an appropriate mask - which is what you are missing, and what is causing the error you are getting (as it's using your session's NLS_DATE_FORMAT setting, which apparently does not match the format of the data; but which you should not rely on anyway, as #MTO said in comments):
to_date(ID_BB_SECURITY, 'YYYYMMDD')
and then extract the month number from that:
select extract(month from to_date(ID_BB_SECURITY, 'YYYYMMDD')) from BT_EXPORT
Or you could just use a substring:
select to_number(substr(ID_BB_SECURITY, 5, 2)) from BT_EXPORT;
Those assume a fixed consistent format, which is always a risky assumption when using the wrong data type. Ans if it's a number they are doing an implicit conversion from number to string, which you could turn into an explicit conversion for greater clarity.
If it's already a date - as it should be, of course - then you don't need the conversion:
select extract(month from ID_BB_SECURITY) from BT_EXPORT
If you have a number, you can use arithmetic to extract the month:
select mod(floor(20190801 / 100), 100)
from dual;
You could try converting the number date to a string, and then extracting the 5th and 6th characters:
SELECT
SUBSTR(TO_CHAR(ID_BB_SECURITY), 5, 2) AS mm
FROM BT_EXPORT;
But, it would be much better for you to use a proper date column. Then, you could use a less draconian method such as:
SELECT
TO_CHAR(ID_BB_SECURITY, 'mm') AS mm -- assuming date
FROM BT_EXPORT;
select to_number(to_char(to_date('20190801', 'yyyymmdd'), 'mm')) from dual
Try this one
select extract(month from to_date(ID_BB_SECURITY, 'YYYYMMDD')) from BT_EXPORT
This one convert number to date then extract month.
also
select extract(month from to_date('20190801', 'yyyymmdd')) from dual
Your date column has the value stored in the following format "yyyymmdd" where
yyyy is the year
mm the month
dd the day
So in order to return the number value of the month (mm) we can do as follows:
1: first transform the value from a number to a date using
to_date(20190801,'yyyymmdd')
2: get month using to_date operator
to_char( to_date(20190801,'yyyymmdd'), 'mm')

Oracle SQL - convert a varchar2 into a date

I have a problem with converting a varchar2 fields into a date format.
I got 2 columns with the datatyp varchar2, one is called qtime the other is called ztime. Both fields contain strings in this format (f.e. 152015 -> would be a timestamp 15:20:15).
For reporting reasons I need to convert this fields into a date format, afterwards I want to substract (qtime-ztime) the fields an convert them into the format [hh] (f.e. after the operation 01:20:00 would be -> 01). Is it possible to to this within Oracle SQL 12c? The biggest problem for me right now is that I don't get those Strings converted into a date format.
select TO_DATE(qtime,'MM/DD/YYYY hh24:mi:ss') just gives me
ORA-01861:"literal does not match format string"
select TO_DATE(qtime,'hh24mmss') gives me a wrong Date
01.03.2018
select TO_TIMESTAMP(qtime,'hh24mmss') gives me a wrong Date
01.03.2018 BUT the correct time with f.e. 15:20:15,0000000
Thank you in advance, any help is appreciated
Note: I only have reading rights on the database Oracle 12c, so I need to to this within Statements
"The Database contains another column with the correct date for each time"
The missing piece of the puzzle! Concatenate the two columns to get something which can be converted to an Oracle DATE:
select to_date(qdate||qtime, 'yyyymmddhh24miss') as qdatetime
, to_date(zdate||ztime, 'yyyymmddhh24miss') as zdatetime
from your_table
Once you have done that you can perform arithmetic of the dates e.g.
select id
, zdatetime - qdatetime as time_diff
from ( select id
, to_date(qdate||qtime, 'yyyymmddhh24miss') as qdatetime
, to_date(zdate||ztime, 'yyyymmddhh24miss') as zdatetime
from your_table
)
If you want the number of hours in the difference you can include this expression in the projection of the outer query:
, extract( hour from (zdatetime - qdatetime) day to second) as hrs_ela
First off, if you are trying to convert a varchar2 into a date without specifying neither day nor month, it will default to the first day of the current month:
If you specify a date value without a date, then the default date is the first day of the current month.
You can read up more here
Also in 2nd and 3rd your example, you are using 'hh24mmss' for specifying hour, minute and second components, but do note that correct format for minutes is 'mi' and not 'mm', which is used for months.
So the solution is to concatenate both date and time component when creating the date as the other answer suggested, tho I would recommend using a single date field as it can store the information you need.

Issue querying date from oracle.

I understand that querying a date will fail as its comparing a string to date and that can cause an issue.
Oracle 11.2 G
Unicode DB
NLS_DATE_FORMAT DD-MON-RR
select * from table where Q_date='16-Mar-09';
It can be solved by
select * from table where trunc(Q_date) = TO_DATE('16-MAR-09', 'DD-MON-YY');
What I don't get is why this works.
select* from table where Q_date='07-JAN-08';
If anyone can please elaborate or correct my mindset.
Thanks
Oracle does allow date literals, but they depend on the installation (particularly the value of NLS_DATE_FORMAT as explained here). Hence, there is not a universal format for interpreting a single string as a date (unless you use the DATE keyword).
The default format is DD-MM-YY, which seems to be the format for your server. So, your statement:
where Q_date = '07-JAN-08'
is interpreted using this format.
I prefer to use the DATE keyword with the ISO standard YYYY-MM-DD format:
where Q_Date = DATE '2008-01-07'
If this gets no rows returned:
select * from table where Q_date='16-Mar-09';
but this does see data:
select * from table where trunc(Q_date) = TO_DATE('16-MAR-09', 'DD-MON-YY');
then you have rows which have a time other than midnight. At this point in the century DD-MON-RR and DD-MON-YY are equivalent, and both will see 09 as 2009, so the date part is right. But the first will only find rows where the time is midnight, while the second is stripping the time off via the trunc, meaning the dates on both sides are at midnight, and therefore equal.
And since this also finds data:
select* from table where Q_date='07-JAN-08';
... then you have rows at midnight on that date. You might also have rows with other times, so checking the count with the trunc version might be useful.
You can check the times you actually have with:
select to_char(q_date, 'YYYY-MM-DD HH24:MI:SS') from table;
If you do want to make sure you catch all times within the day you can use a range:
select * from table where
q_date >= date '2009-03-16'
and q_date < date '2009-03-17';
Quick SQL Fiddle demo.
Although it sounds like you're expecting all the times to be midnight, which might indicate a data problem.

How to take differece between 2 dates of different format in SQL

I have a table with a LOAD_STRT_DTM colum. This is a date column and values are like this - 18-JUL-14 08.20.34.000000000 AM.
I want to find the data which came before 5 days.
My logic is -
Select * from Table where 24 *(To_DATE(Sysdate,'DD-MM-YY') - To_DATE(LOAD_STRT_DTM,'DD-MM-YY')) >120
The issue is -
Select (To_DATE(Sysdate,'DD-MM-YY') - To_DATE(LOAD_STRT_DTM,'DD-MM-YY')) from table
This query should give the NumberOfDays between two dates. But this is not working, I Doubt, the issue is because of the format of the LOAD_STRT_DTM colum.
Please let me know where i am doint it wrong.
If your column is DATE datatype everything is ok, just shoot an:
select * from table where LOAD_STRT_DTM > sysdate - 5;
No need to convert dates to DATE datatype.
(To_DATE(Sysdate,'DD-MM-YY') - To_DATE(LOAD_STRT_DTM,'DD-MM-YY'))
You don't have to convert a DATE into a DATE again. IT is already a DATE. You just need to use it for date calculations. You use TO_DATE to convert a STRING into a DATE.
For example, if you have a string value like '18-JUL-14', then you would need to convert it into date using TO_DATE. Since your column is DATE data type, you just need to use as it is.
This is a date column
I want to find the data which came before 5 days.
Simply use the filter predicate as:
WHERE load_strt_dtm > SYSDATE - 5;
NOTE : SYSDATE has both date and time elements, so it will filter based on the time too. If you want to use only the date part in the filter criteria, then you could use TRUNC. IT would truncate the time element.
I have answered a similar question, have a look at this https://stackoverflow.com/a/29005418/3989608
It looks like LOAD_STRT_DTM is a TIMESTAMP rather than a DATE, given the number of decimal points following the seconds. The only thing you have to be cautious about is that Oracle will convert a DATE to a TIMESTAMP implicitly where one of the operands is a TIMESTAMP. So the solution
WHERE load_strt_dtm > SYSDATE - 5
will work; as will
WHERE load_strt_dtm + 5 > SYSDATE
but the following will not:
WHERE SYSDATE - load_start_dtm < 5
the reason being that TIMESTAMP arithmetic produces an INTERVAL rather than a NUMBER.
first convert two dates to same format select datediff(dd,convert(varchar(20),'2015-01-01',112),convert(varchar(20),'01-10-2015',112))