Insert data convert to date from an existing table - oracle

I have a table that contains a time stamp number TEST1 (TIMESTAMP) and I want to create another table TEST2 that displays (TIMESTAMP, TIME) from the first table (the TIME field displays the timstamp converted to date). I tried this
insert into TEST2
values (TEST1.TIMESTAMP,to_date('1970-01-01 ','yyyy-mm-dd ') +
(TEST1.TIMESTAMP)/60/60/24 ,'YYYY-MM-DD');
can have help !

Assuming the TIMESTAMP column is really in seconds, your code is almost right. However: to_date('1970-01-01', 'yyyy-mm-dd') is correct, but to it you must add a number - plain and simple. That is: + TIMESTAMP/60/60/24. Just like that!
Or, to avoid rounding errors, you could do something like
to_date('1970-01-01', 'yyyy-mm-dd') + interval '1' second * test1.timestamp
Note that the fixed date can also be written simply as
date '1970-01-01'
Finally: If you want to store the date portion, wrap the result of that addition within TRUNC(...) - which truncates to the beginning of the day. Or, you can use the arithmetic expression, without INTERVAL and without TRUNC, but instead add TRUNC(TEST1.TIMESTAMP)/60/60/24 - that will truncate the seconds to a whole number of days.
Note that dates in Oracle do not have a "format" (format only applies to text representations of dates, not to dates themselves).
EDIT: It seems you also need help with the INSERT statement. When you insert into a table using data from another table, you don't INSERT ... VALUES, you INSERT ... SELECT. Something like (using your poorly chosen column names - poorly chosen because they are Oracle keywords):
insert into test2 (timestamp, time)
select timestamp, date '1970-01-01' + trunc(timestamp/60/60/24)
from test1
;
Notice that there are no calls whatsoever to either TO_CHAR or TO_DATE; and there is no format model like 'yyyy-mm-dd'. One of the good things about the SQL Standard date literal, date '1970-01-01', is that it accepts only one format, 'yyyy-mm-dd' (even the dashes are mandatory; / would be rejected).
If you want to see what is now in table TEST2:
select timestamp, time from test2;
And if you don't like how the date is displayed, you can control that:
select timestamp, to_char(time, 'yyyy-mm-dd') as time from test2;

Related

changing Date format in query

in some part of my program , I want to run a sql query and have the result which is a date like : %Y/%m/%d %H:%M:%S
SELECT MAX(created_at)
FROM HOT_FILES_LOGS
WHERE FILE_NAME = 'test'
date in created_at column is stored like 04/03/2021 15:45:30 ( it is fulled with SYSDATE)
but when I run this query, I get just 04.03.21
what should I do to fix it?
Apply TO_CHAR with appropriate format mask:
select to_char(max(created_at), 'yyyy.mm.dd hh24:mi:ss') as created_at
from hot_files_logs
where file_name = 'test'
Oracle does not store dates or timestamps in any display format, they are stored in an internal structure, every date in every Oracle database since at least 8i and probably earlier. This structure consists of 7 1-byte integers (timestamps in a similar but larger structure). How the date is displayed or a string converted to a date is controlled the specified date format string in the to_char or to_date function or if no format string given by the NLS_DISPLAY_FORMAT setting. To get a gimps at the internal settings run the following:
create table td( d date);
insert into td(d) values(sysdate);
select d "The Date" , dump(d) "Stored As" from td;
See example. The last used format is not practical but strictly demonstrable. Well I guess you could use it to seed a repeatable random sequence.

Split Date from Oracle Form to DB

