I am creating a web page to store data which is read from a Microsoft Excel worksheet.
I am passing the data to a stored procedure in SQL Server 2008.
Here is my C# code:
SqlConnection conn = new SqlConnection(AppDB);
conn.Open();
SqlCommand command = new SqlCommand();
command.Connection = conn;
command.CommandType = CommandType.StoredProcedure;
command.CommandText = "sp_ins_TaskDetails_from_Excel";
command.Parameters.AddWithValue("#TaskDetails", dtTaskDetailsFromExcel);
string sReturnValue = command.ExecuteNonQuery().ToString();
The stored procedure has one user defined table data type as parameter.
Here is my stored procedure:
ALTER PROCEDURE dbo.sp_ins_TaskDetails_from_Excel
(
#TaskDetails TypeInsertTaskFromExcel11 readonly
)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
DECLARE
#ProjectID int,
#ProjectTeamID int,
#TeamLeaderUserID int,
#TaskCategoryName varchar(max),
#TaskDescription varchar(max),
#TeamMemberUserID int,
#TaskPriorityName varchar(10),
#PlanDuration float,
#PlanStartDate datetime,
#PlanEndDate datetime,
#TaskTypeName varchar(30),
#TaskStatusName varchar(30),
#TaskAllotName varchar(10),
#CreatedBy varchar(30),
#CreatedDate datetime,
#ISMailSend bit,
#Isvisible bit,
#UniqueID int
DECLARE TMSTaskDetailFromExcelCursor CURSOR FOR SELECT
ProjectID,
ProjectTeamID,
TeamLeaderUserID,
TaskCategoryName,
TaskDescription,
TeamMemberUserID,
TaskPriorityName,
PlanDuration,
PlanStartDate,
PlanEndDate,
TaskTypeName,
TaskStatusName,
TaskAllotName,
CreatedBy,
CreatedDate,
ISMailSend,
Isvisible,
UniqueID
FROM #TaskDetails
OPEN TMSTaskDetailFromExcelCursor
FETCH NEXT FROM TMSTaskDetailFromExcelCursor INTO
#ProjectID,
#ProjectTeamID,
#TeamLeaderUserID,
#TaskCategoryName,
#TaskDescription,
#TeamMemberUserID,
#TaskPriorityName,
#PlanDuration,
#PlanStartDate,
#PlanEndDate,
#TaskTypeName,
#TaskStatusName,
#TaskAllotName,
#CreatedBy,
#CreatedDate,
#ISMailSend,
#Isvisible,
#UniqueID;
WHILE ##FETCH_STATUS=0 BEGIN
-- Insert statements for procedure here
INSERT INTO ManageTasks (ProjectID, ProjectTeamID, TeamLeaderUserID,
TaskCategoryName,TaskDescription, TeamMemberUserID, TaskPriorityName,
PlanDuration, PlanStartDate, PlanEndDate, TaskTypeName,
TaskStatusName, TaskAllotName, CreatedBy, CreatedDate, ISMailSend, Isvisible,UniqueID)
VALUES (#ProjectID, #ProjectTeamID, #TeamLeaderUserID, #TaskCategoryName,
#TaskDescription, #TeamMemberUserID, #TaskPriorityName, #PlanDuration,
#PlanStartDate, #PlanEndDate, #TaskTypeName, #TaskStatusName,
#TaskAllotName, #CreatedBy, #CreatedDate, #ISMailSend,#Isvisible,#UniqueID);
FETCH NEXT FROM TMSTaskDetailFromExcelCursor INTO
#ProjectID,
#ProjectTeamID,
#TeamLeaderUserID,
#TaskCategoryName,
#TaskDescription,
#TeamMemberUserID,
#TaskPriorityName,
#PlanDuration,
#PlanStartDate,
#PlanEndDate,
#TaskTypeName,
#TaskStatusName,
#TaskAllotName,
#CreatedBy,
#CreatedDate,
#ISMailSend,
#Isvisible,
#UniqueID;
END;
CLOSE TMSTaskDetailFromExcelCursor;
DEALLOCATE TMSTaskDetailFromExcelCursor;
END
It receives the data and using a cursor in the same stored procedure each row will be inserted using an Insert statement in the same procedure.
While executing, all the data from Excel is passed to the stored procedure as exactly mentioned in the user defined table type.
But, the values are not stored in database and the stored procedure returns -1.
All the values are in correct format and order. I don't know what is going wrong.
Is there something I should change in the stored procedures?
Related
Model model=new Model();
model.id=0;
model.name="";
model.surname="";
db.Model.Add(model);
db.SaveChanges();
int id_returned=model.id;
This block gives me the id field of the inserted row.
But i use stored procedure for this insert process.
Model model=new Model();
model.id=0;
model.name="";
model.surname="";
int returned_id2=db.Sp_Model_insert(model.name, model.surname);
this block inserts the row. returned_id2 returns -1.
How can i get the row id that inserted via Sp ?
Here is my Stored Procedure:
USE [KayaShop]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [KS_ACCOUNTS].[SP_AccountModules_Insert](
#Area nvarchar(50),
#Controller nvarchar(50),
#Action nvarchar(50),
#SubAction nvarchar(50),
#Name nvarchar(50),
#TopName nvarchar(50),
#Level int,
#Visible int,
#Clickable int,
#HomePage int,
#Icon nvarchar(20),
#Status int
)
AS
BEGIN
SET NOCOUNT ON
INSERT INTO [KS_ACCOUNTS].[AccountModules]
([Area]
,[Controller]
,[Action]
,[SubAction]
,[Name]
,[TopName]
,[Level]
,[Visible]
,[Clickable]
,[HomePage]
,[Icon]
,[Status])
VALUES
(#Area,
#Controller,
#Action,
#SubAction,
#Name,
#TopName,
#Level,
#Visible,
#Clickable,
#HomePage,
#Icon,
#Status)
END
SELECT SCOPE_IDENTITY()
Add this after the insert query in your stored procedure
Multiple ways:
SCOPE_IDENTITY() - https://msdn.microsoft.com/en-us/library/ms190315.aspx - Returns the last single IDENTITY value in the current session's current scope.
##IDENTITY - https://msdn.microsoft.com/en-us/library/ms187342.aspx - Returns the last single IDENTITY value in the current session (regardless of scope).
INSERT INTO ... VALUES ... OUTPUT - https://msdn.microsoft.com/en-us/library/ms177564.aspx - outputs all inserted values, including IDENTITY values, this is the only way to retrieve IDENTITY values when your INSERT statement will insert multiple rows.
As your stored procedure only seems to insert a single row, you should be fine with SCOPE_IDENTITY.
Note that if all your stored procedure does is INSERT you probably don't need a stored procedure, your database client code should perform the INSERT directly.
Note that you should not use the RETURN keyword to return the IDENTITY value to the caller, you should use output parameters - a stored procedure's return-value is intended to convey status information and it is restricted to just an int value (e.g. return 0 for success).
I added these lines to the end of my sp:
SELECT #Id =SCOPE_IDENTITY()
RETURN
and at my code side:
int Id = 0;
ObjectParameter prm = new ObjectParameter("Id", typeof(int));
DB.SP_AccountModules_Insert(DTO.Area, DTO.Controller, DTO.Action, DTO.SubAction, DTO.Name, DTO.TopName, DTO.Level, DTO.Visible, DTO.Clickable, DTO.HomePage, DTO.Icon, DTO.Status, prm);
Id = Convert.ToInt32(prm.Value);
return Id;
i send and out parameter from my code to my sp, then i assign the last inserted id to my parameter and return it to my code. thats it.
Thank you for all help.
Can I perform a bulk update using a stored procedure that sends data to a temp table from user input which is not in a datatable.
If I have a foreach loop that takes user input such as values from a checkboxlist and text boxes what I want to know is how to parameterize those separate values in my stored procedure or if I can do it in my code. I cannot use table-valued parameters since I'm using a version of SQL that does not support it.
conn.Open();
foreach(ListItem item in CheckBoxList1.Items)
{
if(item.Selected)
{
//handling parameters in loop.
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "Update_Account_Table";
cmd.Parameters["#SeqNum"].Value = amount.Text;
cmd.Parameters["#SeqDate"].Value = DateTime.ParseExact(datepicker.Text, "mmddyyyy", CultureInfo.InvariantCulture);
cmd.Parameters["#Account_ID"].CheckBoxList1.SelectedValue;
cmd.ExecuteNonQuery();
}
conn.Close();
}
Stored procedure
CREATE TABLE TempTable
(
SeqNum int,
SeqDate datetime,
Account_ID varchar(2)
);
CREATE PROCEDURE [ACCOUNTTABLE_UPDATE]
AS
SET NOCOUNT ON
BEGIN
UPDATE AccountTable
SET SeqNum = t.SeqNum, SeqDate = t.SeqDate
FROM AccountTable AT
INNER JOIN TempTable t ON AT.AccountID = t.AccountID
END
This uses a dynamic table name in stored procedure, and sets value based on incoming parameter. You could use code below instead of temp table, or use parameters #seqnum, #SeqDate, #AcctID in place of #Stats_Value below:
USE [EODData]
GO
/****** Object: StoredProcedure [dbo].[erase_Stats] Script Date: 8/23/2016 4:32:55 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[erase_Stats]
#table varchar(25), #stats_value int
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
Declare #ProductsSQL nvarchar(max);
SET #ProductsSQL = 'update ' + #table + ' set stats_completed = #Stats_Value'
exec sp_executesql #ProductsSQL
END
GO
you can add # before the table to make it temporary table
your should be like
CREATE TABLE #TempTable
will create temporary table and destroyed after process completes
I am executing an Insert query. I want to return the identity element. I am also using this same stored procedure. Inside another stored procedure to return the identity element.
Alter Proc Proc1
#name varchar(10),
#value int
As
Begin
insert into Table1
values (#name, #value)
return SCOPE_IDENTITY()
C# code:
I have a method to call my database every time, so I use that
_database.StoredProcedure = "Proc1";
_database.parameter("name","michael");
_database.parameter("value",10);
int id = Convert.ToInt32(_database.ExecuteScalar());
Here, I get id=0 every time //BUG
SQL other stored procedure:
Alter Proc2
// Some other logic
Execute #id = Proc1 #name, #value // THIS WORKS
Now, If I change Proc1's last line to Select SCOPE_IDENTITY() from RETURN SCOPE_IDENTITY() then C# code works but Proc2 returns 0.
What should I do such that it works in C# code and in Proc2 also.
I thought about an output parameter, but I don't know how would I call it with my this database method in C#.
If you want data out of a procedure the correct thing is to use output parameters. Do NOT use the return_value from your procedures. This value indicates a status of the execution, not data from the procedure.
Here is an example of what this might look like.
Alter Proc Proc1
#name varchar(10),
#value int,
#IdentityValue int OUTPUT
As
Begin
insert into Table1 values (#name,#value)
Select #IdentityValue = SCOPE_IDENTITY()
END
select * from table1
GO
Alter Proc2
(
#name varchar(10)
, #value int
, #IdentityValue int OUTPUT
)
as
//SOme other logic
declare #IdentityValue int
Execute Proc1 #name, #value, #IdentityValue OUTPUT
GO
Also, please notice that you have an insert in Proc1 but you don't specify the columns. This is very bad practice. If your table structure changes your procedure is broken. You should ALWAYS specify the columns in your insert.
Change your procedure body to like below, to change the RETURN statement to SELECT SCOPE_IDENTITY()
Alter Proc Proc1
#name varchar(10),
#value int
As
Begin
insert into Table1 values (#name,#value);
SELECT SCOPE_IDENTITY();
END
In that case, make it a output parameter and set that output parameter to scope_identity
Alter Proc Proc1
#name varchar(10),
#value int,
#ID INT OUTPUT
As
Begin
insert into Table1 values (#name,#value);
SET #ID = SCOPE_IDENTITY();
END
You can call the procedure
cmd.Parameters.Add("#ID", SqlDbType.Int, 0, "ID");
cmd.Parameters["#ID"].Direction = ParameterDirection.Output;
conn.Open();
cmd.ExecuteNonQuery();
int id = (int)cmd.Parameters["#ID"].Value;
I have a SQL procedure that I'm calling from my c# code.
cmd = new SqlCommand("InsertData", con, transaction);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#IP_No", SqlDbType.VarChar, 50);
cmd.Parameters["#IP_No"].Value = data.IP_No;
result = cmd.ExecuteNonQuery().ToString();
This is my procedure:
(
#IP_No varchar(15),
#Indent_No varchar(20)
)
AS
BEGIN
set #Indent_No = (SELECT IndentId from IdTable)
INSERT INTO InsertData(IP_No,Indent_No)
VALUES(#IP_No,#Indent_No)
Update IdTable set IndentId=IndentId+1;
END
Basically, I want my ID to be pulled from a database where I keep incrementing it.
It throws this error:
Procedure or function expects parameter #Indent_No which was not
supplied.
Please Help!
As you use #Indent_No only internally within the stored procedure, you don't need to declare it as an input parameter. You need to declare it within the body of your stored procedure
CREATE PROCEDURE InsertData
(
#IP_No varchar(15)
)
AS
BEGIN
DECLARE #Indent_No varchar(20)
set #Indent_No = (SELECT IndentId from IdTable)
INSERT INTO InsertData(IP_No,Indent_No)
VALUES(#IP_No,#Indent_No)
Update IdTable set IndentId=IndentId+1;
END
I saw few solutions here but none worked. I tried SCOPE_IDENTITY() didn't wotk. the id is autoincrement.
This is my stored procedure
CREATE PROCEDURE [dbo].[uploadVid]
#video varbinary(MAx),
#vidTitle varchar(50),
#vidCategory varchar(50),
#vidDate date,
#vidDescription varchar(Max),
#vidName varchar(50),
#vidSize bigint
AS
INSERT INTO Video(video, vidTitle, vidCategory, vidDate, vidDescription, vidName, vidSize)
VALUES (#video, #vidTitle, #vidCategory, #vidDate, #vidDescription, #vidName, #vidSize)
& in the back end I tried
Object i = register.ExecuteScalar();
&
int newId = (Int32)register.ExecuteScalar();
I put a break point and it gave me a value of null or 0. any help appreciated
Thanks
try this
CREATE PROCEDURE [dbo].[uploadVid]
#video varbinary(MAx),
#vidTitle varchar(50),
#vidCategory varchar(50),
#vidDate date,
#vidDescription varchar(Max),
#vidName varchar(50),
#vidSize bigint
AS
begin
declare #id as int --assuming your identity column is int
INSERT INTO Video(video, vidTitle, vidCategory, vidDate, vidDescription, vidName, vidSize)
VALUES (#video, #vidTitle, #vidCategory, #vidDate, #vidDescription, #vidName, #vidSize)
set #id = scope_identity()
select #id --return the value for executescaler to catch it
end
Probably you don't execute the commands in the correct sequence: (supposing you are using an SQL Server DB)
SqlCommand cmd = new SqlCommand("uploadVid", connnection);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(.....)
......
// After adding the parameters you execute the command to insert the new row....
int rowsInserted = cmd.ExecuteNonQuery();
if(rowsInserted > 0)
{
SqlCommand cmd1 = new SqlCommand("SELECT SCOPE_IDENTITY()", connection);
int newID = (int)cmd1.ExecuteScalar();
}
ExecuteScalar returns only the value of the first row in the first column of the query executed. In case of an insert this value is meaningless. You need an ExecuteNonQuery that returns the rows inserted by the command. After that run a new command with the SELECT SCOPE_IDENTITY() command text with the ExecuteScalar. This, of course, if you cannot modify the SP, the answer from th1rdey3 is better if you could change the proc because it avoids a run-trip to the database.