Referencing inserted ID in multiple insert transactions in Postgres - sql

I need to build a SQL query that must be able to insert data in a first table, grab the inserted ID and then use it as foreign key in the following tables.
WITH inserted AS (
INSERT INTO firstTable (name) VALUES ('somename') RETURNING id
)
SELECT * FROM inserted; -- this has the inserted id
INSERT INTO secondTable (name, foreign_id) VALUES ('someexternalname', ???)
So how do I reference the id in inserted in the secondTable insert?

You have completed this 80% percent, the complete SQL is:
with inserted as (
insert into first_table(name) values ('somename') returning id
)
insert into second_table(name, foreign_id) select 'someexternalname',id from inserted

You can do this:
WITH inserted AS (
INSERT INTO firstTable (name) VALUES ('somename') RETURNING id
)
INSERT INTO secondTable (name, foreign_id)
SELECT
'someexternalname',
id
FROM inserted;

You can try this:
INSERT INTO secondTable (name, foreign_id) VALUES ('someexternalname', (SELECT
MAX (id) FROM firstTable))

Related

Using sequence while inserting data into 2 tables at same time

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

How to Lock multiple tables for Insert command in Sql

This is my table Structure
When I insert Data into the first table, it will have multiple entries in table 2
I am Using code
To Get ID
Select MAX(ID)+1 From Table1
To Insert Data
Insert Into Table1 Values('1','abc','add1');
Insert into table2 values('1','med','english');
Insert into table2 values('1','eng','english');
Code is working fine for single computer but when we used in application in multiple terminals it is inserting wrong data i.e. data of another id in table2
You need ensure that the ID column of table1 is an identity column and then do the following:
DECLARE #ID INT
INSERT table1 ([columns])
VALUES (...)
SELECT #ID = SCOPE_IDENTITY()
INSERT table2 (table1ID, [columns])
VALUES (#ID, ...)
You can read more about SCOPE_IDENTITY() here.
MAX(ID) will include ID values created by other processes, which is why your second insert is mixing up data.

Insert a table variable into a temp table with multiple columns (ID, Number, etc.)

I need to insert multiple Table variables into one temp table.
One of the table variables is:
DECLARE ##TempTable_Number TABLE (Number bigint)
insert into ##TempTable_Number (Number) values ('000000000000');
insert into ##TempTable_Number (Number) values ('100000000000');
This works for inserting just one table variable
select * into ##GlobalTempTable_1 from ##TempTable_Number
I have a couple more table variables like
DECLARE ##TempTable_ID TABLE (Number int)
insert into ##TempTable_ID (ID) values ('1');
insert into ##TempTable_ID (ID) values ('12');
etc...
I tried this to insert data from multiple table variables into one TempTable:
Select * into ####GlobalTempTable_1 From ##TempTable_ID, ##TempTable_Number;
The query goes to a continuous loop...
EDIT:
One of the table variables is:
DECLARE ##TempTable_Number TABLE (Number bigint, ID int)
insert into ##gvTempTable (Number) values ('21212321332332');
insert into ##gvTempTable (Number) values ('100000000000');
insert into ##gvTempTable (ID) values ('1');
insert into ##gvTempTable (ID) values ('12');
select * into ##GlobalTempTable from ##gvTempTable;
select * from ##GlobalTempTable;
This returns a kind of a cartesian product
Use UNION ALL:
SELECT ID
INTO ##GlobalTempTable_1
FROM ##TempTable_ID
UNION ALL
SELECT Number
FROM ##TempTable_Number;
LiveDemo
Select * into ####GlobalTempTable_1 From ##TempTable_ID, ##TempTable_Number;
The query goes to a continuous loop...
It is probably not loop but very long query. Keep in mind that you do Cartesian product.
So your query is the same as:
SELECT *
INTO ##GlobalTempTable_1
FROM ##TempTable_ID
CROSS JOIN ##TempTable_Number;
And the result is NxM records where N is number of records in first table and M in the second.
Try like this,
DECLARE #TempTable TABLE (
ID INT
,Number BIGINT
)
INSERT INTO #TempTable (Number)
VALUES ('21212321332332');
INSERT INTO #TempTable (Number)
VALUES ('100000000000');
INSERT INTO #TempTable (ID)
VALUES ('1');
INSERT INTO #TempTable (ID)
VALUES ('12');
--select * into #GlobalTempTable from ##gvTempTable;
--select * from ##GlobalTempTable;
SELECT *
FROM #TempTable
SELECT A.ID
,B.Number
FROM (
SELECT ID
,ROW_NUMBER() OVER (
ORDER BY ID
) TempId
FROM #TempTable
WHERE id IS NOT NULL
) A
INNER JOIN (
SELECT number
,ROW_NUMBER() OVER (
ORDER BY id
) TempId
FROM #TempTable
WHERE number IS NOT NULL
) B ON A.TempId = B.TempId

