How to insert values using Joins in asp.net stored procedure? - c#

CREATE PROCEDURE [dbo].[K_HRM_Insert_VehicleAssign]
#vehiclename varchar(50),
#empname varchar(50),
#updatedby varchar(50),
#updatedon datetime
AS
BEGIN
INSERT INTO K_MasterEmpDetails ME
INNER JOIN K_HRM_Vehicle_Assign VA ON VA.[empname+id] = ME.Firstname +' '+ME.Lastname + ' - ' + ME.kjlid AS ME.Employee
(VA.vehiclename, ME.Employee, VA.updatedby, VA.updatedon)
VALUES (#vehiclename, #empname, #updatedby, GETDATE())
END
I am getting an error near ME...please help me

You can't use this syntax. Correct syntax is:
INSERT INTO Table
(COLUMNS)
VALUES
(value)
For correct insert into two tables you have to use transaction and insert into two table separately.

You're syntactically wrong. The correct syntax is what user said is basic
but you can use
Insert into Table
select statement
It will select the rows based on condition then insert into table.
and in select statement you can use join.

Related

How to get Scope Identity Column while inserting datatable using stored procedure

I'm inserting datatable using stored procedure and created a type table before,
the query is i want to get back all the 'ProdID' that has been inserted in this session.
for the single insertion i can get the scope identity but i want to get all for the recent insertion.
Thanks in advance.
[dbo].[sp_Isert] (#dt_Product Product_Table READONLY, #ProdID int out)
AS
INSERT into tblProduct (Name,Batch,Qty,ExpDate)
SELECT Name, Batch, Qty, ExpDate
FROM #dt_Product;
set #ProdID = Scope_Identity( )
select Scope_Identity( ) ProdID
Do not use scope_identity() - use the output clause instead.
Note that SQL Server does not support table valued parameters as out parameters, meaning the only way to return a record set from a stored procedure is either by using the output clause (not into table) or by executing a select statement.
Also, do not use the sp prefix for stored procedured.
Microsoft is using this prefix for system procedues, so you might get a name collision.
ALTER PROCEDURE [dbo].[stp_Isert] (#dt_Product Product_Table READONLY)
AS
INSERT into tblProduct (Name,Batch,Qty,ExpDate)
OUTPUT Inserted.Id -- This will return a recordset with the inserted ids to the calling application.
SELECT Name, Batch, Qty, ExpDate
FROM #dt_Product;
Update
I've made a sample script for you to check. When I'm running this on my SQL Server instance, I get the expected results:
CREATE TABLE tbl_TestOutputClause (Id int identity(1,1), Col int );
GO
CREATE TYPE udt_TestOutputClauseIntegers AS TABLE (Value int);
GO
CREATE PROCEDURE stp_TestOutputClauseInsert (#Values dbo.udt_TestOutputClauseIntegers READONLY)
AS
INSERT INTO tbl_TestOutputClause(Col)
OUTPUT INSERTED.Id
SELECT Value
FROM #Values;
GO
CREATE PROCEDURE stp_TestOutputClauseGetInsertedValues
AS
DECLARE #Ids AS TABLE (Id int);
DECLARE #Vals dbo.udt_TestOutputClauseIntegers;
INSERT INTO #Vals (Value) VALUES (1), (2), (3);
INSERT INTO #Ids
EXEC stp_TestOutputClauseInsert #Vals;
-- should return three rows with the values 1, 2 and 3.
SELECT *
FROM #Ids;
GO
EXEC stp_TestOutputClauseGetInsertedValues;
-- clean up
DROP TABLE tbl_TestOutputClause;
DROP PROCEDURE stp_TestOutputClauseInsert;
DROP PROCEDURE stp_TestOutputClauseGetInsertedValues
DROP TYPE udt_TestOutputClauseIntegers;

How to simplify batched SQL Inserts with too many parameters

So I am trying to insert data that looks like this:
INSERT INTO RELATIONSHIP_CONFIG (USERID, WORKGROUPID, PRIORITY) VALUES
(#userId, #WorkgroupId10, #SmartFeedPriority10),
(#userId, #WorkgroupId11, #SmartFeedPriority11),
(#userId, #WorkgroupId12, #SmartFeedPriority12),
(#userId, #WorkgroupId13, #SmartFeedPriority13);
Which generally is very simple and linear as all inserts happen one after the other and performs fine (I think).
The issue is that there is a hard limit with the number of SQL Parameters I am allowed to use- 2100.
The upper limit edge case accounts for an insert that is quite a bit above that.
I was thinking about passing the data for WorkgroupId and SmartFeedPriority as a csvs and using a split function to create tables or something like that...
What is the best approach for dealing with data like this?
Maybe creating a stored procedure, passing the #UserId, #WorkgroupId (CSV), and #SmartFeedPriority (CSV) and having linear, one by one inserts done this way, but I am not too sure how the logic for this will look...
Looking at your question it's a bit difficult to suggest a good approach. I'm unable to see how and where the source of the data is.
I see you mentioned a CSV file. You can import data from a CSV file using the below script. Once the data is in a table, you can try one of the below examples.
IF OBJECT_ID('tempdb.dbo.#TempTable', 'U') IS NOT NULL
DROP TABLE #TempTable ;
CREATE TABLE #TempTable
(
[UserID] NVARCHAR(MAX) NULL,
[WorkGroup] NVARCHAR(MAX) NULL,
[SmartFeedPriority] NVARCHAR(MAX) NULL,
)
BULK INSERT #TempTable
FROM ' put your csv file path here '
WITH
(
FIELDTERMINATOR = ',', -- comma delimited
ROWTERMINATOR = '\n',
CODEPAGE = 65001 --'65001'
)
If the data you're trying to insert is from a table, you could try selecting the data into the table you need it to be.
Example :
SELECT [UserID], [WorkgroupID], [SmartFeedPriority]
INTO [dbo].[RELATIONSHIP_CONFIG]
FROM [dbo].[SorceTable]
If you would like to take the procedural route you can try the below. The below sample would work if the source of your data is in a table and you would like to individually insert each record.
Example :
procedure for insert
CREATE PROCEDURE [dbo].[CREATE_RELATIONSHIP_CONFIG](#UserId INT, #WorkgroupId INT, #SmartFeedPriority INT)
AS
BEGIN
INSERT INTO RELATIONSHIP_CONFIG (UserId, WorkgroupId, Priority) VALUES
(#userId, #WorkgroupId, #SmartFeedPriority)
END
You can wrap the above procedure in a while loop.
I've added a example for it below.
declare #UserId int;
declare #WorkgroupId int;
declare #Priority int;
WHILE EXISTS (SELECT [UserID] FROM #TempTable)
BEGIN
SELECT TOP 1 #UserId=[UserID], #WorkgroupId=[WorkGroup] , #Priority=[SmartFeedPriority] FROM #TempTable
EXEC [dbo].[CREATE_RELATIONSHIP_CONFIG] #UserId, #WorkgroupId, #Priority
DELETE TOP (1)FROM #TempTable
END

C# TableAdapter Fill/Get by Multiple IDs

I'm faced with a little problem. The situation is:
I have a MSSQL table which contains IDs (int, identity, primarykey), and names (string).
This table is huge, so i don't want to fill the entire dataset just for one LINQ-query.
I have a search algorithm, which fills a List<int> with more than one ID.
I want to load the matching rows in a datagridview with the following code:
dataGridView1.DataSource = tbl_WorklistTableAdapter.GetDataByID(ids_here);
But i can't handle multiple IDs, just a single. The GetDataByID() code needs to be this (i think):
SELECT [ID]
,[NAME]
FROM [DataBase].[dbo].[tbl_Namelist]
WHERE ID IN (#searchterm)
However WHERE ID IN accepts comma-separated ints, like 1,2,3. But the #variable is just one int.
How should i convert string to ints?
Thank you, and sorry for bad eng. :)
In that case you need to change in sql so you need to generate one temp table for comma separated id and apply condition in the your query.
Like:-
DECLARE #variables VARCHAR(200) = #searchterm -- Your Variable
CREATE TABLE #temp(ID NUMERIC) DECLARE #temp VARCHAR(200)
SET #temp = #variables WHILE LEN(#temp) > 0 BEGIN DECLARE #t1 VARCHAR(200)
IF CHARINDEX(',',#temp) > 0
BEGIN
SET #t1 = SUBSTRING(#temp,0,CHARINDEX(',',#temp))
INSERT INTO #TEMP SELECT #t1
SET #temp = SUBSTRING(#temp,CHARINDEX(',',#temp)+1,len(#temp))
END
ELSE
BEGIN
INSERT INTO #TEMP SELECT #temp
SET #temp = ''
END
END
SELECT [ID]
,[NAME]
FROM [DataBase].[dbo].[tbl_Namelist]
WHERE ID IN (SELECT ID FROM #temp)
You can use the built-in function SPLIT_STRING function:
SELECT [ID], [NAME]
FROM [DataBase].[dbo].[tbl_Namelist]
WHERE ID IN (SELECT VALUE FROM SPLIT_STRING(#searchterm,','))
This only works on Compatibility level 130 or greater.
If you are on an older version of SQL Server you can follow this answer, which defines an equivalent function:
SELECT [ID], [NAME]
FROM [DataBase].[dbo].[tbl_Namelist]
WHERE ID IN (SELECT VALUE FROM fn_split_string(#searchterm,','))

Problem in stored procedure

create procedure InsertQuestionEntry
#round_name varchar(40),
#question varchar(100),
#answer varchar(40),
#option1 varchar(20),
#option2 varchar(30),
#option3 varchar(30)
as
begin
insert into QuestionEntry(Question,Round_Name) values(#question,#round_name);
declare #quesion_id int
exec #quesion_id= select Question_ID from QuestionEntry;
insert into Answer(Question_ID,Answer,Option1,Option2,Option3) values(#quesion_id,#answer,#option1,#option2,#option3);
end
Here I want to retrieve the Question_ID from table QuestionEntry and use that Question_ID to another table Answer
But this didn't work.
So how can I use above way?
please help me
Instead of
insert into QuestionEntry(Question,Round_Name) values(#question,#round_name);
declare #quesion_id int
exec #quesion_id= select Question_ID from QuestionEntry;
use the following:
DECLARE #quesion_id int
INSERT INTO QuestionEntry(Question,Round_Name) values(#question,#round_name)
SET #quesion_id = SCOPE_IDENTITY()
You should not use "exec" there.
What exec does is:
Executes a command string or character
string within a Transact-SQL batch, or
one of the following modules: system
stored procedure, user-defined stored
procedure, scalar-valued user-defined
function, or extended stored
procedure.
You should use "set" or "select" instead of exec.
SET can only assign one variable at
a time, SELECT can make multiple
assignments at once. When assigning
from a query if there is no value
returned then SET will assign
NULL, where SELECT will not make
the assignment at all (so the variable
will not be changed from it's previous
value)
You can find more info about when to use SET or SELECT here: SET vs SELECT when assigning variables
Sample:
set #quesion_id = (select Question_ID from QuestionEntry)
select #quesion_id = (select Question_ID from QuestionEntry)
But that's also wrong way to get identity value from inserted record. If you have N users execute a same procedure at a same time it can happen that you will get wrong value (from last inserted record).
To do this properly you should use ##IDENTITY or even better SCOPE_IDENTITY(). More info: here.
After INSERT you can simply call:
SELECT #quesion_id = ##IDENTITY
--or
SELECT #quesion_id = SCOPE_IDENTITY()
Also, check your Question_ID is configured properly. It should be set to auto increment.
Sample:
Question_ID int IDENTITY(1,1)PRIMARY KEY CLUSTERED
The 1's following the IDENTITY keyword indicate the SEED number (value for first record in table) and increment property (0 or 1).
If your server's version is SQL Server 2005 or higher, you could also try something like this:
create procedure InsertQuestionEntry
#round_name varchar(40),
#question varchar(100),
#answer varchar(40),
#option1 varchar(20),
#option2 varchar(30),
#option3 varchar(30)
as
begin
insert into QuestionEntry(Question,Round_Name)
output inserted.Question_ID, #answer, #option1, #option2, #option3
into Answer (Question_ID, Answer, Option1, Option2, Option3)
values(#question,#round_name);
end

Creating a SQL table from a comma concatenated list

I am running SQL Server and I have a stored procedure. I want do a select statement with a WHERE IN clause. I don't know how long the list will be so right now I have tried something as follows
SELECT * FROM table1 WHERE id IN (#idList)
in this solution #idList is a varChar(max). but this doesn't work. I heard about passing in table values, but I am confused about how to do that. Any help would be great
I would suggest using a function to split the incoming list (use the link that Martin put in his comment).
Store the results of the split function in a temporary table or table variable and join it in your query instead of the WHERE clause
select * into #ids from dbo.Split(',', #idList)
select t.*
from table1 t
join #ids i
on t.id = i.s
The most efficient way would be to pass in a table valued parameter (if you're on SQL Server 2008), or an XML parameter (if you're on SQL Server 2005/2000). If your list is small (and you're on SQL Server 2005/2000), passing in your list as a comma (or otherwise) delimited list and using a split function to divide the values out into rows in a temporary table is also an option.
Whichever option you use, you would then join this table (either the table parameter, the table resulting from the XML select, or the temporary table created by the values from the split) to your main query.
Here is a table valued function that takes a nvarchar and returns a table to join on:
Create function [ReturnValues]
(
#Values nvarchar(4000)
)
Returns #ValueTable table(Value nvarchar(2000))
As
Begin
Declare #Start int
Declare #End int
Set #Start = 1
Set #End = 1
While #Start <= len(#Values)
Begin
Set #End = charindex(',', #Values, #Start)
If #End = 0
Set #End = len(#Values) + 1
Insert into #ValueTable
Select rtrim(ltrim(substring(#Values, #Start, #End - #Start)))
Set #Start = #End + 1
End
Return
End
GO
Binding an #idList parameter as you suggested is not possible with SQL.
The best would be bulk inserting the ids into a separated table and than query that table by using an subselect, or joining the IDs.
e.g.
INSERT INTO idTable (id, context) values (#idValue, 1);
INSERT INTO idTable (id, context) values (#idValue, 1);
INSERT INTO idTable (id, context) values (#idValue, 1); // as often as you like
SELECT * FROM table1, idTable WHERE table1.id == idTable.id and idTable.context = 1
The context must be a unique value that identifies the Id Range. That is important for running the stored proc parallel. Without the context information, running the stored procecure in parallel would mix the values from different selections.
If the number of parameters are reasonably small (< 100) you can use several parameters
SELECT * FROM table1 WHERE IN id IN (#id1, #id2, #id3)
If it is longer, look for a split function.

Categories