Issue with variables and proc oracle - oracle

Im a beginner in oracle and i need help. I want to use variables in my proc but I dont know how to do it. I want to affect a string value to a variable depending to an other variable but when i lunch my proc nothing is happened. The code is not passing through the IF statement and I dont know why.
What I tried to do :
PROCEDURE contractual_control(p_id_depot IN depot.id_depot%TYPE) IS
-- Code_out proc
v_cod_out varchar(15) := null;
-- List of CODE KO_FCT
ko_fct_01 varchar(15) := 'KO_FCT_01';
ko_fct_02 varchar(15) := 'KO_FCT_02';
ko_fct_03 varchar(15) := 'KO_FCT_03';
ko_fct_04 varchar(15) := 'KO_FCT_04';
-- List of CODE KO_TEC
ko_tec_01 varchar(15) := 'KO_TEC_01';
ko_tec_02 varchar(15) := 'KO_TEC_02';
BEGIN
-----------------------------------------------------------------------------------------------------
-- CC1 - Objets interdits avec Presse Export - JIRA 968
-----------------------------------------------------------------------------------------------------
SELECT ko_fct_04 INTO v_cod_out FROM DEPOT_IMPORT
WHERE DEPOT_IMPORT.ID_ZONE IS NOT NULL
AND DEPOT_IMPORT.TYP_ELEMENT IN ('ENCART','INCARTO','INCPLUS','OPP');
IF v_cod_out is not null THEN
insert into babas_test values ('code retours = ' || v_cod_out);
ELSE
insert into babas_test values ('Pas de code retours');
END IF;
COMMIT;
END contractual_control;

Can you check your select statement ,probably it returns more than one row.
SELECT ko_fct_04 FROM DEPOT_IMPORT
WHERE DEPOT_IMPORT.ID_ZONE IS NOT NULL
AND DEPOT_IMPORT.TYP_ELEMENT IN ('ENCART','INCARTO','INCPLUS','OPP');
also you can add exception to your procedure to see the errors.
exception when others then
DBMS_OUTPUT.put_line ('ERROR :' || SQLERRM );

Related

Insert values from a type list PLSQL ORACLE 11

thanks for helping me.
The first insert works OK but the second doesnt insert anything. Can you help me please. Im learning plsql but there is still some things i dont know.
PROCEDURE PR_INS_INVESTIGATION (
PIN_INS_INVESTIGATION IN IN_INS_INVESTIGATION)
IS
LST_INS_INVESTIGATED RC_INS_INVESTIGATED;
EX_NO_DATA EXCEPTION;
BEGIN
INSERT INTO PQR076INVESTIGATION (CCPQR076IDINVESTIGATION,
CCPQR076DATE,
CCPQR076AREA,
CCPQR076STATE,
CCPQR076USER)
VALUES (PIN_INS_INVESTIGATION.IDINVESTIGACION,
SYSDATE,
PIN_INS_INVESTIGATION.AREA,
PIN_INS_INVESTIGATION.STATE,
USER);
COMMIT;
IF LST_INS_INVESTIGATED IS NOT NULL
AND LST_INS_INVESTIGATED.COUNT > 0
THEN
FOR j IN LST_INS_INVESTIGATED.FIRST .. LST_INS_INVESTIGATED.LAST
LOOP
INSERT INTO PQR075INVESTIGATED (CCPQR075IDINVESTIGATION,
CCPQR075NIDENT,
CCPQR075NAME,
CCPQR075USER)
VALUES (PIN_INS_INVESTIGATION.IDINVESTIGAtION,
LST_INS_INVESTIGATED (J).NUMBERID,
LST_INS_INVESTIGATED (J).NAME,
USER);
COMMIT;
END LOOP;
END IF;
END;
This is the way im testing the procedure:
´´´
declare
pin_ins_investigation in_ins_investigation;
begin
pin_ins_investigation := in_ins_investigation();
pin_ins_investigation.IDinvestigation := '1234460';
pin_ins_investigation.AREA := '05';
pin_ins_investigation.STATE := 'E';
pin_ins_investigation.LST_INS_investigated.extend;
pin_ins_investigation.LST_INS_investigated(1).NUMBERID := '1014350360';
pin_ins_investigation.LST_INS_investigated(1).NAME := 'PETER TOSH';
pkg_package.pr_ins_investigation(pin_ins_investigation => pin_ins_investigation);
end;
´´´
The way I see it, this:
IF LST_INS_INVESTIGATED IS NOT NULL
AND LST_INS_INVESTIGATED.COUNT > 0
is never true so nothing within the IF - END IF block is ever executed.
You declared it as
LST_INS_INVESTIGATED RC_INS_INVESTIGATED;
but lst_ins_investigated doesn't contain anything, it is just declared, never populated with any values. Once you fix that, code might work.

