Need to insert date column along with time and mins - sql

I need to insert the date column record along with hour,min,sec, for example my joining date is 10/10/2021 but i need to insert 10/10/2021 08:05:25 i need output like this to get inserted
My insert query:
INSERT INTO lease_rent_receipts
(billing_start_date, billing_end_date,
charge_category, due_amount,
due_date, client_id,total_payable, description)
VALUES (l_billing_start_date,l_billing_end_date,l_charge_category, l_due_amount,
l_due_date, l_client_id,l_total_payable, l_description);
Main for due_date column i need to insert along with hrs:min:sec
kindly assist

To demonstrate my earlier comments. Notice on the final query of the table, I am querying the same column - the same data - with three different formats:
SQL> create table my_demo
2 (demo_date date)
3 ;
Table created.
SQL> declare
2 l_demo_date date := to_date('2021-10-22 12:21:43','yyyy-mm-dd hh24:mi:ss');
3 begin
4 insert into my_demo (demo_date)
5 values (l_demo_date)
6 ;
7 end;
8 /
PL/SQL procedure successfully completed.
SQL> select demo_date,
2 to_char(demo_date,'dd-Mon-yyyy') demo1,
3 to_char(demo_date,'yyyy-mm-dd hh24:mi:ss') demo2
4 from my_demo;
DEMO_DATE DEMO1 DEMO2
--------- -------------------- -------------------
22-OCT-21 22-Oct-2021 2021-10-22 12:21:43
1 row selected.
SQL> --
SQL> drop table my_demo purge;
Table dropped.

Use timestamp
to_timestamp(date_col, 'DD/MM/YYYY 24hh:mm:ss' )

DECLARE
l_billing_start_date lease_rent_receipts.billing_start_date%TYPE;
l_billing_end_date lease_rent_receipts.billing_end_date%TYPE;
l_charge_category lease_rent_receipts.charge_category%TYPE;
l_due_amount lease_rent_receipts.due_amount%TYPE;
l_due_date lease_rent_receipts.due_date%TYPE;
l_client_id lease_rent_receipts.client_id%TYPE;
l_total_payable lease_rent_receipts.total_payable%TYPE;
l_description lease_rent_receipts.description%TYPE;
BEGIN
-- Use a DATE literal and add an INTERVAL DAY TO SECOND literal.
billing_start_date := DATE '2021-10-10' + INTERVAL '08:05:25' HOUR TO SECOND;
-- or use a TIMESTAMP literal.
billing_start_date := TIMESTAMP '2021-10-10 08:05:25';
-- Or use TO_DATE.
billing_start_date := TO_DATE('10/10/2021 08:05:25', 'DD/MM/YYYY HH24:MI:SS');
-- Set other variables.
INSERT INTO lease_rent_receipts(
billing_start_date, billing_end_date, charge_category, due_amount,
due_date, client_id,total_payable, description
) VALUES (
l_billing_start_date, l_billing_end_date, l_charge_category, l_due_amount,
l_due_date, l_client_id,l_total_payable, l_description
);
END;
/

Related

"not a valid month" while inserting timestamp into table

