Oracle TO_DATE with only time input will add date component based on what logic? - oracle

Running this code in Oracle 11/12:
select to_date('101200', 'hh24miss') from dual
will return a DATE component that Oracle automatically adds based on what logic?
Eg:
select to_char(to_date('101200', 'hh24miss'), 'yyyymmdd') from dual
returns
20160701
We see the added date component is always set to the first day of the current month. Where does this logic come from?
Thanks in advance

A value of date data type always has date and time components. if you specify only time portion of the datetime value as you did, the date portion defaults to the first day of the current month.
Here is one of the places (7th paragraph) in the Oracle documentation where this behavior is documented.
There is also undocumented TIME literal and TIME data type (needs to be enabled via 10407 (datetime TIME datatype creation) event) if you need to use and store just time, without date part.
Here is a small demonstration of using time literal and time data type. But again it's undocumented and unsupported feature.
SQL> select time '11:32:00' as res
2 from dual;
res
------------------------
11.32.00.000000000 AM
You can use time literal without enabling 10407 event, but in order to be able to define a column of time data type the 10407 event needs to be enabled:
SQL> create table time_table(time_col time);
create table time_table(time_col time)
*
ERROR at line 1:
ORA-00902: invalid datatype
-- enable 10407 event
SQL> alter session set events '10407 trace name context forever, level 1';
Session altered.
Now we can create a table with a column of time data type:
SQL> create table time_table(time_col time);
Table created.
SQL> insert into time_table(time_col)
2 values(time '11:34:00');
1 row created.
SQL> select * from time_table;
TIME_COL
---------------
11.34.00 AM
SQL> alter session set events '10407 trace name context off';
Session altered.

Related

Not able to Delete records on sysdate in oracle

I have been trying deleting records from a table which are of the current date that is sysdate in oracle. You can refer the below image where I tried
Tables Structure and inserted data
Querying Records
As you could see in the first image the type of updated_date is date. When I make an insert the data gets inserted with sysdate but when I try to select/delete it doesnt work in the second image.
At first, I thought maybe due to change in time may have caused this but the type is date and even I have tried to format it to dd-mon-yy so that shouldnt be the case
DATE data type has time component, which is not displayed in your tool.
DATE
The DATE datatype stores point-in-time values (dates and times) in a table. The DATE datatype stores the year (including the century), the month, the day, the hours, the minutes, and the seconds (after midnight).
You need to truncate both SYSDATE and updated_date columns.
SELECT * FROM EMPL WHERE TRUNC(updated_date) = TRUNC(SYSDATE);
To check "real value" you should change the NLS_DATE_FORMAT:
alter session set nls_date_format = 'DD-MON-YYYY HH24:MI:SS';
SELECT * FROM EMPL;

Why do oracle triggers show a different timestamp what is being inserted

