Copy data from one database to another - referenced tables and identities included - sql

I have a database with this two tables :
[OldDb].[Per].[Person]
PersonId | FirstName | LastName | Code
2003 | 'Mike' | 'Jordan' | 2
2357 | 'Sara' | 'Jacobs' | 1
3481 | 'John' | 'Gates' | 5
[OldDb].[Sal].[Customer]
CustomerId | PersonId | CustomerType
830 | 2003 | 3
945 | 2357 | 2
1333 | 3481 | 2
And my new database with same tables and schema :
[NewDb].[Per].[Person]
PersonId | FirstName | LastName | Code
[NewDb].[Sal].[Customer]
CustomerId | PersonId | CustomerType
PersonId in table Person is identity and I can use this code to copy people but PersonId's will be different from old database so I can't use the second query I said below to copy data from customer table.
INSERT INTO NewDb.per.Person
(FirstName,LastName,Code)
SELECT FirstName,LastName,Code
FROM OldDb.per.Person
INSERT INTO NewDb.Sal.Customer
(PersonId,CustomerType)
SELECT PersonId,CustomerType
FROM OldDb.Sal.Customer
Now I want a query so I can copy data to new db for both tables.
Any help would be a great help.
Thank you.

Your new database is empty, if you want to keep your old PersonId, you could use SET IDENTITY_INSERT NewDb.per.Person ON
SET IDENTITY_INSERT NewDb.per.Person ON -- then you could use personId in Insert
INSERT INTO NewDb.per.Person
(PersonId, FirstName,LastName,Code)
SELECT PersonId, FirstName,LastName,Code
FROM OldDb.per.Person
SET IDENTITY_INSERT NewDb.per.Person OFF -- remember set it off after insert
-- then insert new Customer without conflict
INSERT INTO NewDb.Sal.Customer
(PersonId,CustomerType)
SELECT PersonId,CustomerType
FROM OldDb.Sal.Custome
Reference link: SET IDENTITY_INSERT
And if you want new PersonId auto increment you could do this:
----CREATE `OldPersonId` column in your NewDb.per.Person
INSERT INTO NewDb.per.Person
(OldPersonId, FirstName,LastName,Code)
SELECT PersonId, FirstName,LastName,Code
FROM OldDb.per.Person
-- You could insert you new customer Inner join by `OldPersonId` Column
INSERT INTO NewDb.Sal.Customer
(PersonId,CustomerType)
SELECT np.PersonId,CustomerType
FROM OldDb.Sal.Customer oc
INNER JOIN NewDb.per.Person np ON oc.PersonId = np.OldPersonId
-----DELETE `OldPersonId` column in NewDb.per.Person

Related

Find difference between two table in SQL and append back result to source table & update column values only for newly inserted rows

I am new to SQL Server. I want to create a procedure which should check difference between master table & quarterly table and insert the different rows back to the master table and update the corresponding column values.
Master table is like:
|PID | Release_date | Retired_date
|loc12|202108 |
|loc34|202108 |
Quaterly table is like:
|PID | Address | Post_code
|loc12| Srinagar | 5678
|loc34| Girinagar | 6789
|loc45| RRnagar | 7890
|loc56| Bnagar | 9012
Resultant Master table should be like:
|PID | Release_date | Retired_date
|loc12|202108 |
|loc34|202108 |
|loc45|202111 |
|loc56|202111 |
I have tried except but I'm not able to update the master table after inserting the difference. My code is
insert into master(select PID from Master
except
select PID from Quaterly)
update master
set Release_date = '202111'
where PID in (select PID from Master
except
select PID from Quaterly)
TIA
You could do everything in one query, no need to use UPDATE:
INSERT INTO Master(PID, Release_date)
SELECT q.PID, '202111'
FROM Quaterly q
WHERE q.PID NOT IN (SELECT PID FROM Master)
Other approach you can use by leveraging SQL JOINs:
INSERT INTO MASTER
SELECT q2.PID, '202111'
FROM Quaterly q1
LEFT JOIN Quaterly q2
ON q1.PID = q2.PID
WHERE q1.PID IS NULL

SQL Server: Insert row into table, for all id's not existing yet

