Update values of one table from other table - sql

For Example I have 2 tables
Table 1:
id number name
-----------------------
1 1684 abc
2 9666 pqr
3 1234 adf
Table 2:
id number name
-----------------------
1 9109 xyz
2 9564 pqr
How do i get output like this?
Table 1:
id number name
-----------------------
1 9109 xyz
2 9564 pqr
3 1234 adf
I want to merge table 2 in table.
Also if the column-"name" value is updated/changed from this merge, I need to update status column and i need to call a procedure of smtp mail, how can i handle this?
The status column has different status transitions(eg: x->y, a->b).
and if the record is not in table1 it should be inserted.
These all operations are inside a procedure used in batch job.
Please advice me with this.
Thank you in advance for help.

There are different ways to do this, say, using MERGE statement, but most simple is
Connected to Oracle Database 12c Enterprise Edition Release 12.1.0.2.0
SQL> create table t$1 ("id" integer, "number" integer, "name" varchar2(3));
Table created
SQL> create table t$2 ("id" integer, "number" integer, "name" varchar2(3));
Table created
SQL> insert into t$1 values (1, 1684, 'abc');
1 row inserted
SQL> insert into t$1 values (2, 9666, 'pqr');
1 row inserted
SQL> insert into t$1 values (3, 1234, 'adf');
1 row inserted
SQL> insert into t$2 values (1, 9109, 'xyz');
1 row inserted
SQL> insert into t$2 values (2, 9564, 'pqr');
1 row inserted
SQL> update t$1 set
2 ("number", "name") = (select "number", "name" from t$2 where t$2."id" = t$1."id")
3 where
4 "id" in (select "id" from t$2);
2 rows updated
SQL> select * from t$1;
id number name
-------- -------- --------
1 9109 xyz
2 9564 pqr
3 1234 adf

You can use MERGE to do it very simply:
MERGE INTO table1 dst
USING table2 src
ON ( src.id = dst.id )
WHEN MATCHED THEN
UPDATE SET number = src.number,
name = src.name;

Related

Using Insert/Update with 2 Tables - Oracle Apex

I'm still new to SQL and am having a hard time figuring out how to update and insert from one table into another table in Oracle Apex (uses SQL).
The two tables are named Temp and Table (example) and both have the same columns. Basically they are copies of each other but with different data. I would like to compare the ID field in Temp to the ID field in Table and if there is a row that matches that ID field in Temp, then to overwrite all the data on the row in Table with the data in the corresponding row in Temp.
Note: Table has 10 million rows of data, Temp has like 500.
if Temp.ID = Table.ID then
update
set
Table.ID = Temp.ID
Table.Address = Temp.Address
else
insert
(Table.ID,
Table.Address)
values
(Temp.ID,
Temp.Address
That is basically what I want done but not sure how to write it in SQL. Have seen a lot of different answers, but none really involving 2 tables and mostly for MySQL or SQL Server specific SQL that I am not sure also works with Oracle.
MERGE into TEST1
USING TEST2 on (TEST2.ID = TEST1.ID)
WHEN matched THEN UPDATE
SET TEST1.ID = TEST2.ID, TEST1.NAME = TEST2.NAME, TEST1.ADDRESS = TEST2.ADDRESS, TEST1.EMAIL = TEST2.EMAIL
WHEN not matched THEN INSERT (ID, NAME, ADDRESS, EMAIL) values (TEST2.ID, TEST2.NAME, TEST2.ADDRESS, TEST2.EMAIL);
I tried this but it is giving me the error:
ORA-38104: Columns referenced in the ON Clause cannot be updated: "TEST1"."ID"
UPDATE: Got it to work!
http://db-oriented.com/2013/09/20/the-merge-statement/
Was helpful with the answer to the error and I did not know that you could not have the IDs in the update clause, which makes total sense now. Thank you also to the respondent below for explaining the merge code to me. :)
Looks like a good candidate for MERGE. Have a look at the example.
Sample tables & data:
SQL> create table ttable (id number, address varchar2(20));
Table created.
SQL> create table temp (id number, address varchar2(20));
Table created.
SQL> insert into ttable
2 select 1, 'Address 1' from dual union all
3 select 2, 'Address 2' from dual union all
4 select 3, 'Address 3' from dual;
3 rows created.
SQL> insert into temp
2 select 1, 'New address 1' from dual union all
3 select 2, 'New address 2' from dual union all
4 select 4, 'New address 4' from dual;
3 rows created.
Merge & the result:
SQL> merge into ttable a
2 using temp e on (e.id = a.id)
3 when matched then update set a.address = e.address
4 when not matched then insert (id, address) values (e.id, e.address);
3 rows merged.
SQL> select * from ttable;
ID ADDRESS
---------- --------------------
1 New address 1
2 New address 2
3 Address 3
4 New address 4
SQL>

Insert unique values after addition of a column in a table

We have a table with two columns and have added another column recently (named sequence_no) , Is there a way to insert unique values like , 1,2,3 for every row in the table ?
eg
table name : test
desc test
name varchar2
value varchar2
--> n_seq_no number
select * from test
Name value n_Seq_no
test1 100
test2 200
test3 300
test4 500
The table already had name, and value as the columns of the table, I need to add unique values for the n_Seq_no column with the existing data,
Output format:
select * from test
Name value n_Seq_no
test1 100 1
test2 200 2
test3 300 3
test4 500 4
and so on for all the rows in table.
You could simply set the new column as ROWNUM.
Something like,
SQL> CREATE TABLE t(
2 A NUMBER,
3 b NUMBER);
Table created.
SQL>
SQL> INSERT INTO t(A) VALUES(100);
1 row created.
SQL> INSERT INTO t(A) VALUES(200);
1 row created.
SQL> INSERT INTO t(A) VALUES(300);
1 row created.
SQL>
SQL> SELECT * FROM t;
A B
---------- ----------
100
200
300
SQL>
SQL> UPDATE t SET b = ROWNUM;
3 rows updated.
SQL> SELECT * FROM T;
A B
---------- ----------
100 1
200 2
300 3
SQL>
If you are on 12c, you could use an IDENTITY COLUMN.
Assuming that your table is really big it's better to recreate and repopulate:
rename test to old_test;
create table new_test
as
select t.*, rownum as n_seq_no
from old_test t
order by value;
Don't forget to migrate grants, indexes, triggers and etc if any.
UPDATE: ordering is optional. It is required only if you want to assign n_seq_no value using some predefine ordering.

