Oracle date seems equals - oracle

there is a table INCASSO in my database:
CREATE TABLE "GEC_AP"."INCASSO"
("ID_INCASSO" VARCHAR2(50 BYTE) NOT NULL ENABLE,
"ID_FATTURA" VARCHAR2(50 BYTE) NOT NULL ENABLE,
"ID_PIANO_RATE" VARCHAR2(22 BYTE) DEFAULT -1 NOT NULL ENABLE,
"DATA_ESECUZIONE" DATE DEFAULT SYSDATE NOT NULL ENABLE,
...)
The primary key includes four fields:
CONSTRAINT "PK_INCASSO" PRIMARY KEY ("ID_INCASSO", "ID_FATTURA", "ID_PIANO_RATE", "DATA_ESECUZIONE")
It seems there is a duplicated record when I run the following query:
select id_incasso, id_fattura, id_piano_rate, data_esecuzione
from incasso
where id_incasso = 'TO_20110521258225'
But with another query, 0 records are extracted:
select id_incasso, id_fattura, id_piano_rate, data_esecuzione, count(*)
from incasso where id_incasso = 'TO_20110521258225'
group by id_incasso, id_fattura, id_piano_rate, data_esecuzione
having count(*) > 1
The database is on Oracle 11.2.0.1.0 and I'm using SQL Developer 4.1.1.19.
In SQL Developer, the date format is:
I would to know if the records are different or there is a format date problem in the editor. If the records are different based on the date, in which part of the date they are different? If it's a format date problem in the editor, how can I fix it?

Change the date format to DD-MON-YYYY HH24:MI:SS and you are likely to see the difference in that the dates have different centuries.
Using RR to format the year can hide that one date is 1911 and the other is 2011
Try:
SELECT TO_CHAR( DATE '2011-01-01', 'RR-MM-DD' ),
TO_CHAR( DATE '1911-01-01', 'RR-MM-DD' )
FROM DUAL
Both will output the same although they are different dates and will not be grouped together.
If the dates are still the same then look for additional spaces or other hidden characters in the strings; you can use LENGTH() to check the size of the strings or DUMP() to get the byte values of the contents:
select id_incasso,
id_fattura,
LENGTH( id_fattura ) AS f_length,
id_piano_rate,
LENGTH( id_piano_rate ) AS pr_length,
TO_CHAR( data_esecuzione, 'YYYY-MM-DD HH24:MI:SS' ) AS data_esecuzione
from incasso
where id_incasso = 'TO_20110521258225'

I've changed the date format used in SQL Developer to DD-MON-YYYY HH24:MI:SS
and the following query:
select id_incasso, id_fattura, id_piano_rate, data_esecuzione from incasso where id_incasso = 'TO_20110521258225'
show that the difference is in the year:
Thanks everyone.

Related

Create ExpiryDate during table definition in Oracle

I'm trying to create a table named MEMBER. The datatype for REGISTERDATE is DATE and the default value is SYSDATE. There is another column named EXPIRYDATE, datatype is DATE and the default value is 1 year after SYSDATE. So how am I going to create for the column of EXPIRYDATE when creating the table definition?
I tried REGISTERDATE DATE DEFAULT SYSDATE,
EXPIRYDATE DATE + 365,
It showed error..
You're so close, you're just missing the default keyword and sysdate after expirydate date
-
create table MEMBER (
REGISTERDATE date default sysdate,
expirydate date default sysdate+365
)
test:
insert into MEMBER(REGISTERDATE) values (sysdate)
output:
Not all years have 365 days; on average, only 3 out of 4. But you can literally define an expression that expresses "1 year after":
create table member (
id number(*,0) not null primary key,
registerdate date default sysdate,
expirydate date default sysdate + interval '1' year
);
Remember that Oracle won't use the default value if you provide your own, even if it's null. You need to complete omit the field from the INSERT INTO statement.
Demo

Compare Integer and varchar

I have a simple yet frustrating problem in hive.
I want to basically say , only show me the orders_date older than today -30.My order dates are VARCHAR and the compared to date is integer.
select *
from my_table
where Order_Date > cast(date_format(current_date - interval '30' day,'%Y%m%d') as int);
ERROR: line 3:16: '>' cannot be applied to varchar, integer

Update trigger column based on date in ddmmyyy format in Oracle

