

Series about loading data using SQL and LOG ERRORS continued. The more get you in the wood, the more interested is becomes : D
Loading data - SQL: is there any error? [GTT, tab]
Previously, I used the Global Temporary Table and the regular table to verify if an error occured. Today, I will use global PL/SQL variables for the same job.
Previously, I used the Global Temporary Table and the regular table to verify if an error occured. Today, I will use global PL/SQL variables for the same job.
I remind you that I use the standard HR scheme. For the purposes of the test, I create an empty myEmp table as a copy of the Employees table. Then I reduce length of the last_name column to 9 characters (there are 4 records with last_name > 9 in the employees table) to force an error. We have 107 records in the source table (in my example), of which we expect 4 errors.
1. In the package body I have declared the gnCnt variable to record the number of records. You can also declare it in the specification, if you prefer :)
2. I created the function upd_cnt (pcnt number) to update the global variable gnCnt. The function sets the variable gnCnt to the value obtained in the input parameter pnCnt.
function upd_cnt(pncnt number) return number is
begin
-- all rows counter
gnCnt := pncnt;
-- counter for test
gtest := nvl(gtest,0) + 1;
return 0;
exception when others then dbms_output.put_line(sqlerrm);
end;
3. I used INSERT ALL statement to load the data. For the first record I call the function upd_cnt with the parameter number of records. The function always returns 0 . I use it to always make a row insert.
insert all
when rownum = 1 and upd_cnt (cnt) = 0 then into myEmp (
employee_id (...)
4. I calculate the number of records in the SELECT clause of the INSERT ALL statement using the analytic function count (*) over
select rownum , count(*) over () cnt, employee_id (...)
5. The remaining lines are loaded without any weirdness.
else
into myEmp( employee_id,
6. Inserted rows:
ncnt_ins := sql%rowcount.
7. Erros = count of all rows - inserted rows
gnCnt - ncnt_ins
Of course, I use a clause
log errors reject limit unlimited
Now run:
begin
delete from myEmp;
delete from err$_myEmp;
commit;
test_log_err.gtest := 0;
end;
/
Function upd_cnt executed 1 time/s.
all rows: 107 , Inserted: 103, Errors: 4
PL/SQL procedure successfully completed.
And voila! Done! 107 all records, 103 records inserted, 4 errors.
select count(*) from Employees;
COUNT(*)
----------
107
select count(*) from myEmp;
COUNT(*)
----------
103
select count(*) from err$_myEmp
COUNT(*)
----------
4
I still need to explain the gTest variable. This variable is set in the upd_cnt function to prove that the function will run only once. PL/SQL functions in SQL are very inefficient, but one run should not have a significant impact on performance.
Code:
create or replace package test_log_err is
--gnCnt number ; -- all rows counter
gTest number; --counter forc checking how many times function is executed
function upd_cnt ( pncnt number) return number ;
procedure ins;
end;
/
-----------------------------------------------------------------------------
create or replace package body test_log_err is
gnCnt number ; -- all rows counter
-----------------------------------------------------------------------------
function upd_cnt(pncnt number) return number is
begin
-- all rows counter
gnCnt := pncnt;
-- counter for test
gtest := nvl(gtest,0) + 1;
return 0;
exception when others then dbms_output.put_line(sqlerrm);
end;
-----------------------------------------------------------------------------
procedure ins is
ncnt_ins number;
begin
insert all
when rownum = 1 and upd_cnt (cnt) = 0 then into myEmp (
employee_id,
first_name,
last_name,
email,
phone_number,
hire_date,
job_id,
salary,
commission_pct,
manager_id,
department_id) values ( employee_id,
first_name,
last_name,
email,
phone_number,
hire_date,
job_id,
salary,
commission_pct,
manager_id,
department_id)
log errors reject limit unlimited
else
into myEmp( employee_id,
first_name,
last_name,
email,
phone_number,
hire_date,
job_id,
salary,
commission_pct,
manager_id,
department_id) values ( employee_id,
first_name,
last_name,
email,
phone_number,
hire_date,
job_id,
salary,
commission_pct,
manager_id,
department_id)
log errors reject limit unlimited
select rownum , count(*) over () cnt, employee_id,
first_name,
last_name,
email,
phone_number,
hire_date,
job_id,
salary,
commission_pct,
manager_id,
department_id
from employees ;
ncnt_ins := sql%rowcount;
dbms_output.put_line('Function upd_cnt executed '|| gTest || ' time/s.');
dbms_output.put_line ('all rows: '||nvl(gnCnt,0) ||' , Inserted: ' ||ncnt_ins||', Errors: '||to_char(nvl(gnCnt,0) - ncnt_ins));
end;
end;
/
Komentarze
Prześlij komentarz