Oracle — separate time and date - sql

I have a question with Oracle (I've installed Oracle 11g Express Edition).
I want to insert values for 'date' and 'time', but I cannot separate them.
create table Match
(
numMatch number(2) constraint PKMatch primary key,
dateM date,
heureM date,
numE_Eq number(2),
numE_Eq2 number(2),
nomTerrain varchar2(30)
);
--"tools"=>"preferences"=>"format de date:DD/MM/YYYY HH24:MI:SS"
insert into Match values (1,to_date
('10/12/2010','DD/MM/YYYY'),to_date('15:00:00','HH24:MI:SS'),1,3,'Stade Argentina'
);
result:
dateM: 10/12/2010 00:00:00
heureM: 01/11/2012 15:00:00
PS: I've tried to_char instead of to_date, but it didn't work at all.
Yes, I'm aware of that 'DATE datatype contains both date and time', but it's the prof who insists showing date and time separately in the table,
and I've seen your solutions before, but for me, it's a query, not to 'insert values' in the table.
So I'd like to know how I can have a table directly presenting date and time.

Oracle doesn't have a TIME datatype. You can store a DATE with a time component, and just query based on time, and display based on time.
select to_char(my_date_field, 'HH24:MI:SS')
from my_table
where to_date(my_date_field, 'HH24:MI') = '18:51';
Alternatively, you can store seconds from midnight as an integer, and calculate the time of day from that. It will also make querying for range times easier I think.
Also, within a session, execute the following to have all dates formatted the way you wish:
alter session set nls_date_format = 'YYYY-MM-DD HH24:MI:SS'

Another way to represent a TIME equivalent type in Oracle is with the INTERVAL type, such as:
SQL> CREATE TABLE foo (
bar INTERVAL DAY(0) TO SECOND(3)
);
This would allow the storage of a time period with 0 precision of the DAY component, and 3 decimal points for the SECOND component. An INSERT example is:
SQL> INSERT INTO foo VALUES ('0 01:01:01.333');
What's great about this approach is that it automatically presents the results of a SELECT in an intuitive format without the need for conversion:
SQL> SELECT * FROM foo;
BAR
---------------------------------------------------------------------------
+0 01:01:01.333

but it's the prof who insists showing date and time separately in the table
While this sounds like a pretty stupid requirement, one thing you could do is to create two computed columns that show the date and time as varchar columns:
create table match
(
nummatch number(2) constraint pkmatch primary key,
the_date date,
datem generated always as to_char(the_date, 'yyyy-mm-dd'),
heurem generated always as to_char(the_date, 'hh24:mi')
nume_eq number(2),
nume_eq2 number(2),
nomterrain varchar2(30)
);
insert into Match (nummatch, the_date, nume_eq, nume_eq2, nomterrain)
values
(1,to_date('10/12/2010 15:00:00','DD/MM/YYYY hh24:mi:ss'),1,3,'Stade Argentina');
Then a
select *
from match;
will return:
NUMMATCH | THE_DATE | DATEM | HEUREM | NUME_EQ | NUME_EQ2 | NOMTERRAIN
---------+---------------------+------------+--------+---------+----------+----------------
1 | 2010-12-10 15:00:00 | 2010-12-10 | 15:00 | 1 | 3 | Stade Argentina
Alternatively you could just create a view on the table that separates the date and time using to_char()

Oracle DATE type includes both DATE and TIME information (because it pre-dates the SQL-92 standard when the standard DATE, TIME and TIMESTAMP types were added). So, you can't separate them in the table; there's no reason to do so, either. You can, if you so desire, create a view which presents the DATE field as separate date-only and time-only display fields.

Related

Adding time to a table in SQLplus without date

I am trying to create a table regarding telecommunication and I want to add time for 2 rows call_start_time and call_end_time and with that, I want to calculate the call_duration.
This is what I used to enter the value
to_date('2021/05/31:20:20:20','yyyy/mm/dd hh24:mi:ss')
If I use this format while displaying the data only the date is displayed not the time.
Can someone help me create a table where I just have to input the time alone not the date and calculate the call_duration using call_start_time and call_end_time?
Heres the table I created:
SQL> create table MOBILE_TRANSACTION (
mob_no number(10),
call_type varchar2(25),
call_category varchar2(25),
call_start_time date,
call_end_time date,
call_duration number,
call_charges_rs number );
I hope my question is clear.
[TL;DR] You don't need to create a time column as the DATE column already has a time but SQL/Plus it not showing it; chage the settings on SQL/Plus and use what you already have.
Your table has a time component; the user interface (SQL/Plus) is chosing not to display it.
If you want to change the default display format then use:
ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS';
Then:
SELECT *
FROM MOBILE_TRANSACTION;
If you want to explicitly convert the date to have a format (since it is stored as a binary value and has no format in the database and it is only when it reaches the user interface you are using that that user interface converts the binary to something human readable) then you can use TO_CHAR:
SELECT mob_no,
call_type,
call_category,
TO_CHAR(call_start_time, 'YYYY-MM-DD HH24:MI:SS') AS call_start_time,
TO_CHAR(call_end_time, 'YYYY-MM-DD HH24:MI:SS') AS call_end_time,
call_duration,
call_charges_rs
FROM MOBILE_TRANSACTION
If you want to calculate the duration then you can use a virtual column:
create table MOBILE_TRANSACTION (
mob_no number(10),
call_type varchar2(25),
call_category varchar2(25),
call_start_time date,
call_end_time date,
call_duration INTERVAL DAY TO SECOND
GENERATED ALWAYS AS (
(call_end_time - call_start_time) DAY TO SECOND
),
call_charges_rs number
);
db<>fiddle here
or
create table MOBILE_TRANSACTION (
mob_no number(10),
call_type varchar2(25),
call_category varchar2(25),
call_start_time date,
call_end_time date,
call_duration number
GENERATED ALWAYS AS ((call_end_time - call_start_time) * 24 * 60 * 60),
call_charges_rs number
);
db<>fiddle here

How to split a datetime column in to two columns of Date and time separately in Oracle SQL?

I have a datetime column.
I want two columns: a date and a time column.
How can I split my column into two?
Use:
a DATE data-type with the time component set to midnight for the date (you can enforce this with a check constraint); and
an INTERVAL DAY(0) TO SECOND data-type for the time component.
CREATE TABLE table_name(
datetime_column DATE,
date_column DATE,
time_column INTERVAL DAY(0) TO SECOND,
CONSTRAINT table_name__date_column__chk CHECK (date_column = TRUNC(date_column))
)
If you want to get the combined date-time then you can easily add the two to get back to a date-time value.
How can I split my column into two?
Assuming you have the columns you can use:
UPDATE table_name
SET date_column = TRUNC(datetime_column),
time_column = (datetime_column - TRUNC(datetime_column)) DAY TO SECOND;
db<>fiddle here
As Gordon commented, there's no time datatype in Oracle.
Though, literally answering what you asked, you can separate date and time and store each of them into their own columns - it's just that these will be VARCHAR2 columns and you can only look at how pretty they are. You can't, for example, do any date arithmetic on them; first you'd have to convert them back to date datatype, so question is what you really want to do with what you get.
Anyway, here you are:
SQL> create table test
2 (datum date,
3 date_only varchar2(10),
4 time_only varchar2(8)
5 );
Table created.
Sample value:
SQL> insert into test (datum) values (sysdate);
1 row created.
Split date to two parts:
SQL> update test set
2 date_only = to_char(datum, 'dd.mm.yyyy'),
3 time_only = to_char(datum, 'hh24:mi:ss');
1 row updated.
What's in there?
SQL> alter session set nls_date_format = 'dd.mm.yyyy hh24:mi:ss';
Session altered.
SQL> select * from test;
DATUM DATE_ONLY TIME_ONL
------------------- ---------- --------
05.08.2021 21:05:06 05.08.2021 21:05:06
SQL>
Since there is no specific datatype for time, here my suggestion would be to keep the datetime in main column and add two VIRTUAL COLUMN for date value and time value respectively.
Oracle 11g has introduced a new feature that allows you to create a VIRTUAL COLUMN, an empty column that contains a function upon other table columns (the function itself is stored in the data dictionary).
However, it all depends on what you are going to do with it.
Please elaborate your requirement so that you will get a more specific answer.

Oracle 12c - how to set 'date' column with year quarter?

I have a need to create a column in Oracle 12c that will be date column with values:
20163
20164
20171
20172
20173
20174
...
How to specify that for a column in a create table statement?
thanks.
You can model the column as containing dates, constrained to fall only on the first moment of each quarter.
CREATE TABLE TEMP
( QUARTER DATE
CONSTRAINT IS_QUARTER CHECK ( (QUARTER = TRUNC(QUARTER, 'Q') ) )
)
To put values into the table, you need to set the date to the start of the quarter:
INSERT INTO temp VALUES ( TO_DATE('2017-04', 'yyyy-mm') );
To read values from the table, you can format as you like:
SELECT TO_CHAR( quarter, 'YYYYQ') FROM temp;
Because the underlying column is a date, you can do things like compare it with other dates, etc.
SELECT TO_CHAR( ADD_MONTHS( quarter, 3 ), 'YYYYQ') FROM temp;
Joe!
Such fields as you described are frequently using for monthly periods.
Typicaly they are encoded in integer datatypes.
If you were not on Oracle, Int32 would be perfect.
In Oracle the decision is not so clear.
I would prefer NUMBER(6,0) and simple constraint that field most be less than any possible date in future.
CHAR(6) - is fine too but constraints will be more complex.

Oracle 10 SQL - How to use a "00:00" time format in a constraint

Small entry level question with Oracle 10 SQL. I'm creating a table with a column with a "date" type which is supposed to hold values looking like this : "00:00". I have a constraint with checks the time to be between 00:00 and 23:00.
Now, what I can't quite grasp is how to approach the problem. I do feel like I'm missing something quite basic but I can't quite figure out what...
Do I :
1) Extract and check the date inside my constraint? If so, is there a way to do that? Can I insert data looking like this : TO_DATE('13-AUG-66 12:56','DD-MON-YY HH:MI'), and use some kind of "Extract" function inside my constraint?
2) The exercise in question does mention the date type for that particular column. By default, I assume that it doesn't hold hours and needs to be modified using alter_session?
A constraint only enforces a restriction. It cannot modify data. A BEFORE INSERT trigger can modify data but is generally less efficient than a constraint.
If you want to create a constraint that ensures that the time component is always midnight
CREATE TABLE table_name (
col DATE CHECK( col1 = TRUNC( col ))
);
If you want to create a trigger that modifies the data
CREATE OR REPLACE TRIGGER trg_trunc_dt
BEFORE INSERT ON table_name
FOR EACH ROW
BEGIN
:new.date_column := TRUNC( :new.date_column );
END;
A DATE always contains a day and a time component. Your client may or may not display either component. Many clients will use implicit data type conversion in which case the session's NLS_DATE_FORMAT controls how a DATE is converted to a VARCHAR2 and what elements are incorporated into the string.
A date type always has a date part and a time part. It is just a value and has thus no formatting. If you display a time as 22:50 or 10:50pm for example is up to you. You either rely on your settings with to_char(mydate) or specify a format to_char(mydate,'hh24:mi').
This said, you can simply use the time part of your column and ignore the date part. If you want to avoid confusion about different dates being stored, you can use a trigger setting the date part to 01.01.0001 for instance:
create or replace Trigger trg_datetable_datepart
before insert or update of mydate on datetable
for each row
begin
:new.mydate := to_date( '01.01.0001 ' || to_char(:new.mydate, 'hh24:mi') , 'dd.mm.yyyy hh24:mi' );
end;
To avoid inserts of times after 23h you would write a check constraint:
alter table datetable add constraint check_datetable_timepart check ( to_char(mydate, 'hh24:mi') <= '23:00' );