I have created a trigger based on which I want to assign column with some value.
For example: I have a column name BILL_CALCULATED_DATE with value 19-10-21 which is in dd-mm-yy format. I want to extract mm and if it is 10 then I want to assign it as October
Below is my trigger
CREATE OR REPLACE TRIGGER TRG_UPD_GTL_BILL
BEFORE INSERT OR UPDATE ON IPFEE_MST_INSRT_GTL
FOR EACH ROW
BEGIN
:new.BILL_CALCULATED_DATE := case :NEW.UPLOADED_MONTH
when '01' then 'January'
when '02' then 'February'
when '03' then 'March'
when '04' then 'April'
when '05' then 'May'
when '06' then 'June'
when '07' then 'July'
when '08' then 'August'
when '09' then 'September'
when '10' then 'October'
when '11' then 'November'
when '12' then 'December'
end;
end;
But the problem is, before assigning month in the trigger I want to extract the month. How should I achieve it ?
Assuming that your BILL_CALCULATED_DATE column is of the DATE data type and you want the UPLOADED_MONTH column to be the name of the month corresponding to BILL_CALCULATED_DATE's month then:
Do not use a trigger; use a virtual column then the column values will always be synchronised.
Either create the table using:
CREATE TABLE IPFEE_MST_INSRT_GTL(
BILL_CALCULATED_DATE DATE,
UPLOADED_MONTH VARCHAR2(9)
GENERATED ALWAYS AS (
CAST(
TO_CHAR(BILL_CALCULATED_DATE, 'fmMonth', 'NLS_DATE_LANGUAGE=English')
AS VARCHAR2(9)
)
)
);
Or modify the existing table to drop the non-virtual column and add a virtual column:
ALTER TABLE IPFEE_MST_INSRT_GTL DROP COLUMN UPLOADED_MONTH;
ALTER TABLE IPFEE_MST_INSRT_GTL
ADD UPLOADED_MONTH VARCHAR2(9)
GENERATED ALWAYS AS (
CAST(
TO_CHAR(BILL_CALCULATED_DATE, 'fmMonth', 'NLS_DATE_LANGUAGE=English')
AS VARCHAR2(9)
)
);
If you must use a trigger and a real column then:
CREATE OR REPLACE TRIGGER TRG_UPD_GTL_BILL
BEFORE INSERT OR UPDATE ON IPFEE_MST_INSRT_GTL
FOR EACH ROW
BEGIN
:NEW.UPLOADED_MONTH := TO_CHAR(
:new.BILL_CALCULATED_DATE,
'fmMonth',
'NLS_DATE_LANGUAGE=English'
);
END;
/
If your BILL_CALCULATED_DATE column is a CHAR or VARCHAR2 data type then:
Change that column to a DATE.
If you cannot change it to a DATE then go and talk to someone who can change it to a DATE.
If you really, really cannot change it to a DATE then spend time despairing about the inability to follow best practice, try to convince people who may have the ability to do something about it that you should change things and then replace BILL_CALCULATED_DATE with TO_DATE(BILL_CALCULATED_DATE, 'DD-MM-YY') or :new.BILL_CALCULATED_DATE with TO_DATE(:new.BILL_CALCULATED_DATE, 'DD-MM-YY') in the snippets above.
db<>fiddle here
As per my understanding your column is not in date format. First convert this into date and then use EXTRACT function -
SELECT EXTRACT(month FROM TO_DATE(BILL_CALCULATED_DATE, 'dd-mm-yy'))
FROM IPFEE_MST_INSRT_GTL;
Something like this?
SELECT EXTRACT(month FROM SYSDATE) from dual

year value in table in oracle