How to Iterate through table and combine it's result with the value coming from SP

I need to join two tables in following way
TABLE_A
Id Name
Table_Ref
RefID --Auto increament
I need to insert into Table_Ref and Join each inserted id with Table_A row
as
Id Name RefId
Do i need Cursors for this
or any Set based operation can let me INSERT a new row into Table_Ref and then return it like
ID NAME RefID
xxxx AAA 1
yyyy BBB 2
You can create sequences and have that value inserted into the table
create sequence SEQ_TEST
minvalue 1
maxvalue 1000000000
start with 1
increment by 1
order;
To insert into the table, use the below syntax:
Insert into table_a (id, name, refid) values ('xxxx','AAA',SEQ_TEST.nextval);
Insert into table_a (id, name, refid) values ('yyyy','BBB',SEQ_TEST.nextval);
P.S: This is the syntax in Oracle. Not sure about tsql, you might need to tweak the syntax as necessary.

Update table based on values in another table

I have two tables I want to update table b in column bcnt by the value that in column acnt in table A where the worlds column in table A match words column in table B, and id in table B match id in table A.
create table a
(
id number(9),
words varchar2(2),
acnt number(9)
);
insert into a values(1,'Cairo',20);
insert into a values(1,'UK',10);
insert into a values(2,'KL',2);
insert into a values(2,'Cairo',2);
insert into a values(2,'London',30);
insert into a values(3,'Cairo',5);
insert into a values(4,'KSA',15);
create table b
(
id number(2),
words varchar2(20),
bcnt number
);
insert into b values(1,'Cairo',null);
insert into b values(1,'UK',null);
insert into b values(2,'KL',null);
insert into b values(2,'Cairo',null);
insert into b values(3,'Cairo',null);
insert into b values(4,'KSA',null);
I used this SQL code but it is not correct.
update b
set bcnt = (select acnt
from a
where a.id = b.id and a.words = b.words);
Expected results:
1 cairo 20
1 uk 10
2 kl 2
2 cairo 5
4 ksa 12
The SQL shows me the following
SQL> /
ID WORDS BCNT
---------- -------------------- ----------
1 Cairo
1 UK 10
2 KL 2
2 Cairo
3 Cairo
4 KSA
6 rows selected.
SQL>
Is the problem that your SQL uses word instead of words as in the table definition?
update b
set bcnt=(select acnt from a where a.id=b.id and a.words=b.words );
Also, your data types are not correct in the two tables. Your create table statements should be consistent:
create table a (id number(9),words varchar2(20), acnt number);
create table b (id number(9), words varchar2(20), bcnt number);
What is happening is that the values longer than 2 characters in the first table are being truncated to two characters. So, instead of 'Cairo' the value is 'Ca' (to fit in varchar2(2)). As a result, you have no match in the join.

how to implement multivalued attribute in oracle?

I want to store more than one Email IDs in the Email id column of a table, as a multivalued attribute. How can I do this in oracle?
The traditional, relational way of doing this would be with a child heap table:
create table emails
(id number
, email_address varchar2(254)
, constraint em_t23_fk foreign key (id)
references t23 (id)
)
/
However, you are hinting at a nested table:
create type email_t as object
(email_address varchar2(254))
/
create type email_nt as table of email_t
/
alter table t23
add emails email_nt
nested table emails store as emails_table
/
Here's how it works:
SQL> update t23
2 set emails = email_nt (email_t('sam_i_am#example.com')
3 , email_t('green_eggs_n_ham#yahoo.co.uk'))
4 where id = 222
5 /
1 row updated.
SQL> select * from t23
2 where id = 222
3 /
ID NAME DOB
---------- ------------------------------ ---------
EMAILS(EMAIL_ADDRESS)
----------------------------------------------------------------------------------
222 Sam-I-Am 06-AUG-02
EMAIL_NT(EMAIL_T('sam_i_am#example.com'), EMAIL_T('green_eggs_n_ham#yahoo.co.uk'))
SQL>
Edit
The solution with VARRAY is basically the same:
SQL> alter table t23
2 drop column emails
3 /
Table altered.
SQL> create type email_va as varray(5) of varchar2(254)
2 /
Type created.
SQL> alter table t23
2 add emails email_va
3 /
Table altered.
SQL> update t23
2 set emails = email_va ('sam_i_am#example.com'
3 , 'green_eggs_n_ham#yahoo.co.uk')
4 where id = 222
5 /
1 row updated.
SQL> select t23.name
2 , e.*
3 from t23
4 , table (t23.emails) e
5 where t23.id = 222
6 /
NAME COLUMN_VALUE
------------------------------ ---------------------------------
Sam-I-Am sam_i_am#example.com
Sam-I-Am green_eggs_n_ham#yahoo.co.uk
SQL>
The standard way to do this is to define a second table, where you can store one email per row.
Oracle also supports nested tables so a single attribute column can contain multiple values.