I have three timestamps in my SQL Table.
Column Name Data Type Nullable Data_Default
STATUS_TIMSTM TIMESTAMP(6) No (null)
CREATED_TIMSTM TIMESTAMP(6) No SYSTIMESTAMP
UPDATED_TIMSTM TIMESTAMP(6) No (null)
INSERT INTO "TABLE_NAME" ("STATUS_TIMSTM","CREATED_TIMSTM","UPDATED_TIMSTM")
VALUES(TIMESTAMP '2020-12-10 00:00:00', TIMESTAMP '2020-06-15 00:00:00',TIMESTAMP '2020-06-15 00:00:00');
The above works correctly.
How do I insert the current systimestamp?
I've tried several options: curdate(), now(), systimestamp().
I usually get errors such as Error report -
SQL Error: ORA-00904: "NOW": invalid identifier 00904. 00000 - "%s: invalid identifier"
You should be able to use current_timestamp:
create table t (x TIMESTAMP(6));
insert into t (x) values (current_timestamp);
Of course, systimestamp should also work.
Here is a db<>fiddle.
Since you already have a DATA DEFAULT, only inserting data in below format must populate the CREATED_TIMSTM column with current TIMESTAMP.
INSERT INTO "TABLE_NAME" ("STATUS_TIMSTM","UPDATED_TIMSTM")
VALUES(TIMESTAMP '2020-12-10 00:00:00', TIMESTAMP '2020-06-15 00:00:00');
Here is a simplified DB fiddle demonstrating the same.
In Oracle you would
insert into my_table(timestamp_column) values (systimestamp);
Notice that the function call does not include parentheses after the function name. Oracle is pretty odd in this regard; functions that don't take parameters, but that you define yourself, must use empty parentheses, but similar functions (no parameters) that are provided by Oracle must be used without parentheses. Only Oracle knows why it's inconsistent this way. This explains why your attempt was failing.
(Actually, some experimentation with systimestamp shows that it can take an argument - a positive integer which shows how many decimal places you want for seconds! In any case, you can't use it with empty parentheses.)
There are other "current" timestamp functions, but they do different things. systimestamp returns the timestamp of the computer system that hosts the database server. (Note that this may, and often is, different from the database timestamp.) In any case, systimestamp is by far the most commonly used of these; similar to sysdate for dates.
Beware of time zone though. systimestamp returns timestamp with time zone. By inserting it into a timestamp column, you are losing information. Is that OK for your business application?
Related
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).
I have created a table in Oracle in which I have KPI_START_DATE column which is a Date datatype, and KPI_START_TIME which is a TIMESTAMP datatype.
Now I want to modify this date dataype for
KPI_START_DATE to dd/mm/yyyy
and
KPI_START_TIME to HH:MI:SS.
So that user should always enter the date and time in this column in this proper format.
I tried below query but its was giving error:
Alter table KPI_DEFINITION MODIFY(to_char(KPI_START_DATE,'dd/mm/yyyy') )
DATE and TIMESTAMP columns do not have any inherent readable format. The values are stored in Oracle's own internal representation, which has no resemblance to a human-readable date or time. At the point to retrieve or display a value you can convert it to whatever format you want, with to_char().
Both DATE and TIMESTAMP have date and time components (to second precision with DATE, and with fractional seconds with TIMESTAMP; plus time zone information with the extended data types), and you should not try to store them separately as two columns. Have a single column and extract the information you need at any time; to get the information out of a single column but split into two fields you could do:
select to_char(KPI_START, 'dd/mm/yyyy') as KPI_START_DATE,
to_char(KPI_START, 'hh24:mi:ss') as KPI_START_TIME
but you'd generally want both together anyway:
select to_char(KPI_START, 'dd/mm/yyyy hh24:mi:ss')
Also notice the 'hh24' format model to get the 24-hour clock time; otherwise you wouldn't see any difference between 3 a.m. and 3 p.m.
You can store a value in either type of column with the time set to midnight, but it does still have a time component - it is just midnight. You can't store a value in either type of column with just a time component - it has to have a date too. You could make that a nominal date and just ignore it, but I've never seen a valid reason to do that - you're wasting storage in two columns, and making searching for and comparing values much harder. Oracle even provides a default date if you don't specify one (first day of current month). But the value always has both a date and a time part:
create table KPI_DEFINITION (KPI_START date);
insert into KPI_DEFINITION (KPI_START)
values (to_date('27/01/2015', 'DD/MM/YYYY'));
insert into KPI_DEFINITION (KPI_START)
values (to_date('12:41:57', 'HH24:MI:SS'));
select to_char(KPI_START, 'YYYY-MM-DD HH24:MI:SS') from KPI_DEFINITION;
TO_CHAR(KPI_START,'YYYY-MM-DDHH24:MI:SS')
-----------------------------------------
2015-01-27 00:00:00
2015-01-01 12:41:57
Your users should be inserting a single value with both date and time as one:
insert into KPI_DEFINITION (KPI_START)
values (to_date('27/01/2015 12:41:57', 'DD/MM/YYYY HH24:MI:SS'));
select to_char(KPI_START, 'YYYY-MM-DD HH24:MI:SS') from KPI_DEFINITION;
TO_CHAR(KPI_START,'YYYY-MM-DDHH24:MI:SS')
-----------------------------------------
2015-01-27 12:41:57
You can also use date or timestamp literals, and if using to_date() you should always specify the full format - don't rely on NLS settings as they may be different for other users.
You should understand difference between datatype and format. DATE is a datatype. TIMESTAMP is a datatype. None of them have formats, they're just numbers.
When converting character datatype to or from date datatype, format should be applied. It's an attribute of an actual conversion, nothing else.
Look at this:
SQL> create table tmp$date(d date);
Table created
SQL> insert into tmp$date values (DATE '2010-11-01');
1 row inserted
SQL> insert into tmp$date values (DATE '2014-12-28');
1 row inserted
SQL> select d, dump(d) from tmp$date;
D DUMP(D)
----------- ---------------------------------
01.11.2010 Typ=12 Len=7: 120,110,11,1,1,1,1
28.12.2014 Typ=12 Len=7: 120,114,12,28,1,1,1
There is no any 'format' here.
DISPLAYING and STORING are NOT the same when it comes to DATE.
When people say Oracle isn’t storing the date in the format they wanted, what is really happening is Oracle is not presenting the date in the character string format they expected or wanted.
When a data element of type DATE is selected, it must be converted from its internal, binary format, to a string of characters for human consumption. The conversion of data from one type to another is known as known a “conversion”, “type casting” or “coercion”. In Oracle the conversion between dates and character strings is controlled by the NLS_DATE_FORMAT model. The NLS_DATE_FORMAT can be set in any of several different locations, each with its own scope of influence.
I could go on with my leacture over DATE data type, but I am glad that someone has already got a good writeup over this. Please read this https://edstevensdba.wordpress.com/2011/04/07/nls_date_format/
We have tables with date fields(type date) and inserting timestamp into the date field works in some of our oracle environments(We have multiple environments for development) and fails in some environment.
I would like to know why it works in some cases and some cases it fails with ORA-01843: not a valid month
Example
Table1
date1 DATE
The following sql works in some environment and fails in some environments
Insert into Table1 (date1) values ( to_timestamp(sysdate))
Oracle version - Oracle Database 11g
Can we insert timestamp into date field(like above)? Does oracle supports inserting timestamp values to date field?
Thanks in advance.
Instead of sysdate, use current_timestamp (although it is pointless, since it will become a date in the database anyway):
insert into Table1 (date1) values (current_timestamp)
I guess the reason it fails is that to_timestamp needs a varchar and the conversion failed.
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
I am using Oracle10g database in which a table contains a Column with Date DataType. I am using the following query to get the record:
select to_char(START_TIME, 'YYMMDD HH24:MI:SS') from table;
So from above query, the result will be of type VARCHAR. I have tried to_Date() method but resulted in displaying only DATE. Can i convert VARCHAR to DATETIME format? The result should be of type DATETIME. Please help me how to resolve this problem.
an Oracle date contains both date and time so you can consider it a datetime (there is no datatype of datetime in Oracle). how is DISPLAYS when you select it is entirely up to your client. the default display setting is controlled by the NLS_DATE_FORMAT parameter. If you're just using the date in your pl/sql block then just assign it into a date datatype and select into that variable without to_char and it will work just fine and contain whatever time component is present in your table.
to control the display, for example using nls_date_format:
SQL> select a from datetest;
A
---------
19-FEB-13
SQL> alter session set nls_date_format='YYMMDD HH24:MI:SS';
Session altered.
SQL> select a from datetest;
A
---------------
130219 07:59:38
but again, this is only for display.
Oracle's Date type fields contain date/time values, therefore converting it to Datetime does not make any sense (it's already datetime)
Read more about oracle date types here
Yeah the Date datatype will meet your needs but you will have to jump through some hoops every time to get the exact time out of it. Definitely use the Timestamp datatype.