we have 2 tables employee and address_check in oracle database. we have a scenario where we need to check whether person address is not full form in address columns and we need to check another table for the abbreviation and full_forms to replace abbreviation to full_forms . we have to do this on daily basics for the new employees . So we need an update or insert statement to this copy address_l1 column value to address_l1_c with full_form .
we have to create a insert/update statement or pl sql procedure where it should check person address columns and find out if any abbreviations are present and if abbreviation are present . It should check that abbreviation present in address_check table and find its full form and get that full form and replace it in address_l1_c .
example and sample data as below:
Advertisement
Answer
This is your sample data and the way to extract the abbreviation. This option presumes that it is the last “word” (w+$
) in the address. If it is located elsewhere, you’ll get wrong result.
SQL> with test (name, address_l1) as
2 (select 'Tom', '330 Darrow Street' from dual union all
3 select 'John', '40 Pine CT' from dual union all
4 select 'Smith', '110 Varady ave' from dual
5 )
6 select t.name,
7 t.address_l1,
8 regexp_substr(t.address_l1, 'w+$') abbrev
9 from test t;
NAME ADDRESS_L1 ABBREV
----- ----------------- ----------
Tom 330 Darrow Street Street
John 40 Pine CT CT
Smith 110 Varady ave ave
SQL>
Now, join extracted abbreviation with another table to get its full form. As it is unknown whether someone will enter “CT” or “Ct” or “ct”, I used the lower
function to match those values. Outer join is used for abbreviations that don’t exist:
SQL> with
2 test (name, address_l1) as
3 (select 'Tom', '330 Darrow Street' from dual union all
4 select 'John', '40 Pine CT' from dual union all
5 select 'Smith', '110 Varady ave' from dual
6 ),
7 abbrev (abbreviation, full_Form) as
8 (select 'St', 'Street' from dual union all
9 select 'Ave', 'Avenue' from dual union all
10 select 'Dr', 'Drive' from dual union all
11 select 'Ct', 'Court' from dual
12 )
13 select t.name,
14 t.address_l1,
15 regexp_substr(t.address_l1, 'w+$') abbrev,
16 a.full_form
17 from test t left join abbrev a on
18 lower(a.abbreviation) = lower(regexp_substr(t.address_l1, 'w+$'));
NAME ADDRESS_L1 ABBREV FULL_F
----- ----------------- ---------- ------
Smith 110 Varady ave ave Avenue
John 40 Pine CT CT Court
Tom 330 Darrow Street Street
SQL>
Finally, substitute abbreviations with their full forms (see comments within the code):
SQL> with
2 test (name, address_l1) as
3 (select 'Tom', '330 Darrow Street' from dual union all
4 select 'John', '40 Pine CT' from dual union all
5 select 'Smith', '110 Varady ave' from dual
6 ),
7 abbrev (abbreviation, full_Form) as
8 (select 'St', 'Street' from dual union all
9 select 'Ave', 'Avenue' from dual union all
10 select 'Dr', 'Drive' from dual union all
11 select 'Ct', 'Court' from dual
12 )
13 select t.name,
14 t.address_l1,
15 -- abbreviation:
16 -- regexp_substr(t.address_l1, 'w+$') abbrev,
17 -- its full form:
18 -- a.full_form,
19 --
20 -- position of the last space character in address string
21 -- regexp_instr(t.address_l1, '[^ ]+', 1, regexp_count(t.address_l1, ' ') + 1) i,
22 --
23 -- concatenate the first part of the address (without the "abbreviation"
24 substr(t.address_l1,
25 1,
26 regexp_instr(t.address_l1, '[^ ]+', 1, regexp_count(t.address_l1, ' ') + 1) - 1
27 )
28 ||
29 -- with its full form if it exists. If not, use what you have
30 -- (this option covers the "Street" example in your test case)
31 nvl(a.full_form, regexp_substr(t.address_l1, 'w+$')) result
32 from test t left join abbrev a on
33 lower(a.abbreviation) = lower(regexp_substr(t.address_l1, 'w+$'));
NAME ADDRESS_L1 RESULT
----- ----------------- ---------------------------------------------------------------------------
----------
Smith 110 Varady ave 110 Varady Avenue
John 40 Pine CT 40 Pine Court
Tom 330 Darrow Street 330 Darrow Street
SQL>
This is the first part of the story. Note that it works for sample data; if it changes or doesn’t match what you posted, this code will have to be adjusted (for example, remove superfluous spaces).
As of:
we have to create a insert/update statement
- that would be a
MERGE
statement; easier to use than separateUPDATE
+INSERT
For example:
SQL> merge into test t
2 using (select t.name,
3 substr(t.address_l1,
4 1,
5 regexp_instr(t.address_l1, '[^ ]+', 1, regexp_count(t.address_l1, ' ') + 1) - 1
6 )
7 ||
8 nvl(a.full_form, regexp_substr(t.address_l1, 'w+$')) result
9 from test t left join abbrev a on
10 lower(a.abbreviation) = lower(regexp_substr(t.address_l1, 'w+$'))
11 ) x
12 on (t.name = x.name)
13 when matched then update set
14 t.result = x.result
15 when not matched then insert (name, result)
16 values (x.name, x.result);
3 rows merged.
SQL> select * From test;
NAME ADDRESS_L1 RESULT
---------- ------------------------------ ----------------------------------------
Tom 330 Darrow Street 330 Darrow Street
John 40 Pine CT 40 Pine Court
Smith 110 Varady ave 110 Varady Avenue
SQL>
we have to do this on daily basis
- use a scheduler, i.e. the
DBMS_SCHEDULER
(orDBMS_JOB
) built-in package. In order to use it, put your code into a stored procedure which will then be called by that utility.
In its simplest option, you’d put the above merge statement into a procedure as is:
create or replace procedure p_merge as
begin
merge into test
end;
/
Schedule it to run every day at noon:
SQL> declare
2 l_job number;
3 begin
4 dbms_Job.submit(l_job,
5 'p_merge;',
6 sysdate,
7 'trunc(sysdate) + 12/24'
8 );
9 commit;
10 end;
11 /
PL/SQL procedure successfully completed.
SQL>
That’s all, more or less.