How to create a year column in monetdb to automatically be set with the current time - monetdb

I want to create a table with default value set to the current year
CREATE TABLE Date
(
"year" smallint NOT NULL DEFAULT extract(year from current_time)
);
It throws an error:
!42000!syntax error, unexpected YEAR in: "select year"
The same command if I run using mclient it works fine.
sql>select extract(year from current_date);
+---------------------+
| second_current_date |
+=====================+
| 2015 |
+---------------------+
1 tuple (0.130ms)
sql>
sql>select "year"(NOW());
+-------------------+
| current_timestamp |
+===================+
| 2015 |
+-------------------+
1 tuple (0.380ms)
I only want the year. Is there any way to do it?

It looks like you are attempting to extract 'year' from CURRENT_TIME when you should be attempting to get it from CURRENT_DATE
Try:
CREATE TABLE Date
(
"year" smallint NOT NULL DEFAULT extract(year from current_date)
);

Related

Oracle: Difference between DATE and TIMESTAMP(0)

What is the difference, if any, between DATE and TIMESTAMP(0) in Oracle? Both data types occupy 6 bytes, and contain date with time, but without fractional seconds and a timezone.
The TIMESTAMP was added to Oracle about 20 years after DATE to comply with ANSI standard. TIMESTAMP or TIMESTAMP(6) can hold fractions of seconds, so it is different from DATE, but is there any difference between TIMESTAMP(0) and DATE?
One is a DATE data type and one is a TIMESTAMP data type.
They both take up 7 bytes (century, year-of-century, month, day, hour, minute and second).
The DATE will be implicitly formatted by the NLS_DATE_FORMAT session parameter when it is displayed.
The TIMESTAMP will be implicitly formatted by the NLS_TIMESTAMP_FORMAT session parameter when it is displayed.
For example:
CREATE TABLE table_name (
dt DATE,
ts TIMESTAMP(0)
);
INSERT INTO table_name ( dt, ts ) VALUES ( SYSDATE, SYSTIMESTAMP );
ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD"T"HH24:MI:SS';
ALTER SESSION SET NLS_TIMESTAMP_FORMAT = 'YYYY-MM-DD"T"HH24:MI:SS.FF6';
Then:
SELECT dt,
DUMP( dt ),
ts,
DUMP( ts )
FROM table_name;
Outputs:
DT | DUMP(DT) | TS | DUMP(TS)
:------------------ | :---------------------------------- | :------------------------- | :-----------------------------------
2020-10-08T14:21:35 | Typ=12 Len=7: 120,120,10,8,15,22,36 | 2020-10-08T14:21:36.000000 | Typ=180 Len=7: 120,120,10,8,15,22,37
Functions that require a TIMESTAMP input won't perform an implicit CAST from a DATE to a TIMESTAMP.
So:
SELECT FROM_TZ( dt, 'UTC' ) FROM table_name;
SELECT FROM_TZ( CAST( dt AS TIMESTAMP(0) ), 'UTC' ) FROM table_name;
SELECT FROM_TZ( ts, 'UTC' ) FROM table_name;
The first statement raises an ORA-00932: inconsistent datatypes: expected TIMESTAMP got DATE exception but the second and third works.
As mentioned by #WernfriedDomscheit in comments, arithmetic is also different between DATE and TIMESTAMP data types. For example:
SELECT dt - dt,
( dt - dt ) DAY TO SECOND,
ts - ts
FROM table_name
Outputs:
DT-DT | (DT-DT)DAYTOSECOND | TS-TS
----: | :------------------ | :------------------
0 | +00 00:00:00.000000 | +000000000 00:00:00
The top expression is DATE - DATE and the result is the difference in days (expressed as a NUMBER data type). However, the bottom expression is TIMESTAMP - TIMESTAMP and the result is an INTERVAL DAY TO SECOND data type. It is possible to get DATE subtraction to output an INTERVAL DAY TO SECOND data type but, as shown in the middle example, you need to explicitly state that that is the output you require.
Addition to a DATE or TIMESTAMP also has differences. For example:
SELECT dt + 1,
dt + INTERVAL '1' DAY,
ts + 1,
ts + INTERVAL '1' DAY
FROM table_name
Outputs:
DT+1 | DT+INTERVAL'1'DAY | TS+1 | TS+INTERVAL'1'DAY
:------------------ | :------------------ | :------------------ | :-------------------------
2020-10-09T19:52:21 | 2020-10-09T19:52:21 | 2020-10-09T19:52:22 | 2020-10-09T19:52:22.000000
Adding a number or an INTERVAL to both a DATE and a TIMESTAMP is both syntactically correct (but may not be as expected). If you look you will see that the output for adding a number or an interval to a date gives the same output in both cases. However, there is a difference between the output when adding a number to a timestamp compared to adding an interval to a timestamp; this is because you can only add numbers to date values and by adding a number to a timestamp then Oracle has performed an implicit cast from timestamp down to a date so:
SELECT ts + 1 FROM table_name
is effectively performing:
SELECT CAST(ts AS DATE) + 1 FROM table_name
So, if you want to perform arithmetic with a TIMESTAMP data type then use INTERVAL data types rather than numbers.
db<>fiddle here

