getting error while inserting values into table? - sql

Table structure is
Name Null Type
------------- ---- ------------
T_NO NUMBER
T_NAME VARCHAR2(10)
ENTERING_TIME TIMESTAMP(6)
LEAVING_TIME TIMESTAMP(6)
TO_DATE DATE
Trigger
create or replace trigger t4
before insert
on t4
for each row
declare
d_entering_time timestamp(6):=to_char('09:00:00AM','HH12:MM:SSAM');
begin
if (:new.entering_time <= d_entering_time) then
raise_application_error
(-20002,'Date of joining cannot be after system date.');
end if;
end;
and my inserting query
insert INTO t3 (entering_time) values ( TO_date('8:31:51AM','HH:MI:SSAM'))
I am getting the following error:
SQL Error: ORA-06502: PL/SQL: numeric or value error: character to number conversion error
ORA-06512: at "SYSTEM.T3", line 2
ORA-04088: error during execution of trigger 'SYSTEM.T3'
06502. 00000 - "PL/SQL: numeric or value error%s"
*Cause:
*Action:
Can any one suggest me where error occuring?

Try this:
CREATE OR REPLACE TRIGGER T4
BEFORE INSERT
ON T3
FOR EACH ROW
DECLARE
SSSSS_ENTERING_TIME NUMBER := 32400;
BEGIN
IF ( TO_NUMBER ( TO_CHAR ( :NEW.ENTERING_TIME,
'SSSSS' ) ) <= SSSSS_ENTERING_TIME )
THEN
RAISE_APPLICATION_ERROR (
-20002,
'Date of joining cannot be after system date.' );
END IF;
END;
INSERT INTO
T3 ( ENTERING_TIME )
VALUES
( TO_TIMESTAMP ( '01/01/2010 8:31:51AM',
'DD/MM/RR HH:MI:SSAM.FF' ) );
Note: I have extracted the total seconds from the time part and converted to a number for comparing. Hence I used 32400 seconds which is nothing but the actual 9 AM.
In Oracle we can turn dates into numbers and apply arithmetic to them in a variety of ways.
Hence to_char(some_date, 'SSSSS') gives us its time element as the number of seconds since midnight.

It looks like there is some errors in your code,
You are trying to store a string literal into to timestamp variable.
d_entering_time timestamp(6):=to_char('09:00:00AM','HH12:MM:SSAM');
It's HH12:MI:SSAM, not HH12:MM:SSAM, MI is for minute and MM is for month.
You can try like this,
CREATE OR REPLACE TRIGGER t4
BEFORE INSERT ON t3 FOR EACH ROW
DECLARE
d_entering_time TIMESTAMP :=to_timestamp('09:00:00AM','HH12:MI:SSAM.FF');
BEGIN
IF (:NEW.entering_time <= d_entering_time) THEN
raise_application_error (-20002,'Date of joining cannot be after system date.');
END IF;
END;
Insert query,
INSERT INTO t3 (entering_time) VALUES ( to_timestamp('8:31:51AM','HH:MI:SSAM.FF'));

Related

Getting unexpected values for number of days between two dates in oracle