Update Oracle table records timezone values

I have a table with an Oracle column of TIMESTAMP (6) WITH TIME ZONE. The table contains records of varying timezones. I'd like to update all of the records of the table to be UTC. Is there a recommended way of doing this in an UPDATE query? I've looked at the Oracle methods to_date(), which is for converting a string to a date, and from_tz() which converts a time to a time with timezone.
It seems like I'd need a way to run a query and pull the timezone from the field, and then somehow update the field to put it in UTC. I don't want to simply change the timezone designation, I want to offset the time of day so
21-JAN-10 03.28.38.713000000 PM -05:00
would become
21-JAN-10 08.28.38.713000000 PM UTC
.
CREATE TABLE "MyDb"."Books"
(
"GUID" RAW(32) DEFAULT SYS_GUID(),
"DATE_CREATED" TIMESTAMP (6) WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
);
You should be able to do something like
UPDATE "Books"
SET date_created = date_created at time zone 'UTC'
which will do something like this
SQL> create table foo( col1 timestamp with time zone );
Table created.
SQL> insert into foo values( current_timestamp );
1 row created.
SQL> select * from foo;
COL1
---------------------------------------------------------------------------
13-FEB-12 01.38.42.372000 PM -05:00
SQL> update foo
2 set col1 = col1 at time zone 'UTC';
1 row updated.
SQL> select * from foo;
COL1
---------------------------------------------------------------------------
13-FEB-12 06.38.42.372000 PM UTC
Now, as a style matter, creating case-sensitive table names and column names is highly discouraged as it will greatly annoy the developers that have to maintain the code.