How to correct this Procedure - oracle

I get an error "ORA-06512" for the following procedure. Please rectify and correct me:
DROP TRIGGER XYZ.CHECK_DATE_TIME;
CREATE OR REPLACE TRIGGER XYZ.CHECK_DATE_TIME
BEFORE INSERT ON RFID.ATTENDANCE
REFERENCING NEW AS NEW OLD AS OLD
FOR EACH ROW
DECLARE
TMPVAR NUMBER;
BEGIN
-------------------------------------
IF SECURITY.F_WS_USER() THEN
RETURN;
END IF;
IF :NEW.CHECK_TIME < (SYSDATE - 10)
OR :NEW.CHECK_TIME > (SYSDATE + ((1 / 24) / 60) * 10) THEN
RAISE_APPLICATION_ERROR(-20000,
'Unable to save machine data in RFID.ATTENDANCE as it is older than 5 days ');
END IF;
END;
/

Related

Cannot insert Third column of data

I am noob in PL/SQL I just start learning and I want to create small peace of software that insert data from .CVS file to Oracle database.
And I stuck in part where I grab data from .CVS file.
I my CVS there are three column: Number_Policy,Contact, Agency
Number_Policy,Contact is catch success, but Agency can not be catched and I dont know why
declare
import_file text_io.file_type;
export_file text_io.file_type;
import_file_name varchar2(1000);
export_file_name varchar2(1000);
import_log_file text_io.file_type;
import_log_file_name varchar2(1000);
vec_importovano number;
brojac number;
brojac_redova number;
linebuf varchar2(10000);
p_rbr varchar2(20);
p_polica varchar2(20);
p_banka VARCHAR2(50);
p_kontakt varchar2(20);
kraj_fajla number;
begin
brojac_redova:=0;
import_file_name := :Global.Lokacija_prenosa||:import.naziv_fajla||:Global.Ekstenzija_prenosa;
import_file := text_io.fopen(import_file_name,'r');
delete from zivot_trajni_nalog_ponude where banka is not null;
commit;
kraj_fajla := 0;
while kraj_fajla = 0 loop
begin
brojac_redova:=brojac_redova+1;
text_io.get_line(import_file, linebuf);
if brojac_redova >= 2 then
p_polica:=substr(linebuf, 1, instr(linebuf,';',1,1)-1);
-- message(p_polica);
p_kontakt:=substr(linebuf, instr(linebuf,';',1,1)+1, instr(linebuf,';',1,2) - instr(linebuf,';',1,1)-1);
p_banka:=substr(linebuf, instr(linebuf,';',1,2)+1, instr(linebuf,';',1,3) - instr(linebuf,';',1,2)-1);
-- message(p_banka);
--p_kontakt:=substr(linebuf, instr(linebuf,';',1,1)+1, instr(linebuf,';',1,2) - instr(linebuf,';',1,1)-1);
-- message(p_kontakt);
/*
p_rbr:=substr(linebuf, 1, instr(linebuf,';',1,1)-1);
-- message(p_rbr);
p_polica:=substr(linebuf, instr(linebuf,';',1,1)+1, instr(linebuf,';',1,2) - instr(linebuf,';',1,1)-1);
-- message(p_polica);
p_banka:=substr(linebuf, instr(linebuf,';',1,2)+1, instr(linebuf,';',1,3) - instr(linebuf,';',1,2)-1);
message(p_banka);
p_kontakt:=substr(linebuf, instr(linebuf,';',1,3)+1, instr(linebuf,';',1,4) - instr(linebuf,';',1,3)-1);
message(p_kontakt);
*/
if vec_importovano = 0 then
insert into ZIVOT_TRAJNI_NALOG_PONUDE
(BROJ_POLICE,BROJ_PONUDE)
values(
p_polica,
--p_rbr,
p_kontakt);
-- p_banka);
commit;
end if;
end if;
EXCEPTION WHEN NO_DATA_FOUND THEN kraj_fajla := 1;
end;
end loop;
IF p_polica IS NOT NULL
THEN
update zivot_trajni_nalog_ponude set BROJ_POLICE=rownum;
commit;
END IF;
text_io.fclose(import_file);
message ('Uspjesno zavrseno');
end;
As you can see from code there is error somewhere here
p_banka:=substr(linebuf, instr(linebuf,';',1,2)+1, instr(linebuf,';',1,3) - instr(linebuf,';',1,2)-1);
-- message(p_banka);
After I disable this column the problem is that column p_polica and p_kontakt can't be inserted into database.
If anyone know where I made mistake I would be very thankful for any help.
Looks like linebuf has only two semicolons. This piece of code worked in my short test:
if instr(linebuf,';',1,3) > 0 then
p_banka := substr(linebuf,
instr(linebuf,';',1, 2) + 1,
instr(linebuf,';',1,3) - instr(linebuf,';',1,2)-1);
else
p_banka := substr(linebuf,
instr(linebuf,';',1, 2) + 1);
end if;

