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>
Related
I have two tables in Oracle db. Table1 and table2. Both have composite primary key. Structure of the tables are same but not data.
I need to delete rows from table1 which are not in table2.
There are various options; you've already seen one in Impaler's post.
SQL> create table a (id1, id2, name) as
2 select 1, 10, 'Little' from dual union all
3 select 2, 20, 'Foot' from dual union all --> these two should be deleted
4 select 3, 30, 'Xyz' from dual; --> as (id1, id2) don't exist in table B
Table created.
SQL> create table b (id1, id2, name) as
2 select 1, 10, 'Mickey' from dual union all
3 select 4, 40, 'Mouse' from dual;
Table created.
NOT IN (the same as Impaler's, obviously):
SQL> delete from a
2 where (id1, id2) not in (select id1, id2 from b);
2 rows deleted.
SQL> select * from a;
ID1 ID2 NAME
---------- ---------- ------
1 10 Little
SQL> rollback;
Rollback complete.
NOT EXISTS:
SQL> delete from a
2 where not exists (select null from b
3 where b.id1 = a.id1
4 and b.id2 = a.id2
5 );
2 rows deleted.
SQL> select * from a;
ID1 ID2 NAME
---------- ---------- ------
1 10 Little
SQL> rollback;
Rollback complete.
IN, with the MINUS set operator:
SQL> delete from a
2 where (id1, id2) in (select id1, id2 from a
3 minus
4 select id1, id2 from b
5 );
2 rows deleted.
SQL> select * from a;
ID1 ID2 NAME
---------- ---------- ------
1 10 Little
SQL> rollback;
Rollback complete.
SQL>
You can do:
delete from t
where (a, b) not in (
select a, b from u
)
See running example at db<>fiddle.
How to print the misisng rows from a table from expected set of values.
I am expecting the values A, B, C, D, E to be in the below employee table, if any of the value is missing, how to get the misisng record.
EMP_NAME STATUS
-------- --------
A VALID
B VALID
D VALID
In the above table C & E are missing. How can I write a sql to print that C & E are missing rows from the table
For a sample table
SQL> select * from test;
EMP_NAME STATUS
---------- ------
A VALID
B VALID
C VALID
you have to know which employees are missing. I hope you have a table that contains the full list; I created a CTE that serves that purpose, having only the first 5 letters of English alphabet (I presume you used dummy names, didn't you?). Then you'd outer join it to table you already have. Something like this:
SQL> with all_emps as
2 (select chr(65 + level - 1) emp_name
3 from dual
4 connect by level <= 5
5 )
6 select a.emp_name,
7 nvl(t.status, 'Unknown') status
8 from all_emps a left join test t on t.emp_name = a.emp_name
9 order by a.emp_name;
EMP_NAME STATUS
---------- -------
A VALID
B VALID
C VALID
D Unknown
E Unknown
SQL>
As it seems that you do know which employees you have, then - by modifying above dummy query - you'd have
SQL> select * from test;
EMP_NAME STATUS
---------- ----------
CAM VALID
POOD VALID
HAM VALID
SQL> with all_emps (emp_name) as
2 (select 'CAM' from dual union all
3 select 'POOD' from dual union all
4 select 'HAM' from dual union all
5 select 'HAL' from dual union all
6 select 'NIL' from dual
7 )
8 select a.emp_name,
9 nvl(t.status, 'Unknown') status
10 from all_emps a left join test t on t.emp_name = a.emp_name
11 order by a.emp_name;
EMP_NAME STATUS
---------- ----------
CAM VALID
HAL Unknown
HAM VALID
NIL Unknown
POOD VALID
SQL>
I am trying to update a column only with the matched condition.
update table1 set col=Match
where id in(select id from
table1,table2 where table1.id=table2.id);
It says sql command not properly ended.
Here's an example which shows what to do (at least, that's what I understood, based on the question and comments you posted).
Test case first:
SQL> create table table1 (id number, criteria varchar2(10));
Table created.
SQL> create table table2 (id number);
Table created.
SQL> insert into table1 (id)
2 select 1 from dual union all
3 select 2 from dual;
2 rows created.
SQL> insert into table2 (id)
2 select 1 from dual;
1 row created.
As you can see, both tables share ID = 1 so we'd expect its table1.criteria to be modified.
Your query:
SQL> update table1 set
2 criteria = 'M1'
3 where id in (select a.id
4 from table1 a join table2 b on a.id = b.id
5 );
1 row updated.
SQL> -- Result
SQL> select * From table1;
ID CRITERIA
---------- ----------
1 M1
2
Alternatively:
SQL> update table1 a set
2 a.criteria = 'M2'
3 where exists (select null
4 from table2 b
5 where b.id = a.id
6 );
1 row updated.
SQL> select * From table1;
ID CRITERIA
---------- ----------
1 M2
2
See if it helps.
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>
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>