Using sequence while inserting data into 2 tables at same time - sql

I am trying to insert data using select statement. The table which I am inserting is having foreign key and it is sequence ID. How do I accomplish this? Because if I insert the sequence key in associated table first then how do I get the list of all the sequence ID to insert into the table.
Please note I am using insert with select statement so is there way to accomplish this without using cursor?

I think you can extract sequence value and then re-use it as many times as you want:
DECLARE #NextValue INT
SELECT #NextValue = NEXT VALUE FOR MySequence
SELECT NextValue = #NextValue
INSERT INTO PrimaryTable(PK_ID) VALUES (#NextValue);
INSERT INTO SecondaryTable(FK_ID) VALUES (#NextValue);

Here what I have tried.
DECLARE #MyTabVaR TABLE
(
FOREIGNKEY_ID INT,
COMMON_COL INT
);
INSERT INTO #MyTabVaR
SELECT NEXT VALUE FOR DBO.MY_SEQ,COMMON_COL FROM another_table2
INSERT INTO actual_table
SELECT FOREIGNKEY_ID FROM #MyTabVaR
INSERT INTO another_table
SELECT * FROM copy_table C
LEFT JOIN actual_table A
ON C.COMMON_COL=A.COMMON_COL
WHERE A.FOREIGNKEY_ID IS NOT NULL

Related

SQL Server: return joined data from insert select

I perform steps:
Create temporal table and fill it with data and unique order column [_oid]
Insert everything from temporal table into real table except fictional [_oid], outputting generated [id]'s
Return those generated [id]'s along with corresponding [_oid]
SQL:
CREATE TABLE #temp
(
[Hash] INT NOT NULL,
[Size] INT NOT NULL,
[Data] NVARCHAR(MAX),
[_oid] INT NOT NULL
)
--here insert data into #temp--
INSERT [dbo].[TestObjects]
OUTPUT INSERTED.[Id]
SELECT [Hash], [Size], [Data]
FROM #temp
DROP TABLE #temp
How I can return ([Id], [_oid]) rows ? ....Or at least return [Id] ordered by [_oid] ?
I know insert does not preserve order of inserted items in it's output, but still...
I think you what you are asking for is INSERT INTO, as so:
INSERT INTO [dbo].[TestObjects]
SELECT Hash, Size, Data FROM #temp
ORDER BY _oid
But as you say, there's no guarantee about order when you select from TestObjects, so if it's important can you not have a field in TestObjects you can ORDER BY when you SELECT from it?
IF your insert into #temp is such that both o_id and (hash,size,data) are unique for each row (ie keys), then you could retrieve the inserted o_id from #temp:
select t.[_oid],to.[Id]
from #temp t
inner join [dbo].[TestObjects] to
on t.Hash=to.Hash and t.Size=to.Size and t.data=to.data
As noted by George Menoutis, I did merge:
MERGE [dbo].[TestObjects] AS T_Base
USING #temp AS T_Source
ON (0<>0)
WHEN NOT MATCHED THEN INSERT ([Hash],[Size],[Data]) VALUES (T_Source.[Hash],T_Source.[Size],T_Source.[Data])
OUTPUT INSERTED.[Id], T_Source.[_oid];
If anyone have better approach - feel free to contribute to this answer.

How to write a check to avoid the message "INSERT statement conflicted with the FOREIGN KEY constraint"?

I read and understood the entries in following asked question: INSERT statement conflicted with the FOREIGN KEY constraint
. I do get the point, however, I'm in this situation where I have around 1 Gb of records need to be inserted into a table, some of those records have conflicted foreign key. The query looks like this:
IF NOT EXISTS (SELECT * FROM [dbo].[tbl_R_TaskHistory] WHERE [TaskID] =
10000529)
BEGIN insert into [dbo].[tbl_History]
([TaskID],[UserID],[ActD],[RequestD],[No],[SignID],[Completed])
values (10000529,'A0000187',NULL,5738366,0,NULL,CAST(N'2011-03-16
04:53:37.210' AS DateTime)) END
The conflict ocurs on RequestID, so I was thinking there must be a way to make a check to avoid the error messages.
My point is that I want my query to check if the RequestID has not FOREIGN KEY constraint it will not insert this record and move to the next one.
If your query contains only one row, you can just expand the check like this:
IF NOT EXISTS (SELECT * FROM [dbo].[tbl_R_TaskHistory] WHERE [TaskID] = 10000529) AND EXISTS(SELECT 1 FROM [dbo].[...referencing table...] WHERE [RequestD] = 5738366)
BEGIN
insert into [dbo].[tbl_History] ([TaskID],[UserID],[ActD],[RequestD],[No],[SignID],[Completed])
values (10000529,'A0000187',NULL,5738366,0,NULL,CAST(N'2011-03-16 04:53:37.210' AS DateTime));
END
Anyway, if you are inserting many rows at the same time and for performance considerations, it will be better to store the values in buffer table. Something like this:
insert into #tbl_History ([TaskID],[UserID],[ActD],[RequestD],[No],[SignID],[Completed])
values (10000529,'A0000187',NULL,5738366,0,NULL,CAST(N'2011-03-16 04:53:37.210' AS DateTime))
,(...)
,(...)
,(...)
Then, just perform an inner join to your referencing table:
insert into [dbo].[tbl_History] ([TaskID],[UserID],[ActD],[RequestD],[No],[SignID],[Completed])
SELECT [TaskID],[UserID],[ActD],[RequestD],[No],[SignID],[Completed]
FROM #tbl_History A
INNER JOIN [dbo].[...referencing table...] B
ON A.[RequestD] = B.[RequestD];
This syntax also works
declare #a int = 5;
declare #b int = 18;
insert into sample (a, b)
select #a, #b
where not exists (select 1 from sample where b = #b)
and exists (select 1 from student where iden = #a)
This avoids creating a #temp
insert into sample (a, b)
select a, b
from ( values (5,19)
, (5,30)
, (5,31)
, (5,32)
, (7,41)
, (7,42)
) v(a,b)
where not exists (select 1 from sample where b = v.b)
and exists (select 1 from student where iden = v.a)

Get List of all last inserted IDs to a table

When I want to get last inserted ID to a table I use it like this:
insert into table1(col1,col2,col3)
values(val1,val2,val3)
declare #last_id int = scope_identity()
Now I have stored procedure that gets a value inserts multiple items:
insert into table1(col1,col2,col3)
select #val1,#val2,val3 from table2 where value=#value //#value is a single value that is passed to procedure as argument
now how can I get the list of IDs of these multiple rows that are added to table1?
declare #inserted table (Id int)
insert into table1(col1,col2,col3)
output inserted.Id into #inserted (Id)
select #val1,#val2,val3
from table2
where value=#value
select * from #inserted
The SCOPE_IDENTITY() gets you the last generated Identity Value in the identity column. to get all the newly inserted values you will need to make use of OUTPUT clause along with a table variable. See below how you can do that.
DECLARE #New_IDs TABLE(IDs INT)
insert into table1(col1,col2,col3)
OUTPUT inserted.Id_column INTO #New_IDs
select #val1,#val2,val3
from table2
where value=#value
SELECT * FROM #New_IDs

Extract Row ID from Table - Insert Then Select

Is it Possible to extract the ID of the record being inserted in a table at the time of inserting dat particular record into that table ??? Reference to Sql Server
Read about INSERT with OUTPUT. This is in my experience the easiest way of achieving an atomic INSERT outputting an inserted value.
Example, assuming that Table contains an auto-incremented field named ID:
DECLARE #outputResult TABLE (ID BIGINT)
INSERT INTO Table
(
Field1,
Field2
)
OUPUT INSERTED.ID INTO #outputResult
VALUES
(
....
)
SELECT TOP 1 ID FROM #outputResult
You can select the ID afterwards with
SELECT ##IDENTITY
or
SELECT SCOPE_IDENTITY()

Help with T-SQL script: Insert record, then use identity of that insert on another statement?

Just as a preface, I'm not very knowledgeable on T-SQL syntax.
I'd like to create a simple SQL script that will make 3 insert statements.
Insert A
Insert B
Insert C
Insert A statement's identity or "ID" would be needed in insert B statement.
And both the identities Inserts A & B would be needed in Insert C statement.
Pseudo code would look something like:
INSERT INTO tableA
VALUES ('blah', 'blah')
INSERT INTO tableB
VALUES (IDENTITY_FROM_A_INSERT, 'foo')
INSERT INTO tableC
VALUES (IDENTITY_FROM_A_INSERT, IDENTITY_FROM_B_INSERT)
How would I go about writing this script?
Use SCOPE_IDENTITY() after each insert in order to get the identity of the inserted row (in the current session).
I have used two variables to capture the two identities and then insert them into the third table:
DECLARE #Id1 INT
DECLARE #Id2 INT
INSERT INTO tableA VALUES ('blah', 'blah')
SET #Id1 = SELECT SCOPE_IDENTITY()
INSERT INTO tableB VALUES (IDENTITY_FROM_A_INSERT, 'foo')
SET #Id2 = SELECT SCOPE_IDENTITY()
INSERT INTO tableC VALUES (#Id1, #Id2)
scope_identity() is perfect for integer identifiers on single-record insertions (+1 to the other answer btw). However, if you find yourself using a guid/uniqueidentifier (newsequentialid(), newid(), etc) or inserting multiple records at once, you'll need something a little different:
declare #id uniqueidentifier;
-- Table variable for storing your newly inserted identifiers:
declare #NewlyInsertedIds table
(
[Id] uniqueidentifier
);
insert [MyTable]
(
[Blah1]
,[Blah2]
)
-- in the output clause you can access the inserted/deleted pseudo tables:
ouptut inserted.[Id]
into #NewlyInsertedIDs
(
[Id]
)
values
(
'Blah'
,'Blah'
);
select
#id = [Id]
from #NewlyInsertedIds;
Check out the OUTPUT Clause for more information.