Hi I am very new in Oracle/PLSQL.
I have a question. I have one to one relationship between two tables. In both tables I have a column named col2. In table 1 this column is null, in the second it is filled. I want to copy all data from one table to another.
Example:
Table 1 Table 2
col1 col2 ... col1 col2 ...
1 null ... 1 A ...
2 B ... 2 B ...
3 null ... 3 C ...
I want it to be:
Table 1 Table 2
col1 col2 col1 col2 ...
1 A ... 1 A ...
2 B ... 2 B ...
3 C ... 3 C ...
How can I do that with a Query?
I have tried:
UPDATE table 1 SET col2 = (SELECT col2 FROM table 2 WHERE col1 = '1') WHERE col1 = '1'
But it is only for one record. How can I change this query to make it work for whole table?
Note: I can not change table structures, can not delete or add new columns, can not use scripts.
merge might be a good choice:
merge into table1 a
using table2 b
on (a.col1 = b.col1)
when matched then update set
a.col2 = b.col2;
Related
I have a little complex requirement on couple of tables which I am finding hard to crack.
There are 2 tables. TableA and TableB
TableA has a structure like:
-------------------------------------
ID COL1 COL2 CAT
-------------------------------------
1 RecAA RecAB 3
2 RecBA RecBB 3
3 RecCA RecCB 2
4 RecDA RecDB 2
5 RecEA RecEB 1
-------------------------------------
TableB has a structure like:
-----------------
COL3 TYPE
-----------------
RecAA 10
RecAA 11
RecAA 12
RecAB 10
RecAB 11
RecAB 12
RecAB 13
RecAB 14
RecBA 10
RecBA 11
RecBA 14
RecBA 15
RecBB 10
-----------------
Requirements:
Records in TableA should have CAT = 3.
Either COL1 or COL2 of TableA should be available in COL3 of TableB.
COL3 should definitely have TYPE in 10,11,12 and should have only that TYPE.
i.e As per the above requirements,
Of the records available in TableA, records with ID 1 and 2 have CAT = 3 in TableA
Both the records have atleast only value in COL3 of TableB. (Record with ID 1 in TableA has both COL1 and COL2 in TableB and record with ID 2 in TableA has COL1 in TableB)
RecAA record has Type 10,11,12 and only 10,11,12. So doesnt matter if RecAB has 10,11,12 or not. But RecBA and RecBB both does not have 10,11,12 types.
Therefore the result should be:
-------------------------------------
ID COL1 COL2 CAT
-------------------------------------
1 RecAA RecAB 3
-------------------------------------
What I tried:
WITH TEMP AS (SELECT COL3 FROM TableB GROUP BY COL3 HAVING SUM(CASE WHEN TYPE IN ('10','11','12') THEN 1 ELSE 0 END) = 0)
SELECT S.ID, S.COL1, S.COL2, S.CAT FROM TableA S
INNER JOIN TEMP T ON S.COL1 = T.COL3
WHERE S.CAT = 3;
Can someone please help on achieving this?
I think you're almost there, it's just your row selection in the CTE that seems problematic, and I think you need an OR:
WITH TEMP AS (
SELECT COL3
FROM TableB
GROUP BY COL3
HAVING SUM(POWER(2, TYPE - 10)) = 7 AND COUNT(*) = 3
)
SELECT
S.ID, S.COL1, S.COL2, S.CAT
FROM
TableA S
INNER JOIN TEMP T ON S.COL1 = T.COL3 OR S.COL2 = T.COL3
WHERE
S.CAT = 3;
I've subtracted 10 from each of your TYPEs to turn your 10,11,12 into 0,1,2 and then used POWER to turn them into 1, 2 and 4 which uniquely sum to 7 - (in other words your 10,11,12 became 2^(10-10), 2^(11-10) and 2^(12-10) which are 1, 2 and 4.. Which must then sum to 7).
I also mandate that there be a count of 3; the only way to get to 7 with three numbers that are powers of 2 is to have 1+2+4 which guarantees that 10,11,12 are present initially. If anything was missing, extra or repeated it wouldn't be 3 numbers that sum to 7
I think RecAB is excluded because even though it has 10,11,12 it also has 13,14 which cause it to be excluded..
You also seemed to be saying that COL3 should be present in either COL1 or COL2 of table A
You can use listagg analytic version to turn TYPE column into type_in_list column like below :
With temp_TableB (COL3, type_in_list) as (
SELECT distinct COL3, listagg(TYPE, ',') within group (order by TYPE)over(partition by COL3)
FROM TableB
)
select tA.*
--, tb.*
from tableA tA
INNER JOIN temp_TableB tB on (tA.COL1 = tB.COL3 or tA.COL2 = tB.COL3)
Where tA.CAT = 3
AND tB.TYPE_IN_LIST = '10,11,12'
;
I have a table A in Schema1 and table B in Schema2.
The tables have different columns.
Table A:
ID1 Name Code
-------------------------------
1 Skyler A0
2 Amanda A1
3 Rachel B0
4 Harvey C0
5 Louis B1
Table B:
ID Names Enterprise Modified_Date
------------------------------------------------------
1 Amanda 1 2018.08.10
2 Skyler 1 2018.08.11
As depicted, Schema1.A.Name = Schema2.B.Names
I want to insert the values "Rachel,Harvey and Louis" from A.Name into B.Names.
For b.ID, i have a sequence in place. Enterprise column is always 1 and modified date can e sysdate.
How can i achieve this in PL/SQL?
use insert Statement with select statement
insert into tabB (names,Enterprise,Modified_Date )
select Name,1,sysdate from tabA where Name in ('Rachel','Harvey','Louis');
You can do this by using below query.
insert into tableB (names,Enterprise,Modified_Date )
select Name,1,sysdate from tableA where Name not in (select distinct(Name) from tableB);
I want to insert data into a column in the table.
Table a
ID col1 col2
1 A null
2 B null
Table b
ID col1
1 C
2 D
Expected results:
Table A
ID col1 col2
1 A C
2 B D
I tried this:
insert into tableA (col2)
select b.col1
from tableB b , tableA a
where b.id = a.id
and I received
0 row inserted.
How do I insert the col1 in B into col2 in A for the matching 'id' columns?
Thank you.
You must use Merge statement when inserting based on joins.
Also in table tableA col2 already exist but you want to insert a value on join then you must update that column.
merge into tablea a
using tableb b
on (b.id = a.id)
when matched
then
update set a.col2 = b.col1;
What you want to do shouldn't require a subquery. I'm not a huge fan of the table a, table b notation, try this:
update a
set col2 = b.col1
from tableB b
join tableA a
on a.id = b.id
I have a structure that I store equal records in a database table. You can think that these records are siblings. For example I have two records in this table; 1=2 and 1=3. And I need a query that will return all siblings of a given record. Let me give an example;
This is my table with two columns:
create table SIBLINGSTEST(col1 number, col2 number);
I have 2 records, 1=2 and 1=3
insert into SIBLINGSTEST values(1,2);
insert into SIBLINGSTEST values(1,3);
I thought using connect by is the best solution for this situation, and write the following query:
SELECT * FROM SIBLINGSTEST
START WITH (col1 = 1 or col2 = 1)
CONNECT BY NOCYCLE (
(PRIOR col1 = col1) or
(PRIOR col1 = col2) OR
(PRIOR col2 = col1) or
(PRIOR col2 = col2))
This query returns correct results, returning both rows.
If I use 2 as a parameter, the query also runs correctly, returning again both rows.
But if I use 3 as a parameter, the query does not run as I expected, returning only the start row.
SELECT * FROM SIBLINGSTEST
START WITH (col1 = 3 or col2 = 3)
CONNECT BY NOCYCLE (
(PRIOR col1 = col1) or
(PRIOR col1 = col2) OR
(PRIOR col2 = col1) or
(PRIOR col2 = col2))
I wonder why the results of 2 and 3 differs. Any help or idea will be appriciated.
Thanks.
I get both rows with your last query as expected:
SQL> SELECT * FROM SIBLINGSTEST
2 START WITH (col1 = 3 or col2 = 3)
3 CONNECT BY NOCYCLE (
4 (PRIOR col1 = col1) or
5 (PRIOR col1 = col2) OR
6 (PRIOR col2 = col1) or
7 (PRIOR col2 = col2));
COL1 COL2
---------- ----------
1 3
1 2
However I would not choose to model it this way. If what you really want is to record that 1, 2, 3 are siblings then I would use:
create table siblings_group (group_id number);
create table people (person_id number, group_id number);
insert into siblings_group values (1);
insert into people values (1, 1);
insert into people values (2, 1);
insert into people values (3, 1);
Then to find all siblings of 3:
SQL> select person_id from people where group_id =
2 (select group_id from people where person_id=3);
PERSON_ID
----------
1
2
3
I have 2 tables - A and B . Table A has two columns, pkey (primary key) and col1. Table B also has two columns, pr_key (primary key but not a foreign key) and column1. Both tables have 4 rows. Table B has no values in column1, while table A has column1 values for all 4 rows. So my data looks like this
Table A
pkey col1
A 10
B 20
C 30
D 40
Table B
pr_key column1
A null
B null
C null
D null
I want to update table B to set the column1 value of each row equal to the column1 value of the equivalent row from table A in a single DML statement.
Should be something like that (depends on SQL implementation you use, but in general, the following is rather standard. In particular should work in MS-SQL and in MySQL.
INSERT INTO tblB (pr_key, column1)
SELECT pkey, col1
FROM tblA
-- WHERE some condition (if you don't want 100% of A to be copied)
The question is a bit unclear as to the nature of tblB's pr_key, if for some reason this was a default/auto-incremented key for that table, it could just then be omitted from both the column list (in parenthesis) and in the SELECT that follows. In this fashion upon insertion of each new row, a new value would be generated.
Edit: It appears the OP actually wants to update table B with values from A.
The syntax for this should then be something like
UPDATE tblB
SET Column1 = A.Col1
FROM tblA AS A
JOIN tblB AS B ON B.pr_key = A.pkey
This may perform better:
MERGE INTO tableB
USING (select pkey, col1 from tableA) a
ON (tableB.pr_key = a.pkey)
WHEN MATCHED THEN UPDATE
SET tableB.column1 = a.col1;
It sounds like you want to do a correlated update. The syntax for that in Oracle is
UPDATE tableB b
SET column1 = (SELECT a.column1
FROM tableA a
WHERE a.pkey = b.pr_key)
WHERE EXISTS( SELECT 1
FROM tableA a
WHERE a.pkey = b.pr_key )
The WHERE EXISTS clause isn't necessary if tableA and tableB each have 4 rows and have the same set of keys in each. It is much safer to include that option, though, to avoid updating column1 values of tableB to NULL if there is no matching row in tableA.