Update table based on values in another table - sql

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.

Related

Get every unique pair combination of a column in SQL

Lets say I have given table:
1 A
2 A
3 A
How do I JOIN / combine the table with itself so I get every possible unique pair combination of the first column:
1 1 A
1 2 A
1 3 A
2 1 A
2 2 A
2 3 A
...
You can do something like this.
Cross JOIN is used for cross product
-- create
CREATE TABLE EMPLOYEE (
empId INTEGER PRIMARY KEY,
name TEXT NOT NULL
);
-- insert
INSERT INTO EMPLOYEE VALUES (0001, 'Clark');
INSERT INTO EMPLOYEE VALUES (0002, 'Dave');
INSERT INTO EMPLOYEE VALUES (0003, 'Ava');
-- fetch
SELECT e1.empId, e2.empId, e1.name FROM EMPLOYEE e1
CROSS JOIN EMPLOYEE e2;

I need to create a Table from two unrelated old tables in sql developer

My problem is that I need to create the table USER_LIBRARY from this two unrelated tables:
USER:
ID_USER NUMBER(9) PRIMARY KEY,
NAME VARCHAR2(50),
SURNAME VARCHAR2(50),
CITY VARCHAR2(50),
ADDRESS VARCHAR2(50),
AGE NUMBER(9),
EMAIL VARCHAR2(50)
LIBRARY:
id_library number(9) PRIMARY KEY NOT NULL,
name VARCHAR2(50) NOT NULL,
city VARCHAR2(50) NOT NULL,
address VARCHAR2(50) NOT NULL,
CP number(9) NOT NULL
I try with an INNER JOIN and with UNION but it doesn´t work, I'm new to Oracle so I know is a basic question but I didn´t know how to solve.
The final table will depend on how many columns of both input tables you want to use. As you have columns with the same name, you need to use alias to resolve this in a good way. Another thing is what result you expect. Normally a user may belong to one or more libraries, but as you have no way to relate both tables, you will get a cartesian product.
Let's assume you want all of them
create table user_library as
select u.id_user ,
l.id_library,
u.name as user_name,
u.surname ,
u.city as user_city ,
u.address as user_address,
u.age, u.email ,
l.name as library_name,
l.city as library_city,
l.address as library_address ,
l.cp as library_cp
from user u cross join library l ;
Let me explain what I mean with an example
SQL> create table test1 ( c1 number , c2 number );
Table created.
SQL> insert into test1 values ( 1 , 1 );
1 row created.
SQL> insert into test1 values ( 2 , 2 );
1 row created.
SQL> commit;
Commit complete.
SQL> create table test2 ( c3 number, c4 number );
Table created.
SQL> insert into test2 values ( 3 , 3 );
1 row created.
SQL> insert into test2 values ( 4 , 4 );
1 row created.
SQL> create table test3 as select a.c1 , a.c2 , b.c3 , b.c4 from test1 a cross join test2 b ;
Table created.
SQL> select * from test1 ;
C1 C2
---------- ----------
1 1
2 2
SQL> select * from test2 ;
C3 C4
---------- ----------
3 3
4 4
SQL> select * from test3 ;
C1 C2 C3 C4
---------- ---------- ---------- ----------
1 1 3 3
1 1 4 4
2 2 3 3
2 2 4 4
SQL>
The cross join creates a row for each combination of values in table1 against table2.
If you want all users to pair with all libraries, you could use:
create table user_library as
select u.id_user, l.id_library
from user u cross join
library l;
This includes only the ids. You can use JOIN to fetch the values corresponding to a particular user and/or library.

Update values of one table from other table

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;

How to create relational tables from a flat table?

