Split One table into Two in SQL Server 2008 - sql

I need to break one table (structure built by someone else but I need the data it contains thousands of records) into two new tables I created.
Table Name: Customers_Info (Old Table)
FullName Telephone Address
Adam Johnson 01555777 Michigan
John Smith 01222333 New York
John Smith 01222333 New Jersey
Lara Thomas 01888999 New Mexico
The above is the old table. Now I created two tables to hold the data, one table for customers with a default address, and the other table to hold additional addresses. In the shown example I need 3 persons to be listed in the Customers table, and the address of "John Smith" (the second one New Jersey) to be listed in the Addresses table.
The common field to look at here is "Telephone" and it's unique for every customer.
Here's how the result should be display.
Table Name: Customers (New Table)
CustomerID FullName Telephone Default_Address
1 Adam Johnson 01555777 Michigan
2 John Smith 01222333 New York
3 Lara Thomas 01888999 New Mexico
Table Name: Addresses (New Table)
AddressID CustomerID Address
1 2 New Jersey
Of course it was easy to copy all data into the new Customers table, but what I'm stuck at now, is how to remove the duplicates from Customers and insert them into the Addresses table with the Customer ID and Address only.
Thanks!

Give a try with below code and let me know the comments/results.
CREATE TABLE [Customers_Info]
(
FullName VARCHAR(50)
,Telephone VARCHAR(50)
,Address VARCHAR(50)
)
GO
CREATE TABLE Customers
(
CustomerID INT IDENTITY(1,1)
,FullName VARCHAR(50)
,Telephone VARCHAR(50)
,Default_Address VARCHAR(50)
)
GO
ALTER TABLE dbo.Customers ADD CONSTRAINT PK_Customers
PRIMARY KEY CLUSTERED (CustomerID);
GO
CREATE TABLE Addresses
(
AddressID INT IDENTITY(1,1)
,CustomerID INT
,[Address] VARCHAR(50)
)
GO
ALTER TABLE dbo.Addresses ADD CONSTRAINT PK_Addresses
PRIMARY KEY CLUSTERED (AddressID);
GO
ALTER TABLE Addresses ADD CONSTRAINT FK_CustomerID_Addresses_Customers FOREIGN KEY (CustomerID)
REFERENCES dbo.Customers(CustomerID);
GO
INSERT INTO [Customers_Info] VALUES ('Adam Johnson', '01555777', 'Michigan')
INSERT INTO [Customers_Info] VALUES ('John Smith' , '01222333', 'New York')
INSERT INTO [Customers_Info] VALUES ('John Smith' , '01222333', 'New Jersey')
INSERT INTO [Customers_Info] VALUES ('Lara Thomas' , '01888999', 'New Mexico')
INSERT INTO [Customers_Info] VALUES ('Lara Thomas' , '01888999', 'New Mexico1')
INSERT INTO [Customers_Info] VALUES ('Lara Thomas' , '01888999', 'New Mexico2')
INSERT INTO [Customers_Info] VALUES ('Adam Johnson', '01555777', 'Michigan1')
INSERT INTO [Customers_Info] VALUES ('Adam Johnson', '01555777A', 'Michigan')
INSERT INTO [Customers_Info] VALUES ('Adam Johnson', '01555777A', 'Michigan2')
GO
SELECT * FROM [Customers_Info]
--DELETE FROM Customers
--TRUNCATE TABLE Addresses
------------------------------------------------------------------------------------------------------------------
;WITH a as
(
SELECT FullName,Telephone,[Address],
rn = row_number() over (partition by FullName, Telephone order by FullName)
FROM [Customers_Info]
)
INSERT INTO Customers SELECT
FullName,Telephone,[Address] from a where rn = 1
------------------------------------------------------------------------------------------------------------------
;WITH b as
(
SELECT FullName,Telephone,[Address],
rn = row_number() over (partition by FullName, Telephone order by FullName)
FROM [Customers_Info]
)
INSERT INTO Addresses SELECT CI.CustomerID,b.[Address] FROM Customers CI
INNER JOIN b ON b.FullName=CI.FullName AND b.Telephone=CI.Telephone
WHERE b.rn>1
SELECT * FROM Customers
SELECT * FROM Addresses
DROP TABLE [Customers_Info]
GO
DROP TABLE Addresses
GO
DROP TABLE Customers
GO

