SQL: Insert new records from 1 table to another - sql

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

Related

Alternative to Iteration for INSERT SELECT UPDATE in a sequence

I have a table with around 17k unique rows for which I need to run these set of statements in sequence
INSERT INTO TABLE1 using MASTERTABLE data (MASTERTABLE have 6 column)
SELECT value of column ID (Primary Key) of newly inserted row from TABLE1
Update that ID value in TABLE2 using a Stored Procedure
I have tried:
while loop: took around 3 hours to complete the execution
cursor: cancelled the query after executing it overnight
In my understanding I can not use JOIN as I need to execute the statements in a sequence
The questions is not detailed enough. The general idea I would like to use something like this
-- create a output table to hold new id, and key columns to join later
DECLARE #OutputTbl TABLE (ID INT, key_Columns in MASTERTABLE)
INSERT INTO TABLE1
OUTPUT INSERTED.ID, MASTERTABLE.key_columns INTO #OutputTbl
SELECT *
FROM MASTERTABLE
UPDATE T2
SET ID = o.ID
FROM TABLE2 t2
INNER JOIN OutputTbl o
ON t2.key_column = o.key_column
Maybe you can consider a TRIGGER on TABLE1 from which to call the stored procedure on TABLE2, and then you can call your INSERT as you wish/need.. one by one or in blocks..
DROP TRIGGER TR_UPD_TABLE2
GO
CREATE TRIGGER TR_UPD_TABLE2 ON TABLE1 AFTER INSERT
AS
BEGIN
SET NOCOUNT ON
DECLARE #columnID INT = NULL
IF (SELECT COUNT(*) FROM INSERTED)=1 BEGIN
-- SINGLE INSERT
SET #columnID = (SELECT columnID FROM INSERTED)
EXEC TableTwoUpdateProcedure #columnID
END ELSE BEGIN
-- MASSIVE INSERT (IF NEEDED)
SET #columnID = 0
WHILE #columnID IS NOT NULL BEGIN
SET #columnID = (SELECT MIN(columnID) FROM INSERTED WHERE columnID > #columnID)
IF #columnID IS NOT NULL BEGIN
EXEC TableTwoUpdateProcedure #columnID
END
END
END
END

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).

How can I update the data row by row by the loop after insert those records into another table in mssql?

Does anyone know how can I update the data row by row by the loop after insert those records into another table in mssql?
Example:
I have the following table (tableA)
ID Name is_Feeded
1 Alvin 0
2 Ben 0
3 Lee 1
4 David 0
I want to insert those table from tableA to tableB then update the column is_Feeded to 1 in tableA through a loop?
Anyone know how can I do it in mssql?
Assuming SQL Server 2005 or higher, you can do this in a single statement.
UPDATE A
OUTPUT
inserted.ID,
inserted.Name
INTO
dbo.TableB (ID, Name)
SET
A.is_Feeded = 1 -- is fed?
FROM
dbo.tableA A
WHERE
A.is_Feeded = 0
;
A trigger is also possible, but I don't recommend using one if you can avoid it. If you must to use a trigger (such as perhaps a case where you can't control updates to tableA) then:
CREATE TRIGGER TableA_U ON dbo.TableA FOR UPDATE
AS
INSERT dbo.tableB (ID, Name)
SELECT
I.ID,
I.Name
FROM
inserted I
;
To me it is more natural to insert to tableB based on an update to tableA than to update tableA in response to an insert to tableB.
I would write a trigger for tableB. After you insert a row there, the trigger can update the specific value in tableA
First copy data from tableA to tableB
INSERT INTO tableB
SELECT Name, id FROM tableA;
then set is feeded:
UPDATE tableA SET is_feeded = true
and finally you should do this in one transaction (syntax depends on your DB system, e.g. MySQL: http://dev.mysql.com/doc/refman/5.0/en/commit.html)
you should directly add update field is_feeded when inserting data to TABLEB.
CREATE PROCEDURE xxxxx
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON ;
DECLARE #iOK INT ;
SET #iOK = 0 ;
BEGIN TRY
BEGIN TRANSACTION -- Start the transaction
--start Inserting --
INSERT INTO tableB
SELECT Name ,
id
FROM tableA ;
UPDATE tableA
SET is_feeded = true
-- If we reach here, success!
COMMIT
SET #iOK = 1 ;
END TRY
BEGIN CATCH
-- Whoops, there was an error
IF ##TRANCOUNT > 0
ROLLBACK
-- Raise an error with the details of the exception
DECLARE #ErrMsg NVARCHAR(4000) ,
#ErrSeverity INT
SELECT #ErrMsg = ERROR_MESSAGE() ,
#ErrSeverity = ERROR_SEVERITY()
RAISERROR(#ErrMsg, #ErrSeverity, 1)
END CATCH
SELECT #iOK ;
END

How to restrict insertion of value that already exists in other table

I have 2 tables. I need to check before insertion in one table if the value exist in other table.
I suggest that, you should first check the records that is going to be inserted in each request.
Create Proc Testing
as
Set NoCount ON
Set XACT_ABORT ON
Begin Try
Begin Tran
IF Not Exists(SELECT 1 FROM Table2 i JOIN Table1 t ON i.key = t.key)
Begin
//Your insert statement
END
Commit Tran
End Try
Begin Catch
Rollback Tran
End Catch
IF NOT EXISTS ( SELECT * FROM TableA WHERE Col1 = #Value)
INSERT INTO TableB(Col1) SELECT #Value
Using an INSERT trigger perhaps?
I'm not very sure about the syntax.
CREATE TRIGGER InsertTableTrigger ON Table1 FOR INSERT
AS
BEGIN
IF EXISTS ( SELECT 1 FROM Inserted i JOIN Table1 t ON i.key = t.key )
BEGIN
RAISERROR('Transaction Failed.',16,1)
ROLLBACK TRAN "insert on Table1"
END
END
GO
Inserted is used to access the inserting values.

INSERT Data From One Table Into Multiple Tables

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