WHEN-BUTTON-PRESSED trigger raise unhendled exception ORA-01407

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.

How to skip insert to an Oracle table in procedure where specified columns going to insert are null

I'm inserting lots of rows into a table and some of the columns are blank for some of the rows.
How can I skip insert if some important fields are blank?
for example there is a table 'people' and my important fields are name,cityName and age.
1 INSERT INTO people VALUES('customerid1','name', 'cityName', 50, 'anotherValue')
2 INSERT INTO people VALUES('customerid2','', '', '' , 'anotherValue')
3 INSERT INTO people VALUES('customerid3','name', 'cityName', 20, 'anotherValue')
4 INSERT INTO people VALUES('customerid4','name', 'cityName', 19, 'anotherValue')
here 2nd row name,cityName and age are blank.
if those three fields are blank then dont insert that row.this is just an example i have more fields to check so need to avoid 'if condition' to check blank or not.
another example
FUNCTION TEST_FUN (increment_i in VARCHAR2, increment_j IN VARCHAR2,mod_id IN VARCHAR2 )
RETURN numeric IS
j_val VARCHAR2(100);
i_val VARCHAR2(100);
BEGIN
i_val := increment_i;
j_val := increment_j;
IF mod_id != 'loop' THEN
j_val := i_val;
END IF;
INSERT
INTO TEST.testpartytable
(
reffer_id,
customer_id,
customer_joint,
fullname,
nature,
counter_bus,
country,
status
)
VALUES
(
REFFER_ID_AR,
CUSTOMER_ID_ARR(i_val),
CUSTOMER_JOINT,
LEGALNAME_KBC_ARR(i_val),
NATURERE_KBC_ARR(j_val),
COUNTERBUSACT_KBC_ARR(j_val),
COUNTRY_KBC_ARR(j_val),
STATUS
);
return i_val;
END TEST_FUN ;
skip insert if 'fullname,nature,counter_bus,country' fields are blank .Datas coming from colletion.
Any help is appreciated.
Thanks!
well you can check first if the values are null or not null:
declare CHECK_VAL varchar2(100);
BEGIN
select CUSTOMER_ID_ARR(i_val) into CHECK_VAL from dual;
if(i_val is not null) then
insert...
end if;
END;
You can alternavely make the column to not null, and raise exeception when you get error for a value not null.
You can apply a NOT NULL constraint to your important columns so that when any of them assigned with a NULL value an error will be raised, specifically ORA -1400 (cannot insert null) exception. You can then catch this exception in your program and just do nothing when this exception is raised.
Sample below,
CREATE TABLE TEST_TABLE
(col1 NUMBER NOT NULL, col2 NUMBER NOT NULL);
DECLARE
CANNOT_INSERT_NULL EXCEPTION;
PRAGMA EXCEPTION_INIT(cannot_insert_null, -1400);
num NUMBER;
BEGIN
FOR i IN 1..10 LOOP
num := 2;
IF i BETWEEN 3 AND 5 THEN
num := NULL; //since this is null, insert statement below will error and handled and won't be inserted
END IF;
BEGIN
INSERt INTO test_table
(col1,col2)
VALUES
(i, num);
EXCEPTION
WHEN CANNOT_INSERT_NULL THEN
NULL;
END;
END LOOP;
END;
/
SELECT *
FROM test_table;

