PL/SQL: I have problem updating a table with data from another table - oracle

First table ROOMDB:
roomnumber
rentalbalance
N327
0
Second table RENTALINVOICE:
invoicedate
roomnumber
totaldue
11/26/2021
N327
2,200.00
My update code:
UPDATE ROOMDB
SET
RENTALBALANCE = (SELECT TOTALDUE
FROM RENTALINVOICE
WHERE RENTALINVOICE.ROOMNUMBER=ROOMDB.ROOMNUMBER
AND INVOICEDATE=SYSDATE) ;
I need to update the totaldue column in ROOMDB with data from RENTALINVOICE though it successfully enters 2,200 to the totaldue column, AT THE SAME TIME IT ALSO WIPES OUT THE REST OF THE RECORDS on this column in ROOMDB.
Everytime I update it, it erases the rest of the records except the roomnumber I specified. Please help.

You basically seem to also updates rows in table roomdb where there is no row in table rentalinvoice and therefore the column rentalbalance will be set to null.
Have a look a following example:
drop table a;
create table a (id number, cost number);
insert into a values (1, 1);
insert into a values (2, 2);
drop table b;
create table b (id number, cost number);
insert into b values (1, 100);
-- updates all rows in a and sets cost to null whenen there is no row in b
update a set cost = (select cost from b where a.id = b.id);
select * from a;
-- only updaes rows in a where there is a row in b
update a set cost = id;
update a set cost = (select cost from b where a.id = b.id) where exists (select 1 from b where a.id = b.id);
select * from a;

When you execute an update command like this Oracle will update all the table rows. For every row Select command will execute with these row values. If the result of select in the update does not find any record will return null. In this situation the RENTALBALANCE column will set null too.
(SELECT TOTALDUE
FROM RENTALINVOICE
where WHERE RENTALINVOICE.ROOMNUMBER = ROOMDB.ROOMNUMBER
AND INVOICEDATE = SYSDATE)

Related

oracle stored procedure updating one table with the help of another table

TABLE A : name empid activeind
TABLE B : name empid activeind
update table A based on table B comparing empid from both the table using Oracle stored procedure
Here's one option.
create or replace procedure p_upd is
begin
merge into a
using b
on (b.empid = a.empid)
when matched then update set a.name = b.name,
a.activeind = b.activeind;
end;
/
[EDIT] Based on your comment: you used wrong syntax. UPDATE should be
UPDATE a
SET (a.name, a.activeind) =
(SELECT b.name, b.activeind
FROM b
WHERE b.empid = a.empid)
WHERE EXISTS
(SELECT NULL
FROM b
WHERE b.empid = a.empid);
Why exists? Without it, you'd set name and activeid values to null for all a.empid rows that don't exist in b table.

I want to update table emp_appointment with data from other table data

I have two tables named emp_appointment and employees. Employees have 2 column named EMPLOYEE_ID1 and SUBSID_ACCOUNT_IDX and table emp_appointment have also 2 column named dep_id and EMPLOYEE_ID1 I want to update table emp_appointment column dep_id with data of employees table from column SUBSID_ACCOUNT_IDX both have same id's so I write this code but not worked
DECLARE
EMP_id EMPLOYEES.EMPLOYEE_ID1%TYPE;
SUBSID_ID EMPLOYEES.SUBSID_ACCOUNT_IDX%TYPE;
CURSOR C_EMP is
SELECT EMPLOYEE_ID1, SUBSID_ACCOUNT_IDX FROM EMPLOYEES WHERE SUBSID_ACCOUNT_IDX = EMPLOYEE_ID1 ;
BEGIN
OPEN C_EMP;
LOOP
FETCH C_EMP into EMP_id,SUBSID_ID ;
UPDATE EMP_APPOINTMENT
SET DEP_ID = SUBSID_ID
WHERE EMPLOYEE_ID1= SUBSID_ID;
EXIT WHEN C_EMP%notfound;
END LOOP;
CLOSE C_EMP;
END;
help needed from Masters Please
First off you should not do this, unless dep_id id necessary as part of a foreign key. What you are doing is just copying data, which is just a bad idea. It exposes you to data inconsistency, what happens when dep_id contains a value that does not exist in employees. Instead you should just Join the tables and select subsid_account_idx from employees. But if you insistant then just use a single update.
update emp_appointment ea
set dep_id = (select subsid_account_idx
from employees e
where e.employee_id1 = ea.employee_id1
);
You can use this :
MERGE INTO emp_appointment e
USING employees. Employees h
ON (h.EMPLOYEE_ID1= e.SUBSID_ID)
WHEN MATCHED THEN
UPDATE SET e.DEP_ID = h.SUBSID_ACCOUNT_IDX ;
and this merge into syntax:
MERGE INTO table1
USING table_reference h
ON (conditions)
WHEN MATCHED THEN
UPDATE SET table1.column1 = h.value1, table1.column2 = h.value2

ORACLE - Update table if exists else insert use rownum to match