It would be more normalized if you broke it up into one more table for three total tables. Have the Customers table that has only customer data, have the Address table (which you could possibly rename to State) that has only the Address, then a CustomerAddress table that has both keys to each of those tables as Foreign Keys.
I will start you off to begin:
INSERT INTO Customers (FullName, Telephone)
SELECT DISTINCT FullName, Telephone
FROM Customers_Info
You would do the same for Address. For the 3rd table, you would perform the lookups like this:
INSERT INTO CustomerAddress (CustomerID, AddressID)
SELECT C.CustomerID, A.AddressID
FROM Customers_Info CI
INNER JOIN Customers C
ON CI.Telephone = C.Telephone
INNER JOIN Address A
ON CI.Address = A.Address

Related

Removing Duplicates added by foriegn key in Oracle DB

I'am working on a Hostel Project in Oracle DB, I have 2 tables (students,rooms) and when I run query to get name of students ,their room IDs and facilities that are provided to them it returns duplicate student names with all the facilities and with little editing in query it returns duplicate facilities.
How can I fix those duplicates?
Here is the Code
--CREATE TABLE STUDENTS
Create table students(
regno integer primary key,
name varchar2(30),
phonenum number,
address varchar2(30),
roomalloc number
);
Alter Table students Add CONSTRAINT fk_roomalloc
FOREIGN KEY (roomalloc)
REFERENCES rooms(roomno);
Alter table students drop constraint fk_roomalloc
--ALTER TABLE STUDENTS ADD JOIN DATE
alter table students add (joindate Date);
--Alter Table for Gender
Alter Table students add(gender varchar2(2));
Alter Table students MODIFY gender NOT NULL;
--Constraint on Gender
Alter Table students Add CONSTRAINT gen
Check (gender IN('M','F','m','f'));
Alter Table students MODIFY mess default 'M';
--Constraint Gender Check for Room Allocation
Alter Table students Add CONSTRAINTS gen_check
Check (Room IN(Gender='M' , 'Gender='F'));
--Constraints:ADD MESS AS TRUE/FALSE
ALTER TABLE students ADD (mess varchar2(4));
Alter Table students Add CONSTRAINT mess_present
Check (mess IN('Yes','No','yes','no'));
Alter Table students MODIFY mess default 'No';
--Drop Constraint
ALTER TABLE students
DROP CONSTRAINT mess_present
--ALTER TABLE NAME AS NOT NULL
alter table students MODIFY name NOT NULL;
--ALTER TABLE PHONE NO
alter table students MODIFY phonenum UNIQUE;
--ALTER TABLE Room Allocated
alter table students MODIFY roomalloc Not Null;
Describe students;
--DATA ENTRY and Modification
INSERT INTO students(regno, name, phonenum, address, roomalloc,joindate,mess)
VALUES (1, 'Haseeb', 012345678,'Rawalpindi',1,'1-sep-14','No');
INSERT INTO students(regno, name, phonenum, address, roomalloc,joindate)
VALUES (2, 'Faisal', 03451111111,'Rawalpindi',1,'12-sep-14');
INSERT INTO students(regno, name, phonenum, address, roomalloc,joindate)
VALUES (3, 'Shahbaz', 03313214567,'Khewra',1,'15-feb-15');
INSERT INTO students(regno, name, phonenum, address, roomalloc,joindate)
VALUES (4, 'Muhaddas', 01235131237,'Kashmir',1,'15-feb-15');
INSERT INTO students(regno, name, phonenum, address, roomalloc,joindate,mess)
VALUES (5, 'Haseem', 01254530987,'Islamabad',2,'15-sep-15','Yes');
INSERT INTO students(regno, name, phonenum, address, roomalloc,joindate,mess)
VALUES (6, 'Asim', 03341234567,'Muzzafargarh',3,'15-sep-14','Yes');
INSERT INTO students(regno, name, phonenum, address, roomalloc,joindate,mess)
VALUES (7, 'Izza', 01231234564,'Sialkot',25,'15-sep-15','Yes');
INSERT INTO students(regno, name, phonenum, address, roomalloc,joindate,mess)
VALUES (8, 'Sara', 01231234561,'Narrowal',25,'15-sep-15','Yes');
INSERT INTO students(regno, name, phonenum, address, roomalloc,joindate,mess)
VALUES (9, 'Maria', 01231234567,'Wah',4,'25-sep-15','Yes');
INSERT INTO students(regno, name, phonenum, address, roomalloc,joindate,Gender)
VALUES (10, 'Faha', 0123123452,'Okara',4,'26-sep-15','F');
Update students SET Gender='M' WHERE regno>=1 And regno<=6;
Update students SET roomalloc=4,Gender='F' WHERE regno>=7 And regno<=9;
Describe students;
--Data Fetching Queries
Select *
From students,rooms
Where rooms.facility='Fan/Net/TV'
ORDER BY roomalloc , regno;
Drop table students;
--CREATE TABLE Rooms
Create table rooms(
roomno integer primary key,
facility varchar2(30)
);
--Altering Rooms Types
Alter Table rooms Add CONSTRAINT rtype
Check (facility IN('AC/Net/TV','Fan/Net/TV','Fan/Net'));
Alter Table rooms MODIFY facility default 'Fan/Net';
Alter table rooms drop constraint str
INSERT INTO rooms( roomno, facility)
VALUES (1,'AC/Net/TV');
INSERT INTO rooms( roomno, facility)
VALUES (2,'Fan/Net/TV');
INSERT INTO rooms( roomno, facility)
VALUES (3,'Fan/Net/TV');
INSERT INTO rooms( roomno, facility)
VALUES (4,'Fan/Net');
Alter table rooms Modify facility UNIQUE
Select *
From rooms;
Select students.name,rooms.facility
From students,rooms
Where roomno=4;
Drop table rooms
You need to join the tables properly to get the desired result:
Select students.name,rooms.facility
From students join rooms on students.roomalloc = rooms.roomno
Where rooms.roomno=4;

SELECT From Multiple tables with many to many relations

Hello everyone I have inherirted a poorly designed database and I need to get some information from 3 tables
Franchise
Id(Int, PK)
FrID (varchar(50))
FirstName (varchar(50))
LastName (varchar(50))
Store
Id (Int, PK)
FrID (varchar(50))
StoreNumber (varchar(50))
StoreName
Address
Pricing
Id (int, PK)
StoreNumber (varchar(50))
Price1
Price2
Price3
and the data
ID, FrID ,FirstName,LastName
1, 10 ,John Q , TestCase
2, 10 ,Jack Q , TestCase
3, 11 ,Jack Q , TestCase
ID, FrID, StoreNumber , StoreName , Address
10, 10 , 22222 , TestStore1, 123 Main street
11, 10 , 33333 , TestStore2, 144 Last Street
12, 10 , 44444 , TestStore2, 145 Next Street
13, 11 , 55555 , Other Test, 156 Other st
ID, StoreNumber, Price1, Price2, Price3
1, 22222 , 19.99, 20.99 , 30.99
2, 33333 , 19.99, 20.99 , 30.99
3, 44444 , 19.99, 20.99 , 30.99
4, 55555 , 19.99, 20.99 , 30.99
Here is what I have done
SELECT F.FirstName,F.LastName,F.FrID , S.StoreNumber,S.StoreName,S.Address,
P.Price1,P.Price2,P.Price3
FROM Franchisee F
JOIN Store S on F.FrID = S.FrID
JOIN Pricing P on P.StoreNumber = S.StoreNumber
This part works, but I end up with lots of duplicates, For example Jack Q gets listed for his store plus every store that John Q is on. Is there anyway to fix this with out a database redesign.
Okay, there is a whole laundry list of issues such as character fields such as [FrId] being used as strings, reserved words such as [address] being used as name, etc.
Let's put the bad design issues aside.
First, I need to create a quick test environment. I did not put in Foreign Keys since that constraint is not needed to get the correct answer.
--
-- Setup test tables
--
-- Just playing
use Tempdb;
go
-- drop table
if object_id('franchise')> 0
drop table franchise;
go
-- create table
create table franchise
(
Id int primary key,
FrID varchar(50),
FirstName varchar(50),
LastName varchar(50)
);
-- insert data
insert into franchise values
( 1, 10, 'John Q', 'TestCase'),
( 2, 10, 'Jack Q', 'TestCase'),
( 3, 11, 'Jack Q', 'TestCase');
-- select data
select * from franchise;
go
-- drop table
if object_id('store')> 0
drop table store;
go
-- create table
create table store
(
Id int primary key,
FrID varchar(50),
StoreNumber varchar(50),
StoreName varchar(50),
Address varchar(50)
);
-- insert data
insert into store values
(10, 10, 22222, 'TestStore1', '123 Main street'),
(11, 10, 33333, 'TestStore2', '144 Last Street'),
(12, 10, 44444, 'TestStore2', '145 Next Street'),
(13, 11, 55555, 'Other Test', '156 Other Street');
-- select data
select * from store;
go
-- drop table
if object_id('pricing')> 0
drop table pricing;
go
-- create table
create table pricing
(
Id int primary key,
StoreNumber varchar(50),
Price1 money,
Price2 money,
Price3 money
);
-- insert data
insert into pricing values
(1, 22222, 19.99, 20.99 , 30.99),
(2, 33333, 19.99, 20.99 , 30.99),
(3, 44444, 19.99, 20.99 , 30.99),
(4, 55555, 19.95, 20.95 , 30.95);
-- select data
select * from pricing;
go
The main issue is that the franchise table should have the primary key (PK) on FrId, not Id. I do not understand why there are duplicates.
However, the query below removes them by grouping. I changed the pricing data for Jack Q to show it is a different record.
--
-- Fixed Query - Version 1
--
select
f.FirstName,
f.LastName,
f.FrID,
s.StoreNumber,
s.StoreName,
s.Address,
p.Price1,
p.Price2,
p.Price3
from
-- Remove duplicates from francise
(
select
LastName,
FirstName,
Max(FrID) as FrID
from
franchise
group by
LastName,
FirstName
) as f
join store s on f.FrID = s.FrID
join pricing p on p.StoreNumber = s.StoreNumber;
The correct output is below.
If I am correct, remove the duplicates entries and change the primary key.
Change Requirements
Okay, you are placing two or more owners in the same table.
Below uses a sub query to combine the owners list into one string. Another way is to have a flag called primary owner. Choose that as the display name.
--
-- Fixed Query - Version 2
--
select
f.OwnersList,
f.FrID,
s.StoreNumber,
s.StoreName,
s.Address,
p.Price1,
p.Price2,
p.Price3
from
-- Compose owners list
(
select
FrID,
(
SELECT FirstName + ' ' + LastName + ';'
FROM franchise as inner1
WHERE inner1.FrID = outer1.FrID
FOR XML PATH('')
) as OwnersList
from franchise as outer1
group by FrID
) as f (FrId, OwnersList)
join store s on f.FrID = s.FrID
join pricing p on p.StoreNumber = s.StoreNumber
Here is the output from the second query.

SQL Server, renumber int column sequentially on two tables

I have the following two tables and data:-
CREATE TABLE customers
([id] int, [name] varchar(10), [sex] varchar(1))
;
INSERT INTO customers
([id], [name], [sex])
VALUES
(1050, 'John Doe', 'M'),
(1060, 'Jane Doe', 'F'),
(1031, 'Joe Bloggs', 'M')
;
CREATE TABLE orders
([id] int, [fk] int, [product] varchar(13))
;
INSERT INTO orders
([id], [fk], [product])
VALUES
(51, 1050, 'Blue car'),
(57, 1050, 'Yellow car'),
(43, 1060, 'Pink bus'),
(32, 1031, 'Black pen'),
(87, 1031, 'Orange jacket')
;
What i want to do is re-number the id column in both tables sequentially starting from 1.
The linked rows in the orders table must also be renumbered, and the foreign key in this table must match the new number in the customers table.
so the data needs to end up looking like this:-
ID NAME SEX
0001 John Doe M
0002 Jane Doe F
0003 Joe Bloggs M
ID FK PRODUCT
0001 0001 Blue car
0002 0001 Yellow car
0003 0002 Pink bus
0004 0003 Black pen
0005 0003 Orange jacket
How would I go about doing this in SQL Server ?
Absolutely no need to resort to cursor (yikes!) here.... you need something like this:
-- Table "Customers" - rename column "id" to "old_id"
EXEC sp_rename 'dbo.Customers.id', 'old_id'
-- add new "id" column
ALTER TABLE Customers ADD id INT
-- fill new "id" column with sequential values, ordered by the "old_id" value
;WITH CTE AS
(
SELECT old_id, new_id = ROW_NUMBER() OVER (ORDER BY old_id)
FROM Customers
)
UPDATE dbo.Customers
SET id = CTE.new_id
FROM CTE
WHERE CTE.old_id = dbo.Customers.old_id
-- Table "Orders" - rename column "id" to "old_id"
EXEC sp_rename 'dbo.orders.id', 'old_id'
-- add new "id" column
ALTER TABLE Orders ADD id INT
-- update the FK references to the new "id" values in table "dbo.Customers"
UPDATE dbo.Orders
SET fk = c.id
FROM dbo.Customers c
WHERE dbo.ORders.fk = c.old_id
-- fill new "id" column with sequential values, ordered by the "old_id" value
;WITH CTE AS
(
SELECT old_id, new_id = ROW_NUMBER() OVER (ORDER BY old_id)
FROM dbo.Orders
)
UPDATE dbo.Orders
SET id = CTE.new_id
FROM CTE
WHERE CTE.old_id = dbo.Orders.old_id
-- drop the old, no longer required columns "old_id" from both tables
ALTER TABLE dbo.Customers DROP COLUMN old_id
ALTER TABLE dbo.Orders DROP COLUMN old_id
That'll work, if you don't have any other FK relationships that are referencing one of those two tables. If you do, then you might need to disable or drop those FK relationships before you start this upgrade script.
If this is a one time maintenace type fix you want to do, I would do this by:
disable all the foregin keys
add an oldid column to your customers table
put the current ID field into the oldid field
replace all the customer id's with new id's
update the orders table with the now udpated id using a join/update on the oldid field from the customer table
drop the oldid column
add back your foriegn key constraints.
voila
Remove foreign key.
Create customers2 table with extra column OldId and column Id as IDENTITY.
Insert all rows from cutomers to customers2 (with mapping customers.Id to customers2.OldId)
Do update on orders.fk setting orders.fk = customers2.id
Do the same with the orders table what you did with the customers in point 2 and 3.
drop customers, drop orders, rename customers2, rename orders2
Recreate foreign key.

SQL: Insert data from another table in a table that contains foreign keys

In a SQL DATABASE
I have a Table Users
Id Name Age AddressId
----+------+------+-----------
Where AddressId is a foreign key to a table names Addresses
The Addresses Table:
Id Country State City ZipCode
----+---------+------+------+---------
This is a ONE-TO-ONE Relationship: Each User Has 1 address and each address has one user
I have a new table named NEWUsers
Id Name
----+------
It has only Id and Name.
What i want to do is this:
Write a script to insert all the records From the NEWUSers Table into the Users Table.
I want The Age to be default 20 for all new users
And for each new user inserted I need to create a new Address record for him
the new Address record will have all it's values (country, city, state, zipcode) equal to "abcd" except the Id which will be used to set the foreign key AddressId for the new user)
How can I do that?
I tried the following:
INSERT INTO Users(Name, Age)
Values((SELECT Name FROM NewUsers),20)
But I don't know how to create a new Address record for each user inserted and specify the foreign key accordingly.
Thanks a lot for any help
One method would be with two queries, formed like the following:
INSERT INTO Addresses (Country, State, City, ZipCode)
SELECT 'abcd', 'abcd', 'abcd', 'abcd' FROM NewUsers
INSERT INTO Users (Name, Age, AddressId)
SELECT Name, 20, ?? FROM NewUsers
Edit: One simple way to link the users to the addresses would be to temporarily set the country to the username. Then you would have a link to determine the addressId. Once the users table is populated and linked up properly, you can set country back to the default value abcd:
insert addresses (country, state, city, zipcode)
select name, 'abcd', 'abcd', 'abcd' from newusers;
insert users (name, age, addressid)
select u.name, 20, a.id from newusers u
join addresses a on a.country = u.name;
update a
set a.country = 'abcd'
from addresses a join newusers u on a.country = u.name;
Demo: http://www.sqlfiddle.com/#!3/1f09b/8
There are more complex ways to do this if you want to guarantee transactional consistency if multiple inserts can happen simultaneously, or if you want to allow duplicate names, etc. But based on the example you've given and details so far, this method should work.
This is a little hacky, but does what you want in two statements - assuming no user is going to have the name 'abcd' or enter that for their country, and that you purge the NewUsers table after this operation:
INSERT dbo.Addresses(Country, State, City, ZipCode)
OUTPUT inserted.Country, 20, inserted.id
INTO dbo.Users
SELECT Name, 'abcd', 'abcd', 'abcd'
FROM dbo.NewUsers;
UPDATE a SET Country = 'abcd'
FROM dbo.Addresses AS a
INNER JOIN dbo.NewUsers AS nu
ON a.Country = nu.Name;
You Must Write Cursor For Insert In Users and Address Table With Forign key
DECLARE #AddressID INT,
#ID INT,
#Name NVARCHAR(50)
DECLARE UserCursor CURSOR FOR
SELECT ID, NAME
FROM NewUsers
OPEN UserCursor
FETCH NEXT FROM UserCursor INTO #ID, #Name
WHILE ##FETCH_STATUS =0 BEGIN
INSERT INTO Addresses(Country, State, City, ZipCode)
VALUES ('abcd', 'abcd', 'abcd', 'abcd')
SET #AddressID = SCOPE_IDENTITY()
INSERT INTO Users(Name, Age, AddressID)
VALUES (#Name, 20, #AddressID)
FETCH NEXT FROM UserCursor INTO #ID, #Name
END
CLOSE UserCursor
DEALLOCATE UserCursor
Assuming you can set the AddressId however you want...
INSERT Addresses
(
Id,
Country,
State,
City,
ZipCode
)
SELECT
Id,
'abcd',
'abcd',
'abcd',
'abcd'
FROM NEWUsers
INSERT Users
(
Id,
Name,
Age,
AddressId
)
SELECT
Id,
Name,
20,
Id
FROM NEWUsers
If AddressId is an identity column, you can disable the identity temporarily first. See SET IDENTITY_INSERT for info and examples.
Honestly, the answer is that you don't want to do what you think you want to do. If the users have one and only one address, as you stated, then you should have only one table (users) that contains the address fields. Modeling your data properly will make this problem go away intrinsically.

Moving away from STI - SQL to break single table into new multi-table structure

I am moving old project that used single table inheritance in to a new database, which is more structured. How would I write a SQL script to port this?
Old structure
I've simplified the SQL for legibility.
CREATE TABLE customers (
id int(11),
...
firstName varchar(50),
surname varchar(50),
address1 varchar(50),
address2 varchar(50),
town varchar(50),
county varchar(50),
postcode varchar(50),
country varchar(50),
delAddress1 varchar(50),
delAddress2 varchar(50),
delTown varchar(50),
delCounty varchar(50),
delPostcode varchar(50),
delCountry varchar(50),
tel varchar(50),
mobile varchar(50),
workTel varchar(50),
);
New structure
CREATE TABLE users (
id int(11),
firstName varchar(50),
surname varchar(50),
...
);
CREATE TABLE addresses (
id int(11),
ForeignKey(user),
street1 varchar(50),
street2 varchar(50),
town varchar(50),
county varchar(50),
postcode varchar(50),
country varchar(50),
type ...,
);
CREATE TABLE phone_numbers (
id int(11),
ForeignKey(user),
number varchar(50),
type ...,
);
With appropriate cross-database notations for table references if appropriate:
INSERT INTO Users(id, firstname, surname, ...)
SELECT id, firstname, surname, ...
FROM Customers;
INSERT INTO Addresses(id, street1, street2, ...)
SELECT id, street1, street2, ...
FROM Customers;
INSERT INTO Phone_Numbers(id, number, type, ...)
SELECT id, phone, type, ...
FROM Customers;
If you want both the new and the old address (del* version), then repeat the address operation on the two sets of source columns with appropriate tagging. Similarly, for the three phone numbers, repeat the phone number operation. Or use a UNION in each case.
First make sure to backup your existing data!
The process is differnt if you are going to use the original id field or generate a new one.
Assuming you are going to use the orginal, make sure that you have the ability to insert id fields into the table before you start (the SQL Server equivalent if you are autogenrating the number is Set identity Insert on, not sure what mysql would use). Wirte an insert from the old table to the parent table:
insert newparenttable (idfield, field1, field2)
select idfield, field1, field2 from old parent table
then write similar inserts for all the child tables depending on what fields you need. Where you have multiple phone numbers in differnt fields, for instance, you would use a union all stament as your insert select.
Insert newphone (phonenumber, userid, phonetype)
select home_phone, id, 100 from oldparenttable
union all
select work_phone, id, 101 from oldparenttable
Union all
select cell_phone, id, 102 from oldparenttable
If you are going to have a new id generated, then create the table with a field for the old id. You can drop this at the end (although I'd keep it for about six months). Then you can join from the new parent table to the old parent table on the oldid and grab the new id from the new parent table when you do you inserts to child tables. Something like:
Insert newphone (phonenumber, userid, phonetype)
select home_phone, n.id, 100 from oldparenttable o
join newparenttable n on n.oldid = o.id
union all
select work_phone, n.id, 101 fromoldparenttable o
join newparenttable n on n.oldid = o.id
Union all
select cell_phone, n.id, 102 from oldparenttable o
join newparenttable n on n.oldid = o.id