I am writing a SQL code which fetches two dates from the database and calculates the number of days between them. Here is the code:
create table borrower(
roll_no number,
date_of_issue date,
name_of_book varchar(20),
status varchar(10)
);
insert into borrower values(1,to_date('02-JAN-2022'),'dbms','issued');
insert into borrower values(2,to_date('10-JAN-2022'),'cns','issued');
insert into borrower values(3,to_date('17-JAN-2022'),'spos','issued');
insert into borrower values(4,to_date('26-JAN-2022'),'toc','issued');
create table fine(
roll_no number,
current_date date,
amount number
);
insert into fine values(1,to_date('14-FEB-2022'),null);
insert into fine values(2,to_date('14-FEB-2022'),null);
insert into fine values(3,to_date('14-FEB-2022'),null);
insert into fine values(4,to_date('14-FEB-2022'),null);
DECLARE
roll_counter number:=1;
initial_date date;
final_date date;
date_calc number;
BEGIN
loop
select date_of_issue into initial_date from borrower where roll_no=roll_counter;
select current_date into final_date from fine where roll_no=roll_counter;
date_calc:=final_date-initial_date;
dbms_output.put_line(date_calc);
roll_counter:=roll_counter+1;
exit when roll_counter>4;
end loop;
END;
/
drop table borrower;
drop table fine;
I am not getting any error, but instead getting unexpected values for the number of days. Here is the output:
Statement processed.
246.4165625
238.4165625
231.4165625
222.4165625
I was expecting the number of days between the two dates(check the table). Can someone help me sort this out.
CURRENT_DATE is an Oracle keyword that returns the current date. Name your column something that is not an Oracle keyword.
https://docs.oracle.com/en/database/oracle/oracle-database/19/sqlrf/CURRENT_DATE.html
As #Matthew McPeak pointed out, CURRENT_DATE is a built-in function and that function is being called rather than returning your column value.
If you want the column value then you need to prefix the column name with the table name/alias and use fine.current_date:
DECLARE
roll_counter number:=1;
initial_date date;
final_date date;
date_calc number;
BEGIN
FOR roll_counter IN 1 .. 4 LOOP
select date_of_issue
into initial_date
from borrower
where roll_no=roll_counter;
select fine.current_date
into final_date
from fine
where roll_no=roll_counter;
date_calc:=final_date-initial_date;
dbms_output.put_line(date_calc);
END LOOP;
END;
/
Which, for your sample data, outputs:
43
35
28
19
Or you can use a single query (rather than multiple queries that are called in each loop iteration):
BEGIN
FOR r IN (
SELECT f.current_date - b.date_of_issue AS diff
FROM borrower b
FULL OUTER JOIN fine f
ON (b.roll_no = f.roll_no)
WHERE COALESCE(b.roll_no, f.roll_no) BETWEEN 1 AND 4
ORDER BY COALESCE(b.roll_no, f.roll_no)
) LOOP
dbms_output.put_line(r.diff);
END LOOP;
END;
/
db<>fiddle here

Oracle PL/SQL error - store procedure - ORA-00979 and ORA-06512

I am using following store procedure to insert data to a table.
create or replace PROCEDURE PM
(
date1 in varchar2
,date2 in varchar2
,date3 in varchar2
) AS
cursor cur_cd is
(
select to_date(date1,'DD-MON-YY') as date1
,trim(t.DEPT_CODE) DEPT_CODE
,count(t.DEPT_CODE) count_dept
,sum(t.amount) amount
from department t
where t.date >= to_date(date2,'DD-MON-YY')
and t.date <= to_date(date2,'DD-MON-YY')
and t.dept_name like 'finance%'
and (trim(t.DT_code)='TR_01' or t.DT_file like 'DTF_20%')
and t.DEPT_CODE not in ('HR','ADMIN','ACADEMIC')
group by t.DEPT_CODE
);
Type rec_set is table of dept_file%rowtype;
v_rec_set record_set;
begin
open cur_cd;
loop
fetch cur_cd
bulk collect into v_rec_set limit 100;
exit when v_rec_set.count()=0;
begin
forall i in v_rec_set.first..v_rec_set.last
insert into dept_file
values v_rec_set(i);
end;
end loop;
close cur_cd;
exception when others then raise;
end PM;
It's giving me a runtime error when execute procedure. But the query execute without error manually.
ORA-000979 : not a GROUP BY expression
ORA-006512 : at "ABS.PM", line 9
Also, when hard code the parameters (date1, date2 and date3) the procedure working without error.
Can you please help me to resolve this error?
All non-aggregated columns must be specified in the GROUP BY clause. Therefore:
GROUP BY TO_DATE (date1, 'DD-MON-YY'), TRIM (t.dept_code)
By the way, are you really storing date values as strings? Why do I ask? Because you're using TO_DATE functions all over the code. If you are, then try not to do it in the future. Oracle offers DATE datatype, you should use it.

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>

ORA-01722: invalid number while select numeric column and same numeric column reference in where

