Delete rows in two tables - sql

I have tow tables
How to make pl/SQL procedure and then job when I delete from table1 where table1.S = Table2.Z and table1.O =90 and table2.P=90 same time to delete in table2

Create trigger for after delete event:
CREATE OR REPLACE TRIGGER trg_aftre_table1
AFTER DELETE
on table1
FOR EACH ROW
BEGIN
-- Delete from table2 when delete ant data from table1
delete from table2 where :OLD.S = Table2.Z and :OLD.O=table2.P ;
END;

That would be a trigger, not a procedure + job.
Here's an example: sample tables & trigger code, which specifies WHEN to fire:
SQL> create table t1 as
2 select 50 s, 90 o from dual union
3 select 51, 90 from dual union
4 select 50, 10 from dual;
Table created.
SQL> create table t2 as
2 select 50 z, 10 p from dual union
3 select 51, 10 from dual union
4 select 50, 90 from dual union
5 select 51, 90 from dual;
Table created.
SQL>
SQL> create or replace trigger trg_ad_t1
2 after delete on t1
3 for each row
4 when (old.o = 90)
5 begin
6 delete from t2
7 where z = :old.s
8 and p = :old.o;
9 end;
10 /
Trigger created.
OK, some deleting: first, one that won't affect TABLE 2:
SQL> delete from t1 where s = 50 and o = 10;
1 row deleted.
SQL> select * From t1;
S O
---------- ----------
50 90
51 90
SQL> select * From t2;
Z P
---------- ----------
50 10
50 90
51 10
51 90
SQL>
And now, the one that affects TABLE 2:
SQL> delete from t1 where s = 50 and o = 90;
1 row deleted.
SQL> select * From t1;
S O
---------- ----------
51 90
SQL> select * From t2;
Z P
---------- ----------
50 10
51 10
51 90
SQL>

Related

How can I select a data from another column from rows that have been selected?