How to select records from Oracle Database where 2 dates are not in same month and year

How to select records from Oracle Database where 2 dates are not in same month and year.
Below table is example, here I want all records where created date and updated date are not in same month and year.
The value for both date field in millisecond (ex.1454738400000) and
Data type of both date field is NUMBER(32).
---------------------------------
id| Created Date | Updated Date |
---------------------------------
1 | 02/26/2018 | 02/26/2017 |
---------------------------------
2 | 03/28/2018 | 03/26/2018 |
---------------------------------
3 | 04/26/2018 | 04/28/2017 |
---------------------------------
4 | 02/26/2018 | 02/26/2016 |
---------------------------------
Have a look at these two options:
select record_id
from your_table
where to_char(created_date, 'mm.yyyy') <> to_char(updated_date, 'mm.yyyy');
select record_id
from your_table
where trunc(created_date, 'yyyy') <> trunc(updated_date, 'yyyy')
and trunc(created_date, 'mm') <> trunc(updated_date, 'mm');
If there's a lot of data involved, consider creating a function-based index(es) on DATE columns.
[EDIT]
If those values really are numbers, then you have to convert them to DATE datatype first, then apply TRUNC function. For example:
SQL> select trunc(to_date(20190226, 'yyyymmdd'), 'yyyy') result from dual;
RESULT
----------
01.01.2019
SQL>
Note that it'll fail if format is wrong, for example 20190231 (which is supposed to be 31st of February 2019) as there aren't 31 days in February.
If possible, change those columns' datatype to DATE.

From string in 24 hours to timestamp

I have a table with one column giving me dates in the form 24-JUL-17 and another column a string telling me the hour in the form hh:mm:ss.several_decimals but they are in 24 hours and not AM/PM, could someone point me on how I can add a column in oracle that combines them both into a timestamp?
CAST the date to a timestamp data type and use TO_DSINTERVAL to convert the time column to a DAY TO SECOND INTERVAL and then add one to the other:
SQL Fiddle
Oracle 11g R2 Schema Setup:
CREATE TABLE table_name (
date_column DATE,
time_column VARCHAR2(15)
);
INSERT INTO table_name ( date_column, time_column )
VALUES ( DATE '2017-06-24', '12:34:56.789012' );
Query 1:
SELECT CAST( date_column AS TIMESTAMP )
+ TO_DSINTERVAL( '+0 ' || time_column ) AS datetime
FROM table_name
Results:
| DATETIME |
|----------------------------|
| 2017-06-24 12:34:56.789012 |
Here is an example with a fabricated table.
WITH test_data AS (
SELECT
SYSDATE date_val,
'14:23:15.123' AS time_val
FROM
dual
) SELECT
to_timestamp(TO_CHAR(date_val,'MM/DD/YYYY')
|| ' '
|| time_val,'MM/DD/YYYY HH24:MI:SS.FF3')
FROM
test_data
Just concatenate both input strings with || and convert it with TO_TIMESTAMP. The format is a bit tricky, took me a while to get it right.
CREATE TABLE mytable (mydate VARCHAR2(9), mytime VARCHAR2(20), mytimestamp TIMESTAMP);
INSERT INTO mytable (mydate, mytime) VALUES ('24-JUL-17', '22:56:47.1915010');
Test it
SELECT TO_TIMESTAMP(mydate||mytime, 'DD-MON-YYHH24:MI:SS.FF9') FROM mytable;
2017-07-24 22:56:47,191501000
Or, in a table:
UPDATE mytable
SET mytimestamp = TO_TIMESTAMP(mydate||mytime, 'DD-MON-YYHH24:MI:SS.FF9');

