I would like to insert data into a table based on all the values of a secondary table's column. For example
I have two tables
CREATE TABLE Table1 (
id int identity(1, 1) not null,
FullName varchar(100),
Age int,
CourseID int
)
CREATE TABLE Table2 (
id int identity(1, 1) not null,
Courses int
)
I would like to perform something like this ..
insert into Table1 ('Auser',20,'And the list of Courses that I get from Table2')
Is there a way I can do this in sql server ?
So for one new user you want to insert all available courses?
INSERT INTO Table1
SELECT 'Ausser', 20, t2.Courses
FROM Table2 t2;
Edit: Here's the fiddle: http://sqlfiddle.com/#!3/89470/1/0
Since, you are using SQL Server 2008, you can use the MERGE STATEMENT . Here is a program for your example
CREATE TABLE Table1
(
Id int identity(1, 1) not null,
FullName varchar(100),
Age int,
CourseID int
)
CREATE TABLE Table2
(
ID int identity(1, 1) not null,
Courses int
);
INSERT INTO Table2
SELECT 10 UNION ALL SELECT 20 UNION ALL
SELECT 30 UNION ALL SELECT 40 UNION ALL SELECT 50;
--The Merge Query
MERGE Table1 AS t1
USING (SELECT * FROM Table2) AS t2
ON t1.CourseID= t2.Courses
WHEN NOT MATCHED THEN
INSERT(FullName,Age,CourseID)
VALUES('Ausser',20,t2.Courses);
SELECT *
FROM Table1
DROP TABLE Table1
DROP TABLE Table2
//Result
Id FullName Age CourseID
1 Ausser 20 10
2 Ausser 20 20
3 Ausser 20 30
4 Ausser 20 40
5 Ausser 20 50
Related
I have this row in the database table:
ID requiredQty
1088 30
And another table:
ID orderLineID bookedInQty
3000 1088 10
3001 1088 10
dbfiddle: https://dbfiddle.uk/?rdbms=sqlserver_2019&fiddle=9ecd8c83fcda08453481ec6d0ce45947
Summary
Total booked in quantity is total of 20 and 10 remaining for that particular order-line.
Question
How can I create an if statement to insert a record into the 2nd table, not to exceed table 1 requiredQty: 30?
Example
If insert bookedInQty: 11 this means it exceeds 30 because there is an extra 1. If it exceeds, simply do nothing.
If to insert bookedInQty: 9 this does not exceeds 30 because the total now equals to 29. Then insert this record.
Note
Without creating any extra tables, I am trying to do it using an if statement.
This uses if to check if the sum of the bookedQty and the new value are lower then the required quantity. You can put the code in a stored procedure.
create table table1(
id int NOT NULL,
requiredQty int
);
create table table2(
id int NOT NULL,
orderLineId int,
bookedInQty int
);
insert into table1(id, requiredQty) VALUES (1088, 30);
insert into table2(id, orderLineId, bookedInQty)
VALUES
(3000, 1088, 10),
(3001, 1088, 10);
declare #sumQty int, #newQty int, #newOrderLineId int;
select #newOrderLineId = 1088, #newQty = 11; -- change #newQty to 10 or lower
select #sumQty = sum(bookedInQty) from table2 where orderLineId = #newOrderLineId
group by orderLineId;
-- I hardcoded the value of id, it should add 1 to the maximum value or use an identity column
if exists(select * from table1 where id = #newOrderLineId and requiredQty >= #sumQty + #newQty)
insert table2 (id, orderLineId, bookedInQty) values (3002, #newOrderLineId, #newQty);
select * from table1;
select * from table2;
Dbfiddle demo:
https://dbfiddle.uk/?rdbms=sqlserver_2019&fiddle=d800624279381f9bbd71cf51bbc5351a
Code:
IF OBJECT_ID('tempdb..#TempMaster','U') IS NOT NULL
DROP TABLE #TempMaster
IF OBJECT_ID('tempdb..#TempTransaction','U') IS NOT NULL
DROP TABLE #TempTransaction
CREATE TABLE #TempMaster
(
Sno INT IDENTITY(1,1),
RangeDesc VARCHAR(100),
RangeFromValue INT,
RangeToValue INT
)
CREATE TABLE #TempTransaction
(
Sno INT IDENTITY(1,1),
[Values] INT
)
INSERT INTO #TempMaster(RangeDesc,RangeFromValue,RangeToValue)
SELECT * FROM (VALUES('Type A',1,10),('Type B',11,20),('Type C',21,30)) AS T(RangeDesc,RangeFromValue,RangeToValue)
INSERT INTO #TempTransaction([Values])
SELECT 1
UNION ALL
SELECT 15
UNION ALL
SELECT 5
SELECT * FROM #TempMaster
SELECT * FROM #TempTransaction
Please anyone help me to get a this kind of a solution based on which range the value falls.
I want to get a range description and write down a query for a below output. Thanks in advance.
-------------------------------
sno Values RangeDesc
-------------------------------
1 1 Type A
2 15 Type B
3 5 Type A
-------------------------------
You do left join based on range values.
select t1.Sno, t1.[Values], t2.RangeDesc
from #TempTransaction t1
left join #TempMaster t2 on t1.[Values] between t2.RangeFromValue and t2.RangeToValue
i have a problem i want to take SQL query language that returns the employee's (id) supervisor to his supervisor.
I have a tab employee
create table employee (
id int not null,
surname varchar(50),
name varchar(30),
boss_id int)
You may try this...
select a.id, b.boss_id
from employee as a
inner join employee as b on a.boss_id=b.id
For test case
create table DemoTable
(
accountid bigint
,parentid bigint
,accountname nvarchar(128)
)
insert DemoTable(accountid,parentid,accountname)
select 1, null, 'Root'
union select 2, 3, 'Child1'
union select 3, 1, 'Child2'
Query:
select a.accountid, b.parentid from DemoTable as a
inner join DemoTable as b on a.parentid=b.accountid
output is as : pass accountid as 2
accountid parentid
2 1
Here 2 >> 3 >> 1
I have a temp table that looks like this:
FirstName
LastName
DOB
Sex
Age
ExternalID
In my stored procedure I'm inserting these values into a regular table that has the following structure:
ID identity(1,1)
FirstName
LastName
So, I do this:
Insert into myTable
select FirstName, LastName from TempTable
During the insert I need to insert primary key from main table back into temp table "ExternalID" column. How can this be achieved?
I tried using OUTPUT statement but it only allows to insert to a separate table and then I have no way to map back to temp table
I need to insert generated IDs to column ExternalID in temp table right after the insert. FirstName and LastName are not unique.
One possible solution would be to use loop and insert one row at a time. This way, I can update temp table row with scope_identity(). But I want to avoid using loops.
Try using MERGE instead of INSERT.
MERGE allows you to output a column you didn't insert, such as an identifier on your temp table. Using this method, you can build another temporary table that maps your temp table to the inserted rows (named #TempIdTable in the sample below).
First, give #TempTable its own primary key. I'll call it TempId. I'll also assume you have a column on #TempTable to store the returned primary key from MyTable, ID.
--Make a place to store the associated ID's
DECLARE #TempIdTable TABLE
([TempId] INT NOT NULL
,[ID] INT NOT NULL)
--Will only insert, as 1 never equals 0.
MERGE INTO myTable
USING #TempTable AS tt
ON 1 = 0
WHEN NOT MATCHED
THEN
INSERT ([FirstName]
,[LastName])
VALUE (t.[FirstName]
,t.[LastName])
OUTPUT tt.[TempId], inserted.[ID] --Here's the magic
INTO #TempIdTable
--Associate the new primary keys with the temp table
UPDATE #TempTable
SET [ID] = t.[ID]
FROM #TempIdTable t
WHERE #TempTable.[TempId] = t.[TempId]
I was working on a similar issue and found this trick over here: Is it possible to for SQL Output clause to return a column not being inserted?
Here's the full code I used in my own testing.
CREATE TABLE [MQ]
([MESSAGEID] INT IDENTITY PRIMARY KEY
,[SUBJECT] NVARCHAR(255) NULL);
CREATE TABLE [MR]
([MESSAGESEQUENCE] INT IDENTITY PRIMARY KEY
,[TO] NVARCHAR(255) NOT NULL
,[CC] NVARCHAR(255) NOT NULL
,[BCC] NVARCHAR(255) NOT NULL);
CREATE TABLE #Messages (
[subject] nvarchar(255) NOT NULL
,[to] nvarchar(255) NOT NULL
,[cc] nvarchar(255) NULL
,[bcc] nvarchar(255) NULL
,[MESSAGEID] INT NULL
,[sortKey] INT IDENTITY PRIMARY KEY
);
INSERT INTO #Messages
VALUES ('Subject1','to1','cc1','bcc1', NULL)
,('Subject2','to2', NULL, NULL, NULL);
SELECT * FROM #Messages;
DECLARE #outputSort TABLE (
[sortKey] INT NOT NULL
,[MESSAGEID] INT NOT NULL
,[subject] NVARCHAR(255)
);
MERGE INTO [MQ]
USING #Messages M
ON 1 = 0
WHEN NOT MATCHED
THEN
INSERT ([SUBJECT])
VALUES (M.[subject])
OUTPUT M.[SORTKEY]
,inserted.[MESSAGEID]
,inserted.[SUBJECT]
INTO #outputSort;
SELECT * FROM #outputSort;
SELECT * FROM [MQ];
UPDATE #Messages
SET MESSAGEID = O.[MESSAGEID]
FROM #outputSort O
WHERE #Messages.[sortKey] = O.[sortKey];
SELECT * FROM #Messages;
DROP TABLE #Messages;
As you said, FirstName and LastName are not unique. This means you cannot use a trigger because there can be the same FirstName + LastName so you cannot join on them.
But you can do the inverse thing: first update your temp table ExternalID (I suggest you to use sequence object and just do update #t set ExternalID = next value for dbo.seq1;) and then just insert your rows including ExternalID into myTable. To be able to insert into identity field you can use set identity_insert myTable on or you can re-design your destination table to contain no identity at all as now you use sequence for the same purpose.
We need a unique column for able to make the comparison at the update operation after the insert. That's why we are using ExternalID column temporarily. ExternalID updated by row_nubmber.
;WITH CTE AS
(
SELECT *, RN = ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) FROM #TempTable
)
UPDATE CTE SET ExternalID = RN
We are keeping the output of the insert operation in a temp table. The trick is order by with ExternalID, it will help us for making the unique row number for same first and last name
DECLARE #output TABLE (
ID INT,
FirstName VARCHAR(10),
LastName VARCHAR(10))
Insert into #myTable
OUTPUT inserted.ID, inserted.FirstName, inserted.LastName INTO #output(ID, FirstName, LastName)
select FirstName, LastName from #TempTable T
order by ExternalID
For replacing the ExternalID column with inserted id value, we are making comparing with first name, last name and row number.
;WITH TMP_T AS(
SELECT *, RN = ROW_NUMBER() OVER(PARTITION BY FirstName, LastName ORDER BY ExternalID) FROM #TempTable )
,OUT_T AS(
SELECT *, RN = ROW_NUMBER() OVER(PARTITION BY FirstName, LastName ORDER BY ID) FROM #output )
UPDATE TMP_T SET ExternalID = OUT_T.ID
FROM
TMP_T INNER JOIN OUT_T ON
TMP_T.FirstName = OUT_T.FirstName
AND TMP_T.LastName = OUT_T.LastName
AND TMP_T.RN = OUT_T.RN
Sample Data:
DECLARE #TempTable TABLE (
FirstName VARCHAR(10),
LastName VARCHAR(10),
DOB VARCHAR(10),
Sex VARCHAR (10),
Age VARCHAR(10),
ExternalID INT)
INSERT INTO #TempTable VALUES
('Serkan1', 'Arslan1', 'A','M','1',NULL),
('Serkan2', 'Arslan2', 'B','M','1',NULL),
('Serkan3', 'Arslan', 'C','M','1',NULL),
('Serkan3', 'Arslan', 'D','M','1',NULL)
DECLARE #myTable TABLE (
ID INT identity(100,1), -- started from 100 for see the difference
FirstName VARCHAR(10),
LastName VARCHAR(10))
Result:
MyTable
ID FirstName LastName
----------- ---------- ----------
100 Serkan1 Arslan1
101 Serkan2 Arslan2
102 Serkan3 Arslan
103 Serkan3 Arslan
TempTable
FirstName LastName DOB Sex Age ExternalID
---------- ---------- ---------- ---------- ---------- -----------
Serkan1 Arslan1 A M 1 100
Serkan2 Arslan2 B M 1 101
Serkan3 Arslan C M 1 102
Serkan3 Arslan D M 1 103
One way to do this is by duplicating the data into a second temp table like so:
SELECT *
INTO #TEMPTABLE
FROM (VALUES (1, 'Adam'), (2, 'Kate'), (3, 'Jess')) AS X (Id, Name)
SELECT TOP 0 CAST(NULL AS INT) AS IdentityValue, *
INTO #NEWTEMPTABLE
FROM #TEMPTABLE
CREATE TABLE #TABLEFORINSERT (
IdentityColumn INT IDENTITY(1,1),
Id INT,
Name VARCHAR(255)
)
INSERT INTO #TABLEFORINSERT (Id, Name)
OUTPUT INSERTED.IdentityColumn, INSERTED.Id, Inserted.Name INTO #NEWTEMPTABLE
SELECT Id, Name FROM #TEMPTABLE
--New temp table with identity values
SELECT * FROM #NEWTEMPTABLE
I have 2 tables, and im trying to insert data from one to another and keepeng the mappings between ids.
I found here someone with the same problem, but the solution isnt good for me.
here is the example:
the two tables
CREATE TABLE [source] (i INT identity PRIMARY KEY, some_value VARCHAR(30))
CREATE TABLE [destination] (i INT identity PRIMARY KEY, some_value VARCHAR(30))
CREATE TABLE [mapping] (i_old INT, i_new INT) -- i_old is source.i value, i_new is the inserted destination.i column
some sample data
INSERT INTO [source] (some_value)
SELECT TOP 30 name
FROM sysobjects
INSERT INTO [destination] (some_value)
SELECT TOP 30 name
FROM sysobjects
Here, i want to transfer everything from source into destination, but be able to keep a mapping on the two tables:
I try to use OUTPUT clause, but i cannot refer to columns outside of the ones being inserted:
INSERT INTO [destination] (some_value)
--OUTPUT inserted.i, s.i INTO [mapping] (i_new, i_old) --s.i doesn't work
SELECT some_value
FROM [source] s
Anyone has a solution for this?
Not sure is it write way but it works :D
MERGE [#destination] AS D
USING [#source] AS s
ON s.i <> s.i
WHEN NOT MATCHED BY TARGET
THEN
INSERT (some_value) VALUES (some_value)
OUTPUT inserted.i, s.i INTO [#mapping] (i_new, i_old);
try this sql below if you don't have permission to modify the tables:
The idea is using a temp table to be a bridge between destination table and the mapping table.
SQL Query:
declare #source table (i INT identity PRIMARY KEY, some_value VARCHAR(30))
declare #destination table (i INT identity PRIMARY KEY, some_value VARCHAR(30))
declare #mapping table (i_old INT, i_new INT) -- i_old is source.i value, i_new is the inserted destination.i column
declare #tempSource table
(
id_source INT identity , source_value VARCHAR(30)
,Id_New int,source_new VARCHAR(30)
)
insert into #source
output inserted.i, inserted.some_value into #tempSource(id_source,source_value)
SELECT TOP 10 name
FROM sysobjects
--select * from #tempsource
insert into #destination
OUTPUT inserted.i, inserted.some_value INTO #tempSource (Id_New,source_new)
select source_value from #tempSource
insert into #mapping
select Id_source, Id_New from
(
select a.id_source, a.source_value
from
#tempSource a
where id_source is not null and source_value is not null
) aa
inner join
(
select a.Id_New, a.source_new
from
#tempSource a
where Id_New is not null and source_new is not null
) bb on aa.source_value = bb.source_new
select * from #mapping
The mapping table result:
i_old i_new
----------- -----------
1 1
2 2
3 3
4 4
5 5
6 6
7 7
8 8
9 9
10 10