Oracle update query with select - oracle

I have two tables with same columns. i want to update table1 records whose status is 'Linked' by the corresponding values from table2.
table 1
ID STATUS VOUCHER
'T010000020 Not Linked null
'T010000021 Linked null
'T010000024 Not Linked null
'T010000026 Linked null
table 2
ID STATUS VOUCHER
'T010000020 Not Linked null
'T010000021 Linked 11234
'T010000024 Not Linked null
'T010000026 Linked 5423

UPDATE Table1 t1
SET Voucher = (SELECT Voucher FROM
Table2 t2 WHERE t2.Id = t1.Id
and t2.Status = 'Linked')
WHERE Status = 'Linked'

Related

oracle conditional query for a single select statement in a pl/sql block

select case when (select LOAN_AMNT from table1 where name = 215) is null or LOAN_AMNT = '0.0'
then select REQUESTED_LOAN_AMOUNT from table2 where name = 215
else select LOAN_AMNT from table1 where wi_name = 215 end as LOAN_AMNT123
there are two tables, table1 and table2. Both the tables contains an entry of name = 215(unique). I wanna store loan amount into LOAN_AMNT123 from table1 if and only if the loan amount present in table 1 is not null or is not equals to zero else i wanna fetch REQUESTED_LOAN_AMOUNT from table 2 into LOAN_AMNT123.
I wanna perform this operation in a single query in my oracle pl/sql block. The query i created is not right, please help me create one such query.
You can use the inner join and case when as follows:
SELECT
CASE
WHEN t1.loan_amt IS NULL
OR t1.loan_amt = 0 THEN
t2.requested_loan_amount
ELSE
t1.loan_amnt
END AS loan_amnt123
FROM
table1 t1
JOIN table2 t2 ON t1.wi_name = t2.name
WHERE
t1.wi_name = 215

ORACLE Query to find value in other table based on dates

I have two tables, Table A has an ID and an Event Date and Table B has an ID, a Description and an Event Date.
Not all IDs in Table A appear in Table B and some IDs appear multiple times in Table B with different Descriptions for each event.
The Description in Table B is an attribute that can change over time, the Event date in Table B is the date that a given ID's Description changes from its default value (kept in another table) to the new value.
I want to find the Description in Table B that matches the Event Date in Table A so, for example
Table Sample Data
A1234 would return Green and A4567 would return Null
I can't create tables here so I need to be able to this with a query.
This query will select last description from before the event:
SELECT * FROM (
SELECT tabA.id, tabA.event_date, tabB.description,
ROW_NUMBER() OVER(PARTITION BY tabB.id ORDER BY tabB.event_date DESC) rn
FROM Table_A tabA
LEFT JOIN Table_B tabB ON tabA.id = tabB.id AND tabB.event_date <= tabA.event_date
) WHERE rn = 1
If I understand well your need, this could be a way:
select a.id, description
from tableA A
left join
(select id,
description,
event_date from_date,
lead(event_date) over (partition by id order by event_date) -1 as to_date
from tableB
) B
on (A.id = B.id and a.event_date between b.from_date and b.to_date)
The idea here is to evaluate, for each row in tableB the range of dates for which that row, and its description, is valid; given this, a simple join should do the job.
You can left join tables like:
select a.ID , b1.DESCRIPTION
from TABLE_A a
left join TABLE_B b1 on a.ID = b1.id and a.EVENT_DATE > b1.EVENT_DATE
left join TABLE_B b2 on a.ID = b2.id and b1.EVENT_DATE < b2.EVENT_DATE and a.EVENT_DATE > b2.EVENT_DATE
where b1.id is null or b2.EVENT_DATE is null;

Oracle - Update rows with a min value in the group of a column from another table