Insert into 2 tables from a single select query using TSQL

I am trying to insert into 3 tables from one single select statement. Here is what I am trying to do:
insert into dbo.temp1 (name, location, city)
select name, location, city from mytable.
I want to be able to insert into 3 tables once I run the select statement like inserting into temp1, temp2 and temp3.
How can I do this? Thanks.
You can do it maximum for 2 tables with using output:
insert into dbo.temp1 (name, location, city)
output inserted.name, inserted.location, inserted.city into temp2
select name, location, city from mytable
You can't do this in one step*
What you can do is to insert the initial query into a #temp table (or a #table variable) as a staging area, and then insert into the tables from there. Wrap the steps in a transaction to retain ACID:
BEGIN TRAN
select name, location, city
into #TEMP
from mytable;
insert into temp1(name, location, city)
select name, location, city
from #TEMP;
-- Same for temp2 and temp3.
COMMIT TRAN
* Excluding hacks such as a view with an Instead-of Trigger.
The staging table is important from a concurrency point of view, as repeating the original query 3 times may result in different results if there are interim concurrent changes to the source table.
You can.
With a trick.
Create a view, then create an 'instead of' trigger for insert on that view where you insert the stuff into your tables. If you now insert into your view, you finally insert data in 3 tables. Here's a demo
-- 1. create 3 test tables
create table t1( id int, f1 varchar(20))
create table t2( id int, f2 varchar(20))
create table t3( id int, f3 varchar(20))
go
-- 2. create the view
create view Tt as
select t1.ID, t1.f1, t2.f2,t3.f3
from t1
join t2 on t1.ID=t2.ID
join t3 on t1.ID=t3.id
go
-- 3. create the trigger
create trigger Tr_Test on Tt INSTEAD OF INSERT
AS
BEGIN
SET NOCOUNT ON;
insert into t1 select id,f1 from inserted
insert into t2 select id,f2 from inserted
insert into t3 select id,f3 from inserted
END
GO
-- 4. now do your insert with a single select
insert into tt
select 1,'A','B','C'
-- 5. and watch the 3 tables
select * from t1
select * from t2
select * from t3
voilá, one insert, 3 tables got modified. Wwe don't count the hidden trigger, do we ;-)
There is no way to insert into X tables with one query (Ok it its with insert and output to table).
So you have to write 3 queries.
Or you can generate SQL statments with dynamic queries.
I don't believe you can insert into multiple tables in one statement. You can definitely do it in one transaction, however.
BEGIN TRANSACTION
INSERT INTO dbo.temp1 (name, location, city)
SELECT name, location, city
FROM myTable
INSERT INTO dbo.temp2 (name, location, city)
SELECT name, location, city
FROM myTable2
COMMIT TRANSACTION
You can insert into multiple tables with one select statement using a TRIGGER.
CREATE TRIGGER TEMP2_TEMP3_INSERT ON TEMP1
AFTER INSERT AS
BEGIN
/* create your insert statements for TEMP2 and TEMP3 here
referencing the data from the first insert */
END;
GO
MySQL doesn't support multi-table insertion in a single INSERT statement. Oracle is the only one I'm aware of that does, oddly...
However, you CAN use a transaction and have both of them be contained within one transaction.
MySQL:
START TRANSACTION;
INSERT INTO table1 VALUES ('1','2','3');
INSERT INTO table2 VALUES ('1','2','3');
COMMIT;
SQL Server:
BEGIN TRAN;
INSERT INTO table1 VALUES ('1','2','3');
INSERT INTO table2 VALUES ('1','2','3');
COMMIT;
SQL Server with error catching/rollback:
BEGIN TRANSACTION [Tran1]
BEGIN TRY
INSERT INTO table1 VALUES ('1','2','3')
INSERT INTO table2 VALUES ('1','2','3')
COMMIT TRANSACTION [Tran1]
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION [Tran1]
END CATCH
GO