PLS-00103 error while trying to compare numbers

Is this prcedure syntaxically wrong? It seems that there is a problem with my if than block. I kepp getting
PLS-00103: Encountered the symbol ")" when expecting one of the
following:
(
CREATE OR REPLACE PROCEDURE Verif(TAB VARCHAR2) IS
MAX NUMBER;
TEMP NUMBER;
BEGIN
FOR i IN (SELECT * FROM CLIENTS1_1 WHERE NOT REGEXP_LIKE (COL2, (SELECT REGULAREXPR FROM REGULAREXPRES WHERE CATEGORY='ABR'))) LOOP
MAX:=0;
FOR j IN (SELECT * FROM ABR) LOOP
SELECT UTL_MATCH.JARO_WINKLER_SIMILARITY(i.Col2, j.ABR) INTO TEMP FROM DUAL;
IF (TEMP >= MAX) THEN
DBMS_OUTPUT.PUT_LINE(TEMP);
end if;
END LOOP;
END LOOP;
END;
/
I did all the tests. All select queries return real values.
Thanks for your help.
It was a stupid mistake. Just needed to replace MAX (which is a key word) by another var name.
Thanks to Barbaros Ozhan.

Oracle: detect exception in type construtor during bulk collect

Environment: Oracle 11g
I have a type ty1 with some arguments like s1, s2.
If I use it like this:
SELECT ty1(s1,s2) BULK COLLECT INTO l_collection_of_ty1 FROM ...
I get a collection of ty1.
Now if there is an exception raised inside one of the constructor calls of ty1 the corresponding element of my collection is set to NULL, but the overall SELECT works (no exception, collection returned).
My question, can I detect this right after the SELECT without having to loop over the collection? Is there maybe even a way to access the original error message in a similar way as SQL%BULK_EXCEPTION does for DML?
One workaround I thought of is to not use the constructor during BULK COLLECT, but read collections of s1 and s2, then construct the TYPE in my own loop where I can handle the exception, but that is much more code and I would prefer it if Oracle has some build in way.
here is a testcase that demonstrates that all exceptions are thrown through a bulk-select, but NO_DATA_FOUND is dropped.
-- remember to retreive dbms_output
SET SERVEROUTPUT ON
CREATE OR REPLACE FUNCTION p1 (v1 PLS_INTEGER)
RETURN NUMBER
AS
BEGIN
CASE v1
WHEN 1
THEN
RAISE ACCESS_INTO_NULL;
WHEN 2
THEN
RAISE CASE_NOT_FOUND;
WHEN 3
THEN
RAISE COLLECTION_IS_NULL;
WHEN 4
THEN
RAISE CURSOR_ALREADY_OPEN;
WHEN 5
THEN
RAISE DUP_VAL_ON_INDEX;
WHEN 6
THEN
RAISE INVALID_CURSOR;
WHEN 7
THEN
RAISE INVALID_NUMBER;
WHEN 8
THEN
RAISE LOGIN_DENIED;
WHEN 9
THEN
RAISE NO_DATA_FOUND;
WHEN 10
THEN
RAISE NOT_LOGGED_ON;
WHEN 11
THEN
RAISE PROGRAM_ERROR;
WHEN 12
THEN
RAISE ROWTYPE_MISMATCH;
WHEN 13
THEN
RAISE SELF_IS_NULL;
WHEN 14
THEN
RAISE STORAGE_ERROR;
WHEN 15
THEN
RAISE SUBSCRIPT_BEYOND_COUNT;
WHEN 16
THEN
RAISE SUBSCRIPT_OUTSIDE_LIMIT;
WHEN 17
THEN
RAISE SYS_INVALID_ROWID;
WHEN 18
THEN
RAISE TIMEOUT_ON_RESOURCE;
WHEN 19
THEN
RAISE TOO_MANY_ROWS;
WHEN 20
THEN
RAISE VALUE_ERROR;
WHEN 21
THEN
RAISE ZERO_DIVIDE;
ELSE
RETURN v1;
END CASE;
END;
/
DECLARE
TYPE type1 IS TABLE OF NUMBER;
col1 type1;
BEGIN
FOR ii IN 1 .. 22
LOOP
BEGIN
SELECT p1 (ii)
BULK COLLECT INTO col1
FROM DUAL;
IF col1 (1) IS NULL
THEN
DBMS_OUTPUT.put_line (TO_CHAR (ii, '00') || ': NULL');
ELSE
DBMS_OUTPUT.put_line (TO_CHAR (ii, '00') || ': ' || col1 (1));
END IF;
EXCEPTION
WHEN OTHERS
THEN
DBMS_OUTPUT.put_line (
TO_CHAR (ii, '00')
|| ': exception '
|| SQLCODE);
END;
END LOOP;
END;
/
I wrote a small test case for you and the exception has to be swallowed inside ty1 and not raised, because otherwise the select would not finish successfully:
create or replace function p1 (v1 number) return number
as
begin
if v1 = 1 then
return 1;
elsif v1 = 2 then
raise_application_error(-20010,'err 2');
else
raise_application_error(-20010,'err 3');
end if;
end;
/
declare
type type1 is table of number;
col1 type1;
begin
select p1(level) bulk collect into col1 from dual connect by level <=3;
end;
/
Result:
Error report -
ORA-20010: err 2
So my suggestion to you is - if you want to stay close to your solution - that at the place where you handle the exception in ty1, you write the exceptions to a table. You can then access this table to find the exceptions and don't need to loop through the whole collection. But honestly, what's wrong with looping in PL/SQL over a collection, it's all in memory? HTH
I see only two options.
An exception is consumed inside constructor.
The another constructor is in use.
Example:
create or replace type ty1 as object (p1 number
, constructor function ty1 (p1 varchar2)
return self as result);
create or replace type body ty1
is
constructor function ty1 (p1 varchar2)
return self as result is
x number;
begin
raise_application_error(-20000,'Always Exception');
return;
end;
end;
Test 1 no exception:
declare
type l_collection_of_ty1 is table of ty1;
a varchar2(4000);
x l_collection_of_ty1;
begin
--test1 select ty1(level) bulk collect into x from dual connect by level < 10;
-- no exceptions
--test2 select ty1(level||1) bulk collect into x from dual connect by level < 10;
-- exceptions
--test3 select ty1(null) bulk collect into x from dual connect by level < 10;
-- exceptions
end;
In Test1 db is using Attribute-Value Constructor. It is generate by default.
In Test2 db is using user defined constructor.
In Test3 db is not able to find out which constructor should be used.()

How to print a particular select statement three times in oracle?

This is the code
declare
a integer;
begin
select to_char(to_date('1/1/2017 ','mm/dd/yyyy') + level -1) into a from dual
connect by level <=365;
for a in 1..3 loop
dbms_output.put_line(a);
end loop;
end;
Error occurring is exact fetch requested more no of rows
Please help
You are trying to get multiple value in a scaler variable.
Try this:
begin
for i in (select to_char(to_date('1/1/2017 ','mm/dd/yyyy') + level -1) col
from dual
connect by level <=365) loop
for j in 1..3 loop
dbms_output.put_line(i.col);
end loop;
end loop;
end;
/
1st of all, please be aware about the fact that you declared the "a" variable as integer but then you assign a varchar2 to it.
2nd, I was testing your code and it seems that there is a problem with level <= 365.
I changed it into level = 365 and it seemed to return the expected result.
declare
a integer;
begin
select to_char(to_date('1/1/2017 ','mm/dd/yyyy') + level -1) into a from dual
-- connect by level <= 365;
connect by level = 365;
for a in 1..3 loop
dbms_output.put_line(a);
end loop;
end;

Error(31,64): PLS-00103: Encountered the symbol "(" when expecting one of the following

I have below function in oracle,
create or replace FUNCTION CALINTEREST
( DNumber IN VARCHAR2,
IRate IN NUMBER
) RETURN NUMBER IS
AInterest NUMERIC(17,8):=0;
PDue NUMERIC(11,2);
IDue NUMERIC(17,8);
INTRate NUMERIC(5,2);
IntDate DATE;
IntDATEDIFF NUMERIC(6):=0;
BEGIN
BEGIN
SELECT
DBRD_PRI_DUE,
DBRD_INT_DUE,
DBRD_INT_RATE,
DBRD_INT_DATE INTO
PDue
,IDue
,INTRate
,IntDate
FROM
DBRD
WHERE
DBRNO = DNumber;
IF(INTRate = 999)
THEN
INTRate := IRate;
END IF;
IntDATEDIFF:=Cast((Sysdate-IntDate) AS NUMBER(11,0));
AInterest := IDue + (PDue * INTRate * IntDATEDIFF / 365 / 100);
END;
RETURN AInterest;
END;
I am getting below two error,
Error(31,64): PLS-00103: Encountered the symbol "(" when expecting one of the following: . ) # % The symbol ")" was substituted for "(" to continue.
Error(31,70): PLS-00103: Encountered the symbol ")" when expecting one of the following: . ( * % & = - + ; < / > at in is mod remainder not rem <> or != or ~= >= <= <> and or like like2 like4 likec between || multiset member submultiset The symbol "(" was substituted for ")" to continue.
Not sure if this will work for you. On my machine the only errors I get on compilation have to do with the table DBRO (because I don't have a table by that name), but that doesn't mean this does the computations you want it to do. Anyway, play with it and write back if you have more questions.
I changed NUMERIC to NUMBER (the correct name of the Oracle data type for numbers), I changed the computation for IntDATEDIFF in a way that will be immediately obvious when you look at it (Trunc changes the time portion of an Oracle DATE to 00:00:00, and taking the arithmetic "minus" between two dates returns the difference as a number of days), and I removed BEGIN and END; for the inner block- there was no need for an inner block.
create or replace FUNCTION CALINTEREST
( DNumber IN VARCHAR2,
IRate IN NUMBER
) RETURN NUMBER IS
AInterest NUMBER(17,8):=0;
PDue NUMBER(11,2);
IDue NUMBER(17,8);
INTRate NUMBER(5,2);
IntDate DATE;
IntDATEDIFF NUMBER(6):=0;
BEGIN
SELECT
DBRD_PRI_DUE,
DBRD_INT_DUE,
DBRD_INT_RATE,
DBRD_INT_DATE INTO
PDue
,IDue
,INTRate
,IntDate
FROM
DBRD
WHERE
DBRNO = DNumber;
IF(INTRate = 999)
THEN
INTRate := IRate;
END IF;
IntDATEDIFF:=trunc(Sysdate) - trunc(IntDate);
AInterest := IDue + (PDue * INTRate * IntDATEDIFF / 365 / 100);
RETURN AInterest;
END;
/
create or replace FUNCTION CALINTEREST(
DNumber IN VARCHAR2,
IRate IN NUMBER
) RETURN NUMBER
IS
PDue NUMERIC(11,2);
IDue NUMERIC(17,8);
INTRate NUMERIC(5,2);
IntDate DATE;
BEGIN
SELECT DBRD_PRI_DUE, DBRD_INT_DUE, DBRD_INT_RATE, DBRD_INT_DATE
INTO PDue, IDue, INTRate, IntDate
FROM DBRD
WHERE DBRNO = DNumber;
IF (INTRate = 999) THEN
INTRate := IRate;
END IF;
RETURN IDue + (PDue * INTRate * TRUNC(SYSDATE - IntDate) / 365 / 100);
END;
/
SHOW ERRORS;
Or moving the logic into SQL:
create or replace FUNCTION CALINTEREST(
DNumber IN VARCHAR2,
IRate IN NUMBER
) RETURN NUMBER
IS
p_interest NUMBER(17,8);
BEGIN
SELECT DBRD_INT_DUE
+ ( DBRD_PRI_DUE
* CASE DBRD_INT_RATE
WHEN 999 THEN IRate
ELSE DBRD_INT_RATE
END
* TRUNC( SYSDATE - DBRD_INT_DATE )
/ 365
/ 100
)
INTO p_interest
FROM DBRD
WHERE DBRNO = DNumber;
RETURN p_interest;
END;
/
SHOW ERRORS;

Resources