I have this query in oracle:
DELETE FROM my_table
WHERE to_date(last_update, 'DD/MM/YYYY') < to_date('01/01/2000', 'DD/MM/YYYY');
when I run this, I get this error:
ORA-01841: (full) year must be between -4713 and +9999 and must not be 0
there is not any 0 value in the table.
any one knows what is the problem?
I am assuming that you have stored your dates as a string with the DD/MM/YYYY format; it would be better if you stored them all as a DATE data type and then you would not have to do this conversion (and you would be using the most appropriate data type for the data).
From Oracle 12, you can use:
SELECT *
FROM my_table
WHERE TO_DATE( last_update, 'DD/MM/YYYY' DEFAULT NULL ON CONVERSION ERROR ) IS NULL;
To identify the rows that are raising that exception.
If you are already storing them as a DATE data type then don't use TO_DATE on a value that is already a DATE as TO_DATE expects a string so Oracle will implicitly cast your DATE to a string and then try to convert it back and your query is effectively:
DELETE FROM my_table
WHERE TO_DATE(
TO_CHAR(
last_update,
( SELECT value FROM NLS_SESSION_SETTINGS WHERE PARAMETER = 'NLS_DATE_FORMAT' )
),
'DD/MM/YYYY'
) < to_date('01/01/2000', 'DD/MM/YYYY');
And if the NLS_DATE_FORMAT and your format model do not match then you will get errors (or, worse, the query will succeed and your data will be inconsistent as it may have swapped days and months or months and years).
Instead, just use:
DELETE FROM my_table
WHERE last_update < DATE '2000-01-01';
If the datatype of last_update is date, don't use the to_date function:
DELETE FROM my_table
WHERE last_update < to_date('01/01/2000', 'DD/MM/YYYY');

Sysdate+days as default value in table column - Oracle

I'm working on my table which is supposed to store data about rented cars.
And there are 3 important columns:
RENT_DATE DATE DEFAULT TO_DATE (SYSDATE, 'DD-MM-YYYY'),
DAYS NUMBER NOT NULL,
RETURN_DATE DATE DEFAULT TO_DATE(SYSDATE+DAYS, 'DD-MM-YYYY')
My problem is that RETURN_DATE column is giving me error:
00984. 00000 - "column not allowed here"
What i want is that RENT_DATE set automatically date when record is added.
DAYS column is to store for how much days someone is renting car.
And the last column should store date of when car should be returned.
Thank you for any type of help.
This doesn't make sense:
DEFAULT TO_DATE (SYSDATE, 'DD-MM-YYYY')
SYSDATE is already a date. TO_DATE requires a char, so this takes a date, Oracle implicitly turns the date into a char, and then TO_DATE converts it back to a date. This is risky/unreliable because it uses a hardcoded date format to operate on a date that has been implicitly turned to a string using the system default format, which might one day not be DD-MM-YYYY (you're building a latent bug into your software)
If you want a date without a time on it use TRUNC(SYSDATE)
The other problem doesn't make sense either: you're storing a number of days rented for and also the return date, when one is a function of the other. Storing redundant data becomes a headache because you have to keep them in sync. My person class stores my birthdate, and I calculate how old I am. I don't store my age too and then update my table every day/year etc
Work out which will be more beneficial to you to store, and store it, then calculate the other whenever you want it. Personally I would store the return date as it's absolute, rather than open to interpretation of "is that working days, calendar days? what about public holidays? if the start date is jan 1 and the rental is for 10 days, is the car brought back on the 10th or the 11th?"
If you're desperate to have both columns in your DB consider using a view to calculate it or a function based column (again, to calculate one from the other) so they stay in sync
All in, you could look at this:
create table X(
RENT_DATE DATE DEFAULT TRUNC(SYSDATE) NOT NULL,
RETURN_DATE DATE NOT NULL,
DAYS AS (TRUNC(RETURN_DATE - RENT_DATE) + 1)
)
I put the days as +1 because to me, a car taken on the 1st and returned on the second is 2 days, but you might want to get more accurate - if it's taken on the first and returned before 10am on the second then it's one day otherwise it's 2 etc...
Use a virtual column:
CREATE TABLE table_name (
RENT_DATE DATE
DEFAULT TRUNC( SYSDATE )
CONSTRAINT table_name__rent_date__nn NOT NULL
CONSTRAINT table_name__rent_date_chk CHECK ( rent_date = TRUNC( rent_date ) ),
DAYS NUMBER
DEFAULT 7
CONSTRAINT table_name__days__nn NOT NULL,
RETURN_DATE DATE
GENERATED ALWAYS AS ( RENT_DATE + DAYS ) VIRTUAL
);
Then you can insert values:
INSERT INTO table_name ( rent_date, days ) VALUES ( DEFAULT, DEFAULT );
INSERT INTO table_name ( rent_date, days ) VALUES ( DATE '2020-01-01', 1 );
And:
SELECT * FROM table_name;
Outputs:
RENT_DATE | DAYS | RETURN_DATE
:------------------ | ---: | :------------------
2020-09-12T00:00:00 | 7 | 2020-09-19T00:00:00
2020-01-01T00:00:00 | 1 | 2020-01-02T00:00:00
db<>fiddle here

Resources