You can insert records into table B if they are in table A
insert into B
select * from A
minus
select * from B
How do you delete records that are in B and not in A?
select * from B
minus
select * from A
How to delete records?
The assumption is that we do not have a primary key or a unique one.
You can do it like this:
delete from a2
where (COLUMN1, COLUMN2, COLUMN3, ...) in (select * from a2
minus
select * from a1);
It works, but you have to enter the column names in the where clause. Can not do delete in such a beautiful way as insert into select * from ...?
If you wanted to continue with your current approach, you should not use select * in your minus query. Rather, you should always explicitly list out the columns which you want to use.
But, I would use an EXISTS query here:
DELETE
FROM tableB b
WHERE NOT EXISTS (SELECT 1 FROM tableA a
WHERE a.col1 = b.col1 AND
a.col2 = b.col2 AND
a.col3 = b.col3 AND ...);
Best practice going forward would to have a primary key column in the A table. Then, you would only need to check that column against the B table for uniqueness.
Related
I have two tables. if the data in table1 is more than a predefined limit (say 2), i need to copy the remaining contents of table1 to table2 and delete those same contents from table1.
I used the below query to insert the excess data from table1 to table2.
insert into table2
SELECT * FROM table1 WHERE ROWNUM < ((select count(*) from table1)-2);
Now i need the delete query to delete the above contents from table1.
Thanks in advance.
A straightforward approach would be an interim storage in a temporary table. Its content can be used to determine the data to be deleted from table1 as well as the source to feed table 2.
Assume (slightly abusing notation) to be the PK column (or that of any candidate key) of table1 - usually there'll be some key that comprises only 1 column.
create global temporary table t_interim as
( SELECT <pk> pkc FROM table1 WHERE ROWNUM < ((select count(*) from table1)-2 )
;
insert into table2
select * from table1 where <pk> IN (
select pkc from t_interim
);
delete from table1 where <pk> IN (
select pkc from t_interim
);
Alternative
If any key of table1 spans more than 1 column, use an EXISTS clause instead as follows ( denoting the i-th component of a candidate key in table1):
create global temporary table t_interim as
( SELECT <ck_1> ck1, <ck_2> ck2, ..., <ck_n> ckn FROM table1 WHERE ROWNUM < ((select count(*) from table1)-2 )
;
insert into table2
select * from table1 t
where exists (
select 1
from t_interim t_i
where t.ck_1 = t_i.ck1
and t.ck_2 = t_i.ck2
...
and t.ck_n = t_i.ckn
)
;
delete from table1 t where
where exists (
select 1
from t_interim t_i
where t.ck_1 = t_i.ck1
and t.ck_2 = t_i.ck2
...
and t.ck_n = t_i.ckn
)
;
(Technically you could try to adjust the first scheme by synthesizing a key from the components of any CK, eg. by concatenating. You run the risk of introducing ambiguities ( (a bc, ab c) -> (abc, abc) ) or run into implementation limits ( max. varchar length ) using the first method)
Note
In case the table doesn't have a PK, you can apply the technique using any candidate key of table1. There will always be one, in the extreme case it's the set of all columns.
This situation may be the right time to improve the db design and add a (synthetic) pk column to table1 ( and any other tables in the system that lack it).
select * into tableA from dataA.
I have created a table tableA.
Next time,
insert * into tableA from dataB. it doesn't work. Because tableA is already exist.
I need insert data twice instead of unioning dataA and dataB.
select * into tableA from dataA.
Next,
INSERT INTO tableA(colum1,colum2)<--Not *
SELECT (colum1,colum2)
FROM B
i'm using oracle 11g. i want to know why these two query giving different answer?
logically they are same:
select * from tableA where
exists (select * from tableB where tableA.ID != tableB.ID);
select * from tableA where
not exists (select * from tableB where tableA.ID = tableB.ID);
in the first one i'm selecting every thing that not exist.
in the second one i'm not selecting everything that exist.
note ("exist" changed to "not exist) and ("!=" changed to "=")
look same right? but they give totally different answer
This statement is probably going to return all values in A:
select *
from tableA
where exists (select * from tableB where tableA.ID != tableB.ID);
The only time a row will fail to match is when it is the same as all rows in TableB that have a non-NULL values in ID. So, if TableB has at least two rows with different ids, then all rows in tableA will be returned.
This statement:
select *
from tableA
where not exists (select * from tableB where tableA.ID = tableB.ID);
Is saying that there is no id in TableB that matched the id in TableA. This would be what you want 99% of the time.
The first statement returns A values different from any B value.
The second statement returns A values different from all B values.
I have two tables
Table A has columns id|name|age.
Table B has columns id|name|age.
Sample Records from table A
1|xavi |23
2|christine|24
3|faisal |25
5|jude |27
Sample Records from table B
1|xavi |23
2|christine|22
3|faisal |23
4|ram |25
If id values from table A matches in table B than take records from table A only.
Also take records which are present in table A only
Also take records which are present in table B only
So my result should be
1|xavi |23
2|christine|24
3|faisal |25
4|ram |25
5|jude |27
You can simply use union operator to get unique values from both tables. Operator UNION will remove repeated values.
SELECT * FROM tableA AS t1
UNION
SELECT * FROM tableB AS t2
You have a precedence problem here. Take all the records from table A and then the extra records from table B:
select *
from A
union all
select *
from B
where B.id not in (select A.id from A);
You can also express this with a full outer join (assuming id is not duplicated in either table):
select coalesce(A.id, B.id) as id,
coalesce(A.name, B.name) as name,
coalesce(A.age, B.age) as age
from A full outer join
B
on A.id = B.id;
In this case, the coalesce() gives priority to the values in A.
select distinct * FROM
(
select ID, NAME, AGE from TableA
UNION ALL
select ID, NAME, AGE from TableB
) TableAB
Some things to consider --> Unless you're updating specific tables and the records are the same, it will not matter which table you're viewing the records from (because they're the same...).
If you want to see which table the records are deriving from, let me know and i'll show you how to do that as well... but the query is more complex and i don't really think it's required for the purpose described above. let me know if this helps... thanks, Brian
If the tables has relation you need:
Select DISTINCT *
from tableA a
Inner Join tableB b
On a.id = b.id
If not:
You have to use UNION and after using DISTINCT.
DISTINCT will not permit repeat rows.
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.