Error while trying to insert a query which transforms multiple merged date(eg.20230208065521019355) into proper timestamp format to a new column.
INSERT INTO NEWTABLE2(RC_DATETIME)
SELECT TO_CHAR(TO_TIMESTAMP(RC_TIMESTAMP, 'YYYY-MM-DD HH:MI:SS:FF'), 'YYYY-MM-DD HH:MI:SS.FF')
FROM NEWTABLE;
Upon just executing the SELECT statement I get the query but while including the INSERT I get the error of 'not valid month'.
Data within the RC_TIMESTAMP(VARCHAR) are the merged data which are as follows:
20230208065521019355, 20230208065523019356, 20230208065532019357, etc.
RC_DATETIME has VARCHAR(35) datatype.
I have tried reordering the format of TO_CHAR, 'YYYY-MM-DD HH:MI:SS.FF' to 'Mon-DD-YYYY HH:MI:SS.FF' to name a few.
From what you posted:
Source table:
SQL> CREATE TABLE newtable (rc_timestamp)
2 AS (SELECT '20230208065521019355' FROM DUAL);
Table created.
Target table:
SQL> CREATE TABLE newtable2
2 (rc_datetime VARCHAR2 (35));
Table created.
Insert:
SQL> INSERT INTO newtable2 (rc_datetime)
2 SELECT TO_CHAR (TO_TIMESTAMP (rc_timestamp, 'yyyymmddhh24missff6'),
3 'yyyy-mm-dd hh24:mi:ss:ff')
4 FROM newtable;
1 row created.
However, you'd rather store timestamps into a timestamp column, not as a string. What benefit do you expect? It causes problems in later data processing.
SQL> DROP TABLE newtable2;
Table dropped.
SQL> CREATE TABLE newtable2
2 (rc_datetime TIMESTAMP);
Table created.
SQL> INSERT INTO newtable2
2 SELECT TO_TIMESTAMP (rc_timestamp, 'yyyymmddhh24missff6') FROM newtable;
1 row created.
SQL>
You commented that you still have the "not a valid month" error.
It means that data - at position where TO_TIMESTAMP expects a valid month value (01, 02, ..., 12) - contains something else. What? No idea, you have all the data. Try to find it by selecting a substring (month starts at position 5 and takes 2 places):
SQL> SELECT rc_timestamp, SUBSTR (rc_timestamp, 5, 2) month FROM newtable;
RC_TIMESTAMP MO
-------------------- --
20230208065521019355 02
SQL>
Invalid data is most probably here:
SELECT rc_timestamp
FROM newtable
WHERE SUBSTR (rc_timestamp, 5, 2) NOT BETWEEN '01' AND '12';
Once you find invalid values, you'll decide what to do with it. Maybe you'll ignore those values (so you'd include appropriate where clause into the insert statement), or fix it (somehow; can't tell how as it depends on what you'll find), or ...
If you want to identify invalid values during insert, a simple option is a loop with an inner begin-exception-end block which lets you capture those values and still proceed with other row(s). Something like this:
create table invalid_values as
select id, value from source_table where 1 = 2;
begin
for cur_r in (select * from source_table) loop
begin
insert into newtable2 ...
exception
when others then
insert into invalid_values (id, value) values (cur_r.id, cur_r.value);
end;
end loop;
end;
Once you're done, select * from invalid_value so that you could deal with what's left.
That should be OK as you have 10.000 rows so loop won't take infinite time to complete. True, it will be slower than set-oriented operation, but ... you have to fetch invalid rows, somehow.

Integrity Constraints for date (using oracle) Current Date not working as it come up with error

I have used this trigger:
CREATE OR REPLACE TRIGGER trg_chk_future
BEFORE INSERT ON your_table
FOR EACH ROW
BEGIN
IF( :new.date_time < sysdate )
THEN
RAISE_APPLICATION_ERROR( -20001, 'date_time must be in the future' );
END IF;
END;
However the current date comes up as an error when entered such as 12/12/2021 (today date) but 13/12/21 and any date after the today date works.
Any ideas what's wrong.
If you really inserted values you wrote in the question, who-knows-what you really inserted. Because, those are strings, not date values. Therefore, Oracle tried to convert them to valid DATE datatype values and - according to what you said - failed.
It means that you should actually insert DATE values, like the following example shows (trigger is exactly the same as you made it):
SQL> create table your_table (date_time date);
Table created.
SQL> CREATE OR REPLACE TRIGGER trg_chk_future
2 BEFORE INSERT ON your_table
3 FOR EACH ROW
4 BEGIN
5 IF( :new.date_time < sysdate )
6 THEN
7 RAISE_APPLICATION_ERROR( -20001, 'date_time must be in the future' );
8 END IF;
9 END;
10 /
Trigger created.
Testing: truncated sysdate is set to midnight (which was in the past, and thus rejected):
SQL> insert into your_table values (trunc(sysdate));
insert into your_table values (trunc(sysdate))
*
ERROR at line 1:
ORA-20001: date_time must be in the future
ORA-06512: at "SCOTT.TRG_CHK_FUTURE", line 4
ORA-04088: error during execution of trigger 'SCOTT.TRG_CHK_FUTURE'
May this year, also in the past:
SQL> insert into your_table values (date '2021-05-25');
insert into your_table values (date '2021-05-25')
*
ERROR at line 1:
ORA-20001: date_time must be in the future
ORA-06512: at "SCOTT.TRG_CHK_FUTURE", line 4
ORA-04088: error during execution of trigger 'SCOTT.TRG_CHK_FUTURE'
This is in the future, so it is accepted:
SQL> insert into your_table values (date '2021-12-26');
1 row created.
SQL>
As of
the current date comes up as an error when entered such as 12/12/2021 (today date)
Maybe you meant to say
IF( :new.date_time < trunc(sysdate))
which truncates sysdate to midnight today. In that case, today's date is also accepted:
SQL> CREATE OR REPLACE TRIGGER trg_chk_future
2 BEFORE INSERT ON your_table
3 FOR EACH ROW
4 BEGIN
5 IF( :new.date_time < trunc(sysdate))
6 THEN
7 RAISE_APPLICATION_ERROR( -20001, 'date_time must be in the future' );
8 END IF;
9 END;
10 /
Trigger created.
SQL> insert into your_table values (date '2021-12-12');
1 row created.
SQL>

NULL Date field is populated with SYSDATE by default

I am running a query on clocking data for my company. I have a query with 2 fields: CLOCK_IN1 and CLOCK_OUT1. When I run the query I see the proper CLOCK_IN1 but the CLOCK_OUT1 is being populated with a date near SYSDATE. CLOCK_OUT1 is NULL in the database and it's replacing the NULL with this date.
Is there a setting that populates a date when it's NULL?
There's either
a DEFAULT value applied to that column, or
a database trigger that does it.
This is how the first works:
SQL> create table test
2 (clock_in1 date,
3 clock_out1 date default sysdate
4 );
Table created.
SQL> insert into test (clock_in1) values (date '2020-08-23');
1 row created.
SQL> alter session set nls_date_format = 'dd.mm.yyyy hh24:mi:ss';
Session altered.
SQL> select sysdate from dual;
SYSDATE
-------------------
03.11.2020 20:23:03
SQL> select * from test;
CLOCK_IN1 CLOCK_OUT1
------------------- -------------------
23.08.2020 00:00:00 03.11.2020 20:22:48
SQL>
And this is the second:
SQL> drop table test;
Table dropped.
SQL> create table test
2 (clock_in1 date,
3 clock_out1 date
4 );
Table created.
SQL> create or replace trigger trg_bi_test
2 before insert on test
3 for each row
4 begin
5 :new.clock_out1 := nvl(:new.clock_out1, sysdate);
6 end;
7 /
Trigger created.
SQL> insert into test (clock_in1) values (date '2020-08-23');
1 row created.
SQL> select * from test;
CLOCK_IN1 CLOCK_OUT1
------------------- -------------------
23.08.2020 00:00:00 03.11.2020 20:24:23
SQL>
How to "fix" it?
SQL> alter table test modify clock_out1 default null;
Table altered.
SQL>
As of the trigger, well ... it depends on what it is doing, but - removing a line that sets column value would do.

Timetable allocation using SQL

I have these two tables in my database:
Session(startTime,endTime,date)
Allocation(startTime,endTime,date)
There are already existing sessions in the timetable, and I need to allocate a new session in a way that there are no confusions between all the sessions. I thought about something like:
ALTER TABLE allocation ADD CONSTRAINT timeC
check (startTime not between (select startTime from session)
and (select endTime from session))
The problem is that it's impossible to do so as we can't use the keyword "between" for two sets of values (same thing with the endTime).
How can I manage to add this constraint ? (I use Oracle 11g)
That can't be done via a check constraint; a trigger might help, though (as Gordon has already said). Here's an example:
SQL> create table tsession
2 (id number constraint pk_tsess primary key,
3 starttime date,
4 endtime date);
Table created.
SQL>
SQL> create table tallocation
2 (id number constraint fk_all_sess references tsession (id),
3 starttime date,
4 endtime date);
Table created.
SQL>
SQL> create or replace trigger trg_biu_all
2 before insert or update on tallocation
3 for each row
4 declare
5 l_dummy varchar2(1);
6 begin
7 select 'x'
8 into l_dummy
9 from tsession s
10 where s.id = :new.id
11 and :new.starttime between s.starttime and s.endtime;
12
13 raise_application_error(-20001, 'Can not set such a start time as it collides with TSESSION values');
14 exception
15 when no_data_found then
16 -- OK, no problem - no collision
17 null;
18 end;
19 /
Trigger created.
Now, testing:
SQL> -- Insert master record, ID = 1; it'll take whole February
SQL> insert into tsession values (1, date '2018-02-01', date '2018-02-28');
1 row created.
SQL> -- I don't want to allow this date to "jump in" between 2018-02-01 and 2018-02-28
SQL> insert into tallocation (id, starttime) values (1, date '2018-02-13');
insert into tallocation (id, starttime) values (1, date '2018-02-13')
*
ERROR at line 1:
ORA-20001: Can not set such a start time as it collides with TSESSION values
ORA-06512: at "HR.TRG_BIU_ALL", line 10
ORA-04088: error during execution of trigger 'HR.TRG_BIU_ALL'
SQL> -- This one should be OK, as it is in March
SQL> insert into tallocation (id, starttime) values (1, date '2018-03-22');
1 row created.
SQL>

check for valid date which is declared in varchar2

My table looks like below which is declared in VARCHAR2:
YMD
20101010
20101112
20100231
20150101
20160101
I have to check for valid dates and filter future dates from sysdate, which are in valid format.
I write the function as below to check for valid dates:
create or replace FUNCTION VALIDATE_DATE (p_string in string) return date is
begin
return to_date(p_string, 'YYYYMMDD');
exception when others then
begin
return to_date(p_string, 'YYYY-MM-DD');
exception when others then
begin
return to_date(p_string, 'RR-MON-DD');
exception when others then
return null;
end;
end;
end;
and written this query to check for valid dates and replace with null for invalid dates
select ymd, VALIDATE_DATE(ymd) as Valid
from temp
and to check future dates I wrote the following query, but it throws error
ORA-01839
select ymd
from temp
where validate_date(ymd)='YES'
and to_date(ymd,'yyyymmdd')>sysdate
How to check future dates in my table if exists?
I will rather fix the design issue as a permanent fix rather than wasting time on the workaround.
Firstly, NEVER store DATE as VARCHAR2. All this overhead is due to the fact that your design is flawed.
'20100231'
How on earth could that be a valid date? Which calendar has a 31 days in FEBRUARY?
Follow these steps:
Add a new column with DATE DATA TYPE.
Update the new column with date values from the old column using TO_DATE.
Do the required DATE arithmetic on the new DATE column, or handle this in the UPDATE statement in step 2 itself.
Drop the old column.
Rename the new column to the old column.
UPDATE Adding a demo
Setup
SQL> CREATE TABLE t
2 (ymd varchar2(8));
Table created.
SQL>
SQL> INSERT ALL
2 INTO t (ymd)
3 VALUES ('20101112')
4 --INTO t (ymd)
5 -- VALUES ('20100231')
6 INTO t (ymd)
7 VALUES ('20150101')
8 INTO t (ymd)
9 VALUES ('20160101')
10 SELECT * FROM dual;
3 rows created.
SQL>
SQL> COMMIT;
Commit complete.
SQL>
Add new column:
SQL> ALTER TABLE t ADD (dt DATE);
Table altered.
SQL>
DO the required update
SQL> UPDATE t
2 SET dt =
3 CASE
4 WHEN to_date(ymd, 'YYYYMMDD') > SYSDATE
5 THEN NULL
6 ELSE to_date(ymd, 'YYYYMMDD')
7 END;
3 rows updated.
SQL>
SQL> COMMIT;
Commit complete.
SQL>
Let's check:
SQL> SELECT * FROM t;
YMD DT
-------- ---------
20101112 12-NOV-10
20150101 01-JAN-15
20160101
SQL>
Drop the old column:
SQL> ALTER TABLE t DROP COLUMN ymd;
Table altered.
SQL>
Rename the new column to old column name
SQL> ALTER TABLE t RENAME COLUMN dt TO ymd;
Table altered.
SQL>
You have just fixed the issue
SQL> SELECT * FROM t;
YMD
---------
12-NOV-10
01-JAN-15
SQL>