Oracle 12c: How to resolve a bad bind variable error?

I have this table named, MOTOR_PRODUCTS, where it needs to store an image. I have written a PL/SQL code and when I already compile it, an error appears that says 'bad bind variable 'MOTOR_PRODUCTS.motor_image'. How to resolve this kind of error? Thank you to people who will help me.
Here with my PL/SQL code:
Declare A number;
Begin
IF
:MOTOR_PRODUCTS.MOTOR_ID IS NULL OR
:MOTOR_PRODUCTS.CATEGORY_ID IS NULL OR
:MOTOR_PRODUCTS.MOTOR_NAME IS NULL OR
:MOTOR_PRODUCTS.MOTOR_YEAR IS NULL OR
:MOTOR_PRODUCTS.MOTOR_COLOR IS NULL OR
:MOTOR_PRODUCTS.MOTOR_PRICE IS NULL OR
:MOTOR_PRODUCTS.MOTOR_WARRANTY_PERIOD IS NULL OR
:MOTOR_PRODUCTS.MOTOR_DESCRIPTION IS NULL
THEN A:= SHOW_ALERT ('ALERT_FILLUP');
ELSE
INSERT INTO MOTOR_PRODUCTS (motor_id, motor_name, category_id, motor_year, motor_color, motor_price, motor_description, motor_features, motor_warranty_period, motor_specifications, motor_image)
VALUES (:MOTOR_PRODUCTS.category_id||:MOTOR_PRODUCTS.motor_id,
:MOTOR_PRODUCTS.motor_name,
:MOTOR_PRODUCTS.category_id,
:MOTOR_PRODUCTS.motor_year,
:MOTOR_PRODUCTS.motor_color,
:MOTOR_PRODUCTS.motor_price,
:MOTOR_PRODUCTS.motor_description,
:MOTOR_PRODUCTS.motor_features,
:MOTOR_PRODUCTS.motor_warranty_period,
:MOTOR_PRODUCTS.motor_specifications,
:MOTOR_PRODUCTS.motor_image);
FORMS_DDL('COMMIT');
A := SHOW_ALERT('ALERT_SAVE');
END IF;
End;

Can I see the DML inside an Oracle trigger?