I have this input table:
CREATE TABLE `data` (
`id` INTEGER,
`a` INTEGER,
`b` INTEGER,
`c` TEXT, PRIMARY KEY(`id`) )
With this data:
id a b c
-- - - -
1 1 4 a
2 1 5 a
3 1 6 b
4 2 4 a
5 1 5 c
As I have many other columns b, c, ... on this table and a lot of redundancy. For example, we see that entry 1 is the same as entry 4 so I would like to create relational tables from this flat table and eventually drop data in favor of my two new tables and create a view named data
The goal is to create two tables bc and a with the following:
a bc
-------- --
id id_bc id b c
-- ----- -- - -
1 1 1 4 a
2 2 2 5 a
3 3 3 6 b
4 1 4 4 c
5 4
Getting bc is easy with:
CREATE TABLE bc AS SELECT DISTINCT b,c FROM data
But I don't know how:
Create bc with an id column
Create a with foreign relation to bc
If you want to customize the creation of table bc, then do so, instead of using create table ... as select. (Or, refer to the row identifier as rowid instead of giving it a custom name.)
create table bc(
id integer primary key,
b integer,
c integer)
insert into bc(b,c) select distinct b,c from data
For a, since you want a foreign key, you cannot use create table ... as select.
create table a(
id integer primary key,
id_bc integer,
foreign key (id_bc) references bc(id))
insert into a(id_bc)
select bc.id from data inner join bc
on data.b = bc.b and data.c = bc.c
Omitting the primary key in each insert statement (or specifying null) will use autoincrement.

How to do I update existing records using a conditional clause?

I'm new to Oracle SQL so I have a question .. I have two tables, Table A and Table B .. Now Table A and Table B have the same column names, but in table A, only one column (named 'tracker') actually has data in it .. The rest of the columns in Table A are empty ... What I need to do is update each record in Table A, so that values for other columns are copied over from Table B, with the condition that the the 'tracker' columns value from Table A is matched with the 'tracker' column in Table B ..
Any ideas ?
MERGE INTO tableA a
USING tableB b
ON (a.tracker=b.tracker)
WHEN MATCHED THEN UPDATE SET
a.column1=b.column1,
a.column2=b.column2;
And if exist rows in B that does not exist in A:
MERGE INTO tableA a
USING tableB b
ON (a.tracker=b.tracker)
WHEN MATCHED THEN UPDATE SET
a.column1=b.column1,
a.column2=b.column2
WHEN NOT MATCHED THEN INSERT VALUES
a.tracker,a.column1,a.column2; --all columns
create table a (somedata varchar2(50), tracker number , constraint pk_a primary key (tracker));
create table b (somedata varchar2(50), tracker number, constraint pk_b primary key (tracker));
/
--insert some data
insert into a (somedata, tracker)
select 'data-a-' || level, level
from dual
connect by level < 10;
insert into b (somedata, tracker)
select 'data-b-' || -level, level
from dual
connect by level < 10;
select * from a;
SOMEDATA TRACKER
-------------------------------------------------- -------
data-a-1 1
data-a-2 2
data-a-3 3
data-a-4 4
data-a-5 5
data-a-6 6
data-a-7 7
data-a-8 8
data-a-9 9
select * from b;
SOMEDATA TRACKER
-------------------------------------------------- -------
data-b--1 1
data-b--2 2
data-b--3 3
data-b--4 4
data-b--5 5
data-b--6 6
data-b--7 7
data-b--8 8
data-b--9 9
commit;
update (select a.somedata a_somedata, b.somedata b_somedata
from a
inner join
b
on a.tracker = b.tracker)
set
a_somedata = b_somedata;
select * from a; --see below for results--
--or you can do it this way: (issuing rollback to get data back in previous state)
--for a one column update, either way will work, I would prefer the former in case there is a multi-column update necessary
-- merge *as posted by another person* will also work
update a
set somedata = (select somedata
from b
where a.tracker = b.tracker
);
select * from A; --see below for results--
-- clean up
-- drop table a;
-- drop table b;
this will give you the results:
SOMEDATA TRACKER
-------------------------------------------------- -------
data-b--1 1
data-b--2 2
data-b--3 3
data-b--4 4
data-b--5 5
data-b--6 6
data-b--7 7
data-b--8 8
data-b--9 9
here is a link to oracle's documentation on UPDATE