I tried my best to figure and google this out, but couldn't really find a solid answer to it.
The problem I'm facing is that
Table 1:
ID Value 1
1 a
2 b
3 c
Table 2:
ID Value 2
1 4a
3 5b
4 6c
and I'd basically have to select the value from Table 1 that doesn't exist on Table 2 (Thus, 'b')
I can select and identify the ID that I want by using minus function between the tables, but can't seem to figure out a way to call a query to instead call the data.
Use the MINUS as a subquery (i.e. an inline view) (lines #14 - 16):
Sample data:
SQL> with
2 table1(id, value1) as
3 (select 1, 'a' from dual union all
4 select 2, 'b' from dual union all
5 select 3, 'c' from dual
6 ),
7 table2 (id, value2) as
8 (select 1, '4a' from dual union all
9 select 3, '5b' from dual union all
10 select 4, '6c' from dual
11 )
Query begins here:
12 select a.*
13 from table1 a
14 where a.id in (select t1.id from table1 t1
15 minus
16 select t2.id from table2 t2
17 );
ID VALUE1
---------- ----------
2 b
SQL>
Alternatively, use not exists:
<snip>
12 select a.*
13 from table1 a
14 where not exists (select null
15 from table2 b
16 where b.id = a.id
17 );
ID VALUE1
---------- ----------
2 b
SQL>

ORACLE SQL - Wildcard on rowname

I have 2 tables - Table1 and Table2.
Table1.ROrd = 00123 and Table2.Ord = 123.
I need to find all values where Table2.Ord contains part of the value in able1.ROrd.
Since I was getting invalid number error, I tried this. But this is not good enough because the values are not exact match.
select * from Table1 where to_char(ROrd) in (select to_char(Ord) from Table2)
If you perform cross join on those tables and compute some similarities or a good, old instr function's result, then you get something like this (with my sample data, of course):
SQL> with
2 tab1 (ord) as
3 (select '00123' from dual union all
4 select 'ab445' from dual union all
5 select 'xyz' from dual
6 ),
7 tab2 (ord) as
8 (select '123' from dual union all
9 select 'ab556' from dual union all
10 select 'zyx' from dual
11 )
12 select a.ord, b.ord,
13 utl_match.jaro_winkler_similarity(a.ord, b.ord) jwsim,
14 utl_match.edit_distance_similarity(a.ord, b.ord) edsim,
15 --
16 instr(a.ord, b.ord) ins
17 from tab1 a cross join tab2 b;
ORD ORD JWSIM EDSIM INS
----- ----- ---------- ---------- ----------
00123 123 0 60 3
00123 ab556 0 0 0
00123 zyx 0 0 0
ab445 123 0 0 0
ab445 ab556 78 40 0
ab445 zyx 0 0 0
xyz 123 0 0 0
xyz ab556 0 0 0
xyz zyx 55 34 0
9 rows selected.
SQL>
Now, decide which option suits you most.
INSTR is simple enough:
<snip>
17 from tab1 a cross join tab2 b
18 where instr(a.ord, b.ord) > 0;
ORD ORD JWSIM EDSIM INS
----- ----- ---------- ---------- ----------
00123 123 0 60 3
SQL>
Choose similarity level by yourself, e.g. 60, but that's probably not what you want in this case:
<snip>
17 from tab1 a cross join tab2 b
18 where utl_match.jaro_winkler_similarity(a.ord, b.ord) > 60;
ORD ORD JWSIM EDSIM INS
----- ----- ---------- ---------- ----------
ab445 ab556 78 40 0
SQL>
I guess instr produces better result (according to what you described).
Use EXISTS and LIKE to compare the two tables:
select *
from Table1 t1
where EXISTS (
SELECT 1
FROM table2 t2
WHERE t1.ROrd LIKE '%' || t2.Ord || '%'
)
or, if the values are just zero-padded then:
select *
from Table1 t1
where EXISTS (
SELECT 1
FROM table2 t2
WHERE t1.ROrd = LPAD( t2.Ord, 5, '0' )
)

Oracle: Check for existence and map a new column

Would like to check the existence of an id from table_1 in table_2 and based on that trying to create a new column mapped_value.
table_2 has huge number of records with duplicate id's and also has a non-unique index on it.
SQL> drop table table_1
Table dropped.
SQL> create table table_1(id varchar2(10),value varchar2(10))
Table created.
SQL> insert into table_1
(select '100','ABC' from dual
union all
select '101','DEF' from dual
union all
select '103','GHI' from dual
)
3 rows created.
SQL> commit
Commit complete.
SQL> select * from table_1
ID VALUE
---------- ----------
100 ABC
101 DEF
103 GHI
3 rows selected.
SQL> drop table table_2
Table dropped.
SQL> create table table_2(id varchar2(10),value varchar2(10),day date)
Table created.
SQL> insert into table_2
(select '100','ABC',sysdate from dual
union all
select '100','ABC',sysdate from dual
union all
select '100','ABC',sysdate from dual
union all
select '101','DEF',sysdate from dual
union all
select '101','DEF',sysdate from dual
union all
select '101','DEF',sysdate from dual
)
6 rows created.
SQL> commit
Commit complete.
SQL> select * from table_2
ID VALUE DAY
---------- ---------- ---------
100 ABC 18-SEP-18
100 ABC 18-SEP-18
100 ABC 18-SEP-18
101 DEF 18-SEP-18
101 DEF 18-SEP-18
101 DEF 18-SEP-18
6 rows selected.
Trying below but its getting duplicate records for ids 100 and 101.
I know,shouldn't use outer join as there are duplicates.
I want to get the desired output but without duplicates by leveraging the non-unique index on table_2.
How do go about this?
SQL> select t1.*,case when t2.id is null then '***EMPTY****' else t2.id end as mapped_value
from table_1 t1,table_2 t2
where t1.id = t2.id(+)
ID VALUE MAPPED_VALUE
---------- ---------- ------------
100 ABC 100
100 ABC 100
100 ABC 100
101 DEF 101
101 DEF 101
101 DEF 101
103 GHI ***EMPTY****
7 rows selected.
If I understand that correctly, an EXISTS in a CASE might be what you're after.
SELECT t1.id,
t1.value,
CASE
WHEN EXISTS (SELECT *
FROM table_2 t2
WHERE t2.id = t1.id) THEN
t1.id
ELSE
'***EMPTY***'
END mapped_value
FROM table_1 t1;

Create procedure and update from two columns

I have two tables A and B, i wont to make update to D from A if C from A = C from B and if LB minus LA >=2 hours set D=0
MERGE might be one of your choices:
SQL> create table a (c number, d number, la date);
Table created.
SQL> create table b (c number, lb date);
Table created.
SQL> insert into a
2 (select 12345, 30, to_date('01.04.2018 20:10', 'dd.mm.yyyy hh24:mi') from dual);
1 row created.
SQL> insert into b
2 (select 12345, to_date('01.04.2018 18:00', 'dd.mm.yyyy hh24:mi') from dual);
1 row created.
SQL>
SQL> merge into a
2 using (select b.c, b.lb from b) x
3 on (a.c = x.c and
4 (a.la - x.lb) * 24 >= 2
5 )
6 when matched then
7 update set a.d = 0;
1 row merged.
SQL>
SQL> select * From a;
C D LA
---------- ---------- ----------
12345 0 01.04.2018
Values that prevent UPDATE:
SQL> delete from a;
1 row deleted.
SQL> insert into a
2 (select 12345, 30, to_date('01.04.2018 19:10', 'dd.mm.yyyy hh24:mi') from dual);
1 row created.
SQL> merge into a
2 using (select b.c, b.lb from b) x
3 on (a.c = x.c and
4 (a.la - x.lb) * 24 >= 2
5 )
6 when matched then
7 update set a.d = 0;
0 rows merged.
SQL> select * From a;
C D LA
---------- ---------- ----------
12345 30 01.04.2018
SQL>

rows convert in oracle sql

I have values like below
1,a,b,c
2,d,e
3,f,g
Expected output
1 a
1 b
1 c
2 d
2 e
Can you please help me?
It is very much close to implementing the logic to Split comma delimited strings in a table. The only tricky thing is that you have the row number along with the string itself.
You could use ROWNUM as pseudo column, and then filter out those rows where the leading substr of the string is repeating with the ROWNUM.
For example,
Setup
SQL> CREATE TABLE t(text VARCHAR2(4000));
Table created.
SQL>
SQL> INSERT INTO t SELECT '1,a,b,c' text FROM dual;
1 row created.
SQL> INSERT INTO t SELECT '2,d,e' text FROM dual;
1 row created.
SQL> INSERT INTO t SELECT '3,f,g' text FROM dual;
1 row created.
SQL> COMMIT;
Commit complete.
SQL>
SQL> SELECT * FROM t;
TEXT
----------
1,a,b,c
2,d,e
3,f,g
SQL>
Solution:
SQL> WITH DATA AS(
2 SELECT ROWNUM rn, text FROM t
3 )
4 SELECT *
5 FROM
6 (SELECT rn,
7 trim(regexp_substr(t.text, '[^,]+', 1, lines.COLUMN_VALUE)) text
8 FROM DATA t,
9 TABLE (CAST (MULTISET
10 (SELECT LEVEL FROM dual CONNECT BY LEVEL <= regexp_count(t.text, ',')+1
11 ) AS sys.odciNumberList ) ) lines
12 )
13 WHERE TO_CHAR(rn) <> text
14 ORDER BY rn
15 /
RN TEXT
---------- ----------
1 a
1 b
1 c
2 d
2 e
3 f
3 g
7 rows selected.
SQL>