INSERT Data From One Table Into Multiple Tables - sql

I'm using SQL Server 2005.
I am migrating data over from a current database (single table) to a new database (normalized - many tables). In the new database, I have a base table (let's call it "BaseTable"), and multiple other tables (let's call them "DependentA", and "DependentB"). Some of the data from the old database will go to BaseTable, and some will go to the other two. BaseTable has a one-to-one relationship with both DependentA and DependentB, using the Id of them as the foreign key.
So here's my question. How should I migrate the data over? Here is a query I've been trying, which is working except for one thing: the foreign keys in BaseTable for the other two are identical, instead or having a different one each.
Begin SQL:
BEGIN TRANSACTION
DECLARE #dep1Id int
DECLARE #dep2Id int
INSERT INTO DependentA (column1, column2)
SELECT c1, c2
FROM OldDatabase.OldTable
SELECT #dep1Id = Scope_Identity()
INSERT INTO DependentB (column3, column4)
SELECT c3, c4
FROM OldDatabase.OldTable
SELECT #dep2Id = Scope_Identity()
INSERT INTO BaseTable (column5, dependentTable1Id, dependentTablr2Id)
SELECT c5, #dep1Id, #dep2Id
FROM OldDatabase.OldTable
COMMIT

The problem is that #dep1Id and #dep1Id are scalar and are retaining the last value only from the two set based inserts.
Since it's a one off you should probably do it as a cursor
DECLARE CURSOR #curs FOR
SELECT c1,c2,c3,c4,c5 FROM OldDatebase
open #curs
fetch next from #curs into
#c1,#c2,#c3,#c4,#c5 --declare these!
while ##fetch_status <> 0
BEGIN
INSERT INTO DependentA (column1, column2) VALUES #c1, #c2
SELECT #dep1Id = Scope_Identity()
INSERT INTO DependentB (column3, column4) VALUES #c3, #c4
SELECT #dep2Id = Scope_Identity()
INSERT INTO BaseTable (column5, department1Id, department2Id) #c5, #dep1Id, #dep2Id
fetch next from #curs into
#c1,#c2,#c3,#c4,#c5
END
close #curs
deallocate #curs
My cursor syntax is probably riddled with errors, but you get the idea.

To avoid a cursor for large data sets, temporarily include the OldTable_id in the new tables.
BEGIN TRANSACTION
INSERT INTO DependentA (OldTable_id, column1, column2)
SELECT ot.id, ot.c1, ot.c2
FROM OldDatabase.OldTable ot
INSERT INTO BaseTable (OldTable_id, column5)
SELECT ot.id, ot.c5
FROM OldDatabase.OldTable ot
UPDATE BaseTable
SET BaseTable.dependentTable1_id = DependentA.id
FROM BaseTable
INNER JOIN DependentA on DependentA.OldTable_id = BaseTable.OldTable_id
COMMIT
Do the same for DependentB table and any other tables being normalized out of the OldTable.
Delete OldTable_id after the data migration.

[enter image description here][1]ZeorOne is the main table from which you want to get data and insert it into zero and one table respectively.
select idzero,namezero,idone,nameone from zeroone
insert into zero
select idzero,namezero from zeroone
insert into one
select idone,nameone from zeroone
or you want to use cursor to insert data with selected columns from Zeroone
into to two tables the query is here
Declare #idzero int
Declare #namezero varchar(50)
Declare #idone int
Declare #nameone varchar(50)
Declare Cur Cursor for
select idzero,namezero,idone,nameone from zeroone
open Cur
fetch Cur into #idzero,#namezero,#idone,#nameone
While ##fetch_status = 0
begin
insert into zero
select #idzero,#namezero
insert into one
select #idone,#nameone
fetch Cur into #idzero,#namezero,#idone,#nameone
end
close Cur
Deallocate Cur