I have table master (A) without field ID_No. So i create table B (copy from A) and set B.ID_No = rownum.
Now i want update B if A exist else will insert B with B.ID_NO = A.rownum
In oracle can create query with B.ID_NO = A.rownum?
My logic is ID of B = rownum of A, row++ then ID++, row have change value then fields ID will update.
For rownum repeatability is not guaranteed. You should find unique column or combination of columns for key in tables A and B, for a one-to-one relationship.

Oracle Inserting or Updating a row through a procedure

I have a table
CREATE TABLE STUDENT
(
ID INTEGER PRIMARY KEY,
FIRSTNAME VARCHAR2(1024 CHAR),
LASTNAME VARCHAR2(1024 CHAR),
MODIFIEDDATE DATE DEFAULT sysdate
)
I am inserting a row of data
insert into STUDENT (ID, FIRSTNAME, LASTNAME, MODIFIEDDATE) values (1,'Scott', 'Tiger', sysdate);
When I have to insert a record of data, I need to write a procedure or function which does the following:
if there is no record for the same id insert the row.
if there is a record for the same id and data matches then do nothing.
if there is a record for the same id but data does not match then update the data.
I am new to oracle. From the java end, It is possible to select the record by id and then update that record, but that would make 2 database calls. just to avoid that I am trying update the table using a procedure. If the same can be done in a single database call please mention.
For a single SQL statement solution, you can try to use the MERGE statement, as described in this answer https://stackoverflow.com/a/237328/176569
e.g.
create or replace procedure insert_or_update_student(
p_id number, p_firstname varchar2, p_lastname varchar2
) as
begin
merge into student st using dual on (id = p_id)
when not matched then insert (id, firstname, lastname)
values (p_id, p_firstname, p_lastname)
when matched then update set
firstname = p_firstname, lastname = p_lastname, modifiedate = SYSDATE
end insert_or_update_student;
instead of procedure try using merge in oracle .
If Values is matched it will update the table and if values is not found it will insert the values
MERGE INTO bonuses b
USING (
SELECT employee_id, salary, dept_no
FROM employee
WHERE dept_no =20) e
ON (b.employee_id = e.employee_id)
WHEN MATCHED THEN
UPDATE SET b.bonus = e.salary * 0.1
DELETE WHERE (e.salary < 40000)
WHEN NOT MATCHED THEN
INSERT (b.employee_id, b.bonus)
VALUES (e.employee_id, e.salary * 0.05)
WHERE (e.salary > 40000)
Try this
To solve the second task - "if there is a record for the same id and data matches then do nothing." - starting with 10g we have additional "where" clause in update and insert sections of merge operator.
To do the task we can add some checks for data changes:
when matched then update
set student.last_name = query.last_name
where student.last_name <> query.last_name
This will update only matched rows, and only for rows where data were changed

Update or insert based on if employee exist in table

Do want to create Stored procc which updates or inserts into table based on the condition if current line does not exist in table?
This is what I have come up with so far:
PROCEDURE SP_UPDATE_EMPLOYEE
(
SSN VARCHAR2,
NAME VARCHAR2
)
AS
BEGIN
IF EXISTS(SELECT * FROM tblEMPLOYEE a where a.ssn = SSN)
--what ? just carry on to else
ELSE
INSERT INTO pb_mifid (ssn, NAME)
VALUES (SSN, NAME);
END;
Is this the way to achieve this?
This is quite a common pattern. Depending on what version of Oracle you are running, you could use the merge statement (I am not sure what version it appeared in).
create table test_merge (id integer, c2 varchar2(255));
create unique index test_merge_idx1 on test_merge(id);
merge into test_merge t
using (select 1 id, 'foobar' c2 from dual) s
on (t.id = s.id)
when matched then update set c2 = s.c2
when not matched then insert (id, c2)
values (s.id, s.c2);
Merge is intended to merge data from a source table, but you can fake it for individual rows by selecting the data from dual.
If you cannot use merge, then optimize for the most common case. Will the proc usually not find a record and need to insert it, or will it usually need to update an existing record?
If inserting will be most common, code such as the following is probably best:
begin
insert into t (columns)
values ()
exception
when dup_val_on_index then
update t set cols = values
end;
If update is the most common, then turn the procedure around:
begin
update t set cols = values;
if sql%rowcount = 0 then
-- nothing was updated, so the record doesn't exist, insert it.
insert into t (columns)
values ();
end if;
end;
You should not issue a select to check for the row and make the decision based on the result - that means you will always need to run two SQL statements, when you can get away with one most of the time (or always if you use merge). The less SQL statements you use, the better your code will perform.
BEGIN
INSERT INTO pb_mifid (ssn, NAME)
select SSN, NAME from dual
where not exists(SELECT * FROM tblEMPLOYEE a where a.ssn = SSN);
END;
UPDATE:
Attention, you should name your parameter p_ssn(distinguish to the column SSN ), and the query become:
INSERT INTO pb_mifid (ssn, NAME)
select P_SSN, NAME from dual
where not exists(SELECT * FROM tblEMPLOYEE a where a.ssn = P_SSN);
because this allways exists:
SELECT * FROM tblEMPLOYEE a where a.ssn = SSN

Resources