select id
from abc
where id = 1001;
return invalid number.
abc is a view
datatype of id is number
In create view cast is used
CREATE OR REPLACE VIEW abc AS
SELECT CAST (SUBSTR(T_ID,3,100) AS NUMBER) AS ID
from TEST
id column has all numeric values only
SELECT * FROM ABC WORKS FINE AND SO insert query works
tried below code which returns nothing in dbms output
declare
l_dummy number;
begin
for cur in (select ID from abc)
loop
begin
l_dummy := to_number(cur.ID);
exception
when others then dbms_output.put_line(cur.ID);
end;
end loop;
end;
column datatype nullable
ID NUMBER Yes 1 NO NO NO
SELECT *
FROM abc
WHERE
ID = 1001
returns:
ORA-01722: invalid number
01722. 00000 - "invalid number"
*Cause: The specified number was invalid.
*Action: Specify a valid number.
There are two problems:
SUBSTR(T_ID,3,100) will not return number always -- We need to consider the only numeric query
If we apply anything in WHERE condition of the view, Order of the execution of the WHERE condition is the call of Oracle optimizer.
Please see below code:
-- Data preparation
create table TEST (T_ID varchar2(20));
INSERT INTO TEST VALUES('AB1000'); -- Good data
INSERT INTO TEST VALUES('AB1001'); -- Good data
INSERT INTO TEST VALUES('CD1001'); -- Good data
INSERT INTO TEST VALUES('XY1004'); -- Good data
INSERT INTO TEST VALUES('XYZ1004'); -- Bad data
--
-- Data in the table
SELECT * FROM TEST;
Output
-- You need to create your view as following
-- rownum is used so that WHERE clause of view is executed first
-- and then any external WHERE clause on the view is executed
CREATE OR REPLACE VIEW ABC_NEWVIEW AS
SELECT
ID
FROM
(
SELECT
CAST(SUBSTR(T_ID, 3, 100) AS NUMBER) AS ID,
ROWNUM RN
FROM
TEST
WHERE
CASE
WHEN TRIM(TRANSLATE(SUBSTR(T_ID, 3, 100), '0123456789-,.', ' ')) IS NULL THEN 'numeric'
ELSE 'alpha'
END = 'numeric'
)
--
-- View
SELECT * FROM ABC_NEWVIEW
Output
-- Query using WHERE condition
SELECT *
FROM ABC_NEWVIEW
WHERE
ID = 1001
Output
You can find the demo in the following link:
DB Fiddle demo
You can see the demo of VIEW without ROWNUM:
Reproduced your issue -- So the issue is the order of the execution.
Cheers!!

SQL PLUS Trigger compilation errors

I am trying to create a trigger to calculate a derived attribute on each insert command. However I am getting compilation errors, I dont know where is the problem.
CREATE OR REPLACE TRIGGER NewTrigger
BEFORE INSERT
ON Dates FOR EACH ROW
BEGIN
SET :NEW.difference := :NEW.date1 - :NEW.date2;
END;
Show errors shows me this information:
LINE/COL ERROR
-------- -----------------------------------------------------------------
1/7 PL/SQL: SQL Statement ignored
1/11 PL/SQL: ORA-00922: missing or invalid option
It's not the trigger, it's the data type. If you substract a date from another date, the result is an interval, not another date:
CREATE TABLE dates (date1 DATE, date2 DATE, datediff DATE, numdiff NUMBER);
INSERT INTO dates (date1, date2) VALUES (sysdate, sysdate-1);
UPDATE dates SET numdiff = date1 - date2;
1 rows updated
UPDATE dates SET datediff = date1 - date2;
SQL Error: ORA-00932: inconsistent datatypes: expected DATE got DATE JULIAN
So, if the trigger stores the interval in a number, it compiles:
CREATE OR REPLACE TRIGGER newtriggernum
BEFORE INSERT ON dates FOR EACH ROW
BEGIN
:new.numdiff := :new.date1 - :new.date2;
END;
/
TRIGGER NEWTRIGGERNUM compiled
and if it stores the interval in a date, it doesn't:
CREATE OR REPLACE TRIGGER newtriggerdate
BEFORE INSERT ON dates FOR EACH ROW
BEGIN
:new.datediff := :new.date1 - :new.date2;
END;
/
Error(2,11): PL/SQL: ORA-00922: missing or invalid option
CREATE OR REPLACE TRIGGER NewTrigger
BEFORE INSERT ON Dates FOR EACH ROW
BEGIN
:NEW.difference := :NEW.date1 - :NEW.date2;
End;
/