Stored Procedure Storing 0 in Auto increment column in Table - c#

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.

Related

SELECT statement won't return row first time after INSERT commit transaction

I have two stored procedures, one AddReportsApi for inserting data with a BEGIN TRANSACTION and COMMIT TRANSACTION, and the other GetReportsApi for selecting the data for inserted row.
I call the INSERT stored procedure first, then I call the SELECT stored procedure but sometimes it does not return any rows for the passed in SearchItemId which is used in the WHERE predicate.
If I execute the SELECT stored procedure a second time, it returns the expected rows.
Is there a delay in inserting the data to the table? Please note that the stored procedures are called from HangFire background job framework. From my test, HangFire should not affect the INSERT and SELECT stored procedure calls. The INSERT stored procedure is called multiple times within a minute to insert the records into the ReprotsApi table.
Insert stored procedure:
CREATE PROCEDURE [dbo].[AddReportsApi]
#OrderID nvarchar(50),
#SearchItemId nvarchar(50),
#SubjectID nvarchar(50),
#SearchType nvarchar(50),
#ApiName nvarchar(50),
#ApiRequest text,
#ApiResponse text,
#IsActive bit,
#CreatedOn datetime,
#CreatedBy nvarchar(50),
#ModifyOn datetime,
#ModifyBy nvarchar(50),
#HitType nvarchar(2)
AS
BEGIN
SET NOCOUNT ON;
BEGIN TRANSACTION
INSERT INTO [dbo].[ReportsApi] ([OrderID], [SearchItemId], [SubjectID], [SearchType],
[ApiName], [ApiRequest], [ApiResponse], [IsActive],
[CreatedOn], [CreatedBy],
[ModifyOn], [ModifyBy], [HitType])
VALUES (#OrderID, #SearchItemId, #SubjectID, #SearchType,
#ApiName, #ApiRequest, #ApiResponse, #IsActive,
#CreatedOn, #CreatedBy,
#ModifyOn, #ModifyBy, #HitType)
IF (##ERROR != 0)
BEGIN
ROLLBACK TRANSACTION
END
ELSE
COMMIT TRANSACTION
END
SELECT stored procedure:
CREATE PROCEDURE [dbo].[GetReportsApi]
#OrderID nvarchar(50)
,#SearchItemId nvarchar(50)
,#SubjectID nvarchar(50)
,#CreatedBy nvarchar(50)
AS
BEGIN
SET NOCOUNT ON;
SELECT [Id]
,[OrderID]
,[SearchItemId]
,[SubjectID]
,[SearchType]
,[ApiName]
,[ApiRequest]
,[ApiResponse]
,[IsActive]
,[CreatedOn]
,[CreatedBy]
,[ModifyOn]
,[ModifyBy]
,[HitType]
FROM [dbo].[ReportsApi] WHERE [SearchItemId] = #SearchItemId
END
it might be because indexes are being rebuilt under the hood after the insert completes.
This can give dirty/phantom reads.
If you have an index on [SearchItemId] then the 2nd query might use this but the index may still being refreshed.
This can even affect clustered indexes if you are inserting into the middle of the B-Tree.
It might be worth sticking a sleep(10000) or WAITFOR DELAY '00:00:10'; into your code...
(That's 10 sec but you could experiment with different timings.)
Good luck!

How do I check that values are being inserted into a table when the result of the insert shows nothing?

I've ran into an issue concerning a SQL Server procedure that is supposed to insert data into three tables. The code below shows that the procedure takes in parameters and then inserts said parameters into three tables: an Address table, a D.O.B table and a Users table.
Ignoring the salt as that has to do with something else, my issue is that when I run this procedure from an ASP.NET MVC file, nothing is inserted into the Users table, even though the Address and D.O.B table both have their respective values inserted into them. I've had an issue like this before which was solved because the problem was that one of the values was returning NULL when I used a HASHBYTES procedure on it, however, here there is nothing that I can think that would be doing something similar.
ALTER PROCEDURE [dbo].[StoreDetails]
#FirstName VARCHAR(50),
#Surname VARCHAR(50),
#Password VARCHAR(100),
#PhoneNumber VARCHAR(50),
#Email VARCHAR(100),
#IsAdmin BIT,
#Address VARCHAR(100),
#DOB DATE
AS
BEGIN
SET NOCOUNT ON
DECLARE #Salt UNIQUEIDENTIFIER = NEWID()
INSERT INTO dbo.OAddress(Address)
VALUES (#Address)
INSERT INTO dbo.ODOB(DOB)
VALUES (#DOB)
INSERT INTO dbo.OUsers (FirstName, Surname, Password, Salt, PhoneNumber, Email, IsAdmin, AddressID, DOBID)
VALUES (#FirstName, #Surname, #Password, #Salt, #PhoneNumber, #Email, #IsAdmin, SCOPE_IDENTITY(), SCOPE_IDENTITY())
END
The C# side of this I believe does work as intended as not too long ago I managed to get this code to work until I changed the stored procedure to try and change the Password parameter to get hashed using HASHBYTES however I decided to just revert back to when it worked normally but as you can see I'm failing.
Seems like what you likely need is a couple of OUTPUT clauses and some table variables:
ALTER PROCEDURE [dbo].[StoreDetails] #FirstName varchar(50),
#Surname varchar(50),
#Password varchar(100),
#PhoneNumber varchar(50),
#Email varchar(100),
#IsAdmin bit,
#Address varchar(100),
#DOB date
AS
BEGIN
SET NOCOUNT ON;
DECLARE #Salt uniqueidentifier = NEWID();
DECLARE #AddressID table (ID int);
DECLARE #DOBID table (ID int);
INSERT INTO dbo.OAddress ([Address])
OUTPUT inserted.ID
INTO #AddressID (ID) --Guessed named for inserted
SELECT #Address;
INSERT INTO dbo.ODOB (DOB)
OUTPUT inserted.ID
INTO #DOBID (ID) --Guessed named for inserted
SELECT #DOB;
INSERT INTO dbo.OUsers (FirstName,
Surname,
Password,
Salt,
PhoneNumber,
Email,
IsAdmin,
AddressID,
DOBID)
SELECT #FirstName,
#Surname,
#Password,
#Salt,
#PhoneNumber,
#Email,
#IsAdmin,
A.ID,
D.ID
FROM #AddressID A
CROSS JOIN #DOBID D;
END;
Note the comments I make on the OUTPUT clauses.
You need to figure out what the database is telling you about the problem.
Put a breakpoint in your code and then grab all the values that the variables contain that you are putting into your parameters. Then switch to SQL, set up all your variables, and try running the statements from the procedure, and get the error message. Something like this:
declare #FirstName VARCHAR(50) = 'John'
declare #Surname VARCHAR(50) = 'Smith'
declare #Password VARCHAR(100) = 'Hek3$s*aSf8'
declare #PhoneNumber VARCHAR(50) = '333-333-3333'
declare #Email VARCHAR(100) = 'john#mailinator.com'
declare #IsAdmin BIT = 0
declare #Address VARCHAR(100) = '100 Somewhere Street, Somewheretown'
declare #DOB date = '2019-10-10'
DECLARE #Salt UNIQUEIDENTIFIER=NEWID()
INSERT INTO dbo.OAddress(Address)
VALUES(#Address)
INSERT INTO dbo.ODOB(DOB)
VALUES(#DOB)
INSERT INTO dbo.OUsers(FirstName,Surname,Password,Salt,PhoneNumber,Email,IsAdmin,AddressID,DOBID)
VALUES(#FirstName,#Surname,#Password,#Salt,#PhoneNumber,#Email,#IsAdmin,SCOPE_IDENTITY(),SCOPE_IDENTITY())
I think we probably need to suspect the SCOPE_IDENTITY() function calls, but there's only one way to find out: run it and see.
The problem here is the use of SCOPE_IDENTITY(). This returns the last identity value generated by the insert statement. In your code, SCOPE_IDENTITY() is returning the value inserted for dbo.oDOB.
In order for this to work, you would need to capture the value for SCOPE_IDENTITY() into a local variable after each of the insert statements, then use those values in your final insert into dbo.oUsers.
The following should get you what you want:
ALTER PROCEDURE [dbo].[StoreDetails]
#FirstName VARCHAR(50),
#Surname VARCHAR(50),
#Password VARCHAR(100),
#PhoneNumber VARCHAR(50),
#Email VARCHAR(100),
#IsAdmin BIT,
#Address VARCHAR(100),
#DOB DATE
AS
BEGIN
SET NOCOUNT ON
DECLARE #addressKey INT,
#dobKey INT;
DECLARE #Salt UNIQUEIDENTIFIER = NEWID();
INSERT INTO dbo.OAddress(Address)
VALUES (#Address);
SET #addressKey = SCOPE_IDENTITY();
INSERT INTO dbo.ODOB(DOB)
VALUES (#DOB);
SET #dobKey = SCOPE_IDENTITY();
INSERT INTO dbo.OUsers (FirstName, Surname, Password, Salt, PhoneNumber, Email, IsAdmin, AddressID, DOBID)
VALUES (#FirstName, #Surname, #Password, #Salt, #PhoneNumber, #Email, #IsAdmin, #addressKey, #dobKey)
END
Firstly, you should run stored procedure with the params to know what are error messages exactly.
Secondly, You should handle error message inner stored procedure and check after each time you inserted.
For example:
INSERT INTO dbo.OAddress(Address)
VALUES(#Address)
IF ##ERROR <> 0
BEGIN
PRINT N'A check constraint violation occurred.';
Return;
END
GO
However, You should also use out put param then RETURN ##ERROR to check in c# whether it's inserted successfully or not

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)

Adding id value into ecaxtly id column

I'm using SQL Managment Studio to connect my database and I'm trying to add some rows into it in Windows App using Stored Procedures.
Whenever I add a row the id value adds into a new column1 as it shown at the screenshot. How can i fix it?
dataGridView1.Columns["id"].ReadOnly = true;
Stored Procedure:
USE [schedule]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[sp_insertProduct]
#date date,
#less_n int,
#teacher nchar,
#room int,
#gr int,
#subject nchar
AS
INSERT INTO dbo.main(date, less_n, teacher, room, gr, subject) VALUES
(#date, #less_n, #teacher, #room, #gr, #subject)
SELECT SCOPE_IDENTITY()
Screenshoot

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

Categories