INSERT to a table using SELECT and VALUES at the same time - sql

how can I insert to a table using values in different way? preferably no temp table. below is my stored procedure code, but i get errors on insert
CREATE PROCEDURE setBARS
-- Add the parameters for the stored procedure here
#BUSINESSAREANAME nvarchar(50),
#STAFFNAME nvarchar(50),
#ROLENAME nvarchar(50),
#BARSSTARTDATE date,
#BARSENDDATE date
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
WITH t1 (BUSINESSAREAID) AS (SELECT BUSINESSAREAID FROM BUSINESSAREA WHERE BUSINESSAREANAME = #BUSINESSAREANAME),
t2 (STAFFID) AS (SELECT STAFFID FROM STAFF WHERE STAFFNAME = #STAFFNAME),
t3 (ROLEID) AS (SELECT ROLEID FROM ROLE WHERE ROLENAME = #ROLENAME)
INSERT INTO BARS ([BUSINESSAREAID],[STAFFID],[ROLEID],[BARSSTARTDATE],[BARSENDDATE])
VALUES ((SELECT t1.BUSINESSAREAID, t2.STAFFID, t3.ROLEID FROM t1,t2,t3), #BARSSTARTDATE, #BARSENDDATE)
END
GO

You should be able to include the values directly in the SELECT statement:
INSERT INTO [BARS]
(
[BUSINESSAREAID]
, [STAFFID]
, [ROLEID]
, [BARSSTARTDATE]
, [BARSENDDATE]
)
SELECT
[t1].[BUSINESSAREAID]
, [t2].[STAFFID]
, [t3].[ROLEID]
, #BARSSTARTDATE
, #BARSENDDATE
FROM [t1]
, [t2]
, [t3];

Try This
insert into bars([BUSINESSAREAID],[STAFFID],[ROLEID],[BARSSTARTDATE][BARSENDDATE])
SELECT t1.BUSINESSAREAID, t2.STAFFID, t3.ROLEID FROM t1,t2,t3, #BARSSTARTDATE, #BARSENDDATE

why not put all the values on a variable for example;
declare #val1
set #val1 = (select top 1 businessareaid from t1)
declare #val2
set #val1 = (select top 1 staffid from t2)
insert into bars (val1,val2)
select #val1 , #val2

Related

Inserting data into table from table-valued parameter

I am trying to create a stored procedure to which is passed a TVP and then some data from the TVP is inserted into two tables.
I have already implemented the stored procedure, but only the second insert (the only one that does not read from the TVP) is working. The other two are not working (do not insert anything) and I can't seem to figure out why.
I have tried to create a dummy TVP in SQL Server and run the procedure there, but that also did not work. Is this being caused by the fact TVPs are readonly? I would assume not, since I am not actually inserting or updating data inside the TVP.
Is there a way to make this work?
Thank you for your assistance!
Table-valued parameter definition:
CREATE TYPE dbo.Ingredients
AS TABLE
(
Quantity int,
Measure nvarchar(50),
Ingredient nvarchar(50),
)
GO
Stored procedure:
ALTER PROCEDURE uspCreateRecipe
(#IDUser int,
#RecipeName nvarchar(50),
#Category nvarchar(50),
#Difficulty nvarchar(50),
#Duration nvarchar(50),
#ING dbo.Ingredients READONLY,
#Execution text)
AS
BEGIN
INSERT INTO dbo.Ingredients
VALUES ((SELECT Ingredient FROM #ING WHERE NOT EXISTS (SELECT Ingredient FROM #ING WHERE Ingredient IN (SELECT IngredientName FROM dbo.Ingredients))), 2)
INSERT INTO dbo.Recipes
VALUES (#IDUser, #RecipeName, NULL,
(SELECT IDDifficulty FROM dbo.Difficulty WHERE Difficulty = #Difficulty),
(SELECT IDDuration FROM dbo.Duration WHERE Duration = #Duration ),
NULL,
(SELECT IDCategory FROM dbo.Category WHERE CategoryName = #Category ),
#Execution , NULL, 2, GETDATE())
INSERT INTO dbo.Recipes_Ingredients
VALUES (SCOPE_IDENTITY(),
(SELECT Quantity FROM #ING),
(SELECT IDMeasure FROM dbo.Measure WHERE Measure IN (SELECT Measure FROM #ING)),
(SELECT IDIngredient FROM dbo.Ingredients WHERE IngredientName IN (SELECT Ingredient FROM #ING)))
END
Rather than using VALUES with sub-queries, just use SELECT.
Always list the columns you are inserting into. Its clearer and will reduce errors especially if you modify the table structure in future,
Your first query appeared to be overcomplicated - if indeed it worked at all.
Your third query should have thrown an error because you have multiple IN sub-queries which should have resulted in a "sub-query returned multiple results" error.
The text datatype is depreciated use varchar(max).
Normally you want to SET NOCOUNT, XACT_ABORT ON.
Always RETURN a status so your calling app knows whether it succeeded or not. 0 will be returned by default by I prefer to be explicit.
Semi-colon terminate all statements.
ALTER PROCEDURE uspCreateRecipe
(
#IDUser int
, #RecipeName nvarchar(50)
, #Category nvarchar(50)
, #Difficulty nvarchar(50)
, #Duration nvarchar(50)
, #ING dbo.Ingredients READONLY
, #Execution nvarchar(max) -- text is depreciated
)
AS
BEGIN
SET NOCOUNT, XACT_ABORT ON;
INSERT INTO dbo.Ingredients ([Name], Col2)
SELECT Ingredient, 2
FROM #ING
WHERE Ingredient NOT IN (SELECT IngredientName FROM dbo.Ingredients);
INSERT INTO dbo.Recipes (IDUser, RecipeName, Col3, IDDifficulty, IDDuration, Col6, IDCategory, Col8, Col9, Col10, Co11)
SELECT #IDUser, #RecipeName, NULL, IDDifficulty
, (SELECT IDDuration FROM dbo.Duration WHERE Duration = #Duration)
, NULL
, (SELECT IDCategory FROM dbo.Category WHERE CategoryName = #Category)
, #Execution, NULL, 2, GETDATE()
FROM dbo.Difficulty
WHERE Difficulty = #Difficulty;
INSERT INTO dbo.Recipes_Ingredients (IDRecipe, Quantity, IDMeasureid, IDIngredient)
SELECT SCOPE_IDENTITY(), Quantity
, (SELECT IDMeasure FROM dbo.Measure WHERE Measure = I.Measure)
, (SELECT IDIngredient FROM dbo.Ingredients WHERE IngredientName = I.Ingredient)
FROM #ING I;
RETURN 0;
END;

Get Scope identity for multiple inserts

For table1 Inserted 3 records
It should get those three identities and it should insert 3 records in table3 (but it’s not happening- it inserts 3 records with same identity ie.last scope identity)
create table table1(ID INT identity(1,1),Name varchar(50))
insert into table1 values('Ram'),('Sitha'),('Laxman')
create table table1(ID INT identity(1,1),Name varchar(50))
create table table3(ID INT ,Name varchar(50))
insert into table2(Name)
select Name from table1
declare #id int;
set #id= (select scope_Identity())
begin
insert into table3(ID,Name)
select #id,Name from table2
end
select * from table2
select * from table3
How can get all identities to insert do I need to write a loop (or) do I need to Create a trigger.
Please give me a solution I am strugguling from past 4 hours.
Thanks in anvance
Use the OUTPUT clause to handle multi-row inserts:
INSERT INTO dbo.table2(Name)
OUTPUT inserted.ID, inserted.Name INTO table3
SELECT Name FROM dbo.table1;
You can use the OUTPUT clause to get the identity from any number of inserts.
create table table1(ID INT identity(1,1),Name varchar(50))
DECLARE #T1 Table (ID int, name varchar(50))
insert into table1
OUTPUT inserted.ID, Inserted.Name INTO #T1
values('Ram'),('Sitha'),('Laxman')
DECLARE #IdentityId INT,#Count INT=1
DECLARE #temp AS TABLE (Id INT IDENTITY ,Name NVARCHAR(100))
INSERT INTO #temp(Name)
SELECT Name FROM table1
WHILE #Count <=(SELECT COUNT(SId) FROM #temp)
BEGIN
INSERT INTO table2(Name)
SELECT Name FROM #temp
WHERE Id=#Count
SET #IdentityId = SCOPE_IDENTITY()
INSERT INTO tabel3(#IdentityId,Name)
SELECT 3, #IdentityId,1,GETDATE()
SET #Count=#Count+1
END

Stored Procedure that updates fields with different values

I am using SQL Server.
I need to create a stored procedure that will update the Data field (table bellow) with different value for every ID value. (the values in the Data fields depend on the user input).
ID | Data
---------
1 | NULL
2 | NULL
3 | NULL
For example:
if ID = 1, Data should be "Test1"
The ID and Data pairs should somehow be input parameters to the stored procedures.
Is this possible, or I'll have to call simple update procedure for every ID/Data pair?
You need to use XML for sending data for multiple rows. For your current problem prepare (generate dynamically) an xml like below.
'<NewDataSet><Table><Id>1</Id><Data>test1</Data></Table><Table><Id>2</Id><Data>test2</Data></Table></NewDataSet>'
Then Prepare a procedure like below.
CREATE PROC [dbo].[UpdateMultipleRecords]
(
#XmlString VARCHAR(MAX)
)
AS
BEGIN
SET NOCOUNT ON;
CREATE TABLE #DATA
(
Id int,
Data varchar(50) NULL
)
DECLARE #DocHandle int
EXEC sp_xml_preparedocument #DocHandle OUTPUT, #XmlString
INSERT INTO #DATA
SELECT Id,Data
FROM OPENXML (#DocHandle, '/NewDataSet/Table',2)
WITH
(
Id int,
Data varchar(50)
)
EXEC sp_xml_removedocument #DocHandle
UPDATE [dbo].[Table1] SET DATA=D.Data
FROM [dbo].[Table1] T INNER JOIN #DATA D ON T.ID=D.Id
IF (SELECT OBJECT_ID('TEMPDB..#DATA')) IS NOT NULL DROP TABLE #DATA
END
And call the procedure as
[UpdateMultipleRecords] '<NewDataSet><Table><Id>1</Id><Data>Test1</Data></Table><Table><Id>2</Id><Data>Test2</Data></Table></NewDataSet>'
You need user-defined table types for this:
Try this:
-- test table
create table yourtable(id int not null, data [varchar](256) NULL)
GO
-- test type
CREATE TYPE [dbo].[usertype] AS TABLE(
[id] [int] not null,
[Data] [varchar](256) NULL
)
GO
-- test procedure
create procedure p_test
(
#tbl dbo.[usertype] READONLY
) as
BEGIN
UPDATE yourtable
SET data = t.data
FROM yourtable
JOIN
#tbl t
ON yourtable.id = t.id
END
go
-- test data
insert yourtable(id)
values(1),(2),(3)
go
Test of script:
declare #t [dbo].[usertype]
insert #t values(1,'hello'),(2,'world')
exec p_test #t
select * from yourtable
Result:
id data
1 hello
2 world
3 NULL
You can use another table with your values as a Source for the update
update t
set
Data = src.Data
from tableDestination t
inner join sourceTable src on
t.ID = src.ID

How can I insert the results of a stored procedure into a new table

ALTER procedure [dbo].[staffscorecard]
#STAFF_ID INT = NULL
as
select
count(STAFF_ID) as countexel
from
TbStudentSurvey
where
FEEDBACK = 'excellent'
and STAFF_ID = ISNULL(#STAFF_ID, STAFF_ID)
select
Score as scoreexel
from
TbStaffScoreMaster
where
Status = 'Excellent'
exec [dbo].[staffscorecard]
GO
CREATE TABLE #temp ( countexel int, scoreexel int)
GO
INSERT INTO #temp (countexel , scoreexel)
EXEC [dbo].[staffscorecard]
GO
SELECT *
FROM #temp
GO
For a given staffid to calculate countexel and scoreexel you can re-write your stored procedure as:
create table TbStudentSurvey (STAFF_ID int,FEEDBACK varchar(20));
insert into TbStudentSurvey values (1,'excellent'),(1,'excellent'),(2,'excellent');
create table TbStaffScoreMaster (Score int,[Status] varchar(20));
insert into TbStaffScoreMaster values(100,'Excellent');
Go
create procedure [dbo].[staffscorecard]
#STAFF_ID INT = NULL,
#countexel int output,-- Explicitly declare output variables to fetch these values
#scoreexel int output
as
Begin
select
#countexel = count(STAFF_ID)
from
TbStudentSurvey
where
FEEDBACK = 'excellent'
and STAFF_ID = ISNULL(#STAFF_ID, STAFF_ID)
select
#scoreexel = Score
from
TbStaffScoreMaster
where
Status = 'Excellent'
End
GO
and then instead of using a temp table use a table variable because when you use temp tables,the table has to match the exact column layout as of the stored procedure.
--CREATE TABLE #temp (countexel int, scoreexel int)
--GO
--Create a table variable:
declare #temp table (countexel int, scoreexel int)
declare #countexel int, #scoreexel int,#STAFF_ID int;
--set value of staff Id for which you want to get countexel and scoreexel.
set #STAFF_ID = 1;
EXEC [dbo].[staffscorecard] #STAFF_ID ,#countexel output,#scoreexel output
INSERT #temp values (#countexel ,#scoreexel);
SELECT *
FROM #temp
GO
Method 2:
You can also write as:
alter procedure [dbo].[staffscorecard]
#STAFF_ID INT = NULL
as
Begin
select
count(STAFF_ID) as countexel , Score as scoreexel
from
TbStudentSurvey TSS
inner join TbStaffScoreMaster TSM on TSM.Status = TSS.FEEDBACK
where
FEEDBACK = 'excellent'
and STAFF_ID = ISNULL(#STAFF_ID, STAFF_ID)
group by STAFF_ID,Score
End
GO
declare #temp table (countexel int, scoreexel int)
declare #STAFF_ID int;
set #STAFF_ID = 1;--set value of staff Id for which you want to get countexel and scoreexel.
INSERT #temp EXEC [dbo].[staffscorecard] #STAFF_ID
SELECT *
FROM #temp
GO
Hope this helps!!

Passing multiple parameters into a Table valued function

I have a table valued function as below. When I am trying to pass more than one parameter at the same time I am getting a error like "Function has too many arguments specified" .
CREATE FUNCTION [dbo].[GetCompanyUsers](#CompanyId BIGINT)
RETURNS #Users TABLE (Id BIGINT,Contact NVarchar(4000))
AS
BEGIN
INSERT INTO #Users(Id,Contact)
SELECT [Id]
,ISNULL([FirstName],'')+' ' +ISNULL([LastName],'') AS [Contact]
FROM [dbo].[CompanyAddressesContacts]
WHERE [CompanyId]=#CompanyId
ORDER BY ISNULL([FirstName],'')+' ' +ISNULL([LastName],'')
RETURN
END
What modifications I require in the above code so that it allows multiple values and I need to use the function in a "WHERE" condition in my dataset.
WHERE(Document_RFIs.CreatedBy IN
(SELECT Id FROM dbo.GetCompanyUsers(#CompanyId)))
This may help (but the fundamental problem is - passing a comma delimited string is something to be avoided unless absolutely necessary - which explains why you have received so few answers):-
--set nocount on
--create table #Document_RFIs (
-- CreatedBy varchar(50),
-- columna varchar(50),
-- columnb varchar(50),
-- columnc varchar(50)
--)
--insert into #Document_RFIs values
-- ('albert einstein','another','value',null),
-- ('marie curie','some',null,'tuna'),
-- ('isaac newton','why','not','provide'),
-- ('kepler','some','test','data'),
-- ('robert boyle','with','your','question'),
-- ('john dalton','it',null,'would'),
-- ('enrico fermi','make','helping','you'),
-- ('peter higgs','so','much','easier')
--create table #CompanyAddressesContacts (
-- companyid int,
-- firstname varchar(50),
-- lastname varchar(50)
--)
--insert into #CompanyAddressesContacts values (22,'albert','einstein')
--insert into #CompanyAddressesContacts values (23,'marie','curie')
--insert into #CompanyAddressesContacts values (23,'isaac','newton')
--insert into #CompanyAddressesContacts values (24,null,'kepler')
--insert into #CompanyAddressesContacts values (25,'robert','boyle')
--insert into #CompanyAddressesContacts values (25,'enrico','fermi')
--insert into #CompanyAddressesContacts values (26,'peter','higgs')
declare #ids varchar(1024)
set #ids='23,24,25'
create table #id (
companyid int
)
declare #pos int
while DATALENGTH(#ids)>0 begin
set #pos=charindex(',',#ids)
if #pos>0 begin
insert into #id values (left(#ids,#pos-1))
set #ids=SUBSTRING(#ids,#pos+1,DATALENGTH(#ids))
end else begin
insert into #id values (#ids)
set #ids=''
end
end
select d.*
from #Document_RFIs d
where exists(
select cac.*
from #CompanyAddressesContacts cac
join #id i on i.companyid=cac.companyid
where isnull(cac.firstname+' ','')+isnull(cac.lastname,'')=d.CreatedBy
)
--drop table #id
--drop table #Document_RFIs
--drop table #CompanyAddressesContacts
I would do something like this:
First convert your #CompanyId to rows
WITH CompanyIds AS (
SELECT Id
FROM CompanyTable -- Same as the source of the #CompanyId
WHERE Id IN (#CompanyId)
)
Then extract all users
,Users AS (
SELECT UserId
FROM CompanyIds
CROSS APPLY (
SELECT Id AS UserId
FROM dbo.GetCompanyUsers(CompanyIds.Id)
) AS CA1
)
And then use it in the where statement
WHERE Document_RFIs.CreatedBy IN (SELECT UserId
FROM Users)