I am facing this scenario: Table Employee has joining_date column. Table Booking has booking_date column and a foreign key (employee_id) to Employee. Employee has some NULL values in its joining_date column. I want to fill them with the FIRST booking_date value of those employees. How can I do?
FYI:
I can query with complex join statements to extract the first booking_date of employees whose joining_date is NULL as below:
SELECT emp.employee_id, emp.joining_date, temp2.booking_date FROM employee emp
LEFT JOIN (SELECT bo.employee_id, bo.booking_date FROM booking bo
INNER JOIN (SELECT employee_id, MIN(booking_date) mindate FROM booking GROUP BY employee_id) temp1
ON bo.employee_id = temp1.employee_id AND bo.booking_date = temp1.mindate) temp2
ON emp.employee_id = temp2.employee_id
WHERE emp.joining_date IS NULL;
But I'm struggling with putting this complex select into the update statement:
UPDATE employee emp
SET emp.joining_date = (SELECT ...)
WHERE emp.joining_date IS NULL;
Your select statement is more complex than it needs to be, you will get the same set this way:
SELECT emp.employee_id,min(bo.booking_date) booking_date
FROM employee emp
LEFT JOIN booking bo
ON bo.employee_id = emp.employee_id
WHERE emp.joining_date is NULL
GROUP BY emp.employee_id;
Your update can be done like this, note that the "and exists" section is optional but I tend to include it to make the intent of the query more clear.
UPDATE employee emp
SET emp.joining_date =
(SELECT min(booking_date) from booking bo where bo.employee_id = emp.employee_id)
WHERE emp.joining_date IS NULL
and exists(select * from booking bo where bo.employee_id = emp.employee_id);

MERGING DATA OF TWO TABLES