DECLARE #Product_Name varchar(50),#Generic_Name varchar(50),#Category_Name varchar(50),#Manufacture_Name varchar(50),
#UOM_Name varchar(50),#ProductId int,#GenericId int,#CategoryId int,#ManufactureId int,#UOMId int
DECLARE MultiplTable CURSOR FOR
SELECT ProductName,GenericName,CategoryName,ManufacturerName,UOMName from Noor_ProductList
open MultiplTable
fetch next from MultiplTable into
#Product_Name,#Generic_Name,#Category_Name,#Manufacture_Name,#UOM_Name --declare these!
while ##fetch_status = 0
BEGIN
INSERT INTO Noor_GenericMaster(GenericName) VALUES (#Generic_Name)
SELECT #GenericId = Scope_Identity()
INSERT INTO Noor_CategoryMaster(CategoryName) VALUES (#Category_Name)
SELECT #CategoryId = Scope_Identity()
INSERT INTO Noor_ManufaturerMaster(ManufaturerName) VALUES (#Manufacture_Name)
SELECT #ManufactureId = Scope_Identity()
INSERT INTO Noor_UOMMaster(UOMName) VALUES (#UOM_Name)
SELECT #UOMId = Scope_Identity()
INSERT INTO Noor_ProductMaster (ProductName,GenericID,CategoryID,ManufaturerID,UOMID)
values (#Product_Name,#GenericId,#CategoryId,#ManufactureId,#UOMId)
SELECT #ProductId = Scope_Identity()
fetch next from MultiplTable into #Product_Name,#Generic_Name,#Category_Name,#Manufacture_Name,#UOM_Name
END
close MultiplTable
deallocate MultiplTable

Related

Generating dummy data from existing data set is slow using cursor

I'm trying to generate dummy data from the existing data I have in the tables. All I want is to increase the number of records in Table1 to N specified amount. The other tables should increase based on the foreign key references.
The tables has one to many relationship. For one record in table 1, I can have multiple entries in table 2, and in table 3 I can have many records based on IDs of the second table.
Since IDs are primary keys, I either capture it by
SET #NEWLY_INSERTED_ID = SCOPE_IDENTITY()
after inserting to table 1 and using in insert for table2, or inserting them to temp table and joining them to achieve the same results for table 3.
Here's the approach I'm taking with the CURSOR.
DECLARE #MyId as INT;
DECLARE #myCursor as CURSOR;
DECLARE #DESIRED_ROW_COUNT INT = 70000
DECLARE #ROWS_INSERTED INT = 0
DECLARE #CURRENT_ROW_COUNT INT = 0
DECLARE #NEWLY_INSERTED_ID INT
DECLARE #LANGUAGE_PAIR_IDS TABLE ( LangugePairId INT, NewId INT, SourceLanguage varchar(100), TargetLangauge varchar(100) )
WHILE (#ROWS_INSERTED < #DESIRED_ROW_COUNT)
BEGIN
SET #myCursor = CURSOR FOR
SELECT Id FROM MyTable
SET #CURRENT_ROW_COUNT = (SELECT COUNT(ID) FROM MyTable)
OPEN #myCursor;
FETCH NEXT FROM #myCursor INTO #MyId;
WHILE ##FETCH_STATUS = 0
BEGIN
IF ((#CURRENT_SUBMISSION_COUNT < #DESIRED_ROW_COUNT) AND (#ROWS_INSERTED < #DESIRED_ROW_COUNT))
BEGIN
INSERT INTO [dbo].[MyTable]
([Column1]
([Column2]
([Column3]
)
SELECT
,convert(numeric(9,0),rand() * 899999999) + 100000000
,COlumn2
,Colum3
FROM MyTable
WHERE Id = #MyId
SET #NEWLY_INSERTED_ID = SCOPE_IDENTITY()
INSERT INTO [dbo].[Language]
([MyTable1Id]
,[Target]
,[Source]
OUTPUT inserted.Id, inserted.MyTable1Id, inserted.Source, inserted.[Target] INTO #LANGUAGE_PAIR_IDS (LangugePairId, NewId, SourceLanguage, TargetLangauge)
SELECT
#NEWLY_INSERTED_ID
,[Target]
,[Source]
FROM [dbo].[Language]
WHERE MyTableId = #MyId
ORDER BY Id
DECLARE #tbl AS TABLE (newLanguageId INT, oldLanguageId INT, sourceLanguage VARCHAR(100), targetLanguage VARCHAR(100))
INSERT INTO #tbl (newLanguageId, oldLanguageId, sourceLanguage, targetLanguage)
SELECT 0, id, [Source], [Target] MyTable1Id FROM Language WHERE MyTable1Id = #MyId ORDER BY Id
UPDATE t
SET t.newlanguageid = lp.LangugePairId
FROM #tbl t
JOIN #LANGUAGE_PAIR_IDS lp
ON t.sourceLanguage = lp.SourceLanguage
AND t.targetLanguage = lp.TargetLangauge
INSERT INTO [dbo].[Manager]
([LanguagePairId]
,[UserId]
,[MyDate])
SELECT
tbl.newLanguageId
,p.[UserId]
,p.[MyDate]
FROM Manager m
INNER JOIN #tbl tbl
ON m.LanguagePairId = tbl.oldLanguageId
WHERE m.LanguagePairId in (SELECT Id FROM Language WHERE MyTable1Id = #MyId) -- returns the old language pair id
SET #ROWS_INSERTED += 1
SET #CURRENT_ROW_COUNT +=1
END
ELSE
BEGIN
PRINT 'REACHED EXIT'
SET #ROWS_INSERTED = #DESIRED_ROW_COUNT
BREAK
END
FETCH NEXT FROM #myCursor INTO #MyId;
END
CLOSE #myCursor
DEALLOCATE #myCursor
END
The above code works! It generates the data I need. However, it's very very slow. Just to give some comparison. Initial load of data for table 1 was ~60,000 records, Table2: ~74,000 and Tabl3 ~3,400
I tried to insert 9,000 rows in Table1. With the above code, it took 17:05:01 seconds to complete.
Any suggestion on how I can optimize the query to run little faster? My goal is to insert 1-2 mln records in Table1 without having to wait for days. I'm not tied to CURSOR. I'm ok to achieve the same result in any other way possible.

Insert Data into Table if a condition is true

SQL statement Question
I have an instance where I need to insert one record multiple times in a DB table that contains a unique reference column. I'm declaring a variable and using a select statement to populate variable and then running an insert statement. The issue is that when grabbing unique value into variable it only grabs the last record in the reference table. I need for insert statement to insert at each point where a record is found.
DECLARE #ID INT;
DECLARE #RuleID INT;
SELECT #RuleID = RuleID from Rules where Rule_Name = 'VERSION_ID' and Field = 'TSH'
SELECT #ID = ID FROM CHANNELS WHERE SUBSTRING(CHANNEL_NAME,0,4) != 'HEL'
BEGIN
INSERT INTO Rule_Items
VALUES(#ID,#RuleID,0,'2.5.1','E','A',0,getdate())
END
If you want all combinations, you can use insert . . . select with a cross join:
INSERT INTO Rule_Items
select c.id, r.ruleid, 0, '2.5.1', 'E', 'A', 0, getdate()
from rules r cross join
channels c
where r.Rule_Name = 'VERSION_ID' and r.Field = 'TSH' and
SUBSTRING(c.CHANNEL_NAME, 0, 4) <> 'HEL';
I decided to use a cursor and create a temp table. Here is query that worked.
**--BEGIN TRAN
DECLARE #Channelid INT
DECLARE #RuleID INT
SELECT #RuleID = RuleID From Rules Where Rule_Name = 'VERSION_ID'
DECLARE GetChannelId CURSOR FOR SELECT Channelid FROM HL7_Channels WHERE Channel_Name not like 'MU2%' AND Channel_Description LIKE '%outbound%'
OPEN GetChannelId
FETCH GetChannelId INTO #Channelid
WHILE (##FETCH_STATUS = 0)
BEGIN
IF NOT EXISTS (Select 1 From Rule_Items Where ChannelId = #Channelid AND RuleID = #RuleID)
BEGIN
INSERT INTO Rule_Items VALUES (#Channelid,#RuleID,0,'2.5.1','E','A',0,getdate())
END
FETCH GetChannelId INTO #Channelid
CONTINUE
END
CLOSE GetChannelId
DEALLOCATE GetChannelId
--ROLLBACK TRAN
--COMMIT TRAN**

MS SQL Store procedure insert not work

I tried creating a store procedure for MS SQL
CREATE PROCEDURE YEARENDPROCESSING
AS
DECLARE #VAR AS VARCHAR(9)
DECLARE ACURSOR CURSOR FOR
SELECT COLUMN FROM TABLEA
OPEN ACURSOR
FETCH NEXT FROM ACURSOR INTO #VAR
while ##FETCH_STATUS = 0
BEGIN
INSERT INTO TABLEB SELECT * FROM TABLEC WHERE TABLEC.COLUMNC = #VAR
FETCH NEXT FROM ACURSOR INTO #VAR
END
CLOSE ACURSOR
DEALLOCATE ACURSOR
Assuming TableC column and TableB have identical columns
I get the result saying X rows affected
But in actual table I see nothing.
I have a new Finding
CREATE PROCEDURE YEARENDPROCESSING
AS
DECLARE #VAR AS VARCHAR(9)
DECLARE ACURSOR CURSOR FOR
SELECT COLUMN FROM TABLEA
OPEN ACURSOR
FETCH NEXT FROM ACURSOR INTO #VAR
while ##FETCH_STATUS = 0
BEGIN
INSERT INTO TABLEB SELECT * FROM TABLEC WHERE TABLEC.COLUMNC = #VAR
DELETE TABLEF where columnf = #VAR
FETCH NEXT FROM ACURSOR INTO #VAR
END
CLOSE ACURSOR
DEALLOCATE ACURSOR
Will get x row affected for the insert and x row affected for the delete
But the actual fact is insert result cannot be seen in the physical table itself. I can see the result of I remove the Delete query. Anyone knows why?
Your code shouldn't have a cursor. You can do this:
CREATE PROCEDURE dbo.YearEndProcessing
AS
BEGIN
SET NOCOUNT ON;
INSERT dbo.TableB(column1, column2, ...)
SELECT column1, column2, ...
FROM dbo.TableA;
END
GO
Well, you changed the code, now there's a third table involved, so let me try again without a cursor:
CREATE PROCEDURE dbo.YearEndProcessing
AS
BEGIN
SET NOCOUNT ON;
INSERT dbo.TableB(column1, column2, ...)
SELECT c.column1, c.column2, ...
FROM dbo.TableA AS a
INNER JOIN dbo.TableC AS c
ON a.[Column] = c.[ColumnC];
END
GO
Or:
CREATE PROCEDURE dbo.YearEndProcessing
AS
BEGIN
SET NOCOUNT ON;
INSERT dbo.TableB(column1, column2, ...)
SELECT c.column1, c.column2, ...
FROM dbo.TableC AS c
WHERE EXISTS
(
SELECT 1 FROM dbo.TableA AS a
WHERE a.[Column] = c.[ColumnC]
);
END
GO
You shouldn't use the INSERT TABLE SELECT * FROM TABLE pattern - this is very prone to breaking in the future (see this post for more details). Also see this post about using a schema prefix and these posts about cursor usage - it should be reserved for cases that actually need it, and when you do actually need it, don't use the default options:
https://sqlblog.org/2012/01/26/bad-habits-to-kick-thinking-a-while-loop-isnt-a-cursor
http://www.sqlperformance.com/2012/07/t-sql-queries/running-totals
http://www.sqlperformance.com/2012/09/t-sql-queries/cursor-options
As for why you see rows inserted but then later can't see the data, I suspect you're looking at a table in the wrong database, in the wrong schema, or you have multiple copies of your database (which happens when you use User Instance and AttachDbFileName options in your connection string).

not able to get first inserted rows identity in cursor loop

I have been trying inserting some rows into a temporary table which required identity from table A ...this A table is being inserted from a cursor..
everything is working fine here but only the problem i am getting is that i don't get identity of first inserted row in table A
suppose i insert 3 rows in table A ...i get last 2 rows in temporary table ..not first one..and if i send just one row in table A then temporary table is blank
here is my stored procedure ..table A is tblClients
Create PROCEDURE [dbo].[lsp1_propAdmClnt]
(
#usrprflId bigint,
#preClient tpClient readonly
)
as
declare #err int
CREATE TABLE #tblids(
clntid int,
imgname nvarchar(350)
)
declare #clntid as int
declare #clntname nvarchar(300)
declare #imgname nvarchar(300)
Begin Transaction
declare transfclntid cursor for select clntname, [imgname] from #preClient
open transfclntid
fetch next from transfclntid into #clntname, #imgname
while ##fetch_status=0
begin
insert into tblClients (usrprflId,Name,Img,cdate)
values(#usrprflId, #clntname, #imgname,GETDATE())
SET #clntid = (SELECT SCOPE_IDENTITY())
insert into #tblids (clntid, imgname) values (#clntid, #imgname)
fetch next from transfclntid into #clntname, #imgname
end
close transfclntid
deallocate transfclntid
select * from #tblids
select #err=##TOTAL_ERRORS
if(#err<>0)
Begin
Rollback Transaction
return 0
End
Commit transaction
First, you should replace that cursor with following INSERT SELECT statement:
declare #tblids table
(
clntid INT NOT NULL,
imgname NVARCHAR(350)
);
insert into tblClients (usrprflId, Name, Img, cdate)
output inserted.clntid, inserted.Img into #tblids (clntid, imgname)
select #usrprflId, clntname, [imgname], GETDATE()
from #preClient
Then if you need the first identity value you could use:
SELECT MIN(clntid)
FROM #tblids

SQL: Insert new records from 1 table to another

I have two tables with students (using Microsoft SQL Server 2008 R2 Standard edition). I Need to write a procedure, so that if 1st table has new students, the second one gets updated as well
this doesnt work and I dont know why:
CREATE PROCEDURE [dbo].[CHECK_NEW]
AS
begin transaction
declare #tempId int
declare #tempName varchar
DECLARE c1 CURSOR FOR
SELECT kId, kName
FROM table1
OPEN c1
FETCH NEXT FROM c1
INTO #tempId, #tempName
WHILE ##FETCH_STATUS = 0
BEGIN
if (SELECT sId FROM table2) NOT IN(#tempId)
insert into table(sId, name) values(#tempId, #tempName)
END
commit
Thanks in advance
Try like this....
CREATE PROCEDURE [dbo].[CHECK_NEW]
AS
Begin Try
begin transaction
Insert into Table2(ulid,Id,Name)
Select newid() as ulid, Id,name from ( Select Row_Number() over(Partition by a.id order by a.id) as row, a.Id,a.name from Table1 a where
not exists(Select * from Table2b where a.Id=b.Id)) t where row =1
Commit
End Try
Begin Catch
RollBack
End Catch