I have a table with columns(year,day-month) -date type- in my database.
and a form with a text field for the user to enter a date.
how can I split the entered date to save it on db as following
year day_month
---- ---------
2018 03-04
I tried SUBSTR(TO_CHAR(TO_DATE(block.field)) in a trigger ,
but it didn't work bcz the column type is date, and I tried to add TO_DATE() as outer but the result was
year day_month
---------- ----------
03-04-2018 03-04-2018
How can I do it without changing my columns type?
I'd suggest you NOT to do that. Always store DATE values into DATE datatype columns. ALWAYS.
Later, if you want to present them differently, apply appropriate functions (such as TO_CHAR) to those values and display them any way you want.
In your example, that would be
TO_CHAR(date_column, 'yyyy') year
or
EXTRACT (year from date_column) year
and
TO_CHAR(date_column, 'dd-mm') day_month
[EDIT]
Once again (to repeat what I've said in a comment): the fact that you named columns in the database "year" (whose datatype is DATE) and "day_month" (whose datatype is also DATE) is completely useless.
Right now is (dd.mm.yyyy hh24:mi) 03.04.2018 10:32.
DATE datatype contains both date and time, so - how do you plan to put "2018" into the "year" column? What will you do with its month/day/hour/minutes/seconds component? It can't just "vanish", has to have some value. Is it the first of January at 00:00:00? Or what?
The same goes to your "day_month" column - it'll contain year, as well as hours/minutes/seconds, whether you want it or not.
Let's start with the "year": if you want to extract it from the Form item, that would be TO_CHAR, such as
to_char(:block.some_item, 'yyyy')
which results in a string, '2018'. You can't store it into a DATE datatype column, so you have to apply TO_DATE to it:
to_date(to_char(:block.some_item, 'yyyy'), 'yyyy')
and it will result in 01.04.2018 00:00:00 >>> see? Day, month, hours ... everything is here.
The alternative is to create those columns as VARCHAR2, but that's even worse.
Seriously, don't do that.
Try the following and make the necessary changes in Oracle Forms, substitute block and columns names instead of variables.
DECLARE
p_year VARCHAR2 (8);
p_date VARCHAR2 (8);
BEGIN
SELECT TO_CHAR (SYSDATE, 'YYYY') INTO p_year FROM DUAL;
SELECT TO_CHAR (SYSDATE, 'DD-MM') INTO p_date FROM DUAL;
DBMS_OUTPUT.put_line ('p_year --> ' || p_year || ' p_date --> ' || p_date);
END;
If your column is a DATE type, expect that it will require you to input a date data also.
In your case, you don't need to split a date. For the YEAR column, if the year value only matters to you, then you can use the TRUNC function
:BLK.YEAR_DATE_FIELD := TRUNC(:BLK.DATE_VALUE, 'YYYY');
and for the MONTH column, just save the date value there.
:BLK.MONTH_DATE_FIELD := :BLK.DATE_VALUE;
Also, maybe you just need to set the format mask of those two fields in Oracle forms. You can set the Format Mask of YEAR field to YYYY and MM-DD to the MONTH field.
The DATE data type is stored dates in tables as 7-bytes
byte 1 - century + 100
byte 2 - (year MOD 100 ) + 100
byte 3 - month
byte 4 - day
byte 5 - hour + 1
byte 6 - minute + 1
byte 7 - seconds+ 1
You CANNOT have a DATE data type that just stores year or month + day; it will always store all the components of the date/time.
So you either store the correct values in each column or you will have to make up values for the components you are not storing and will need to make sure that all the made up values are appropriate for the real values. It is just easier to use the real values in both columns.
So just do:
INSERT INTO your_table(
year,
day_month
) VALUES (
:BLK1.T_DATE,
:BLK1.T_DATE
);
Without splitting the date because a day_month without a year does not make sense (is 29th February a valid date? For the majority of years, no it isn't).
When you want to output it with a format then just format it as a string on output:
SELECT TO_CHAR( year, 'yyyy' ) AS year,
TO_CHAR( day_month, 'dd-mm' ) AS day_month
FROM your_table;

How to write date condition on where clause in oracle

I have data in the date column as below.
reportDate
21-Jan-17
02-FEB-17
I want to write a query to fetch data for 01/21/2017?
Below query not working in Oracle.
SELECT * FROM tablename where reportDate=to_date('01/21/2017','mm/dd/yyyy')
What is the data type of reportDate? It may be DATE or VARCHAR2 and there is no way to know by just looking at it.
Run describe table_name (where table_name is the name of the table that contains this column) and see what it says.
If it's a VARCHAR2 then you need to convert it to a date as well. Use the proper format model: 'dd-Mon-rr'.
If it's DATE, it is possible it has time-of-day component; you could apply trunc() to it, but it is better to avoid calling functions on your columns if you can avoid it, for speed. In this case (if it's really DATE data type) the where condition should be
where report_date >= to_date('01/21/2017','mm/dd/yyyy')
and report_date < to_date('01/21/2017','mm/dd/yyyy') + 1
Note that the date on the right-hand side can also be written, better, as
date '2017-01-21'
(this is the ANSI standard date literal, which requires the key word date and exactly the format shown, since it doesn't use a format model; use - as separator and the format yyyy-mm-dd.)
The query should be something like this
SELECT *
FROM table_name
WHERE TRUNC(column_name) = TO_DATE('21-JAN-17', 'DD-MON-RR');
The TRUNC function returns a date value specific to that column.
The o/p which I got when I executed in sqldeveloper
https://i.stack.imgur.com/blDCw.png

Which Data types are correct for storing numeric year input and numeric month in Oracle?

I am learning oracle 11g. I need to create columns to store Year and Month in the following sample format:
Year: 2015
Month: 6
I saw Date Time data type which takes whole date only .Also Number type may allow invalid year and month. But I want them in the given form while avoiding invalid month and year. Please tell me how to fix it.thanks
Updates: is this okay for such inputs?
CREATE TABLE FOOBAR (YYYY DATE, MM DATE);
The best solution is to store dates in DATE columns. Oracle has some pretty neat date functions, and you'll find it easy to work with storing the first of the month in a single DATE column. Otherwise you'll find yourself constantly extracting elements from other dates or cluttering your code with TO_CHAR() and TO_DATE() calls. Find out more.
However, if you have a rigid requirement, you can use strong typing and check constraints to avoid invalid months:
CREATE TABLE FOOBAR (
YYYY number(4,0) not null
, MM number(2,0) not null
, constraint foobar_yyyy_ck check (yyyy != 0)
, constraint foobar_mm_ck check (mm between 1 and 12)
);
This won't do what you want because it will default the missing elements:
CREATE TABLE FOOBAR (YYYY DATE, MM DATE);
We can't store just a year or just a month in DATE columns.
Use the DATE data type..
and when perform insert operation onto your db.. use
TO_DATE ('November 13, 1992', 'MONTH DD, YYYY')
For input and output of dates, the standard Oracle date format is DD-MON-YY, as follows:
'13-NOV-92'
perform insert operation/query like this:
INSERT INTO table_name (name, created_at) VALUES
('ANDY', TO_DATE ('November 13, 1992', 'MONTH DD, YYYY'));
Here is link to the guide as well:
https://docs.oracle.com/cd/B28359_01/server.111/b28318/datatype.htm#i1847
If you want to store month and year separately in the db you may use NUMBER & NUMBER(n)
https://docs.oracle.com/cd/B28359_01/server.111/b28318/datatype.htm#i22289
Hope this helps..

oracle sql break out records

I have a table that has a StartDate and EndDate field, and also a ton of other fields. I need to break out each record by all the days between and including StartDate & EndDate into another table that looks exactly like the original except it has a CurrentDate field and 2 calculated fields. The CurrentDate field is the current date between StartDate and EndDate that I'm interating on.
My question is, since there are a ton of fields in this, is there any easy way from within my stored proc, to insert the entire row the cursor is currently on AND this 1 new column, without having to list out every single row in the insert statement? It's so tedious.
If your source and destination tables fit this profile:
Destination table columns are the same as your source table's columns, and
The new destination column is at the end
... then you could do something like this:
INSERT INTO dest_table
SELECT Source_Table.*, new_value
FROM Source_Table
WHERE Source_Table.PKValue = cursor.PKValue
If it's a case of your cursor resembling the destination table, something like this may work but note I haven't tested it:
CREATE PROCEDURE whatever IS
destRow dest_table%ROWTYPE;
CURSOR fromSourceTable IS
SELECT <your existing select list>, NULL AS new_value
FROM <the rest of your cursor query>;
BEGIN
FOR destRow IN fromSourceTable LOOP
destRow.new_value = <the split date>;
INSERT INTO dest_table VALUES destRow;
END LOOP;
END whatever;
I'm going out on a limb with the NULL AS new_value. If you have trouble try CAST(NULL AS DATE) AS new_value instead, and if you still have trouble try something like SYSDATE AS new_value. Again, this isn't tested but if you think it's promising and have trouble implementing I'd be happy to test it.
It's easy enough to densify the data in a single SQL statement. Assuming that you know a reasonable minimum and maximum range for your begin_date and end_date (I'll assume Jan 1, 2000 - Dec 31, 2020 for the moment but you can obviously adjust that)
WITH all_days AS (
SELECT date '2000-01-01' + level dt
FROM dual
CONNECT BY level <= date '2020-12-31' - date '2000-01-01'
)
SELECT <<list of colums from your table>>,
all_days.dt current_date
FROM your_table actual
JOIN all_days ON (actual.begin_date <= all_days.dt AND
actual.end_date >= all_days.dt)
If you don't want to hard-code the starting and ending dates, you can fetch them from your table as well. That just requires that you hit the table a second time which will generally be less efficient.

Resources