Problem in stored procedure - c#

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

Related

How do I get a stored procedure to insert ##identity of previous inserts AUTO ID [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
Image above is order details table and the orderID is foreign key ref orders table.
This is my orders table which will generate a id when a table is inserted via this stored procedure below. PK OrderID
The stored procedure that inserts a table will happen first which will generate a orderID. I will then run this stored procedure below wanting to insert the last inserted orderID from orders into Orderdetails table using ##identity
but when I try to insert it comes up with this error saying the orderID is null
Have I written a wrong SQL statement to perform my desired action of inserting previously generated ID from one table to another
You're missing a few things.
First of all, you can't invoke ##IDENTITY. It's purpose is to save the identity value of a row you just inserted. Also, it's got issues with scoping, so you should use SCOPE_IDENTITY instead.
Your first procedure needs to return the inserted identity to the outer wrapper. This can be accomplished by using an OUTPUT parameter.
CREATE PROCEDURE dbo.testinsert333
(
#TableID TINYINT
,#OrderID INT OUTPUT
)
AS
BEGIN
INSERT INTO dbo.Orders (Orders.TableID)
VALUES (#TableID)
SET #OrderID = SCOPE_IDENTITY()
END
Your second procedure needs to just accept #OrderID. There's no way for this thread to snag an inserted identity value from a different thread. It must come in as a parameter.
CREATE PROCEDURE dbo.testinsert666
(
#OrderID INT
,#ProductID INT
,#Price INT
,#Quantity SMALLINT
,#OrderStatus BIT
)
AS
BEGIN
INSERT INTO dbo.OrderDetails
(
OrderID
,ProductID
,Price
,Quantity
,OrderStatus
)
SELECT #OrderID
,#ProductID
,#Price
,#Quantity
,#OrderStatus
END
GO
Now to tie all this together, they need to be called together, as in the example below.
BEGIN
DECLARE #OrderID INT
EXEC dbo.testinsert333 #TableID = 1, #OrderID = #OrderID OUTPUT
EXEC dbo.testinsert666
#OrderID = #OrderID
,#ProductID = #ProductID
,#Price = #Price
,#Quantity = #Quantity
,#OrderStatus = #OrderStatus
END
However, the best approach is to nest these two procedures into one, like below.
CREATE dbo.usp_AllInWonder
(
#TableID INT
,#ProductID INT
,#Price INT
,#Quantity SMALLINT
,#OrderStatus BIT
)
AS
BEGIN
DECLARE #OrderID INT
INSERT INTO dbo.Orders (Orders.TableID)
VALUES (#TableID)
SET #OrderID = SCOPE_IDENTITY()
INSERT INTO dbo.OrderDetails
(
OrderID
,ProductID
,Price
,Quantity
,OrderStatus
)
SELECT #OrderID
,#ProductID
,#Price
,#Quantity
,#OrderStatus
END
Remove line 13 from testinsert666. You're passing in the OrderID, so you don't need to assign it there. Any call to ##identity ( or preferably scope_identity()) would be in `testinsert333'.
For you to use the ##IDENTITY in testinsert666, you need you have the insert creating ##IDENTITY to happen in the procedure testinsert666. testinsert666 can only be used in the same session it was generated.
See ##IDENTITY (Transact-SQL)

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 tell if a record is already exists in the database before executing stored procedure?

I want to create a stored procedure to insert data into a table in the database, but it should be unique so I check first for the incoming parameter:
create procedure SP_Insert
#name varchar(50)
AS
if not exists (select Name from Employees where Name = #name)
begin
insert into Employess (Name)
values (#name)
end
My question is, how to tell in my code if the passing parameter hasn't been accepted as a unique value after the execution of the stored procedure?
In my form I have a button (Insert) and a textbox (name), when the user click insert the text value is passed to the stored procedure, and I want to spring a message box warning the user of duplicated entry
Use ##ROWCOUNT to determine that a row was affected and return the value as a parameter. See this answer: How can I get the number of records affected by a stored procedure?
You can do this:
insert into Employess (Name)
select #name
where not exists (select * from Employees where Name = #name)
select ##rowcount
Now the ##rowcount (returned to the caller) is either zero or one depending on whether there was an insert.
var recordsUpdated = command.ExecuteScalar();
Actually you could skip select ##rowocount and not explicitly return anything.
var recordsUpdated = command.ExecuteNonQuery();
That returns the number of affected records. I prefer to be more explicit. Someone could come behind and alter the procedure so that it does something else that changes ##rowcount. (Why? But they could.) And they might not know that something downstream is depending on that affected record count. But if it's explicit, whether a selected value or an output parameter, then someone can tell that something else depends on that value.
create procedure SP_Insert
#name varchar(50), #result bit output
AS
if not exists (select Name from Employees where Name=#name)
begin
insert into Employess (Name) Values (#name)
set #result = 1
End
else set #result = 0
Stored procedure can return a value.
You can change your SP into something like this:
create procedure SP_Insert
#name varchar(50)
AS
BEGIN
if not exists (select Name from Employees where Name=#name)
begin
insert into Employees (Name) Values (#name)
Return 0
end
else begin
Return 1
end
END
Here is the link to MSDN article with more details and examples:
[https://msdn.microsoft.com/en-us/library/ms188655.aspx]

How can I call a stored procedure with INSERT using LINQ?

Is there any possible way to execute a non query without having to assign it to a LINQ to SQL class?
Let's say I have this procedure and I want to INSERT only if the Town_Name (UNIQUE CONSTRAINT) is non existent. Otherwise, the UPDATE is executed. This procedure works well and does the job when executed through SQL Server. However, I can't manage to execute it through C# code.
I am trying to avoid using SQL client, as part of my coursework, my little application has to be capable of selecting, inserting / updating and deleting data using LINQ.
The approach I'm taking always results in 0 rows affected.
// Call Procedure.
db.P_SaveClient("000000001M", "Test", "Dummy", null, "+35699999999");
-- Procedure to be executed.
CREATE PROCEDURE Appointment.SaveClient
(
#id NVARCHAR(10),
#firstName NVARCHAR(35),
#lastName NVARCHAR(35),
#tel NVARCHAR(12),
#mob NVARCHAR(12)
)
AS
BEGIN
DECLARE #clientCount TINYINT
SELECT #clientCount = COUNT(Client_ID)
FROM Appointment.Client
WHERE Client_ID = #id
IF #clientCount = 0
BEGIN
INSERT INTO Appointment.Client
VALUES (
#id
, #firstName
, #lastName
, #tel
, #mob
)
END
ELSE
BEGIN
UPDATE Appointment.Client
SET Client_ID = #id
, First_Name = #firstName
, Last_Name = #lastName
, Telephone = #tel
, Mobile = #mob
END
END
Some tutorials I found:
https://www.youtube.com/watch?v=dlXT-vE46sc
https://www.youtube.com/watch?v=-PAMtSwplu8
You're looking for a Merge statement to execute in SQL, which you could call via the stored proc. This will allow you to insert or update depending on whether it was found. It can even return the ID of the record inserted which can save you another query.
Merge Town t
using ( select #Town_Name as 'Town_Name')
src on (src.Town_Name = t.Town_Name )
when NOT MATCHED then
insert (Town_Name) values (src.Town_Name)
output INSERTED.Town_ID
See here for syntax and more examples:
https://msdn.microsoft.com/en-us/library/bb510625.aspx

Stored Procedure Storing 0 in Auto increment column in Table

I have the following table where ProspectCode is Identity Not Null
Table LeadMastersNew
ProspectCode int
CompanyName nvarchar(50)
PersonName nvarchar(50)
Designation nvarchar(50)
Number nvarchar(50)
Number2 nvarchar(50)
Emailaddress nvarchar(50)
Address nvarchar(MAX)
Address2 nvarchar(MAX)
CityName nvarchar(50)
State nvarchar(50)
PinNumber nvarchar(50)
Product nvarchar(50)
RemarkNote nvarchar(MAX)
The issue which I am facing lately is that when I am storing records to the above table using stored procedure,ProspectCode is always set to 0 for all the rows that I add.I have 160 Records in the above table,But when I add new Record, its ProspectCode is set to 0 for all the record that I add.
Stored Procedure
ALTER Procedure [dbo].[Proc_InsertLeads]
#ProspectCode nvarchar(50),#CompanyName nvarchar(50),#PersonName nvarchar(50),#Designation nvarchar(50),#Number nvarchar(50),
#Number2 nvarchar(50),#Emailaddress nvarchar(50),#Address nvarchar(MAX),#Address2 nvarchar(MAX),
#CityName nvarchar(50),#State nvarchar(50),#PinNumber nvarchar(50),#Product nvarchar(50),#RemarkNote nvarchar(MAX)
AS
BEGIN
SET IDENTITY_INSERT LeadMastersNew ON;
INSERT INTO LeadMastersNew
(ProspectCode,CompanyName,PersonName,Designation,Number,Number2,Emailaddress,Address,Address2,CityName,State,PinNumber,Product,RemarkNote)
VALUES(#ProspectCode,#CompanyName,#PersonName,#Designation,#Number,#Number2,#Emailaddress,#Address,#Address2,#CityName,#State,#PinNumber,#Product,#RemarkNote)
INSERT INTO LoggerLeadMasters
(ProspectCode,CompanyName,PersonName,Designation,Number,Number2,Emailaddress,Address,Address2,CityName,State,PinNumber,Product,RemarkNote,Activity,ActivityTime)
VALUES(#ProspectCode,#CompanyName,#PersonName,#Designation,#Number,#Number2,#Emailaddress,#Address,#Address2,#CityName,#State,#PinNumber,#Product,#RemarkNote,'New Record Added',getdate())
SET IDENTITY_INSERT LeadMastersNew OFF;
END
EXEC Proc_InsertLeads'ABc','Mr abc','MD','PhoneNumber','','abc#abcindia.com','xyz','','Mumbai','Maharashtra','400059','Abc', 'Abc'
Sets ProspectCode to 0
Can anyone help me to fix this issue? Do I have to change my stored Procedure or Table Schema?
Thanks
If you want an identity column to assign numbers automatically, the thing you really shouldn't be doing is setting IDENTITY_INSERT to ON. Turning that setting on says to SQL Server "trust me, I'll provide the values in the identity column".
You probably want code something like:
BEGIN
DECLARE #NewID int
INSERT INTO LeadMastersNew
(/*ProspectCode,*/CompanyName,PersonName,Designation,Number,Number2,Emailaddress,Address,Address2,CityName,State,PinNumber,Product,RemarkNote)
VALUES(/*#ProspectCode,*/#CompanyName,#PersonName,#Designation,#Number,#Number2,#Emailaddress,#Address,#Address2,#CityName,#State,#PinNumber,#Product,#RemarkNote)
SET #NewID = SCOPE_IDENTITY()
INSERT INTO LoggerLeadMasters
(ProspectCode,CompanyName,PersonName,Designation,Number,Number2,Emailaddress,Address,Address2,CityName,State,PinNumber,Product,RemarkNote,Activity,ActivityTime)
VALUES(#NewID ,#CompanyName,#PersonName,#Designation,#Number,#Number2,#Emailaddress,#Address,#Address2,#CityName,#State,#PinNumber,#Product,#RemarkNote,'New Record Added',getdate())
END
This may not work exactly first time since I can't reconcile the code you've shown with how you're calling it. If ProspectCode is indeed an int column and you're actually trying to insert an nvarchar value of 'Choice Brokers', you should be getting an error.
you don't need identity_insert if you set autoincrement
remove rows
SET IDENTITY_INSERT LeadMastersNew ON;
SET IDENTITY_INSERT LeadMastersNew OFF;
and it should work
Here ProspectCode must set to Auto-increment since it is identity column for table. So basically in store procedure you must remove input parameter #ProspectCode and while inserting new row don't ON OFF IDENTITY_INSERT on table, final store procedure look like:
ALTER Procedure [dbo].[Proc_InsertLeads]
#CompanyName nvarchar(50),#PersonName nvarchar(50),#Designation nvarchar(50),#Number nvarchar(50),
#Number2 nvarchar(50),#Emailaddress nvarchar(50),#Address nvarchar(MAX),#Address2 nvarchar(MAX),
#CityName nvarchar(50),#State nvarchar(50),#PinNumber nvarchar(50),#Product nvarchar(50),#RemarkNote nvarchar(MAX)
AS
BEGIN
DECALRE #ID INT = 0
INSERT INTO LeadMastersNew
(CompanyName,PersonName,Designation,Number,Number2,Emailaddress,Address,Address2,CityName,State,PinNumber,Product,RemarkNote)
VALUES(#CompanyName,#PersonName,#Designation,#Number,#Number2,#Emailaddress,#Address,#Address2,#CityName,#State,#PinNumber,#Product,#RemarkNote)
SET #ID = SCOPE_IDENTITY()
INSERT INTO LoggerLeadMasters
(ProspectCode,CompanyName,PersonName,Designation,Number,Number2,Emailaddress,Address,Address2,CityName,State,PinNumber,Product,RemarkNote,Activity,ActivityTime)
VALUES(#ID,#CompanyName,#PersonName,#Designation,#Number,#Number2,#Emailaddress,#Address,#Address2,#CityName,#State,#PinNumber,#Product,#RemarkNote,'New Record Added',getdate())
END
Here I am using #ID parameter to find newly inserted ProspectCode in table LeadMastersNew which will used in table LoggerLeadMasters as ProspectCode.

Categories