I am new stored procedures and trying to write a procedure to duplicate user(by user_id) master detail data into a new user data. Here is my table structure. I will pass a target user_id and destination user_id to the stored procedure. Could you please let me know the how to achieve this functionality? I appreciate any help.
TABLE A
----------------
a_id int(Primary Key)
desc varchar(50)
user_id int
TABLE B
-----------------
b_id int(Primary Key)
a_id int(Foreign Key)
detail varchar(100)
CREATE PROCEDURE [duplicate_user_data]
#old_user_id int,
#new_user_id int
AS
BEGIN
INSERT INTO TABLEA
([desc]
,[user_id]
)
select desc, user_id from TABLEA where user_id = #old_user_id
END
You can use a self-join to match the old and new parent ids.
CREATE PROCEDURE [duplicate_user_data]
#old_user_id int,
#new_user_id int
AS
INSERT INTO TableA ([desc], [user_id])
SELECT [desc], #new_user_id
FROM TableA
WHERE [user_id] = #old_user_id
INSERT INTO TableB ([a_id], [detail])
SELECT NewTableA.[a_id], TableB.[detail]
FROM TableA AS NewTableA
CROSS JOIN TableA AS OldTableA
JOIN TableB ON TableB.[a_id] = OldTableA.[a_id]
WHERE NewTableA.[user_id] = #new_user_id
AND OldTableA.[user_id] = #old_user_id
if I am understanding you correctly, you want to insert a new record for the new user but copy the details from another user. If so, then you can do something like this:
CREATE PROCEDURE [duplicate_user_data]
#old_user_id int,
#new_user_id int
AS
BEGIN
declare #old_a_id int
-- get the old a_id first
SELECT #old_a_id = a_id
FROM TableA
WHERE [user_id] = #old_user_id
-- insert the new record into TableA
INSERT INTO TABLEA
(
[desc]
,[user_id]
)
select [desc]
, #new_user_id
from TABLEA
where [user_id] = #old_user_id
-- insert new record into tableB using the #old_a_id
INSERT INTO TableB
(
a_id
, detail
)
SELECT #old_a_id
, detail
FROM TableB
WHERE a_id = #old_a_id
END
This will then insert your new_user_id into TableA but will have the [desc] from your old_user_id
Related
I am updating a table called tableA by joining tableB and tableC at the same time I am capturing updated records into temp table using output clause from tableA . Now I want capture columns from table B for the updated data but output clause isn't allowing the same.
Eg:
Update SLC Set SLC.Datascrublevel = C.Datascrublevel
OUTPUT [Deleted].Systemcode,
[Deleted].Systemkey,
[Deleted].datascrublevel,
[Inserted].datascrublevel
INTO #TEMP1
FROM TABLEA SLC with(nolock)
INNER JOIN TABLEB SC ON SC.SystemCode = SLC.SystemCode
INNER JOIN TABLEC SL ON SL.SystemCode = SLC.SystemCode and SLC.SystemKey = SL.Systemkey
INNER JOIN #TEMP C ON SLC.Datascrublevel <> C.DataScrubLevel AND C.Systemcode = SLC.SystemCode and C.Systemkey = SLC.SystemKey
Now I want columns from tableB to capture into temp table using output clause. Please provide your advise if there are any alternative ways.
Just Like you have given it as [deleted].[Column Name] and [Inserted].[Column Name] add one more column as [SC].[Column Name]
Example :
IF OBJECT_ID('TempDb..#TABLEA') IS NOT NULL
DROP TABLE #TABLEA
IF OBJECT_ID('TempDb..#TABLEB') IS NOT NULL
DROP TABLE #TABLEB
IF OBJECT_ID('TempDb..#TABLEC') IS NOT NULL
DROP TABLE #TABLEC
IF OBJECT_ID('TempDb..#TABLED') IS NOT NULL
DROP TABLE #TABLED
CREATE TABLE #TABLEA
(
SeqNo INT IDENTITY(1,1),
MyDate DATE
)
CREATE TABLE #TABLEB
(
SeqNo INT IDENTITY(1,1),
FullName VARCHAR(20)
)
CREATE TABLE #TABLEC
(
SeqNo INT IDENTITY(1,1),
FullName VARCHAR(20),
MyDate DATE
)
CREATE TABLE #TABLED
(
SeqNo INT,
MyDate DATE,
FullName VARCHAR(20)
)
INSERT INTO #TABLEA
(
MyDate
)
SELECT GETDATE()
UNION
SELECT GETDATE()+1
UNION
SELECT GETDATE()-1
INSERT INTO #TABLEB
(
FullName
)
VALUES('A'),('B'),('C')
INSERT INTO #TABLEC
(
FullName
)
VALUES('A'),('B'),('C')
UPDATE C
SET MyDate = A.MyDate
OUTPUT
deleted.SeqNo,
deleted.MyDate,
B.FullName
INTO #TABLED
FROM #TABLEC C
INNER JOIN #TABLEB B
ON C.FullName = B.FullName
INNER JOIN #TABLEA A
ON A.SeqNo = B.SeqNo
SELECT * FROM #TABLED
I need to get the data in two parent > child table sets merged/combined into a third parent > child table.
The tables look like this:
The only difference in the three sets of tables is that TableC has a TableType column to help discern the difference between a TableA record and a TableB record.
My first thought was to use a cursor.. Here's code to create the table structure, insert some records, and then merge the data together. It works very well, sooooo....
--Create the tables
CREATE TABLE TableA
(
ID int not null identity primary key,
Name VARCHAR(30)
);
CREATE TABLE TableAChild
(
ID int not null identity primary key,
Parent int not null,
Name VARCHAR(30),
CONSTRAINT FK_A FOREIGN KEY (Parent) REFERENCES TableA(ID)
);
CREATE TABLE TableB
(
ID int not null identity primary key,
Name VARCHAR(30)
);
CREATE TABLE TableBChild
(
ID int not null identity primary key,
Parent int not null,
Name VARCHAR(30),
CONSTRAINT FK_B FOREIGN KEY (Parent) REFERENCES TableB(ID)
);
CREATE TABLE TableC
(
ID int not null identity primary key,
TableType VARCHAR(1),
Name VARCHAR(30)
);
CREATE TABLE TableCChild
(
ID int not null identity primary key,
Parent int not null,
Name VARCHAR(30),
CONSTRAINT FK_C FOREIGN KEY (Parent) REFERENCES TableC(ID)
);
-- Insert some test records..
INSERT INTO TableA (Name) Values ('A1')
INSERT INTO TableAChild (Name, Parent) VALUES ('A1Child', SCOPE_IDENTITY())
INSERT INTO TableB (Name) Values ('B1')
INSERT INTO TableBChild (Name, Parent) VALUES ('B1Child', SCOPE_IDENTITY())
-- Needed throughout..
DECLARE #ID INT
-- Merge TableA and TableAChild into TableC and TableCChild
DECLARE TableACursor CURSOR
-- Get the primary key from TableA
FOR SELECT ID FROM TableA
OPEN TableACursor
FETCH NEXT FROM TableACursor INTO #ID
WHILE ##FETCH_STATUS = 0
BEGIN
-- INSERT INTO SELECT the parent record into TableC, being sure to specify a TableType
INSERT INTO TableC (Name, TableType) SELECT Name, 'A' FROM TableA WHERE ID = #ID
-- INSERT INTO SELECT the child record into TableCChild using the parent ID of the last row inserted (SCOPE_IDENTITY())
-- and the current record from the cursor (#ID).
INSERT INTO TableCChild(Name, Parent) SELECT Name, SCOPE_IDENTITY() FROM TableAChild WHERE Parent = #ID
FETCH NEXT FROM TableACursor INTO #ID
END;
CLOSE TableACursor
DEALLOCATE TableACursor
-- Repeat for TableB
DECLARE TableBCursor CURSOR
FOR SELECT ID FROM TableB
OPEN TableBCursor
FETCH NEXT FROM TableBCursor INTO #ID
WHILE ##FETCH_STATUS = 0
BEGIN
INSERT INTO TableC (Name, TableType) SELECT Name, 'B' FROM TableB WHERE ID = #ID
INSERT INTO TableCChild(Name, Parent) SELECT Name, SCOPE_IDENTITY() FROM TableBChild WHERE Parent = #ID
FETCH NEXT FROM TableBCursor INTO #ID
END;
CLOSE TableBCursor
DEALLOCATE TableBCursor
Now, my question(s):
I've always been told that cursors are bad. But I couldn't find another way of doing it. I'm wondering if there's some way to do that with a CTE?
If the cursor is appropriate in this situation, how did I do? Is there a better way of doing what I did? It doesn't look very DRY to me, but I'm no SQL expert.
Lastly, if you want to re-run the query above, here's a small script to delete the tables that were created.
DROP TABLE TableAChild
DROP TABLE TableBChild
DROP TABLE TableCChild
DROP TABLE TableA
DROP TABLE TableB
DROP TABLE TableC
The correct result should look like:
You can use merge as described by Adam Machanic in Dr. OUTPUT or: How I Learned to Stop Worrying and Love the MERGE and in this question to get a mapping between the new identity value and the old primary key value in a table variable and the use that when you insert to your child tables.
declare #T table(ID int, IDC int);
merge dbo.TableC as C
using dbo.TableA as A
on 0 = 1
when not matched by target then
insert (TableType, Name) values('A', A.Name)
output A.ID, inserted.ID into #T(ID, IDC);
insert into dbo.TableCChild(Parent, Name)
select T.IDC, AC.Name
from dbo.TableAChild as AC
inner join #T as T
on AC.Parent = T.ID;
delete from #T;
merge dbo.TableC as C
using dbo.TableB as B
on 0 = 1
when not matched by target then
insert (TableType, Name) values('B', B.Name)
output B.ID, inserted.ID into #T(ID, IDC);
insert into dbo.TableCChild(Parent, Name)
select T.IDC, BC.Name
from dbo.TableBChild as BC
inner join #T as T
on BC.Parent = T.ID;
SQL Fiddle
Here is one way to do this without a cursor or other RBAR type stuff.
ALTER TABLE TableC ADD LegacyID INT
GO
INSERT INTO TableC (TableType, Name, LegacyID)
SELECT 'A', Name, ID
FROM TableA
INSERT TableCChild
SELECT C.ID, AC.Name
FROM TableAChild AC
JOIN TableA A ON A.Id = AC.ID
JOIN TableC C ON C.LegacyID = A.ID AND C.TableType = 'A'
INSERT INTO TableC (TableType, Name, LegacyID)
SELECT 'B', Name, ID
FROM TableB
INSERT TableCChild
SELECT C.ID, AC.Name
FROM TableBChild AC
JOIN TableB A ON A.Id = AC.ID
JOIN TableC C ON C.LegacyID = A.ID AND C.TableType = 'B'
ALTER TABLE TableC DROP COLUMN LegacyID
GO
You can use a map table to link the old and new ids together based on some key.
In my example, I am using the order of insertion into TableC.
Create a map table with an identity column.
Add data in TableC table based on order of ID of TableA and get the inserted ids in the map
Use the same order of TableA.id to get a ROWNUMBER() and match it with the identity column of the map table and update the old_id in map to match TableA.id with TableC.id .
Use the map to insert into the TableCChild table
Truncate the map and rinse and repeat for other tables.
Sample Query
CREATE TABLE #map(id int identity,new_id int,old_id int);
INSERT INTO TableC
(
TableType,
Name
)output inserted.id into #map(new_id)
SELECT 'A',Name
FROM TableA
ORDER BY ID
update m
set m.old_id = ta.id
FROM #map m
inner join
(
select row_number()OVER(order by id asc) rn,id
from tableA
)ta on ta.rn = m.id
INSERT INTO TableCChild (Name, Parent)
SELECT Name,M.new_ID
FROM #Map M
INNER JOIN TableAChild TA ON M.old_id = TA.Parent
TRUNCATE TABLE #map
INSERT INTO TableC
(
TableType,
Name
)output inserted.id into #map(new_id)
SELECT 'B',Name
FROM TableB
ORDER BY ID
update m
set m.old_id = tb.id
FROM #map m
inner join
(
select row_number()OVER(order by id asc) rn,id
from tableB
)tb on tb.rn = m.id
INSERT INTO TableCChild (Name, Parent)
SELECT Name,M.new_ID
FROM #Map M
INNER JOIN TableBChild TB ON M.old_id = TB.Parent
DROP TABLE #Map
I just wrote the following SQL to do it if the Name is unique in TableA and unique in TableB
INSERT INTO TableCChild
(
Parent,
NAME
)
SELECT tc.ID,
ta.Name
FROM TableAChild AS ta
JOIN TableA a
ON a.ID = ta.Parent
JOIN TableC AS tc
ON tc.Name = a.Name
AND tc.TableType = 'A'
UNION
SELECT tc.ID,
tb.Name
FROM TableBChild AS tb
JOIN TableB b
ON b.ID = tb.Parent
JOIN TableC AS tc
ON tc.Name = b.Name
AND tc.TableType = 'B'
If Name is not unique and only the ID is the Unique Identifier then I would add the LegacyId as suggested and the code would then be as follows
/* Change Table C to Have LegacyId as well and this is used to find the New Key for Inserts
CREATE TABLE TableC
(
ID INT NOT NULL IDENTITY PRIMARY KEY,
TableType VARCHAR(1),
LegacyId INT,
NAME VARCHAR(30)
);
*/
INSERT INTO TableC (Name, TableType, LegacyId)
SELECT DISTINCT NAME,
'A',
Id
FROM TableA
UNION
SELECT DISTINCT NAME,
'B',
Id
FROM TableB
INSERT INTO TableCChild
(
Parent,
NAME
)
SELECT tc.ID,
ta.Name
FROM TableAChild AS ta
JOIN TableA a
ON a.ID = ta.Parent
JOIN TableC AS tc
ON tc.LegacyId = a.Id
AND tc.TableType = 'A'
UNION
SELECT tc.ID,
tb.Name
FROM TableBChild AS tb
JOIN TableB b
ON b.ID = tb.Parent
JOIN TableC AS tc
ON tc.LegacyId = b.Id
AND tc.TableType = 'B'
We can reach this by turning the Identity column off till we finish the insertion like the following example.
--Create the tables
CREATE TABLE TableA
(
ID int not null identity primary key,
Name VARCHAR(30)
);
CREATE TABLE TableAChild
(
ID int not null identity primary key,
Parent int not null,
Name VARCHAR(30),
CONSTRAINT FK_A FOREIGN KEY (Parent) REFERENCES TableA(ID)
);
CREATE TABLE TableB
(
ID int not null identity primary key,
Name VARCHAR(30)
);
CREATE TABLE TableBChild
(
ID int not null identity primary key,
Parent int not null,
Name VARCHAR(30),
CONSTRAINT FK_B FOREIGN KEY (Parent) REFERENCES TableB(ID)
);
CREATE TABLE TableC
(
ID int not null identity primary key,
TableType VARCHAR(1),
Name VARCHAR(30)
);
CREATE TABLE TableCChild
(
ID int not null identity primary key,
Parent int not null,
Name VARCHAR(30),
CONSTRAINT FK_C FOREIGN KEY (Parent) REFERENCES TableC(ID)
);
-- Insert some test records..
INSERT INTO TableA (Name) Values ('A1')
INSERT INTO TableAChild (Name, Parent) VALUES ('A1Child', SCOPE_IDENTITY())
INSERT INTO TableB (Name) Values ('B1')
INSERT INTO TableBChild (Name, Parent) VALUES ('B1Child', SCOPE_IDENTITY())
SET IDENTITY_INSERT TableC ON
INSERT INTO TableC(ID, TableType, Name)
SELECT ID, 'A', Name FROM TableA
INSERT INTO TableCChild(Parent, Name)
SELECT Parent, Name FROM TableAChild
DECLARE #MAXID INT
SELECT #MAXID = MAX(ID) FROM TableC
PRINT #MAXID
SET IDENTITY_INSERT TableC ON
INSERT INTO TableC(ID, TableType, Name)
SELECT ID + #MAXID, 'B', Name FROM TableB
SET IDENTITY_INSERT TableC OFF
INSERT INTO TableCChild(Parent, Name)
SELECT Parent + #MAXID, Name FROM TableBChild
SET IDENTITY_INSERT TableC OFF
SELECT * FROM TableC
SELECT * FROM TableCChild
DROP TABLE TableAChild
DROP TABLE TableBChild
DROP TABLE TableCChild
DROP TABLE TableA
DROP TABLE TableB
DROP TABLE TableC
If you need to insert records in third table TableC and TableCChild for later use then it's fine to insert data in these tables but if you only need this table data to use it in your stored procedure for the time being then you can also just work with first two tables to get the desired result.
select * from (
select a.ID,'A' as TableType,a.Name from TableA a inner join TableAChild b on a.ID=b.ID
union
select a.ID,'B' as TableType,a.Name from TableB a inner join TableBChild b on a.ID=b.ID) TableC
Similarly get TableCChild
select * from
(
select b.ID,b.Parent,b.Name from TableA a inner join TableAChild b on a.ID=b.ID
union
select b.ID,b.Parent,b.Name from TableB a inner join TableBChild b on a.ID=b.ID) TableCChild
And if you have to insert in TableC and TableCChild then you have to recreate TableC with primary key on ID and TableType, and turn off the identity for ID column.
I have two table Table1 and Table2 and structure of table as
Table1
Primary Key | Name
Table2
Primary Key | Table1_Id_pk | Status - true/false value
When I insert data into Table2 I want to automatically transfer that data in table1 from Table2 which have Status false.
You can create AFTER INSERT trigger:
CREATE TRIGGER DataMigration
ON Table2
AFTER INSERT
AS
BEGIN
INSERT INTO Table1
SELECT *
FROM TAble2
WHERe Status = 'false'
END
GO
Check this example, use ##identity to get inserted row-id and use that id for child table.
declare #t1 table (pk int identity(1,1) not null , name varchar(50) )
declare #t2 table (pk int identity(1,1) not null , t1pk int, status bit )
declare #new_table1Id int
insert into #t1 values( 'ajay')
set #new_table1Id = ##IDENTITY -This gives you last inserted id of #t1
insert into #t2 values( #new_table1Id , 0)
select * from #t1
select * from #t2
##IDENTITY official documentation
Suppose there are two tables which have the data mentioned in the insert query. There is no foreign key references between the two table.
create table uref.slave (
SLAVE_ID SMALLINT NOT NULL PRIMARY KEY,
DESC VARCHAR(20)
);
INSERT INTO uref.SLAVE values (1, null)
INSERT INTO uref.SLAVE values (2, null)
create table uref.master (
MASTER_ID SMALLINT NOT NULL PRIMARY KEY,
SLAVE_ID SMALLINT,
DESC VARCHAR(20)
);
INSERT INTO uref.MASTER values (1,1,'value1')
INSERT INTO uref.MASTER values (2,2,'value2')
Now I need a query which will copy uref.master.DESC into uref.slave.DESC based on uref.master.SLAVE_ID = uref.slave.SLAVE_ID.
The simplest solution may be to use MERGE.
MERGE INTO uref.SLAVE s
USING uref.MASTER m
ON (s.SLAVE_ID = m.SLAVE_ID)
WHEN MATCHED
THEN UPDATE SET Desc = m.Desc
It could be refined to update only when there is a change to be made
MERGE INTO uref.SLAVE s
USING uref.MASTER m
ON (s.SLAVE_ID = m.SLAVE_ID)
WHEN MATCHED
and ( s.Desc <> m.Desc
or (s.Desc is null and m.Desc is not null)
)
THEN UPDATE SET Desc = m.Desc
UPDATE uref.SLAVE t1
SET Desc =
(
SELECT t2.Desc
FROM uref.MASTER t2
WHERE t1.SLAVE_ID = t2.SLAVE_ID
)
WHERE EXISTS
(
SELECT *
FROM uref.MASTER t2
WHERE t1.SLAVE_ID = t2.SLAVE_ID
AND NOT t1.Desc=t2.Desc
)
AND t1.Desc IS NULL
if sql server, Try below sql: (recheck the table name and fields)
declare #urefSlave table (
SLAVE_ID SMALLINT ,
[DESC] VARCHAR(20)
);
INSERT INTO #urefSlave values (1, null)
INSERT INTO #urefSlave values (2, null)
Declare #urefMaster table (
MASTER_ID SMALLINT,
SLAVE_ID SMALLINT,
[DESC] VARCHAR(20)
);
INSERT INTO #urefMaster values (1,1,'value1')
INSERT INTO #urefMaster values (2,2,'value2')
select * from #urefMaster
select * from #urefSlave
update #urefSlave
set [DESC] = b.[DESC]
from #urefSlave a inner join #urefMaster b on a.SLAVE_ID = b.SLAVE_ID
select * from #urefSlave
REsult:
MASTER_ID SLAVE_ID DESC
--------- -------- --------------------
1 1 value1
2 2 value2
SLAVE_ID DESC
-------- --------------------
1 value1
2 value2
Updated
cannot help much in db2, because i don't have the tools to run the syntax
but from this link db2 update help
you can modify an example in there to meet your requirement:
UPDATE EMPLOYEE EU
SET (EU.SALARY, EU.COMM)
=
(SELECT AVG(ES.SALARY), AVG(ES.COMM)
FROM EMPLOYEE ES
WHERE ES.WORKDEPT = EU.WORKDEPT)
WHERE EU.EMPNO = '000120'
Hope this help.
Is This Possible?
Here is something I'm looking for, executed together:
First, it would execute the INSERT based on how many rows in the SELECT
INSERT INTO TABLE2 (xID, NAME)
SELECT xID, NAME FROM TABLE
Then getting the ##IDENTITY of each INSERTED ROW, it would create a new Insert including the same data of the first SELECT statement:
INSERT INTO TABLE3 (xID, NAME, ID)
SELECT xID, NAME, ID as Scope_IdentitY()
If not, what the best way without using cursor or while?
You have, at least, two options:
1) The OUTPUT...INTO target_table clause (SQL2005+)
2) Or you could write composable DML(SQL2008+).
Example:
DECLARE #Table2 TABLE(
ID INT IDENTITY PRIMARY KEY, --IDENTITY
xID INT NOT NULL,
NAME VARCHAR(25) NOT NULL
);
DECLARE #Table3 TABLE(
ID INT PRIMARY KEY, --No IDENTITY
xID INT NOT NULL,
NAME VARCHAR(25) NOT NULL
);
--First solution: OUTPUT ... INTO
INSERT INTO #Table2 (xID, NAME)
OUTPUT inserted.xID, inserted.NAME, inserted.ID INTO #Table3(xID, NAME, ID)
SELECT t.Col1, t.Col2
FROM (SELECT 11,'A' UNION ALL SELECT 22,'B' UNION ALL SELECT 33,'C') AS t(Col1,Col2);
--Second solution: composable DML
INSERT INTO #Table3(xID, NAME, ID)
SELECT src.xID, src.NAME, src.ID
FROM
(
INSERT INTO #Table2 (xID, NAME)
OUTPUT inserted.xID, inserted.NAME, inserted.ID
SELECT t.Col1, t.Col2
FROM (VALUES(44,'D'),(55,'E'),(66,'F')) AS t(Col1,Col2)
) src
SELECT * FROM #Table2
SELECT * FROM #Table3
INSERT INTO TABLE2 (xID, NAME)
OUTPUT
INSERTED.xID, INSERTED.NAME, INSERTED.ID
INTO TABLE3 (xID, NAME, ID)
SELECT xID, NAME FROM [TABLE]
You can declare a table variable and store the output of the rows inserted into dbo.Table2 in this variable and use the table variable as the input for table dbo.Table3.
CREATE TABLE dbo.Table1
(
xid int NOT NULL
, name varchar(30) NOT NULL
);
CREATE TABLE dbo.Table2
(
id int NOT NULL IDENTITY
, xid int NOT NULL
, name varchar(30) NOT NULL
);
CREATE TABLE dbo.Table3
(
id int NOT NULL
, xid int NOT NULL
, name varchar(30) NOT NULL
);
INSERT INTO dbo.Table1 (xid, name) VALUES
(195, 'abc'),
(242, 'def'),
(332, 'ghi');
GO
DECLARE #tempTable table
( id int
, xid int
, name varchar(30)
);
INSERT dbo.Table2
OUTPUT INSERTED.id, INSERTED.xid, INSERTED.name
INTO #tempTable
SELECT xid, name FROM dbo.Table1;
INSERT dbo.Table3 (id, xid, name)
SELECT id, xid, name FROM #tempTable;
SELECT id, xid, name FROM dbo.Table2;
SELECT id, xid, name FROM dbo.Table3;
GO
OK, based on your comments below, try this:
INSERT INTO TABLE2 (xID, NAME)
SELECT xID, NAME FROM TABLE;
INSERT INTO TABLE3 (xID, NAME, ID)
SELECT xID, NAME, ##identity
FROM TABLE2;
Assuming these table structures:
TABLE_A
-----------
X_ID
NAME
TABLE_B
----------------
TABLE_B_ID [PK]
X_ID
NAME
TABLE_C
----------------
TABLE_C_ID [PK]
X_ID
NAME
TABLE_B_ID [FK]
Then wouldn't this work (best in a transaction)?:
-- Grab data from TABLE_A and INSERT INTO TABLE_B
INSERT INTO TABLE_B (
X_ID,
NAME
)
SELECT
X_ID,
NAME
FROM
TABLE_A
-- Grab data from TABLE_B that matches the data imported from TABLE_A
-- and INSERT that data into TABLE_C (incl. the PK from TABLE_B)
INSERT INTO TABLE_C (
X_ID,
NAME,
TABLE_B_ID
)
SELECT
b.X_ID,
b.NAME,
b.TABLE_B_ID
FROM
TABLE_B b
INNER JOIN
TABLE_A a ON a.X_ID = b.X_ID