MS SQL Server Last Inserted ID

In my database all tables are using a common table for Sequence(ID_Table).
TABLE_ID has two fields (Common_ID, Table_Name).
If I insert any record in the table, I have to first insert a record in Table_ID(Auto-increment, Table_name) then use that Auto-increment value in my Other Table.
For example, I want to insert in Table_Products which has fields ID(Common_ID), Product_Name, Product_ID(Auto Increment)
I want to do something like this:
INSERT INTO TABLE_ID (Table_NAME), Values (Table_Products)
Get the Inserted ID and use it in Table_Products:
INSERT INTO Table_Products (ID, Product_Name, Product_ID(Auto Increment)
VALUES (ID from TABLE_ID, SomeProduct, Increment)
Try this one -
DECLARE #ID BIGINT
INSERT INTO dbo.TABLE_ID (Table_NAME)
SELECT 'Table_Products'
SELECT #ID = SCOPE_IDENTITY()
INSERT INTO dbo.Table_Products (ID, Product_Name)
SELECT #ID, 'SomeProduct'
You can use an insert statement with the output clause to generate a new Common_ID. Using insert ... select, you can specify that ID in an insert operation:
declare #Common_ID as table(ID int)
insert Table_ID
(Table_Name)
output inserted.Common_ID into #Common_ID
values ('Table_Products')
insert Table_Products
(ID, Product_Name)
select ID
, 'Some Product'
from #Common_ID
Use SCOPE_IDENTITY() after ur insert statementto get the last inserted id.
DECLARE #Product_Id int
INSERT INTO TABLE_ID (Table_NAME) VALUES (Table_Products);
SELECT #Product_Id=SCOPE_IDENTITY();
Insert INTO Table_Products (ID, Product_Name)
VALUES (ID from TABLE_ID, 'SomeProduct')
Dear friend you have to select id of last record inserted
and then pass it in another table so bellow code will help you very well
Insert INTO TABLE_ID (Table_NAME), Values (Table_Products)
DECLARE #ID int;
set #ID = SCOPE_IDENTITY();
Insert INTO Table_Products (ID, Product_Name)
Values (#ID, SomeProduct)
this code will solve your problem i define #ID for your last record id and then insert it in your other table
For MySql use select LAST_INSERT_ID();
All the other answers so far declare intermediary variables for SCOPE_IDENTITY(), but it could be simpler:
INSERT INTO dbo.TABLE_ID (Table_NAME) VALUES 'Table_Products';
INSERT INTO dbo.Table_Products (ID, Product_Name) VALUES (SCOPE_IDENTITY(),'SomeProduct');
You could be also more table-specific using IDENT_CURRENT()
Insert INTO TABLE_ID (Table_NAME), Values (Table_Products)
select #NewID=IDENT_CURRENT('TABLE_ID')
Insert INTO Table_Products (ID, Product_Name, Product_ID
Values (#NewID, SomeProduct, Increment)