I have three tables in MS SQL Server, one with addresses, one with addresstypes and one with assignments of addresstypes:
Address:
IdAddress | Name | ...
1 | xyz
2 | abc |
...
AddressTypes
IdAddresstype | Caption
1 | Customer
2 | Supplier
...
Address2AddressType
IdAddress2AddressType | IdAddress | IdAddressType
1 | 1 | 2
3 | 3 | 2
Now I want to insert a row into Address2AddressType for each address, which is not assigned yet / not emerging in this table with the Addresstype Customer.
So to select those addresses, I use this query:
SELECT adresses.IdAddress
FROM [dbo].[Address] AS adresses
WHERE adresses.IdAddress NOT IN (SELECT adresstypeassignment.IdAddress
FROM [dbo].[Address2AddressType] AS adresstypeassignment)
Now I need to find a way to loop through all those results to insert like this:
INSERT INTO (Address2AddressType (IdAddress, IdAddresstype)
VALUES (<IdAddress from result>, 1)
Can anybody help, please?
Thanks in advance.
Regards
Lars
Use insert . . . select:
INSERT INTO Address2AddressType (IdAddress, IdAddresstype)
SELECT a.IdAddress, 1
FROM [dbo].[Address] a
WHERE a.IdAddress NOT IN (SELECT ata.IdAddress FROM [dbo].Address2AddressType ata);
I also simplified the table aliases.
Note: I don't recommend NOT IN for this purpose, because it does not handle NULLs the way you expect (if any values returned by the subquery are NULL no rows at all will be inserted). I recommend NOT EXISTS instead:
INSERT INTO Address2AddressType (IdAddress, IdAddresstype)
SELECT a.IdAddress, 1
FROM [dbo].[Address] a
WHERE NOT EXISTS (SELECT 1
FROM [dbo].Address2AddressType ata
WHERE ata.IdAddress = a.IdAddress
);

Postgresql Sequence vs Serial

I was wondering when it is better to choose sequence, and when it is better
to use serial.
What I want is returning last value after insert using
SELECT LASTVAL();
I read this question
PostgreSQL Autoincrement
I never use serial before.
Check out a nice answer about Sequence vs. Serial.
Sequence will just create sequence of unique numbers. It's not a datatype. It is a sequence. For example:
create sequence testing1;
select nextval('testing1'); -- 1
select nextval('testing1'); -- 2
You can use the same sequence in multiple places like this:
create sequence testing1;
create table table1(id int not null default nextval('testing1'), firstname varchar(20));
create table table2(id int not null default nextval('testing1'), firstname varchar(20));
insert into table1 (firstname) values ('tom'), ('henry');
insert into table2 (firstname) values ('tom'), ('henry');
select * from table1;
| id | firstname |
|----|-----------|
| 1 | tom |
| 2 | henry |
select * from table2;
| id | firstname |
|----|-----------|
| 3 | tom |
| 4 | henry |
Serial is a pseudo datatype. It will create a sequence object. Let's take a look at a straight-forward table (similar to the one you will see in the link).
create table test(field1 serial);
This will cause a sequence to be created along with the table. The sequence name's nomenclature is <tablename>_<fieldname>_seq. The above one is the equivalent of:
create sequence test_field1_seq;
create table test(field1 int not null default nextval('test_field1_seq'));
Also see: http://www.postgresql.org/docs/9.3/static/datatype-numeric.html
You can reuse the sequence that is auto-created by serial datatype, or you may choose to just use one serial/sequence per table.
create table table3(id serial, firstname varchar(20));
create table table4(id int not null default nextval('table3_id_seq'), firstname varchar(20));
(The risk here is that if table3 is dropped and we continue using table3's sequence, we will get an error)
create table table5(id serial, firstname varchar(20));
insert into table3 (firstname) values ('tom'), ('henry');
insert into table4 (firstname) values ('tom'), ('henry');
insert into table5 (firstname) values ('tom'), ('henry');
select * from table3;
| id | firstname |
|----|-----------|
| 1 | tom |
| 2 | henry |
select * from table4; -- this uses sequence created in table3
| id | firstname |
|----|-----------|
| 3 | tom |
| 4 | henry |
select * from table5;
| id | firstname |
|----|-----------|
| 1 | tom |
| 2 | henry |
Feel free to try out an example: http://sqlfiddle.com/#!15/074ac/1
2021 answer using identity
I was wondering when it is better to choose sequence, and when it is better to use serial.
Not an answer to the whole question (only the part quoted above), still I guess it could help further readers. You should not use sequence nor serial, you should rather prefer identity columns:
create table apps (
id integer primary key generated always as identity
);
See this detailed answer: https://stackoverflow.com/a/55300741/978690 (and also https://wiki.postgresql.org/wiki/Don%27t_Do_This#Don.27t_use_serial)

update a table from another table and add new values

How would I go about updating a table by using another table so it puts in the new data and if it doesnt match on an id it adds the new id and the data with it. My original table i much bigger than the new table that will update it. and the new table has a few ids that aren't in the old table but need to be added.
for example I have:
Table being updated-
+-------------------+
| Original Table |
+-------------------+
| ID | Initials |
|------+------------|
| 1 | ABC |
| 2 | DEF |
| 3 | GHI |
and...
the table I'm pulling data from to update the other table-
+-------------------+
| New Table |
+-------------------+
| ID | Initials |
|------+------------|
| 1 | XZY |
| 2 | QRS |
| 3 | GHI |
| 4 | ABC |
then I want my Original table to get its values that match up to be updated by the new table if they have changed, and add any new ID rows if they aren't in the original table so in this example it would look like the New Table.
+-------------------+
| Original Table |
+-------------------+
| ID | Initials |
|------+------------|
| 1 | XZY |
| 2 | QRS |
| 3 | GHI |
| 4 | ABC |
You can use MERGE statement to put this UPSERT operation in one statement but there are issues with merge statement I would split it into two Statements, UPDATE and INSERT
UPDATE
UPDATE O
SET O.Initials = N.Initials
FROM Original_Table O INNER JOIN New_Table N
ON O.ID = N.ID
INSERT
INSERT INTO Original_Table (ID , Initials)
SELECT ID , Initials
FROM New_Table
WHERE NOT EXISTS ( SELECT 1
FROM Original_Table
WHERE ID = Original_Table.ID)
Important Note
Reason why I suggested to avoid using merge statement read this article Use Caution with SQL Server's MERGE Statement by Aaron Bertrand
You need to use the MERGE statement for this:
MERGE original_table AS Target
USING updated_table as Source
ON original_table.id = updated_table.id
WHEN MATCHED THEN UPDATE SET Target.Initials = Source.Initials
WHEN NOT MATCHED THEN INSERT(id, Initials) VALUES(Source.id, Source.Initials);
You have not specified, what happens in case the valuesin original table are not found in the updated one. But, just in case, you can add this to remove them from original table:
WHEN NOT MATCHED BY SOURCE
THEN DELETE
if you can use loop in PHP and go through all tables and copy one by one to another table.
another option
DECLARE #COUT INT
SET #COUT = SELECT COUNT(*) FROM New_Table
WHILE (true)
BEGIN
IF #COUT = 0
BREAK;
SET #COUT = #COUT - 1
DECLARE #id INT
DECLARE #ini VARCHAR(20)
SET #id = (SELECT id FROM New_Table);
SET #ini = (SELECT Initials FROM New_Table);
IF (SELECT COUNT(*) FROM Original_Table WHERE id=#id ) > 0
UPDATE SET ID = #id,Initials = #ini FROM Original_Table WHERE id = #id;
insert into Original_Table values(#id,#ini);
END
GO

Write SQL script to insert data

In a database that contains many tables, I need to write a SQL script to insert data if it is not exist.
Table currency
| id | Code | lastupdate | rate |
+--------+---------+------------+-----------+
| 1 | USD | 05-11-2012 | 2 |
| 2 | EUR | 05-11-2012 | 3 |
Table client
| id | name | createdate | currencyId|
+--------+---------+------------+-----------+
| 4 | tony | 11-24-2010 | 1 |
| 5 | john | 09-14-2010 | 2 |
Table: account
| id | number | createdate | clientId |
+--------+---------+------------+-----------+
| 7 | 1234 | 12-24-2010 | 4 |
| 8 | 5648 | 12-14-2010 | 5 |
I need to insert to:
currency (id=3, Code=JPY, lastupdate=today, rate=4)
client (id=6, name=Joe, createdate=today, currencyId=Currency with Code 'USD')
account (id=9, number=0910, createdate=today, clientId=Client with name 'Joe')
Problem:
script must check if row exists or not before inserting new data
script must allow us to add a foreign key to the new row where this foreign related to a row already found in database (as currencyId in client table)
script must allow us to add the current datetime to the column in the insert statement (such as createdate in client table)
script must allow us to add a foreign key to the new row where this foreign related to a row inserted in the same script (such as clientId in account table)
Note: I tried the following SQL statement but it solved only the first problem
INSERT INTO Client (id, name, createdate, currencyId)
SELECT 6, 'Joe', '05-11-2012', 1
WHERE not exists (SELECT * FROM Client where id=6);
this query runs without any error but as you can see I wrote createdate and currencyid manually, I need to take currency id from a select statement with where clause (I tried to substitute 1 by select statement but query failed).
This is an example about what I need, in my database, I need this script to insert more than 30 rows in more than 10 tables.
any help
You wrote
I tried to substitute 1 by select statement but query failed
But I wonder why did it fail? What did you try? This should work:
INSERT INTO Client (id, name, createdate, currencyId)
SELECT
6,
'Joe',
current_date,
(select c.id from currency as c where c.code = 'USD') as currencyId
WHERE not exists (SELECT * FROM Client where id=6);
It looks like you can work out if the data exists.
Here is a quick bit of code written in SQL Server / Sybase that I think answers you basic questions:
create table currency(
id numeric(16,0) identity primary key,
code varchar(3) not null,
lastupdated datetime not null,
rate smallint
);
create table client(
id numeric(16,0) identity primary key,
createddate datetime not null,
currencyid numeric(16,0) foreign key references currency(id)
);
insert into currency (code, lastupdated, rate)
values('EUR',GETDATE(),3)
--inserts the date and last allocated identity into client
insert into client(createddate, currencyid)
values(GETDATE(), ##IDENTITY)
go