Need help with Oracle SQL Formatting. I have the below code which outputs the data (MINNEEDTIME) in DD-MM-YY format. Need to change this to MM/DD/YYYY HH:MI AM format. Tried TO_CHAR for converting and that threw an error. Any assistance will be appreciated. Thank you
min(case when ve.REASON in ('Need Time', 'WAITING Time') then ve.EVENT_DTIME end) as MINNEEDTIME
You can use TO_CHAR(<date>, <format>) as in:
select to_char(current_date, 'MM/DD/YYYY HH:MI AM') from dual
In your case replace ve.EVENT_DTIME with:
to_char(ve.EVENT_DTIME, 'MM/DD/YYYY HH:MI AM')
In Oracle, a DATE is a binary data type consisting of 7 bytes that represent: century, year-of-century, month, day, hour, minute and second. It ALWAYS contains those components and it is never stored with any human-readable format.
What you are seeing is the client application you are using to access the database receiving the (unformatted) binary data and trying to be helpful and applying its own format to the date.
You need to either:
Explicitly convert the value from a DATE to a string and apply a format using the TO_CHAR function:
TO_CHAR(
min(
case
when ve.REASON in ('Need Time', 'WAITING Time')
then ve.EVENT_DTIME
end
),
'MM/DD/YYYY HH12:MI AM'
) as MINNEEDTIME
Or, you need to change how the client application you are using formats dates. You can either look for the settings/preferences in the application or some applications (for example, SQL*Plus or SQL Developer) will use the NLS_DATE_FORMAT session parameter which you can change using:
ALTER SESSION SET NLS_DATE_FORMAT = 'MM/DD/YYYY HH:MI AM';
Related
I've tried multiple solutions, but I keep getting errors. I need to create a new column casting VARCHAR to TIMESTAMP that includes AM, PM or -ideally- changes it to 24 hrs format.
VARCHAR format (Start_Date column): 8/3/2022 4:58:49 PM
I found the below solution is some other post, but I'm getting error: 'Format code appears twice'
SELECT itab.*,
TO_TIMESTAMP(Start_Date, 'MM/DD/YYYY HH:MM:SS AM') AS start_TS
FROM db.info_table itab
Please advise.
You have two problems.
MI is the format for minutes, MM is for months (you have it twice, this is why you are getting that error).
Your date/time string has single digit values for month, day, etc. You can use a pretty simple regex for that.
select to_timestamp(regexp_replace('8/3/2022 4:58:49 PM', '\b([0-9])\b', '0\1'), 'MM/DD/YYYY HH:mi:SS AM')
TO_TIMESTAMP returns a TIMESTAMP(6). If you don't want microseconds you can specify the precision using
CAST(RegExp_Replace(start_date, '\b([0-9])\b', '0\1') AS timestamp(0) FORMAT 'MM/DD/YYYYbHH:Mi:SSbT')
All you need is pad day and month in Teradata (as opposed to Oracle etc). m/d/y format has not been implemented.
select '8/3/2022 4:58:49 PM' date1,
to_timestamp(
lpad(strtok(date1,'/',1),2,'0')||'/'||lpad(strtok(date1,'/',2),2,'0')||'/'||strtok(date1,'/',3)
,'mm/dd/yyyy hh24:mi:ss AM'
);
I firstly run the following command, and get the following result:
select to_char(systimestamp, 'YYYY-MM-DD HH24:MI:SS') from dual;
TO_CHAR(SYSTIMESTAM
-------------------
2018-07-10 10:21:40
This is the format I want to have a TIMESTAMP object stored in.
When I convert it back though, it does not come in the format I want:
select to_timestamp(to_char(systimestamp, 'YYYY-MM-DD HH24:MI:SS'), 'YYYY-MM-DD HH24:MI:SS') from dual;
TO_TIMESTAMP(TO_CHAR(SYSTIMESTA
-------------------------------
10-JUL-18 10.21.40.000000000 AM
In fact, it changes 2018 to be at the end, sets 07 to be "JUL" and the 10 is now at the front. Also the time is separated by dots, has many 0's and an AM.
How can I fix this? I am new to SQL development so I am not sure about the formatting.
Thank you so much
As #Gordon said, timestamps (and dates) are not stored in a format you would recognise Oracle uses an internal representation that you never really need to know about or examine (but it is documented if you're interested in that sort of thing).
When you query a timestamp it is displayed using your client's NLS settings, unless you have a client that overrides those. I can set my session up to match what you are seeing:
alter session set nls_timestamp_format = 'DD-MON-RR HH.MI.SS.FF AM';
select to_char(systimestamp, 'YYYY-MM-DD HH24:MI:SS') from dual;
TO_CHAR(SYSTIMESTAM
-------------------
2018-07-10 15:37:31
select to_timestamp(to_char(systimestamp, 'YYYY-MM-DD HH24:MI:SS'), 'YYYY-MM-DD HH24:MI:SS') from dual;
TO_TIMESTAMP(TO_CHAR(SYSTIMESTA
-------------------------------
10-JUL-18 03.37.31.000000000 PM
And I can change it see what you want to see:
alter session set nls_timestamp_format = 'YYYY-MM-DD HH24:MI:SS';
select to_timestamp(to_char(systimestamp, 'YYYY-MM-DD HH24:MI:SS'), 'YYYY-MM-DD HH24:MI:SS') from dual;
TO_TIMESTAMP(TO_CHA
-------------------
2018-07-10 15:37:32
But all you are doing is converting from a timestamp with time zone (which is what systimestamp is) to a string and then back to a timestamp. You are losing the time zone portion, and any fractional seconds; which you could also do with a cast:
select cast(systimestamp as timestamp(0)) from dual;
CAST(SYSTIMESTAMPAS
-------------------
2018-07-10 15:37:32
You can see the timezone and fraction seconds with your default timestamp_tz format:
select systimestamp from dual;
SYSTIMESTAMP
------------------------------------
2018-07-10 15:37:33.776469000 +01:00
and change it with a different alter:
alter session set nls_timestamp_tz_format = 'YYYY-MM-DD HH24:MI:SS.FF3 TZH:TZM';
select systimestamp from dual;
SYSTIMESTAMP
------------------------------
2018-07-10 15:37:34.070 +01:00
Which isn't entirely relevant if you're really talking about storing timestamps in a table, but shows that there are variations.
In your table make the data type timestamp (or timestamp with time zone or timestamp with local time zone), and only worry about formatting the value as a string for presentation to the end user, at the last possible moment.
When you do need to display it, if the display format is important to you then use to_char() with an explicit format mask - do not assume that anyone else running your queries will have the same NLS settings. As you can see, it's easy to change those to modify the output. (Most clients have a way to let you set the defaults so you don't have to do the same alter commands every time you connect; e.g. in SQL Developer, from Tools->Preferences->Database->NLS). If you want to always show the same format then use something like:
select to_char(your_column, 'YYYY-MM-DD HH24:MI:SS') as column_alias
from your_table
where your_column < timestamp '2018-01-01 00:00:00'
which also shows the column value being filtered (as a timestamp still) using a timestamp literal.
This is the format I want to have a TIMESTAMP object stored in.
This is a common misconception - timestamp (and date) data types do not have a format; they are stored in the database as 20 bytes (or 7 bytes for dates) representing:
year (2 bytes),
month, day, hour, minute, integer seconds (1 bytes each),
fractional seconds (4 bytes),
time zone offset hours (1 byte),
time zone offset minutes (1 byte),
other data (including time zone location) (7 bytes)
You can see the bytes using the DUMP function:
SELECT DUMP( your_timestamp_column ) FROM your_table;
The database will operate on these 20 bytes without any format. But that would not be useful to display to you, the user, so the user interface you use to access the database (SQL/Plus, SQL Developer, Toad, Java, C#, etc) will receive those raw bytes from the database and will silently format them into a more intelligible format for you, the user.
What you are actually asking is:
How can I get the application I am using to access the Oracle database to change the default format it uses to display TIMESTAMP data types?
For SQL/Plus (and SQL Developer) you can use the NLS_TIMESTAMP_FORMAT session parameter:
ALTER SESSION SET NLS_TIMESTAMP_FORMAT = 'YYYY-MM-DD HH24:MI:SS';
Then:
SELECT SYSTIMESTAMP FROM DUAL;
Will output:
2018-07-10 16:24:53
However, this only sets the default format for your user's current session; other users can set their own parameters and can change the value during their session so you should not rely on this to provide a consistent formatting.
Instead, if you want to have a TIMESTAMP with a particular format then you should convert it to a datatype which can have a format - a string.
SELECT TO_CHAR( SYSTIMESTAMP, 'YYYY-MM-DD HH24:MI:SS' ) FROM DUAL;
Then it does not matter what the user changes their default timestamp format to - your values will always be formatted how you expect.
So based on your replies above it sounds like you may be trying to do something you don't actually need to do.
As Gordon mentioned, timestamps are stored in an internal format so you can do things with the values. If you have the field stored as a timestamp data type you don't need to care how it's formatted in the database, you just need to care about how it looks for your query at the end. You can display a date field using to_char and still use a date range if you have the query built correctly.
select to_char(systimestamp, 'YYYY-MM-DD HH24:MI:SS')
from dual
WHERE systimestamp <= current_timestamp;
I don't think it is possible to to display the timestamp as you've described without using to_char and losing the data type.
I'm getting an Error when I run the query below:
to_date('30-APR-19 09.53.35.000000 AM', 'DD-Mon-yy hh24.mi.ss')
Date format picture ends before converting entire input into string
Can I get an assistance please
The major problem you've got is that your date-and-time string can't be parsed using TO_DATE - you'll need to use TO_TIMESTAMP. The issue is that TO_DATE doesn't recognize the FFn format specifier, which is used to process fractional seconds. This makes sense because DATE values are only accurate to the second. So you'll need to use
TO_TIMESTAMP('30-APR-19 09.53.35.000000 AM', 'DD-MON-YY HH.MI.SS.FF6 AM')
Which will return a TIMESTAMP value. If you really need this to be a DATE rather than a TIMESTAMP you can cast the value to DATE by using
CAST(TO_TIMESTAMP('30-APR-19 09.53.35.000000 AM', 'DD-MON-YY HH.MI.SS.FF6 AM') AS DATE)
dbfiddle here
You can directly use to_date function and miliseconds can be ignored using # as following:
to_date('30-APR-19 09.53.35.000000 AM', 'DD-MON-YY HH.MI.SS.###### AM')
Number of # is equal to number of 0s after dot(.)
db<>fiddle demo
Cheers!!
I firstly run the following command, and get the following result:
select to_char(systimestamp, 'YYYY-MM-DD HH24:MI:SS') from dual;
TO_CHAR(SYSTIMESTAM
-------------------
2018-07-10 10:21:40
This is the format I want to have a TIMESTAMP object stored in.
When I convert it back though, it does not come in the format I want:
select to_timestamp(to_char(systimestamp, 'YYYY-MM-DD HH24:MI:SS'), 'YYYY-MM-DD HH24:MI:SS') from dual;
TO_TIMESTAMP(TO_CHAR(SYSTIMESTA
-------------------------------
10-JUL-18 10.21.40.000000000 AM
In fact, it changes 2018 to be at the end, sets 07 to be "JUL" and the 10 is now at the front. Also the time is separated by dots, has many 0's and an AM.
How can I fix this? I am new to SQL development so I am not sure about the formatting.
Thank you so much
As #Gordon said, timestamps (and dates) are not stored in a format you would recognise Oracle uses an internal representation that you never really need to know about or examine (but it is documented if you're interested in that sort of thing).
When you query a timestamp it is displayed using your client's NLS settings, unless you have a client that overrides those. I can set my session up to match what you are seeing:
alter session set nls_timestamp_format = 'DD-MON-RR HH.MI.SS.FF AM';
select to_char(systimestamp, 'YYYY-MM-DD HH24:MI:SS') from dual;
TO_CHAR(SYSTIMESTAM
-------------------
2018-07-10 15:37:31
select to_timestamp(to_char(systimestamp, 'YYYY-MM-DD HH24:MI:SS'), 'YYYY-MM-DD HH24:MI:SS') from dual;
TO_TIMESTAMP(TO_CHAR(SYSTIMESTA
-------------------------------
10-JUL-18 03.37.31.000000000 PM
And I can change it see what you want to see:
alter session set nls_timestamp_format = 'YYYY-MM-DD HH24:MI:SS';
select to_timestamp(to_char(systimestamp, 'YYYY-MM-DD HH24:MI:SS'), 'YYYY-MM-DD HH24:MI:SS') from dual;
TO_TIMESTAMP(TO_CHA
-------------------
2018-07-10 15:37:32
But all you are doing is converting from a timestamp with time zone (which is what systimestamp is) to a string and then back to a timestamp. You are losing the time zone portion, and any fractional seconds; which you could also do with a cast:
select cast(systimestamp as timestamp(0)) from dual;
CAST(SYSTIMESTAMPAS
-------------------
2018-07-10 15:37:32
You can see the timezone and fraction seconds with your default timestamp_tz format:
select systimestamp from dual;
SYSTIMESTAMP
------------------------------------
2018-07-10 15:37:33.776469000 +01:00
and change it with a different alter:
alter session set nls_timestamp_tz_format = 'YYYY-MM-DD HH24:MI:SS.FF3 TZH:TZM';
select systimestamp from dual;
SYSTIMESTAMP
------------------------------
2018-07-10 15:37:34.070 +01:00
Which isn't entirely relevant if you're really talking about storing timestamps in a table, but shows that there are variations.
In your table make the data type timestamp (or timestamp with time zone or timestamp with local time zone), and only worry about formatting the value as a string for presentation to the end user, at the last possible moment.
When you do need to display it, if the display format is important to you then use to_char() with an explicit format mask - do not assume that anyone else running your queries will have the same NLS settings. As you can see, it's easy to change those to modify the output. (Most clients have a way to let you set the defaults so you don't have to do the same alter commands every time you connect; e.g. in SQL Developer, from Tools->Preferences->Database->NLS). If you want to always show the same format then use something like:
select to_char(your_column, 'YYYY-MM-DD HH24:MI:SS') as column_alias
from your_table
where your_column < timestamp '2018-01-01 00:00:00'
which also shows the column value being filtered (as a timestamp still) using a timestamp literal.
This is the format I want to have a TIMESTAMP object stored in.
This is a common misconception - timestamp (and date) data types do not have a format; they are stored in the database as 20 bytes (or 7 bytes for dates) representing:
year (2 bytes),
month, day, hour, minute, integer seconds (1 bytes each),
fractional seconds (4 bytes),
time zone offset hours (1 byte),
time zone offset minutes (1 byte),
other data (including time zone location) (7 bytes)
You can see the bytes using the DUMP function:
SELECT DUMP( your_timestamp_column ) FROM your_table;
The database will operate on these 20 bytes without any format. But that would not be useful to display to you, the user, so the user interface you use to access the database (SQL/Plus, SQL Developer, Toad, Java, C#, etc) will receive those raw bytes from the database and will silently format them into a more intelligible format for you, the user.
What you are actually asking is:
How can I get the application I am using to access the Oracle database to change the default format it uses to display TIMESTAMP data types?
For SQL/Plus (and SQL Developer) you can use the NLS_TIMESTAMP_FORMAT session parameter:
ALTER SESSION SET NLS_TIMESTAMP_FORMAT = 'YYYY-MM-DD HH24:MI:SS';
Then:
SELECT SYSTIMESTAMP FROM DUAL;
Will output:
2018-07-10 16:24:53
However, this only sets the default format for your user's current session; other users can set their own parameters and can change the value during their session so you should not rely on this to provide a consistent formatting.
Instead, if you want to have a TIMESTAMP with a particular format then you should convert it to a datatype which can have a format - a string.
SELECT TO_CHAR( SYSTIMESTAMP, 'YYYY-MM-DD HH24:MI:SS' ) FROM DUAL;
Then it does not matter what the user changes their default timestamp format to - your values will always be formatted how you expect.
So based on your replies above it sounds like you may be trying to do something you don't actually need to do.
As Gordon mentioned, timestamps are stored in an internal format so you can do things with the values. If you have the field stored as a timestamp data type you don't need to care how it's formatted in the database, you just need to care about how it looks for your query at the end. You can display a date field using to_char and still use a date range if you have the query built correctly.
select to_char(systimestamp, 'YYYY-MM-DD HH24:MI:SS')
from dual
WHERE systimestamp <= current_timestamp;
I don't think it is possible to to display the timestamp as you've described without using to_char and losing the data type.
I am facing the following problem.
I have a database with a table which saves Dates (with its time).
Now I would like to know all the tables information where the date is in between two timestamps, but I am getting the following error:
01830. 00000 - "date format picture ends before converting entire input string".
What I did so far is this query:
SELECT * FROM ARBEITSBLOCK WHERE STARTZEIT BETWEEN '30.11.2015 19:00:00'
and '01.12.2015 19:05:00';
And this which doesn't give me any result but there should be:
SELECT * FROM ARBEITSBLOCK
WHERE TO_CHAR(STARTZEIT,'DD.MM.YYYY H24:MM:SS') BETWEEN '30.11.2015 13:00:00'
and '01.12.2015 19:05:00';
Try this statement (using Oracle syntax)
SELECT *
FROM ARBEITSBLOCK
WHERE STARTZEIT BETWEEN TO_DATE ('12/04/2015 09:00:00 AM', 'mm/dd/yyyy hh:mi:ss AM')
AND TO_DATE ('12/04/2015 10:00:00 AM', 'mm/dd/yyyy hh:mi:ss AM');
If STARTZEIT is a DATE column, then why are you trying to compare it to a string?
By doing that, you are relying on Oracle being able to say "aha! This string is really a date, so I will attempt to convert it for you!". That's all well and good, but how will Oracle know how the date-in-the-string is formatted?
Well, there's the nls_date_format parameter which is defaulted to 'DD-MON-RR', and I think you can now see why you're getting the "date format picture ends before converting entire input string" error, since 'DD-MON-RR' is a lot shorter than '30.11.2015 19:00:00'.
Instead of relying on this implicit conversion and the bugs that go right along with that (as you've discovered!), you should explicitly convert the string into a date, which you can easily do with the to_date() function.
E.g.:
select *
FROM ARBEITSBLOCK
WHERE STARTZEIT BETWEEN to_date('30.11.2015 19:00:00', 'dd.mm.yyyy hh24:mi:ss')
and to_date('01.12.2015 19:05:00', 'dd.mm.yyyy hh24:mi:ss');
Oracle does not store dates in the format you see. It stores it internally in 7 bytes with each byte storing different components of the datetime value.
You must use TO_DATE with proper FORMAT MODEL to explicitly convert the literal to DATE.
SELECT *
FROM ARBEITSBLOCK
WHERE STARTZEIT BETWEEN
TO_DATE('30.11.2015 19:00:00', 'DD.MM.YYYY HH24:MI:SS')
AND
TO_DATE('01.12.2015 19:05:00', 'DD.MM.YYYY HH24:MI:SS');
Remember, the DATE data type has both date and time elements, TIMESTAMP is an extension to DATE data type.