I am new in PL SQL and I am trying to resolve problem with copy-past data from .CVS file to database
I create a small application which will take data from .CVS and past it to database.
I create a method, but after I compile it's writtend Successfully compiled
But when I run form I get error
WHEN-BUTTON-PRESSED trigger raise unhendled exception ORA-01407
Does anyone know what this means since I google it and could not find anything ?
I would be very thankfull
declare
import_file text_io.file_type;
import_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(5000);
p_rbr varchar2(4);
p_polica varchar2(20);
p_banka varchar2 (20);
p_kontakt varchar2(20);
kraj_fajla number;
begin
import_file_name := :Global.Lokacija_prenosa||:import.naziv_fajla||:Global.Ekstenzija_prenosa;
import_file := text_io.fopen(import_file_name,'r');
--p_rbr := 100000;
delete from zivot_trajni_nalog_ponude where banka is not null;
commit;
kraj_fajla := 0;
while kraj_fajla = 0 loop
begin
text_io.get_line(import_file, linebuf);
if brojac_redova>=2 then
if length(linebuf)>100 then
p_rbr:=substr(linebuf, 1, instr(linebuf,';',1,1)-1);
p_polica:=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);
p_kontakt:=substr(linebuf, instr(linebuf,';',1,3)+1, instr(linebuf,';',1,4) - instr(linebuf,';',1,3)-1);
select count(*)
into vec_importovano
from ZIVOT_TRAJNI_NALOG_PONUDE
where broj_police=p_polica and p_rbr=redni_broj;
if vec_importovano=0 then
insert into ZIVOT_TRAJNI_NALOG_PONUDE values(p_rbr, p_polica, p_banka, p_kontakt);
commit;
end if;
end if;
end if;
EXCEPTION WHEN NO_DATA_FOUND THEN kraj_fajla := 1;
end;
end loop;
update zivot_trajni_nalog_ponude set redni_broj = p_rbr;
commit;
text_io.fclose(import_file);
message('Zavrseno prepisivanje fajla');
end;
The error you got (ORA-01407) means that you are trying to update a column (which is set to NOT NULL) with a NULL value. That won't work. For example:
SQL> create table test (id number not null);
Table created.
SQL> insert into test (id) values (100);
1 row created.
SQL> update test set id = null;
update test set id = null
*
ERROR at line 1:
ORA-01407: cannot update ("SCOTT"."TEST"."ID") to NULL
SQL>
The only UPDATE in your code is this:
UPDATE zivot_trajni_nalog_ponude SET redni_broj = p_rbr;
Apparently, p_rbr is NULL, redni_broj won't accept it and you got the error.
What to do? Debug your code and see why p_rbr doesn't have a value. A simple "solution" might be
IF p_rbr IS NOT NULL
THEN
UPDATE zivot_trajni_nalog_ponude
SET redni_broj = p_rbr;
END IF;
Also, although not related to your problem: don't COMMIT within a loop.
ORA-01407 occurs as you are trying to update/Insert a column to NULL
when the column does not accept NULL values.
To find all the "not null" columns in table ZIVOT_TRAJNI_NALOG_PONUDE, Please check the DDL of the table.
Related
How do I record the oracle error in a pl/sql script? I have been to the oracle error handling documentation and I see the built in exceptions, but what if I do not know what the exception is? How can I log this in an exception block?
I want to do something like the below.
exception
when others then DBMS_OUTPUT.PUT_LINE(the error)
It's easier to create error logging database trigger with conditional logging, for example my actual error_logging trigger: https://github.com/xtender/xt_scripts/blob/master/error_logging/on_database.sql
create table ERROR_LOG
(
id NUMBER,
username VARCHAR2(30),
errcode INTEGER,
seq INTEGER,
tmstmp TIMESTAMP(6),
msg VARCHAR2(4000),
sql_text CLOB
)
/
create sequence err_seq
/
create or replace trigger trg_error_logging
after servererror
on database
disable
declare
v_id number := err_seq.nextval();
v_tmstmp timestamp:= systimestamp;
n int;
sql_text dbms_standard.ora_name_list_t;
v_sql_text clob;
begin
-- only if plsql_debug is set to TRUE:
for r in (select * from v$parameter p where p.name='plsql_debug' and upper(p.value)='TRUE') loop
v_sql_text:=null;
n := ora_sql_txt(sql_text);
for i in 1..n loop
v_sql_text := v_sql_text || sql_text(i);
end loop;
for i in 1.. ora_server_error_depth
loop
if i=1 then
insert into error_log(id,seq,tmstmp,username,errcode,msg,sql_text)
values( v_id, i, v_tmstmp, user, ora_server_error(i), ora_server_error_msg(i), v_sql_text);
else
insert into error_log(id,seq,tmstmp,username,errcode,msg)
values( v_id, i, v_tmstmp, user, ora_server_error(i), ora_server_error_msg(i) );
end if;
end loop;
commit;
end loop;
END;
/
select object_name,object_type,status from user_objects o where object_name='TRG_ERROR_LOGGING'
/
alter trigger trg_error_logging enable
/
As you can see it logs all errors into the table ERROR_LOG, but only if session parameter plsql_debug is set to true. Obviously, you can change it to own parameters or conditions.
I'm trying to create a stored procedure in Oracle that has one input parameter and one output variable and, in case of results, return a dataset to my .Net Application. The main issue is that I can't change the signature of the procedure and need to do if condition to validate if exist records or not.
The main issue that i've being struggled is with cursors (to execute and return the information), and to count the results of the select.
Here is an example of what i'm doing to try to retrieve the data.
CREATE PROCEDURE SP_Testing (v_input IN VARCHAR2(50), v_OutID NUMBER(1))
AS
TYPE v_record_botoes IS RECORD (
v_dummy_col1 VARCHAR2(50),
v_dummy_col2 VARCHAR2(250)
);
TYPE table_botoes IS TABLE OF v_record_botoes;
tt_botoes table_botoes;
v_ref_cursor SYS_REFCURSOR;
CURSOR v_cursor IS
(SELECT dt.v_dummy_col1,
dt.v_dummy_col2
FROM dummy_table dt
WHERE v_dummy_col3 = v_input);
v_check NUMBER;
BEGIN
tt_botoes := table_botoes();
v_check := 0;
FOR v_row IN v_cursor
LOOP
tt_botoes.extend;
tt_botoes(tt_botoes.COUNT) := v_row;
END LOOP;
v_check := tt_botoes.COUNT;
-- condition that need to know the nr of records of the select
IF v_check = 0 THEN
v_OutID := 0;
ELSE
v_OutID := 1;
OPEN v_ref_cursor FOR
SELECT *
FROM tt_botoes; -- also tryed "FROM TABLE (tt_botoes)" and "FROM TABLE (cast(tt_botoes AS table_botoes))"
-- return dataset to .net application
DBMS_SQL.RETURN_RESULT(v_ref_cursor)
END IF;
END;
Already tryed to convert the v_cursor into a sys_refcursor to be outputed by the DBMS_SQL package but didn't get anywhere.
Also i've tried to create a temporary table to hold the information, but then have a concurrency issue.
Any idea what i'm doing wrong, or any other possible solution to solve this issue?
Thanks in advance
Completely untested because I do not have the environment to test it but I would structure this quite differently, see below (I am assuming that the missing out in the specification is just a typo)
CREATE PROCEDURE SP_Testing (v_input IN VARCHAR2(50), v_OutID **out** NUMBER(1))
AS
v_ref_cursor SYS_REFCURSOR;
v_check NUMBER;
BEGIN
select count(1)
into v_check
from dummy_table dt
WHERE v_dummy_col3 = v_input
-- condition that need to know the nr of records of the select
IF v_check = 0 THEN
v_OutID := 0;
ELSE
v_OutID := 1;
OPEN v_ref_cursor FOR
SELECT dt.v_dummy_col1,
dt.v_dummy_col2
FROM dummy_table dt
WHERE v_dummy_col3 = v_input
-- return dataset to .net application
DBMS_SQL.RETURN_RESULT(v_ref_cursor)
END IF;
END;
I am receiving the following error when trying to compile and execute. I am having issues how to figure this out.
14/7 PL/SQL: Statement ignored
14/10 PLS-00204: function or pseudo-column 'EXISTS' may be used inside a SQL statement only
Errors: check compiler log
CREATE OR REPLACE PROCEDURE AddAgent(
p_Agent_Fname IN Agent.Agent_Fname%TYPE,
p_Agent_Lname IN Agent.Agent_Lname%TYPE,
p_Agent_Address IN Agent.Agent_Address%TYPE,
p_Agent_Tsales IN Agent.Agent_Tsales%TYPE,
p_Agent_Salary IN Agent.Agent_Salary%TYPE)
IS
p_ErrorCode number; --USED FOR ERROR CHECKING
p_ErrorMsg Varchar2(200);
p_CurrentUser Varchar2(100);
BEGIN
IF EXISTS
(SELECT * FROM Agent WHERE Agent_Lname = p_Agent_Lname) THEN
dbms_output.put_line('Failure');
ELSE
INSERT INTO Agent (Agent_Fname, Agent_Lname, Agent_Address, Agent_Tsales, Agent_Salary)
SELECT p_Agent_Fname, p_Agent_Lname, p_Agent_Address, 0, p_Agent_Salary
from Dual;
COMMIT;
dbms_output.put_line('Success');
END IF;
END;
As you were told, you can't use EXISTS out of the SELECT statement. Therefore, you'll have to check for existence in the AGENT table elsewhere.
Here's one option you might consider. Note that I've also rewritten the INSERT INTO statement - there's no need to SELECT FROM DUAL, you already have all those values.
CREATE OR REPLACE PROCEDURE AddAgent(
p_Agent_Fname IN Agent.Agent_Fname%TYPE,
p_Agent_Lname IN Agent.Agent_Lname%TYPE,
p_Agent_Address IN Agent.Agent_Address%TYPE,
p_Agent_Tsales IN Agent.Agent_Tsales%TYPE,
p_Agent_Salary IN Agent.Agent_Salary%TYPE)
IS
p_ErrorCode number; --USED FOR ERROR CHECKING
p_ErrorMsg Varchar2(200);
p_CurrentUser Varchar2(100);
l_cnt number; --> newly added
BEGIN
-- check whether something exists in a table
select count(*)
into l_cnt
from dual
where exists (select null
from agent
where agent_lname = p_agent_lname
);
IF l_cnt > 0 then
dbms_output.put_line('Failure');
ELSE
INSERT INTO Agent
(Agent_Fname, Agent_Lname, Agent_Address, Agent_Tsales, Agent_Salary)
VALUES
(p_Agent_Fname, p_Agent_Lname, p_Agent_Address, 0, p_Agent_Salary);
COMMIT;
dbms_output.put_line('Success');
END IF;
END;
/
I have an update trigger on my oracle table..but seems like it's not working..Schema under which triggers and table created is HR
CREATE OR REPLACE Trigger TR_FinlStatAssetDesignation_U
BEFORE update
on FINLSTATASSETDESIGNATION FOR EACH ROW
DECLARE
v_AtDateTime TIMESTAMP(3);
v_LogOperation NUMBER(3,0);
v_UserName VARCHAR2(255);
v_AppName VARCHAR2(255);
SWV_error NUMBER(10,0) DEFAULT 0;
BEGIN
begin
select USERNAME INTO v_UserName FROM v$session WHERE (audsid = SYS_CONTEXT('userenv','sessionid')) AND ROWNUM <=1;
EXCEPTION
WHEN NO_DATA_FOUND THEN
NULL;
end;
SELECT program INTO v_AppName FROM v$session WHERE audsid=userenv('sessionid');
if (LENGTH(v_AppName) = 0) then
v_AppName := 'Unknown';
end if;
SELECT SYSTIMESTAMP INTO v_AtDateTime FROM dual;
if UPDATING('FinlStatAssetDesignation') then
RAISE_APPLICATION_ERROR(-20000,'Invalid attempt to update OID FinlStatAssetDesignation in FinlStatAssetDesignation');
/*
ROLLBACK */
return;
end if;
if not UPDATING('UpdDate') then
SWV_error := 0;
begin
UPDATE FinlStatAssetDesignation a SET(UpdDate) =(SELECT distinct v_AtDateTime FROM dual where a.FinlStatAssetDesignation = :NEW.FinlStatAssetDesignation)
WHERE ROWID IN(SELECT a.ROWID FROM FinlStatAssetDesignation a where a.FinlStatAssetDesignation = :NEW.FinlStatAssetDesignation);
EXCEPTION
WHEN OTHERS THEN
SWV_error := SQLCODE;
end;
if SWV_error <> 0 then
/*
ROLLBACK */
return;
In this trigger.. second part i.e below is not working of trigger..please help....it is not updating the timestamp in upddate column
SQL> select * from finlstatassetdesignation;
FINLSTATAS FINLSTATASSETDESIGNATIONDESC UPDOPERATION
---------- -------------------------------------------------- ------------
UPDDATE
---------------------------------------------------------------------------
one19 anyt 0
hinh
01-JAN-17 08.00.00.000000 AM
SQL> update finlstatassetdesignation set finlstatassetdesignationdesc ='nothing';
1 row updated.
SQL> select * From finlstatassetdesignation;
FINLSTATAS FINLSTATASSETDESIGNATIONDESC UPDOPERATION
---------- -------------------------------------------------- ------------
UPDDATE
---------------------------------------------------------------------------
one19 nothing 0
01-JAN-17 08.00.00.000000 AM
What are you trying to accomplish in the ON INSERT trigger? From your comment of
I still can insert a row as user "hello"..hence trigger is not working..
you seem to want to prevent a user named HELLO from being added - but in your trigger code if a username of HELLO is found you simply return from the trigger. That doesn't accomplish anything. To signal to the system that you don't want the INSERT to proceed you must raise an exception in your trigger. For example:
CREATE OR REPLACE Trigger TR_FinlStatAssetDesignation_I
BEFORE Insert on FINLSTATASSETDESIGNATION
BEGIN
if USER = 'HELLO' or USER = 'SYSTEM' then
RAISE_APPLICATION_ERROR(-20000, 'Invalid user in TR_FinlStatAssetDesignation_I');
end if;
END TR_FinlStatAssetDesignation_I;
Raising an exception in this manner will prevent the INSERT from proceeding to successful completion. Your code is responsible for providing an appropriate error handler.
Best of luck.
Hi im setting up some triggers and i cant get past this error
SET SERVEROUTPUT ON
CREATE OR REPLACE TRIGGER trigger2
BEFORE INSERT ON new_donation
FOR EACH ROW
--WHEN (new.contamt <= 10)
DECLARE
v_idno VARCHAR2(5);
v_driveno VARCHAR2(3);
v_contdate DATE;
v_contamt NUMBER(6,2);
BEGIN
SELECT IDNO, DRIVENO, CONTDATE, CONTAMT INTO v_idno, v_driveno, v_contdate, v_contamt
FROM OLD_DONATION2
WHERE IDNO = :new.idno;
IF :new.contamt < 50 THEN
RAISE_APPLICATION_ERROR (-20001, 'CONTRIBUTION TOO LOW FOR '
|| :new.idno || ' ' || :new.contamt);
END IF;
END;
/
SET SERVEROUTPUT OFF
another part
DECLARE
v_idno new_donation.idno%TYPE := '&in_idno';
v_driveno new_donation.driveno%TYPE := '&in_driveno';
v_contdate new_donation.contdate%TYPE := '&in_contdate';
v_contamt new_donation.contamt%TYPE := &in_contamt;
BEGIN
INSERT INTO new_donation
VALUES (v_idno, v_driveno, v_contdate, v_contamt);
END;
/
Im getting this error when I insert values at trigger2.
ERROR at line 1: ORA-04098: trigger 'XXXXXXXXX.NEW_DONATION' is
invalid and failed re-validation ORA-06512: at line 7
All im trying to do is insert some values input by the user to this new table, which is empty.
Also when donation amount is < 10 I want a error out.
Follow these steps.
Run this query select status from all_objects where object_name = 'TBL_USER_TRIGGER' and object_type = 'TRIGGER';
If the status is invalid run alter trigger trigger2 compile;
Then run show errors
It will throw the errors for you. You need to fix those.