My table has a Trigger that stores current_timestamp into a field when the row in the table is updated.
When a row is first inserted it is inserted with a Created date equal to Current_Timestamp. It appears when the procedure inserts the created_date it is given the correct time for daylight savings time but the trigger is inserting the incorrect time.
So the records in question are showing a created date of '2018-03-11 03:13:53.392086000' and a modified date of '2018-03-11 02:13:53.392086000'.
To add to this, we use goldengate for replication and it is using '2018-03-11 03:13:53.392086000' as the audit timestamp and not '2018-03-11 02:13:53.392086000'
Why would a trigger show a time differently then goldengate and the insert? database version I am working with is Oracle 11.2.0.4.0.
Trigger that handles the insert modified time
create or replace trigger UT_INSERT before insert on MYTABLE
REFERENCING NEW AS NEWROW OLD AS OLDROW FOR EACH ROW
begin
:NEWROW.MODIFIED_TIMESTAMP := CURRENT_TIMESTAMP;
end;
Trigger for updated modified time
create or replace trigger UT_UPDATE before update on MYTABLE
REFERENCING NEW AS NEWROW OLD AS OLDROW FOR EACH ROW
begin
:NEWROW.MODIFIED_TIMESTAMP := CURRENT_TIMESTAMP;
end;
The insert statement that is setting created_date is using Current_timestamp. All sessions are currently using a TZ offset of -05:00 and the sessiontimezone is America/Chicago.
That can't always be true. The only way to get the two values you have is for the insert to have been done with created_date set to systimestamp and for the session that issued that to have had it's session time zone set to -05:00, not to America/Chicago.
The reason that must be the case is that there was no 02:13 on March 11th because of the DST change:
select timestamp '2018-03-11 03:13:53.392086000 America/Chicago' from dual;
TIMESTAMP'2018-03-1103:13:53.392086000AMERICA
---------------------------------------------
2018-03-11 03:13:53.392086000 AMERICA/CHICAGO
select timestamp '2018-03-11 02:13:53.392086000 America/Chicago' from dual;
Error report -
SQL Error: ORA-01878: specified field not found in datetime or interval
01878. 00000 - "specified field not found in datetime or interval"
select timestamp '2018-03-11 02:13:53.392086000 -5:00' from dual;
TIMESTAMP'2018-03-1102:13:53.3920860
------------------------------------
2018-03-11 02:13:53.392086000 -05:00
So assuming the column value was set from your trigger, which seems entirely reasonable, the session which did that must have been -05:00 to be able to have got the timestamp at 02:13; and the created_date must have been using systimestamp, where the server OS had the correct time zone of America/Chicago to pick up the DST change (ignore dbtimezone for this), to have got 03:13 at the same moment in time.
As long as the session time zone and server time zone are the same you won't see a discrepancy between using current_timestamp or systimestamp, but you can't always control how sessions are configured, so a mistake or deliberate time zone change can cause problems like this.
Unless you are specifically trying to record a user's local time for some reason (and then you should probably be using a timestamp data type that preserves the time zone), it's safer to always use systimestamp for all of the values you record; and if you're storing as a plain timestamp then it might be safer to always store UTC time.
(Changing to UTC now, particularly with existing data to worry about, probably isn't an option; and not sure how Golden Gate would handle that but seems like a common scenario. Something to think about for the future though. Changing to always use systimestamp ought to be fairly transparent, except that you have this and probably other discrepancies to worry about. Finding and changing all code that might do inserts could be an issue - but then you seem to have inconsistencies already).

How can Time and Date be automatically updated when a data is inserted or updated in oracle?

I want that every time a data is input in oracle table the date and time must automatically be updated in one of the column named 'CREATION_DATE'.
Setting default value of SYSDATE is more efficient than a trigger. As helpc mentioned, a default value can be overridden if NULL is explicitly provided in the INSERT. If you don't intend to pass date time thru application at all, you can define the column as NOT NULL with a default as sysdate .
A trigger will do what you want. I think something like this is what you are looking for:
CREATE OR REPLACE TRIGGER date_trigger
AFTER INSERT ON your_table
FOR EACH ROW
WHEN (new.your_table> 0)
BEGIN
:NEW.CREATION_DATE:= SYSDATE;
END;
/
Depending on your needs I usually like to add both a create_date and an update_date column to pick up timestamps for changes that may occur later.

Oracle - Timestamp

When importing columns of type "Timestamp" to an Oracle DB:
Import tbl:
02.09.13 00:00:00
After importing:
Oracle tbl:
02.09.13 08:23:44,000000000
In the Oracle tbl the type is also "Timestamp".
How can I remove the ",000000000"?
The TIMESTAMP datatype includes fractional seconds; there is no way to remove them within the database whilst maintaining the datatype. If you don't want fractional seconds then put the date into a DATE column.
It shouldn't matter whether the fractional seconds are stored or not. When selecting from the database into anything other than another date datatype you should format the date as required by the client displaying it. The normal method of doing this would be by using the function TO_CHAR(); for instance:
select to_char(column_name, 'dd.mm.yy hh24:mi:ss') from table_name
You can also do this at a session level by changing your NLS settings.
Unrelated to your question, but to address the comment on a comma being part of your timestamp; the default date format is determined by NLS_TERRITORY. A comma is a perfectly valid character to have here. Altering the NLS_TERRITORY, for example to France, it will appear as part of the NLS_DATE_FORMAT:
SQL> alter session set nls_territory = 'FRANCE';
Session altered.
SQL> select systimestamp from dual
2 ;
SYSTIMESTAMP
------------------------------------------------------------
18/09/13 13:09:54,418387 +01:00

How to change Number format in oracle?

I have a requirement to globalize the application based on culture specified in config file.
I have Amounts and date values .I decided to convert them in query itself.Like below
For Spanish Chile Es-CL:
for Date format is "dd-mm-yyyy" I will use Select TO_CHAR(busdate,'dd-mm-yyyy') from itemTable.
Similarly i want to use same for the amounts Select to_char(Amount,'99.999.99,00') from table1.
But its in vain.
Please suggest me the right way to achive my requirement.
These amounts and date formats can be available.but need to know how to convert them.
I thought to use in On_Data_bound event for datagrids ,but still this will be a performance issue.
You would use the NLS_NUMERIC_CHARACTERS session variable, along with globalized format model:
SQL> alter session set NLS_NUMERIC_CHARACTERS='.,';
Session altered
SQL> select to_char(123456789.01, 'fm999G999G990D00') from dual;
TO_CHAR(123456789.01,
---------------------
123,456,789.01
SQL> alter session set NLS_NUMERIC_CHARACTERS=', ';
Session altered
SQL> select to_char(123456789.01, 'fm999G999G990D00') from dual;
TO_CHAR(123456789.01,
---------------------
123 456 789,01

Resources