Dates increment by row [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
I have one table (in Oracle database) in which Date column is empty (NULL). table has 100 rows. I want to fill (insert or update) date column starting from aug-15-2017 and increment date by one day in every next row.
I explain it - in first row date should be Aug-15-2017, in second row date should be Aug-16-2017, in third row date should be Aug-17-2017 and so on ...
Kindly help me on this.
Thanks.
UPDATE table
SET dt = TO_DATE('AUG-14-2017','MON-DD-YYY') + ROWNUM
WHERE dt is null
If you have another column (i.e. an id column) that you wish to ensure the order of the dates is based upon then you can use:
MERGE INTO table_name dst
USING (
SELECT ROWID rid,
ROW_NUMBER() OVER ( ORDER BY id ) AS rn
FROM table_name
) src
ON ( dst.ROWID = src.RID )
WHEN MATCHED THEN
UPDATE SET dt = DATE '2017-08-14' + rn;
Using ROWNUM without an ORDER BY clause is not guaranteed to generate rows in the order you wish. You can see the difference in the following example:
SQL Fiddle
Oracle 11g R2 Schema Setup:
CREATE TABLE table_name ( id, dt1, dt2 ) AS
SELECT LEVEL, CAST( NULL AS DATE ), CAST( NULL AS DATE )
FROM DUAL
CONNECT BY LEVEL <= 10
ORDER BY DBMS_RANDOM.VALUE;
UPDATE table_name
SET dt1 = DATE '2017-08-14' + ROWNUM
WHERE dt1 IS NULL;
MERGE INTO table_name dst
USING (
SELECT ROWID rid,
ROW_NUMBER() OVER ( ORDER BY id ) AS rn
FROM table_name
) src
ON ( dst.ROWID = src.RID )
WHEN MATCHED THEN
UPDATE SET dt2 = DATE '2017-08-14' + rn;
Query 1:
SELECT * FROM table_name ORDER BY id
Results:
| ID | DT1 | DT2 |
|----|----------------------|----------------------|
| 1 | 2017-08-18T00:00:00Z | 2017-08-15T00:00:00Z |
| 2 | 2017-08-22T00:00:00Z | 2017-08-16T00:00:00Z |
| 3 | 2017-08-23T00:00:00Z | 2017-08-17T00:00:00Z |
| 4 | 2017-08-15T00:00:00Z | 2017-08-18T00:00:00Z |
| 5 | 2017-08-20T00:00:00Z | 2017-08-19T00:00:00Z |
| 6 | 2017-08-17T00:00:00Z | 2017-08-20T00:00:00Z |
| 7 | 2017-08-19T00:00:00Z | 2017-08-21T00:00:00Z |
| 8 | 2017-08-21T00:00:00Z | 2017-08-22T00:00:00Z |
| 9 | 2017-08-16T00:00:00Z | 2017-08-23T00:00:00Z |
| 10 | 2017-08-24T00:00:00Z | 2017-08-24T00:00:00Z |

Creating fact table with year of 9999

I'm building a simple fact table in oracle based on a customer status where a customer has a status, 'Active' and 'Lost' and a date they started with that status and a date they ended.
A sample 3 rows would be;
CustID | status | date_start | date_end
---------------------------------------
1 | active | 1/1/13 | 1/12/14
1 | lost | 1/12/14 | 31/12/9999
2 |active | 1/12/14 | 31/12/9999
Here, cust 1 was active and then was lost. When a account status is current (as of today) the end date column is 31/12/9999. Cust 2 is active as of today
My question is, how can I bring this into a fact table?
CREATE TABLE temp AS
SELECT CS.contract_status_id , to_char(ASH.Contract_Status_Start, 'DD/MM/YYYY') AS cust_status_start_date, to_char(ASH.CONTRACT_STATUS_END, 'DD/MM/YYYY') As cust_status_end_date
FROM account_status_history ASH,
customer_status_dim CS
WHERE ASH.contract_status = CS.contract_status
Fact Table:
CREATE TABLE customer_status_fact AS
SELECT T.cust_status_start_date, T.cust_status_end_date, T.contract_status_id,
count(T.contract_status_id) AS TOTAL_ACCOUNTS
FROM temp T
GROUP BY T.cust_status_start_date, T.cust_status_end_date, T.contract_status_id
And testing it;
select sum(F.TOTAL_ACCOUNTS), CS.contract_status_txt
from customer_status_fact F, customer_status_dim CS
where F.contract_status_id = CS.contract_status_id
and F.cust_status_start_date <= sysdate
and F.cust_status_end_date = '31/12/9999'
group by CS.contract_status_txt
I can't seem to get oracle to recognise the year 9999 Any help is appreciated
and F.cust_status_end_date = '31/12/9999'
'31/12/9999' is NOT a DATE, it is a string enclosed within single-quotation marks. You must use TO_DATE to explicitly convert it into a DATE.
For example,
SQL> alter session set nls_date_format='DD/MM/YYYY HH24:MI:SS';
Session altered.
SQL> SELECT to_date('31/12/9999 23:59:59','DD/MM/YYYY HH24:MI:SS') FROM dual;
TO_DATE('31/12/9999
-------------------
31/12/9999 23:59:59
SQL>
OR,
SQL> SELECT to_date(5373484, 'J') + (1 - 1/24/60/60) FROM dual;
TO_DATE(5373484,'J'
-------------------
31/12/9999 23:59:59
SQL>
CREATE TABLE temp AS SELECT CS.contract_status_id ,
to_char(ASH.Contract_Status_Start, 'DD/MM/YYYY') AS
cust_status_start_date, to_char(ASH.CONTRACT_STATUS_END, 'DD/MM/YYYY')
As cust_status_end_date
Why would you create a table with DATEs converted to a STRING? You should let the dates as it is. You should use TO_CHAR only for display purpose. For any date calculations, let the date remain as a date.

Resources