Insert new/Changes from one table to another in Oracle SQL - sql

I have two tables with same number of columns :-Table A and Table B
Every day I insert data from Table B to Table A. now the insert query is working
insert into table_a (select * from table_b);
But by this insert the same data which was inserted earlier that is also getting inserted. I only want those rows which are new or are changed from the old data. How can this be done ?

You can use minus:
insert into table_a
select *
from table_b
minus
select *
from table_a;
This assumes that by "duplicate" you mean that all the columns are duplicated.

If you have a timestamp field, you could use it to limit the records to those created after the last copy.
Another option is, assuming that you have an primary key (id column in my example) that you can use to know whether a record has already been copied, you can create a table c (with the same structure as a and b) and do the following:
insert into table c
select a.* from table a
left join table b on (a.id=b.id)
where b.id is null;
insert into table b select * from table c;
truncate table c;
You need to adjust this query in order to use the actual primary key.
Hope this helps!

If the tables have a primary or unique key, then you could leverage that in an anti-join:
insert into table_a
select *
from table_b b
where not exists (
select null
from table_a a
where
a.pk_field_1 = b.pk_field_1 and
a.pk_field_2 = b.pk_field_2
)

You don't say what your key is. Assuming you have a key ID, that is you only want ID's that are not already in Table A. You can also use Merge-Statement for this:
MERGE INTO A USING B ON (A.ID = B.ID)
WHEN NOT MATCHED THEN INSERT (... columns of A) VALUES (... columns of B)

Related

Delete data comparing two tables

I have two tables: Table A and Table B. Both tables have a column like a Name, Location, Level. Table A is an initial table and Table B is the updated version of Table A. That means there will be new data present in Table B. I want to write a query that deletes the data from Table B if data is present in Table A but not in Table B. I don't want to delete the data from Table B if the table has a new row of data.
My approach was like this
Delete From TableB Where Exist(
SELECT * FROM dbo.TableB AS TB
EXCEPT
SELECT * FROM dbo.TableA as TA)
This one deletes the data, but it deletes the data from Table B if it is new inserted data as well. Any kind of suggestion is appreciated.
DELETE FROM TableB
WHERE EXIST(
SELECT 1
FROM TableA
WHERE TableA.Name = Name AND TableA.Location = Location AND TableA.Level = Level
)
If TableA has a primary key, then it's enough to check only this key in WHERE condition. Furthermore, if you have this primary key (e.g. it's Name), then you can do like this:
DELETE FROM TableB
WHERE Name IN (SELECT Name FROM TableA)

Insert into table without duplicates

I have a Table A from where I have to copy Data to Table B. Now problem is In both table A and Table B there is a column ID which is primary key and can't be null.Table A is having Duplicates. Can any one tell me How to insert Data into Table B from Table A without Duplicates?
It would be something like
INSERT INTO TableA(ID) SELECT DISTINCT ID FROM TableB B LEFT JOIN TableA A ON A.ID = B.ID WHERE A.ID IS NULL
You can use the DISTINCT function in a select statement to remove duplicates.
In the example I'm going to assume that both tables have 3 columns called ID, Name and Surname:
insert into tableB (ID, Name, Surname)
select
distinct(ID) as ID
,Name
,Surname
from tableA
;
Please note that the DISTINCT function will provide distinct rows.

How to get max of "not exists" query