Is it possible to see the DML (SQL Statement) that is being run that caused a trigger to be executed?
For example, inside an INSERT trigger I would like to get this:
"insert into myTable (name) values ('Fred')"
I read about ora_sql_txt(sql_text) in articles such as this but couldn't get it working - not sure if that is even leading me down the right path?
We are using Oracle 10.
Thank you in advance.
=========================
[EDITED] MORE DETAIL: We have the need to replicate an existing database (DB1) into a classified database (DB2) that is not accessible via the network. I need to keep these databases in sync. This is a one-way sync from (DB1) to (DB2), since (DB2) will contain additional tables and data that is not contained in the (DB1) system.
I have to determine a way to sync these databases without bringing them down (say, for a backup and restore) because it needs to stay live. So I thought that if I can store the actual DML being run (when data changes), I could "play-back" the DML on the new database to update it, just like someone was hand-entering it back in.
I can't bring over all the data because of the sheer size of it, and I can't just copy over the changed records because of FK constraints and the order in which I insert/update records. I figured that if I could "play-back" a log of what happened, using the exact SQL that changed the master, I could keep the databases in sync.
My current plan of attack was to keep a log of all records that were changed, inserted, and deleted and when I want to sync, the system generates DML to insert/update/delete those records. Then I just take the .SQL file to the classified system and run the script. The problem I'm running into are FKs. (Because when I generate the DML I only know what the current state of the data is, not it's path to get there - so ordering of statements is an issue). I guess I could disable all FK's, do the merge, then re-enable all FK's...
So - does my approach of storing the actual DML as-it-happens suck pondwater, or is there a better solution???
"does my approach of storing the actual DML as-it-happens suck pondwater?" Yes..
Strict ordering of the DML on your DB1 does not really exist. Multiple processes, muiltiple cores, things essentially happening at the essentially the same time.
And the DML, even when it happens sequentially doesn't act like it. Say the following two update statements run in seperate processes with seperate transactions, where the update in transaction 2 starts before transaction 1 commits:
update table_a set col_a = 10 where col_b = 'A' -- transaction 1
update table_a set col_c = 'Error' where col_a = 10 -- transaction 2
Since the changes made in the first transaction are not visibible to the second transaction, the rows changed by the second transaction will not include those of the first. But if you manage to capture the DML and replay it sequentially, transaction 1's changes will be visible, so transaction 2's changes will be different. (See pages 40 and 41 of Tom Kyte's Expert Oracle Database Architecture Second Edition.)
Hopefully you are using bind variables, so the DML by itself wouldn't be meaningful: update table_a set col_a = :col_a where id = :id Now what? Ok, so you want the DML with it's variable bindings.
Do you use sequences? If so, the next_val will not stay in synch between DB1 and DB2. (For example, instance failures can cause lost values, are both systems going to fail at the same time?) And if you are dealing with RAC, where the next_val varies depending on node, forget it.
I would start by investigating Oracle's replication.
I had a situation where I needed to move metadata/configuration changes (stored in a handful of tables) from a development environment to a production environment once tested. Something like Goldengate is the product to use for this but this can be costly and complicated to set up and administer.
The following procedure generates a trigger and attaches it to a table that needs the DML saved. The trigger re-creates the DML and in the following case saves it to an audit table - its up to you what you do with it. You can use the statements saved to the audit table to replay changes from a given point in time (cut and paste or develop a procedure to apply them to the target).
Hope you find this useful.
procedure gen_trigger( p_tname in varchar2 )
is
l_theCursor integer default dbms_sql.open_cursor;
l_query varchar2(1000) default 'select * from ' || p_tname;
l_colCnt number := 0;
l_descTbl dbms_sql.desc_tab;
trg varchar(32767) := null;
expr varchar(32767) := null;
cmd varchar(32767) := null;
begin
dbms_sql.parse( l_theCursor, l_query, dbms_sql.native );
dbms_sql.describe_columns( l_theCursor, l_colCnt, l_descTbl );
trg := q'#
create or replace trigger <%TABLE_NAME%>_audit
after insert or update or delete on <%TABLE_NAME%> for each row
declare
qs varchar2(20) := q'[q'^]';
qe varchar2(20) := q'[^']';
command clob;
nlsd varchar2(100);
begin
select value into nlsd from nls_session_parameters where parameter = 'NLS_DATE_FORMAT';
execute immediate 'alter session set nls_date_format = ''YYYY/MM/DD hh24:mi:ss'' ';
if inserting then
command := <%INSERT_COMMAND%>;
end if;
if updating then
command := <%UPDATE_COMMAND%>;
end if;
if deleting then
command := <%DELETE_COMMAND%>;
end if;
insert into x_audit values (systimestamp, command);
execute immediate q'+alter session set nls_date_format = '+'|| nlsd || q'+'+';
end;
#';
-- Create the insert command
cmd := q'#'insert into <%TABLE_NAME%> (<%INSERT_COLS%>) values ('||<%INSERT_VAL%>||')'#';
-- columns clause
for i in 1 .. l_colCnt loop
if expr is not null then
expr := expr || ',';
end if;
expr := expr || l_descTbl(i).col_name;
end loop;
cmd := replace(cmd,'<%INSERT_COLS%>',expr);
-- values clause
expr := null;
for i in 1 .. l_colCnt loop
if expr is not null then
expr := expr || q'#||','||#';
end if;
expr := expr || 'qs||:new.' || l_descTbl(i).col_name || '||qe';
end loop;
cmd := replace(cmd,'<%INSERT_VAL%>',expr);
trg := replace(trg,'<%INSERT_COMMAND%>',cmd);
-- create the update command
-- set clause
expr := null;
cmd := q'#'update <%TABLE_NAME%> set '||<%UPDATE_COLS%>||' where '||<%WHERE_CLAUSE%>#';
for i in 1 .. l_colCnt loop
if expr is not null then
expr := expr || q'#||','||#';
end if;
expr := expr || q'#'#' || l_descTbl(i).col_name || q'# = '||#'|| 'qs||:new.'||l_descTbl(i).col_name || '||qe';
end loop;
null;
cmd := replace(cmd,'<%UPDATE_COLS%>',expr);
trg := replace(trg,'<%UPDATE_COMMAND%>',cmd);
-- create the delete command
expr := null;
cmd := q'#'delete <%TABLE_NAME%> where '||<%WHERE_CLAUSE%>#';
trg := replace(trg,'<%DELETE_COMMAND%>',cmd);
-- where clause using primary key columns (used by update and delete)
expr := null;
for pk in (SELECT column_name FROM all_cons_columns WHERE constraint_name = (
SELECT constraint_name FROM user_constraints
WHERE UPPER(table_name) = UPPER(p_tname) AND CONSTRAINT_TYPE = 'P'
)) loop
if expr is not null then
expr := expr || q'#|| ' and '||#';
end if;
expr := expr || q'#'#' || pk.column_name || q'# = '||#'|| 'qs||:old.'|| pk.column_name || '||qe';
end loop;
if expr is null then -- must have a primary key
raise_application_error(-20000,'The table must have a primary key defined');
end if;
trg := replace(trg,'<%WHERE_CLAUSE%>',expr);
trg := replace(trg,'<%TABLE_NAME%>',p_tname);
execute immediate trg;
null;
exception
when others then
execute immediate 'alter session set nls_date_format=''YYYY/MM/DD'' ';
raise;
end;
/* Example
create table t1 (
col1 varchar2(100),
col2 number,
col3 date,
constraint pk_t1 primary key (col1)
)
/
BEGIN
GEN_TRIGGER('T1');
END;
/
-- Trigger generated ....
create or replace trigger t1_audit after
insert or
update or
delete on t1 for each row
declare
qs varchar2(20) := q'[q'^]';
qe varchar2(20) := q'[^']';
command clob;
nlsd varchar2(100);
begin
select value into nlsd from nls_session_parameters where parameter = 'NLS_DATE_FORMAT';
execute immediate 'alter session set nls_date_format = ''YYYY/MM/DD hh24:mi:ss'' ';
if inserting then
command := 'insert into T1 (COL1,COL2,COL3) values ('||qs||:new.col1||qe||','||qs||:new.col2||qe||','||qs||:new.col3||qe||')';
end if;
if updating then
command := 'update T1 set '||'COL1 = '||qs||:new.col1||qe||','||'COL2 = '||qs||:new.col2||qe||','||'COL3 = '||qs||:new.col3||qe||' where '||'COL1 = '||qs||:old.col1||qe;
end if;
if deleting then
command := 'delete T1 where '||'COL1 = '||qs||:old.col1||qe;
end if;
insert into x_audit values
(systimestamp, command
);
execute immediate q'+alter session set nls_date_format = '+'|| nlsd || q'+'+';
end;
*/
That function only works for 'event' triggers as discussed here.
You should look into Fine-Grained Auditing as a mechanism for this. Details here
When the trigger code runs don't you already know the dml that caused it to run?
CREATE OR REPLACE TRIGGER Print_salary_changes
BEFORE INSERT OR UPDATE ON Emp_tab
FOR EACH ROW
...
In this case it must have been an insert or an update statement on the emp_tab table.
To find out if it was an update or an insert
if inserting then
...
elsif updating then
...
end if;
The exact column values are available in the :old and :new pseudo-columns.

Resources