I want to write a query which finds the difference between two tables and writes updates or new data into third table. My two tables have identical column names. Third table which captures changes have extra column called comment. I would like to insert the comment whether it is a new row or updated row based on the row modification.
**TABLE1 (BACKUP)**
KEY,FIRST_NAME,LAST_NAME,CITY
1,RAM,KUMAR,INDIA
2,TOM,MOODY,ENGLAND
3,MOHAMMAD,HAFEEZ,PAKISTAN
4,MONIKA,SAM,USA
5,MIKE,PALEDINO,USA
**TABLE2 (CURRENT)**
KEY,FIRST_NAME,LAST_NAME,CITY
1,RAM,KUMAR,USA
2,TOM,MOODY,ENGLAND
3,MOHAMMAD,HAFEEZ,PAKISTAN
4,MONIKA,SAM,INDIA
5,MIKE,PALEDINO,USA
6,MAHELA,JAYA,SL
**TABLE3 (DIFFERENCE FROM TABLE2 TO TABLE1)**
KEY,FIRST_NAME,LAST_NAME,CITY,COMMENT
1,RAM,KUMAR,USA,UPDATE
4,MONIKA,SAM,INDIA,UPDATE
6,MAHELA,JAYA,SL,INSERT
table scripts
DROP TABLE TABLE1;
DROP TABLE TABLE2;
DROP TABLE TABLE3;
CREATE TABLE TABLE1
(
KEY NUMBER,
FIRST_NAME VARCHAR2(100),
LAST_NAME VARCHAR2(100),
CITY VARCHAR2(50)
);
/
CREATE TABLE TABLE2
(
KEY NUMBER,
FIRST_NAME VARCHAR2(100),
LAST_NAME VARCHAR2(100),
CITY VARCHAR2(50)
);
/
CREATE TABLE TABLE3
(
KEY NUMBER,
FIRST_NAME VARCHAR2(100),
LAST_NAME VARCHAR2(100),
CITY VARCHAR2(50),
COMMENTS VARCHAR2(200)
);
/
INSERT ALL
INTO TABLE1
VALUES(1,'RAM','KUMAR','INDIA')
INTO TABLE1 VALUES(2,'TOM','MOODY','ENGLAND')
INTO TABLE1 VALUES(3,'MOHAMMAD','HAFEEZ','PAKISTAN')
INTO TABLE1 VALUES(4,'MONIKA','SAM','USA')
INTO TABLE1 VALUES(5,'MIKE','PALEDINO','USA')
SELECT 1 FROM DUAL;
/
INSERT ALL
INTO TABLE2
VALUES(1,'RAM','KUMAR','USA')
INTO TABLE2 VALUES(2,'TOM','MOODY','ENGLAND')
INTO TABLE2 VALUES(3,'MOHAMMAD','HAFEEZ','PAKISTAN')
INTO TABLE2 VALUES(4,'MONIKA','SAM','INDIA')
INTO TABLE2 VALUES(5,'MIKE','PALEDINO','USA')
INTO TABLE2 VALUES(6,'MAHELA','JAYA','SL')
SELECT 1 FROM DUAL;
I was using the merge statement to accomplish the same. but i have hit a roadblock in merge statement , it's rhrowing an error "SQL Error: ORA-00905: missing keyword
00905. 00000 - "missing keyword"" I dont understand where is the error. please help
INSERT INTO TABLE3
SELECT KEY,FIRST_NAME,LAST_NAME,CITY,NULL AS COMMENTS FROM TABLE2
MINUS
SELECT KEY,FIRST_NAME,LAST_NAME,CITY,NULL AS COMMENTS FROM TABLE1
;
MERGE INTO TABLE3 A
USING TABLE1 B
ON (A.KEY=B.KEY)
WHEN MATCHED THEN
UPDATE SET A.COMMENTS='UPDATED'
WHEN NOT MATCHED THEN
UPDATE SET A.COMMENTS='INSERTED';
There is no such WHEN NOT MATCHED THEN UPDATE clause, you should use WHEN NOT MATCHED THEN INSERT. Refer to MERGE for details.
A few assumptions made about the data:
An INSERT event will be a record identified by its key in table2 (current data) that does not have a matching key in the original back-up table: table1.
An UPDATE event is a field that exists in both table1 and table2 for the same KEY but is not the same.
Records which did not change between tables are not to be recorded in table3.
Example Query: Check for Updates
SELECT UPD_QUERY.NEW_CITY, 'UPDATED' as COMMENTS
FROM (SELECT CASE WHEN REPLACE(CURR.CITY, BKUP.CITY,'') IS NOT NULL THEN CURR.CITY
ELSE NULL END as NEW_CITY
FROM table1 BKUP, table2 CURR
WHERE BKUP.KEY = CURR.KEY) UPD_QUERY
WHERE UPD_QUERY.NEW_CITY is NOT NULL;
You can repeat this comparison method for the other fields:
SELECT UPD_QUERY.*
FROM (SELECT CURR.KEY,
CASE WHEN REPLACE(CURR.FIRST_NAME, BKUP.FIRST_NAME,'') IS NOT NULL
THEN CURR.FIRST_NAME
ELSE NULL END as FIRST_NAME,
CASE WHEN REPLACE(CURR.LAST_NAME, BKUP.LAST_NAME,'') IS NOT NULL
THEN CURR.LAST_NAME
ELSE NULL END as LAST_NAME,
CASE WHEN REPLACE(CURR.CITY, BKUP.CITY,'') IS NOT NULL
THEN CURR.CITY
ELSE NULL END as CITY
FROM table1 BKUP, table2 CURR
WHERE BKUP.KEY = CURR.KEY) UPD_QUERY
WHERE COALESCE(UPD_QUERY.FIRST_NAME, UPD_QUERY.LAST_NAME, UPD_QUERY.CITY)
is NOT NULL;
NOTE: This could get unwieldy very quickly if the number of columns compared are many. Since the target table design (table3) requires not only identification of a change, but the field and its new value are also recorded.
Example Query: Look for Newly Added Records
SELECT CURR.*, 'INSERTED' as COMMENTS
FROM table2 CURR, table1 BKUP
WHERE CURR.KEY = BKUP.KEY(+)
AND BKUP.KEY is NULL;
Basically MERGE forces the operation: MATCHED=UPDATE (or DELETE), NOT MATCHED = INSERT. It's in the docs.
You can do what you want but you need two insert statements with different set operators,
For UPDATED:
Insert into table3
table1 INTERSECT table2
For INSERTED:
Insert into table3
table2 MINUS table1

Bulk update in Oracle gives error ORA-01779

I have a table which doesnot have any unique key column and I want to perform bulk update using self join.
Update
(
select t1.Col1 col1, t2.col1 col2
from table t1
inner join table t2 on <join condtn>
where <condtn>
)
Set col1 = col2
but as the table does not have unique key column, it gives error:
ORA-01779: cannot modify a column which maps to a non key-preserved
table.
Is there any solution other than adding unique constraint :)
You should be able to refactor the query to do a correlated update
UPDATE table t1
SET col1 = (SELECT col1
FROM table t2
WHERE t1.<<some column>> = t2.<<some column>>)
WHERE EXISTS( SELECT 1
FROM table t2
WHERE t1.<<some column>> = t2.<<some column>>)

Resources