I'm not super great with SQL, but I'm using it for a project. Below is the query I would like to write, but of course it isn't valid SQL
select * from a
where not exists (
select * from b
where a.name = b.name) common
where a.id > max(common.id)
My goal is to get the rows in a that do not join with those in b, but only those with a greater id than any of the ones that do join. The point of this is so that I can begin filling a database with values, stop, and then continue later where I left off.
I'm using sqlite with python; I know I could do two queries with python, but I'm guessing there is a way to do it with SQL (and I'm assuming that's 'better')
Dump:
BEGIN TRANSACTION;
CREATE TABLE "a" (
`Id` INTEGER NOT NULL UNIQUE,
`Name` TEXT,
PRIMARY KEY(`Id`)
);
INSERT INTO a VALUES(16,'Bob');
INSERT INTO a VALUES(17,'George');
INSERT INTO a VALUES(18,'Jimmy');
INSERT INTO a VALUES(19,'Billy');
INSERT INTO a VALUES(20,'Johnny');
INSERT INTO a VALUES(21,'James');
INSERT INTO a VALUES(22,'Bart');
CREATE TABLE "b" (
`Id` INTEGER NOT NULL UNIQUE,
`Name` TEXT NOT NULL,
PRIMARY KEY(`Id`)
);
INSERT INTO b VALUES(16,'Bob');
INSERT INTO b VALUES(19,'Billy');
COMMIT;
There are other columns, so these aren't identical tables, but the query should get Johnny, James, and Bart from table a.
I propose:
make a convenient common table expression for the inner join (first line)
select all from a which are not in ab (second line and fourth line)
restrict according to desired condition (third line)
Note that the ids from ab are identical to those from a which join with b. So their max is the max from ids in a which join.
I simply output *, using only the desired fields is possible should be easy.
Code:
with ab(id, field) as (select id, a.name from a join b using(id))
select * from a
where id > (select max(id) from ab)
except select * from ab;
Output:
20|Johnny
21|James
22|Bart
The following gets all rows from a that are bigger than the largest corresponding value in row b:
select a.*
from a
where a.id > (select max(b.id) from b where a.a_field = b.b_field)
It assumes that at least one record matches in b.
If you want to include all values, even when none exist, then I think this will do:
select a.*
from a
where a.id > all (select b.id from b where a.a_field = b.b_field)

SQL Select Into Field

I want to accomplish something of the following:
Select DISTINCT(tableA.column) INTO tableB.column FROM tableA
The goal would be to select a distinct data set and then insert that data into a specific column of a new table.
SELECT column INTO tableB FROM tableA
SELECT INTO will create a table as it inserts new records into it. If that is not what you want (if tableB already exists), then you will need to do something like this:
INSERT INTO tableB (
column
)
SELECT DISTINCT
column
FROM tableA
Remember that if tableb has more columns that just the one, you will need to list the columns you will be inserted into (like I have done in my example).
You're pretty much there.
SELECT DISTINCT column INTO tableB FROM tableA
It's going to insert into whatever column(s) are specified in the select list, so you would need to alias your select values if you need to insert into columns of tableB that aren't in tableA.
SELECT INTO
Try the following...
INSERT INTO tableB (column)
Select DISTINCT(tableA.column)
FROM tableA
The goal would be to select a distinct data set and then insert that data into a specific column of a new table.
I don't know what the schema of tableB is... if table B already exists and there is no unique constraint on the column you can do as any of the others suggest here....
INSERT INTO tableB (column)Select DISTINCT(tableA.column)FROM tableA
but if you have a unique constraint on table B and it already exists you'll have to exclude those values already in table B...
INSERT INTO tableB (column)
Select DISTINCT(tableA.column)
FROM tableA
WHERE tableA.column NOT IN (SELECT /* NOTE */ tableB.column FROM tableB)
-- NOTE: Remember if there is a unique constraint you don't need the more
-- costly form of a "SELECT DISTICT" in this subquery against tableB
-- This could be done in a number of different ways - this is just
-- one version. Best version will depend on size of data in each table,
-- indexes available, etc. Always prototype different ways and measure perf.

Compare unique values from two mysql tables

I have two mysql tables: TableA has 10,000 records TableB has 2,000 records.
I want to copy the 8,000 unique records from TableA into TableB ignoring the 2,000 in TableB which have already been copied.
If uniqueness is determined by PRIMARY KEY constraint or UNIQUE constraint, then you can use INSERT IGNORE:
INSERT IGNORE INTO TableB SELECT * FROM TableA;
The rows that are duplicates and that conflict with rows already in TableB will be silently skipped and the other 8,000 rows should be inserted.
See the docs on INSERT for more details.
If you need to do this in PHP, read about the array_diff_key() function. Store your arrays with the primary key values as the key of the array elements. No guarantees for the performance of this PHP function on such large arrays, though!
Use the INSERT INTO syntax:
INSERT INTO TABLE_B
SELECT *
FROM TABLE_A a
WHERE NOT EXISTS(SELECT NULL
FROM TABLE_B b
WHERE b.column = a.column)
You'll need to update the WHERE b.column = a.column) to satisfy however you determine that a record already exists in TABLE_B.
What about something like this :
insert into TableB
select *
from Table A
where not exists (
select 1
from TableB
where TableB.id = TableA.id
)
Or, if the entries in table B are "not unique" because of their primary key, an insert ignore might do the trick, I suppose.